@deck.gl/extensions 9.4.0-beta.1 → 9.4.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dist.dev.js +1281 -120
- package/dist/fill-style/fill-style-extension.d.ts +38 -6
- package/dist/fill-style/fill-style-extension.d.ts.map +1 -1
- package/dist/fill-style/fill-style-extension.js +88 -10
- package/dist/fill-style/fill-style-extension.js.map +1 -1
- package/dist/fill-style/procedural-pattern.d.ts +65 -0
- package/dist/fill-style/procedural-pattern.d.ts.map +1 -0
- package/dist/fill-style/procedural-pattern.js +135 -0
- package/dist/fill-style/procedural-pattern.js.map +1 -0
- package/dist/fill-style/shader-module.d.ts +13 -4
- package/dist/fill-style/shader-module.d.ts.map +1 -1
- package/dist/fill-style/shader-module.js +212 -21
- package/dist/fill-style/shader-module.js.map +1 -1
- package/dist/index.cjs +946 -172
- package/dist/index.cjs.map +3 -3
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/mask/shader-module.d.ts +1 -0
- package/dist/mask/shader-module.d.ts.map +1 -1
- package/dist/path-style/path-style-extension.d.ts +49 -6
- package/dist/path-style/path-style-extension.d.ts.map +1 -1
- package/dist/path-style/path-style-extension.js +237 -37
- package/dist/path-style/path-style-extension.js.map +1 -1
- package/dist/path-style/shaders.glsl.d.ts +30 -1
- package/dist/path-style/shaders.glsl.d.ts.map +1 -1
- package/dist/path-style/shaders.glsl.js +136 -21
- package/dist/path-style/shaders.glsl.js.map +1 -1
- package/dist/terrain/shader-module.d.ts +1 -0
- package/dist/terrain/shader-module.d.ts.map +1 -1
- package/dist.min.js +377 -98
- package/package.json +6 -6
- package/src/fill-style/fill-style-extension.ts +135 -13
- package/src/fill-style/procedural-pattern.ts +203 -0
- package/src/fill-style/shader-module.ts +233 -23
- package/src/index.ts +10 -1
- package/src/path-style/path-style-extension.ts +350 -44
- package/src/path-style/shaders.glsl.ts +268 -27
package/dist/index.cjs
CHANGED
|
@@ -15,7 +15,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
15
|
}
|
|
16
16
|
return to;
|
|
17
17
|
};
|
|
18
|
-
var __toCommonJS = (
|
|
18
|
+
var __toCommonJS = (mod2) => __copyProps(__defProp({}, "__esModule", { value: true }), mod2);
|
|
19
19
|
|
|
20
20
|
// dist/index.js
|
|
21
21
|
var index_exports = {};
|
|
@@ -608,7 +608,7 @@ fn project_mercator_(lnglat: vec2<f32>) -> vec2<f32> {
|
|
|
608
608
|
let y = clamp(lnglat.y, -89.9, 89.9);
|
|
609
609
|
return vec2<f32>(
|
|
610
610
|
radians(x) + PI,
|
|
611
|
-
PI + log(
|
|
611
|
+
PI + log(tan_fp32(PI * 0.25 + radians(y) * 0.5))
|
|
612
612
|
) * WORLD_SCALE;
|
|
613
613
|
}
|
|
614
614
|
|
|
@@ -1480,6 +1480,10 @@ var import_core2 = require("@math.gl/core");
|
|
|
1480
1480
|
function createMat4() {
|
|
1481
1481
|
return [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
|
|
1482
1482
|
}
|
|
1483
|
+
function mod(value, divisor) {
|
|
1484
|
+
const modulus = value % divisor;
|
|
1485
|
+
return modulus < 0 ? divisor + modulus : modulus;
|
|
1486
|
+
}
|
|
1483
1487
|
function getCameraPosition(viewMatrixInverse) {
|
|
1484
1488
|
return [viewMatrixInverse[12], viewMatrixInverse[13], viewMatrixInverse[14]];
|
|
1485
1489
|
}
|
|
@@ -1603,8 +1607,8 @@ var _Viewport = class _Viewport {
|
|
|
1603
1607
|
}
|
|
1604
1608
|
return PROJECTION_MODE.IDENTITY;
|
|
1605
1609
|
}
|
|
1606
|
-
// Two viewports are equal if
|
|
1607
|
-
//
|
|
1610
|
+
// Two viewports are equal if their dimensions, common-space scale, and
|
|
1611
|
+
// view and projection matrices are (approximately) equal.
|
|
1608
1612
|
equals(viewport) {
|
|
1609
1613
|
if (!(viewport instanceof _Viewport)) {
|
|
1610
1614
|
return false;
|
|
@@ -1612,7 +1616,7 @@ var _Viewport = class _Viewport {
|
|
|
1612
1616
|
if (this === viewport) {
|
|
1613
1617
|
return true;
|
|
1614
1618
|
}
|
|
1615
|
-
return viewport.width === this.width && viewport.height === this.height && viewport.scale === this.scale && (0, import_core3.equals)(viewport.projectionMatrix, this.projectionMatrix) && (0, import_core3.equals)(viewport.viewMatrix, this.viewMatrix);
|
|
1619
|
+
return viewport.width === this.width && viewport.height === this.height && viewport.scale === this.scale && viewport.projectionMode === this.projectionMode && viewport.resolution === this.resolution && (0, import_core3.equals)(viewport.distanceScales.unitsPerMeter, this.distanceScales.unitsPerMeter) && (0, import_core3.equals)(viewport.projectionMatrix, this.projectionMatrix) && (0, import_core3.equals)(viewport.viewMatrix, this.viewMatrix);
|
|
1616
1620
|
}
|
|
1617
1621
|
/**
|
|
1618
1622
|
* Projects xyz (possibly latitude and longitude) to pixel coordinates in window
|
|
@@ -1949,6 +1953,10 @@ var _WebMercatorViewport = class _WebMercatorViewport extends Viewport {
|
|
|
1949
1953
|
}
|
|
1950
1954
|
return this._subViewports;
|
|
1951
1955
|
}
|
|
1956
|
+
/** Returns whether two Web Mercator viewports use the same projection settings. */
|
|
1957
|
+
equals(viewport) {
|
|
1958
|
+
return viewport instanceof _WebMercatorViewport && viewport._pseudoMeters === this._pseudoMeters && super.equals(viewport);
|
|
1959
|
+
}
|
|
1952
1960
|
projectPosition(xyz) {
|
|
1953
1961
|
if (this._pseudoMeters) {
|
|
1954
1962
|
return super.projectPosition(xyz);
|
|
@@ -2198,15 +2206,52 @@ function deepEqual(a, b, depth) {
|
|
|
2198
2206
|
return false;
|
|
2199
2207
|
}
|
|
2200
2208
|
|
|
2209
|
+
// ../core/src/utils/shader.ts
|
|
2210
|
+
function mergeShaders(target, source2) {
|
|
2211
|
+
if (!source2) {
|
|
2212
|
+
return target;
|
|
2213
|
+
}
|
|
2214
|
+
const result = { ...target, ...source2 };
|
|
2215
|
+
if ("defines" in source2) {
|
|
2216
|
+
result.defines = { ...target.defines, ...source2.defines };
|
|
2217
|
+
}
|
|
2218
|
+
if ("modules" in source2) {
|
|
2219
|
+
result.modules = (target.modules || []).concat(source2.modules);
|
|
2220
|
+
if (source2.modules.some((module2) => module2.name === "project64")) {
|
|
2221
|
+
const index = result.modules.findIndex((module2) => module2.name === "project32");
|
|
2222
|
+
if (index >= 0) {
|
|
2223
|
+
result.modules.splice(index, 1);
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
2227
|
+
if ("inject" in source2) {
|
|
2228
|
+
if (!target.inject) {
|
|
2229
|
+
result.inject = source2.inject;
|
|
2230
|
+
} else {
|
|
2231
|
+
const mergedInjection = { ...target.inject };
|
|
2232
|
+
for (const key in source2.inject) {
|
|
2233
|
+
mergedInjection[key] = (mergedInjection[key] || "") + source2.inject[key];
|
|
2234
|
+
}
|
|
2235
|
+
result.inject = mergedInjection;
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
return result;
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2201
2241
|
// ../core/src/viewports/globe-viewport.ts
|
|
2202
2242
|
var import_core5 = require("@math.gl/core");
|
|
2203
2243
|
var import_web_mercator3 = require("@math.gl/web-mercator");
|
|
2204
|
-
var import_core6 = require("@math.gl/core");
|
|
2205
|
-
var import_web_mercator4 = require("@math.gl/web-mercator");
|
|
2206
2244
|
var DEGREES_TO_RADIANS2 = Math.PI / 180;
|
|
2207
2245
|
var RADIANS_TO_DEGREES = 180 / Math.PI;
|
|
2246
|
+
var NORTH_UP_BEARING_THRESHOLD = 1;
|
|
2208
2247
|
var EARTH_RADIUS = 6370972;
|
|
2209
2248
|
var GLOBE_RADIUS = 256;
|
|
2249
|
+
var GLOBE_ZOOM_ANCHOR_DAMPING_START_RATIO = 0.75;
|
|
2250
|
+
var GLOBE_ZOOM_ANCHOR_MAX_DISTANCE_RATIO = 1.15;
|
|
2251
|
+
function isGlobeNorthUp(bearing) {
|
|
2252
|
+
const normalizedBearing = mod(bearing + 180, 360) - 180;
|
|
2253
|
+
return Math.abs(normalizedBearing) < NORTH_UP_BEARING_THRESHOLD;
|
|
2254
|
+
}
|
|
2210
2255
|
function getDistanceScales2() {
|
|
2211
2256
|
const unitsPerMeter2 = GLOBE_RADIUS / EARTH_RADIUS;
|
|
2212
2257
|
const unitsPerDegree = Math.PI / 180 * GLOBE_RADIUS;
|
|
@@ -2240,7 +2285,7 @@ var GlobeViewport = class extends Viewport {
|
|
|
2240
2285
|
} else {
|
|
2241
2286
|
fovy = (0, import_web_mercator3.altitudeToFovy)(altitude);
|
|
2242
2287
|
}
|
|
2243
|
-
const scaleLatitude = Math.max(Math.min(latitude,
|
|
2288
|
+
const scaleLatitude = Math.max(Math.min(latitude, import_web_mercator3.MAX_LATITUDE), -import_web_mercator3.MAX_LATITUDE);
|
|
2244
2289
|
const scale = Math.pow(2, zoom - zoomAdjust(scaleLatitude));
|
|
2245
2290
|
const pitchRadians = pitch * DEGREES_TO_RADIANS2;
|
|
2246
2291
|
const nearZ = opts.nearZ ?? nearZMultiplier;
|
|
@@ -2291,6 +2336,67 @@ var GlobeViewport = class extends Viewport {
|
|
|
2291
2336
|
Math.max(left[1], right[1], top[1], bottom[1])
|
|
2292
2337
|
];
|
|
2293
2338
|
}
|
|
2339
|
+
/**
|
|
2340
|
+
* Builds the screen-pixel → globe-center ray and the intermediate ray/sphere
|
|
2341
|
+
* math reused by `unproject` and anchored zoom. One function so the same
|
|
2342
|
+
* pixelUnprojectionMatrix work isn't duplicated.
|
|
2343
|
+
*/
|
|
2344
|
+
_getRayToGlobe(screenPosition, { topLeft = true, targetZ } = {}) {
|
|
2345
|
+
const [screenX, screenY] = screenPosition;
|
|
2346
|
+
const adjustedScreenY = topLeft ? screenY : this.height - screenY;
|
|
2347
|
+
const { pixelUnprojectionMatrix } = this;
|
|
2348
|
+
const rayStartPosition = transformVector(pixelUnprojectionMatrix, [
|
|
2349
|
+
screenX,
|
|
2350
|
+
adjustedScreenY,
|
|
2351
|
+
-1,
|
|
2352
|
+
1
|
|
2353
|
+
]);
|
|
2354
|
+
const rayEndPosition = transformVector(pixelUnprojectionMatrix, [
|
|
2355
|
+
screenX,
|
|
2356
|
+
adjustedScreenY,
|
|
2357
|
+
1,
|
|
2358
|
+
1
|
|
2359
|
+
]);
|
|
2360
|
+
const radius = ((targetZ || 0) / EARTH_RADIUS + 1) * GLOBE_RADIUS;
|
|
2361
|
+
const rayLengthSquared = import_core5.vec3.sqrLen(import_core5.vec3.sub([], rayStartPosition, rayEndPosition));
|
|
2362
|
+
const rayStartDistanceSquared = import_core5.vec3.sqrLen(rayStartPosition);
|
|
2363
|
+
const rayEndDistanceSquared = import_core5.vec3.sqrLen(rayEndPosition);
|
|
2364
|
+
const triangleAreaSquared = (4 * rayStartDistanceSquared * rayEndDistanceSquared - (rayLengthSquared - rayStartDistanceSquared - rayEndDistanceSquared) ** 2) / 16;
|
|
2365
|
+
const distanceToCenterSquared = 4 * triangleAreaSquared / rayLengthSquared;
|
|
2366
|
+
return {
|
|
2367
|
+
rayStartPosition,
|
|
2368
|
+
rayEndPosition,
|
|
2369
|
+
radius,
|
|
2370
|
+
rayLengthSquared,
|
|
2371
|
+
rayStartDistanceSquared,
|
|
2372
|
+
distanceToCenterSquared
|
|
2373
|
+
};
|
|
2374
|
+
}
|
|
2375
|
+
_getRayDistanceToGlobeCenterRatio(screenPosition, options) {
|
|
2376
|
+
const { distanceToCenterSquared, radius } = this._getRayToGlobe(screenPosition, options);
|
|
2377
|
+
return Math.sqrt(Math.max(0, distanceToCenterSquared)) / radius;
|
|
2378
|
+
}
|
|
2379
|
+
/**
|
|
2380
|
+
* Returns how strongly a screen position should anchor zoom on the visible globe.
|
|
2381
|
+
* A value of `0` means that the controller should fall back to center zoom.
|
|
2382
|
+
* @param screenPosition - Screen position to evaluate.
|
|
2383
|
+
* @returns Anchor strength from `0` to `1`.
|
|
2384
|
+
*/
|
|
2385
|
+
getZoomAnchorStrength(screenPosition) {
|
|
2386
|
+
const distanceRatio = this._getRayDistanceToGlobeCenterRatio(screenPosition);
|
|
2387
|
+
if (distanceRatio >= GLOBE_ZOOM_ANCHOR_MAX_DISTANCE_RATIO) {
|
|
2388
|
+
return 0;
|
|
2389
|
+
}
|
|
2390
|
+
const edgeProgress = Math.max(
|
|
2391
|
+
0,
|
|
2392
|
+
Math.min(
|
|
2393
|
+
1,
|
|
2394
|
+
(distanceRatio - GLOBE_ZOOM_ANCHOR_DAMPING_START_RATIO) / (GLOBE_ZOOM_ANCHOR_MAX_DISTANCE_RATIO - GLOBE_ZOOM_ANCHOR_DAMPING_START_RATIO)
|
|
2395
|
+
)
|
|
2396
|
+
);
|
|
2397
|
+
const smoothProgress = edgeProgress * edgeProgress * (3 - 2 * edgeProgress);
|
|
2398
|
+
return 1 - smoothProgress;
|
|
2399
|
+
}
|
|
2294
2400
|
unproject(xyz, { topLeft = true, targetZ } = {}) {
|
|
2295
2401
|
const [x, y, z] = xyz;
|
|
2296
2402
|
const y2 = topLeft ? y : this.height - y;
|
|
@@ -2299,18 +2405,22 @@ var GlobeViewport = class extends Viewport {
|
|
|
2299
2405
|
if (Number.isFinite(z)) {
|
|
2300
2406
|
coord = transformVector(pixelUnprojectionMatrix, [x, y2, z, 1]);
|
|
2301
2407
|
} else {
|
|
2302
|
-
const
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
const
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2408
|
+
const {
|
|
2409
|
+
rayStartPosition,
|
|
2410
|
+
rayEndPosition,
|
|
2411
|
+
radius,
|
|
2412
|
+
rayLengthSquared,
|
|
2413
|
+
rayStartDistanceSquared,
|
|
2414
|
+
distanceToCenterSquared
|
|
2415
|
+
} = this._getRayToGlobe(xyz, { topLeft, targetZ });
|
|
2416
|
+
const rayStartToClosestApproach = Math.sqrt(
|
|
2417
|
+
rayStartDistanceSquared - distanceToCenterSquared
|
|
2418
|
+
);
|
|
2419
|
+
const closestApproachToIntersection = Math.sqrt(
|
|
2420
|
+
Math.max(0, radius * radius - distanceToCenterSquared)
|
|
2421
|
+
);
|
|
2422
|
+
const intersectionRatio = (rayStartToClosestApproach - closestApproachToIntersection) / Math.sqrt(rayLengthSquared);
|
|
2423
|
+
coord = import_core5.vec3.lerp([], rayStartPosition, rayEndPosition, intersectionRatio);
|
|
2314
2424
|
}
|
|
2315
2425
|
const [X, Y, Z] = this.unprojectPosition(coord);
|
|
2316
2426
|
if (Number.isFinite(z)) {
|
|
@@ -2328,7 +2438,7 @@ var GlobeViewport = class extends Viewport {
|
|
|
2328
2438
|
}
|
|
2329
2439
|
unprojectPosition(xyz) {
|
|
2330
2440
|
const [x, y, z] = xyz;
|
|
2331
|
-
const D =
|
|
2441
|
+
const D = import_core5.vec3.len(xyz);
|
|
2332
2442
|
const phi = Math.asin(z / D);
|
|
2333
2443
|
const lambda = Math.atan2(x, -y);
|
|
2334
2444
|
const lng = lambda * RADIANS_TO_DEGREES;
|
|
@@ -2343,73 +2453,64 @@ var GlobeViewport = class extends Viewport {
|
|
|
2343
2453
|
return xyz;
|
|
2344
2454
|
}
|
|
2345
2455
|
/**
|
|
2346
|
-
* Pan the globe
|
|
2347
|
-
*
|
|
2348
|
-
* @param
|
|
2349
|
-
* @param
|
|
2350
|
-
* @
|
|
2456
|
+
* Pan the globe to place geographic coordinates at a screen pixel.
|
|
2457
|
+
* When `dragStartPosition` is supplied, applies the delta-based movement used by globe dragging.
|
|
2458
|
+
* @param coordinates - Geographic anchor, or the starting longitude, latitude and zoom.
|
|
2459
|
+
* @param screenPosition - Current screen position.
|
|
2460
|
+
* @param dragStartPosition - Screen position where a drag started.
|
|
2461
|
+
* @returns Updated viewport options.
|
|
2351
2462
|
*/
|
|
2352
|
-
panByPosition(
|
|
2463
|
+
panByPosition(coordinates, screenPosition, dragStartPosition) {
|
|
2464
|
+
if (!dragStartPosition) {
|
|
2465
|
+
let anchorStrength = this.getZoomAnchorStrength(screenPosition);
|
|
2466
|
+
if (anchorStrength === 0) {
|
|
2467
|
+
return { longitude: this.longitude, latitude: this.latitude };
|
|
2468
|
+
}
|
|
2469
|
+
const currentCoordinates = this.unproject(screenPosition);
|
|
2470
|
+
const longitudeDelta = mod(coordinates[0] - currentCoordinates[0] + 180, 360) - 180;
|
|
2471
|
+
const latitudeDelta = coordinates[1] - currentCoordinates[1];
|
|
2472
|
+
const crossesPole = Math.abs(currentCoordinates[1]) > import_web_mercator3.MAX_LATITUDE || Math.abs(longitudeDelta) > 90;
|
|
2473
|
+
if (isGlobeNorthUp(this.bearing) && crossesPole) {
|
|
2474
|
+
return { longitude: this.longitude, latitude: this.latitude };
|
|
2475
|
+
}
|
|
2476
|
+
if (isGlobeNorthUp(this.bearing) && latitudeDelta !== 0) {
|
|
2477
|
+
const latitudeLimit = latitudeDelta > 0 ? import_web_mercator3.MAX_LATITUDE : -import_web_mercator3.MAX_LATITUDE;
|
|
2478
|
+
const latitudeConstraintStrength = (latitudeLimit - this.latitude) / latitudeDelta;
|
|
2479
|
+
anchorStrength = Math.min(anchorStrength, Math.max(0, latitudeConstraintStrength));
|
|
2480
|
+
}
|
|
2481
|
+
const longitude2 = this.longitude + longitudeDelta * anchorStrength;
|
|
2482
|
+
const latitude2 = Math.max(Math.min(this.latitude + latitudeDelta * anchorStrength, 90), -90);
|
|
2483
|
+
return { longitude: longitude2, latitude: latitude2 };
|
|
2484
|
+
}
|
|
2485
|
+
const [startLongitude, startLatitude, startZoom] = coordinates;
|
|
2353
2486
|
const scale = Math.pow(2, this.zoom - zoomAdjust(this.latitude));
|
|
2354
2487
|
const rotationSpeed = 0.25 / scale;
|
|
2355
|
-
const longitude =
|
|
2356
|
-
let latitude =
|
|
2488
|
+
const longitude = startLongitude + rotationSpeed * (dragStartPosition[0] - screenPosition[0]);
|
|
2489
|
+
let latitude = startLatitude - rotationSpeed * (dragStartPosition[1] - screenPosition[1]);
|
|
2357
2490
|
latitude = Math.max(Math.min(latitude, 90), -90);
|
|
2358
|
-
const
|
|
2359
|
-
|
|
2360
|
-
return
|
|
2491
|
+
const nextViewState = { longitude, latitude, zoom: startZoom - zoomAdjust(startLatitude) };
|
|
2492
|
+
nextViewState.zoom += zoomAdjust(nextViewState.latitude);
|
|
2493
|
+
return nextViewState;
|
|
2361
2494
|
}
|
|
2362
2495
|
};
|
|
2363
2496
|
GlobeViewport.displayName = "GlobeViewport";
|
|
2364
2497
|
function zoomAdjust(latitude, clampToPoles) {
|
|
2365
2498
|
if (clampToPoles) {
|
|
2366
|
-
latitude = Math.max(Math.min(latitude,
|
|
2499
|
+
latitude = Math.max(Math.min(latitude, import_web_mercator3.MAX_LATITUDE), -import_web_mercator3.MAX_LATITUDE);
|
|
2367
2500
|
}
|
|
2368
2501
|
const scaleAdjust = Math.PI * Math.cos(latitude * Math.PI / 180);
|
|
2369
2502
|
return Math.log2(scaleAdjust);
|
|
2370
2503
|
}
|
|
2371
2504
|
function transformVector(matrix, vector) {
|
|
2372
|
-
const result =
|
|
2373
|
-
|
|
2374
|
-
return result;
|
|
2375
|
-
}
|
|
2376
|
-
|
|
2377
|
-
// ../core/src/utils/shader.ts
|
|
2378
|
-
function mergeShaders(target, source2) {
|
|
2379
|
-
if (!source2) {
|
|
2380
|
-
return target;
|
|
2381
|
-
}
|
|
2382
|
-
const result = { ...target, ...source2 };
|
|
2383
|
-
if ("defines" in source2) {
|
|
2384
|
-
result.defines = { ...target.defines, ...source2.defines };
|
|
2385
|
-
}
|
|
2386
|
-
if ("modules" in source2) {
|
|
2387
|
-
result.modules = (target.modules || []).concat(source2.modules);
|
|
2388
|
-
if (source2.modules.some((module2) => module2.name === "project64")) {
|
|
2389
|
-
const index = result.modules.findIndex((module2) => module2.name === "project32");
|
|
2390
|
-
if (index >= 0) {
|
|
2391
|
-
result.modules.splice(index, 1);
|
|
2392
|
-
}
|
|
2393
|
-
}
|
|
2394
|
-
}
|
|
2395
|
-
if ("inject" in source2) {
|
|
2396
|
-
if (!target.inject) {
|
|
2397
|
-
result.inject = source2.inject;
|
|
2398
|
-
} else {
|
|
2399
|
-
const mergedInjection = { ...target.inject };
|
|
2400
|
-
for (const key in source2.inject) {
|
|
2401
|
-
mergedInjection[key] = (mergedInjection[key] || "") + source2.inject[key];
|
|
2402
|
-
}
|
|
2403
|
-
result.inject = mergedInjection;
|
|
2404
|
-
}
|
|
2405
|
-
}
|
|
2505
|
+
const result = import_core5.vec4.transformMat4([], vector, matrix);
|
|
2506
|
+
import_core5.vec4.scale(result, result, 1 / result[3]);
|
|
2406
2507
|
return result;
|
|
2407
2508
|
}
|
|
2408
2509
|
|
|
2409
2510
|
// ../core/src/viewports/orthographic-viewport.ts
|
|
2410
|
-
var
|
|
2411
|
-
var
|
|
2412
|
-
var viewMatrix = new
|
|
2511
|
+
var import_core6 = require("@math.gl/core");
|
|
2512
|
+
var import_web_mercator4 = require("@math.gl/web-mercator");
|
|
2513
|
+
var viewMatrix = new import_core6.Matrix4().lookAt({ eye: [0, 0, 1] });
|
|
2413
2514
|
function getProjectionMatrix({
|
|
2414
2515
|
width,
|
|
2415
2516
|
height,
|
|
@@ -2423,14 +2524,14 @@ function getProjectionMatrix({
|
|
|
2423
2524
|
let top = height / 2;
|
|
2424
2525
|
if (padding) {
|
|
2425
2526
|
const { left: l = 0, right: r = 0, top: t = 0, bottom: b = 0 } = padding;
|
|
2426
|
-
const offsetX = (0,
|
|
2427
|
-
const offsetY = (0,
|
|
2527
|
+
const offsetX = (0, import_core6.clamp)((l + width - r) / 2, 0, width) - width / 2;
|
|
2528
|
+
const offsetY = (0, import_core6.clamp)((t + height - b) / 2, 0, height) - height / 2;
|
|
2428
2529
|
left -= offsetX;
|
|
2429
2530
|
right -= offsetX;
|
|
2430
2531
|
bottom += offsetY;
|
|
2431
2532
|
top += offsetY;
|
|
2432
2533
|
}
|
|
2433
|
-
return new
|
|
2534
|
+
return new import_core6.Matrix4().ortho({
|
|
2434
2535
|
left,
|
|
2435
2536
|
right,
|
|
2436
2537
|
bottom,
|
|
@@ -2496,10 +2597,10 @@ var OrthographicViewport = class extends Viewport {
|
|
|
2496
2597
|
}
|
|
2497
2598
|
/* Needed by LinearInterpolator */
|
|
2498
2599
|
panByPosition(coords, pixel, startPixel) {
|
|
2499
|
-
const fromLocation = (0,
|
|
2600
|
+
const fromLocation = (0, import_web_mercator4.pixelsToWorld)(pixel, this.pixelUnprojectionMatrix);
|
|
2500
2601
|
const toLocation = this.projectFlat(coords);
|
|
2501
|
-
const translate =
|
|
2502
|
-
const newCenter =
|
|
2602
|
+
const translate = import_core6.vec2.add([], toLocation, import_core6.vec2.negate([], fromLocation));
|
|
2603
|
+
const newCenter = import_core6.vec2.add([], this.center, translate);
|
|
2503
2604
|
return { target: this.unprojectFlat(newCenter) };
|
|
2504
2605
|
}
|
|
2505
2606
|
};
|
|
@@ -3549,7 +3650,7 @@ Fp64Extension.extensionName = "Fp64Extension";
|
|
|
3549
3650
|
var fp64_extension_default = Fp64Extension;
|
|
3550
3651
|
|
|
3551
3652
|
// dist/path-style/path-style-extension.js
|
|
3552
|
-
var
|
|
3653
|
+
var import_core13 = require("@math.gl/core");
|
|
3553
3654
|
|
|
3554
3655
|
// dist/path-style/shaders.glsl.js
|
|
3555
3656
|
var dashShaders = {
|
|
@@ -3557,26 +3658,68 @@ var dashShaders = {
|
|
|
3557
3658
|
"vs:#decl": `
|
|
3558
3659
|
in vec2 instanceDashArrays;
|
|
3559
3660
|
#ifdef HIGH_PRECISION_DASH
|
|
3560
|
-
in
|
|
3661
|
+
in vec2 instanceDashOffsets;
|
|
3561
3662
|
#endif
|
|
3562
3663
|
out vec2 vDashArray;
|
|
3563
3664
|
out float vDashOffset;
|
|
3665
|
+
out float vDashPathLength;
|
|
3666
|
+
layout(std140) uniform pathStyleUniforms {
|
|
3667
|
+
float dashAlignMode;
|
|
3668
|
+
bool dashGapPickable;
|
|
3669
|
+
highp int dashUnits;
|
|
3670
|
+
} pathStyle;
|
|
3564
3671
|
`,
|
|
3565
3672
|
"vs:#main-end": `
|
|
3566
|
-
|
|
3673
|
+
float dashWidthPixels = path.billboard
|
|
3674
|
+
? width.x * project.focalDistance
|
|
3675
|
+
: width.x * project.scale;
|
|
3676
|
+
float strokeHalfWidthPixels = path.billboard ? width.x : width.x * project.scale;
|
|
3677
|
+
float dashUnitPixels = strokeHalfWidthPixels;
|
|
3678
|
+
if (pathStyle.dashUnits == 1) {
|
|
3679
|
+
dashUnitPixels = 1.0;
|
|
3680
|
+
} else if (pathStyle.dashUnits == 2) {
|
|
3681
|
+
dashUnitPixels = project_size_to_pixel(1.0);
|
|
3682
|
+
} else if (pathStyle.dashUnits == 3) {
|
|
3683
|
+
dashUnitPixels = project.scale;
|
|
3684
|
+
}
|
|
3685
|
+
vDashArray = instanceDashArrays * (dashUnitPixels / dashWidthPixels);
|
|
3567
3686
|
#ifdef HIGH_PRECISION_DASH
|
|
3568
|
-
|
|
3687
|
+
vec2 dashOffsetAndLength = (instanceDashOffsets * project.scale) / dashWidthPixels;
|
|
3688
|
+
vDashPathLength = dashOffsetAndLength.y;
|
|
3689
|
+
float dashUnitLength = vDashArray.x + vDashArray.y;
|
|
3690
|
+
float dashPeriod = pathStyle.dashAlignMode == 0.0
|
|
3691
|
+
? dashUnitLength
|
|
3692
|
+
: vDashPathLength / max(round(vDashPathLength / max(dashUnitLength, 0.0001)), 1.0);
|
|
3693
|
+
vDashOffset = dashPeriod > 0.0 ? mod(dashOffsetAndLength.x, dashPeriod) : 0.0;
|
|
3569
3694
|
#else
|
|
3570
3695
|
vDashOffset = 0.0;
|
|
3696
|
+
vDashPathLength = 0.0;
|
|
3571
3697
|
#endif
|
|
3572
3698
|
`,
|
|
3573
3699
|
"fs:#decl": `
|
|
3574
3700
|
layout(std140) uniform pathStyleUniforms {
|
|
3575
3701
|
float dashAlignMode;
|
|
3576
3702
|
bool dashGapPickable;
|
|
3703
|
+
highp int dashUnits;
|
|
3577
3704
|
} pathStyle;
|
|
3578
3705
|
in vec2 vDashArray;
|
|
3579
3706
|
in float vDashOffset;
|
|
3707
|
+
in float vDashPathLength;
|
|
3708
|
+
float dashPatternIntegral(float position, float solidLength, float unitLength) {
|
|
3709
|
+
return floor(position / unitLength) * solidLength +
|
|
3710
|
+
min(mod(position, unitLength), solidLength);
|
|
3711
|
+
}
|
|
3712
|
+
float dashPatternCoverage(
|
|
3713
|
+
float position,
|
|
3714
|
+
float solidLength,
|
|
3715
|
+
float unitLength,
|
|
3716
|
+
float filterWidth
|
|
3717
|
+
) {
|
|
3718
|
+
float halfFilter = 0.5 * filterWidth;
|
|
3719
|
+
float reducedPosition = mod(position, unitLength);
|
|
3720
|
+
return (dashPatternIntegral(reducedPosition + halfFilter, solidLength, unitLength) -
|
|
3721
|
+
dashPatternIntegral(reducedPosition - halfFilter, solidLength, unitLength)) / filterWidth;
|
|
3722
|
+
}
|
|
3580
3723
|
`,
|
|
3581
3724
|
// if given position is in the gap part of the dashed line
|
|
3582
3725
|
// dashArray.x: solid stroke length, relative to width
|
|
@@ -3587,36 +3730,90 @@ in float vDashOffset;
|
|
|
3587
3730
|
// 1 - stretch to fit, draw half dash at each end for nicer joints
|
|
3588
3731
|
// o-- ---- ---- ---- --o-- --o-- ---- --o
|
|
3589
3732
|
"fs:#main-start": `
|
|
3733
|
+
float dashCoverage = 1.0;
|
|
3734
|
+
bool shouldDiscardDash = false;
|
|
3735
|
+
bool inRoundedDashGap = false;
|
|
3736
|
+
float roundedDashResolvedCoverage = 1.0;
|
|
3737
|
+
float roundedDashSubPixelBlend = 0.0;
|
|
3738
|
+
float roundedDashDutyCycle = 1.0;
|
|
3590
3739
|
float solidLength = vDashArray.x;
|
|
3591
3740
|
float gapLength = vDashArray.y;
|
|
3592
3741
|
float unitLength = solidLength + gapLength;
|
|
3742
|
+
if (unitLength > 0.0 && gapLength > 0.0) {
|
|
3593
3743
|
float offset;
|
|
3594
|
-
if (unitLength > 0.0) {
|
|
3595
3744
|
if (pathStyle.dashAlignMode == 0.0) {
|
|
3596
3745
|
offset = vDashOffset;
|
|
3597
3746
|
} else {
|
|
3598
|
-
|
|
3747
|
+
#ifdef HIGH_PRECISION_DASH
|
|
3748
|
+
unitLength = vDashPathLength / max(round(vDashPathLength / unitLength), 1.0);
|
|
3749
|
+
#else
|
|
3750
|
+
unitLength = vPathLength / max(round(vPathLength / unitLength), 1.0);
|
|
3751
|
+
#endif
|
|
3752
|
+
solidLength = min(solidLength, unitLength);
|
|
3599
3753
|
offset = solidLength / 2.0;
|
|
3754
|
+
#ifdef HIGH_PRECISION_DASH
|
|
3755
|
+
offset += vDashOffset;
|
|
3756
|
+
#endif
|
|
3600
3757
|
}
|
|
3601
|
-
float
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
if (
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
float distToEnd = length(vec2(
|
|
3758
|
+
float alongPath = vPathPosition.y + offset;
|
|
3759
|
+
float unitOffset = mod(alongPath, unitLength);
|
|
3760
|
+
float filterWidth = max(fwidth(alongPath), 0.0001);
|
|
3761
|
+
if (bool(picking.isActive)) {
|
|
3762
|
+
bool inGap = unitOffset > solidLength;
|
|
3763
|
+
if (inGap && path.capType > 0.5) {
|
|
3764
|
+
inGap = length(vec2(
|
|
3609
3765
|
min(unitOffset - solidLength, unitLength - unitOffset),
|
|
3610
3766
|
vPathPosition.x
|
|
3611
|
-
));
|
|
3612
|
-
if (distToEnd > 1.0) {
|
|
3613
|
-
if (!(pathStyle.dashGapPickable && bool(picking.isActive))) {
|
|
3614
|
-
discard;
|
|
3767
|
+
)) > 1.0;
|
|
3615
3768
|
}
|
|
3769
|
+
if (inGap && !pathStyle.dashGapPickable) {
|
|
3770
|
+
shouldDiscardDash = true;
|
|
3616
3771
|
}
|
|
3772
|
+
} else if (path.capType <= 0.5) {
|
|
3773
|
+
dashCoverage = dashPatternCoverage(alongPath, solidLength, unitLength, filterWidth);
|
|
3774
|
+
} else {
|
|
3775
|
+
float distanceAlongGap = min(unitOffset - solidLength, unitLength - unitOffset);
|
|
3776
|
+
float distanceToEnd = length(vec2(max(distanceAlongGap, 0.0), vPathPosition.x));
|
|
3777
|
+
float capEdgePixels = (1.0 - distanceToEnd) / max(fwidth(distanceToEnd), 1e-6);
|
|
3778
|
+
if (distanceAlongGap > 0.0) {
|
|
3779
|
+
inRoundedDashGap = true;
|
|
3780
|
+
roundedDashResolvedCoverage = smoothedge(0.0, capEdgePixels);
|
|
3781
|
+
dashCoverage = roundedDashResolvedCoverage;
|
|
3782
|
+
}
|
|
3783
|
+
float subPixelBlend = smoothstep(unitLength, 2.0 * unitLength, filterWidth);
|
|
3784
|
+
roundedDashSubPixelBlend = subPixelBlend;
|
|
3785
|
+
float boundedSolidLength = min(solidLength, unitLength);
|
|
3786
|
+
float effectiveGap = max(unitLength - boundedSolidLength, 0.0);
|
|
3787
|
+
float capSpan = 2.0 * sqrt(max(1.0 - vPathPosition.x * vPathPosition.x, 0.0));
|
|
3788
|
+
float roundedDutyCycle = clamp(
|
|
3789
|
+
(boundedSolidLength + min(effectiveGap, capSpan)) / unitLength,
|
|
3790
|
+
0.0,
|
|
3791
|
+
1.0
|
|
3792
|
+
);
|
|
3793
|
+
roundedDashDutyCycle = roundedDutyCycle;
|
|
3794
|
+
dashCoverage = mix(dashCoverage, roundedDutyCycle, subPixelBlend);
|
|
3617
3795
|
}
|
|
3796
|
+
dashCoverage = clamp(dashCoverage, 0.0, 1.0);
|
|
3797
|
+
shouldDiscardDash = shouldDiscardDash || dashCoverage <= 0.0;
|
|
3618
3798
|
}
|
|
3799
|
+
`,
|
|
3800
|
+
"fs:#main-end": `
|
|
3801
|
+
#ifdef ANTIALIASING
|
|
3802
|
+
if (inRoundedDashGap) {
|
|
3803
|
+
float pathCoverage = smoothedge(0.0, edgePixels);
|
|
3804
|
+
float resolvedCapMultiplier =
|
|
3805
|
+
min(pathCoverage, roundedDashResolvedCoverage) / max(pathCoverage, 1e-6);
|
|
3806
|
+
dashCoverage = mix(
|
|
3807
|
+
resolvedCapMultiplier,
|
|
3808
|
+
roundedDashDutyCycle,
|
|
3809
|
+
roundedDashSubPixelBlend
|
|
3810
|
+
);
|
|
3811
|
+
}
|
|
3812
|
+
#endif
|
|
3813
|
+
if (shouldDiscardDash) {
|
|
3814
|
+
discard;
|
|
3619
3815
|
}
|
|
3816
|
+
fragColor.a *= dashCoverage;
|
|
3620
3817
|
`
|
|
3621
3818
|
}
|
|
3622
3819
|
};
|
|
@@ -3817,13 +4014,32 @@ float offsetDir = sign(instanceOffsets);
|
|
|
3817
4014
|
vPathPosition.x = (vPathPosition.x + offsetDir) * offsetWidth - offsetDir;
|
|
3818
4015
|
vPathPosition.y *= offsetWidth;
|
|
3819
4016
|
vPathLength *= offsetWidth;
|
|
4017
|
+
#ifdef DASH_ENABLED
|
|
4018
|
+
if (pathStyle.dashUnits != 0) {
|
|
4019
|
+
vDashArray *= offsetWidth;
|
|
4020
|
+
}
|
|
4021
|
+
vPathBounds *= offsetWidth;
|
|
4022
|
+
#ifdef HIGH_PRECISION_DASH
|
|
4023
|
+
vDashPathLength *= offsetWidth;
|
|
4024
|
+
float restoredDashUnitLength = vDashArray.x + vDashArray.y;
|
|
4025
|
+
float restoredDashPeriod = pathStyle.dashAlignMode == 0.0
|
|
4026
|
+
? restoredDashUnitLength
|
|
4027
|
+
: vDashPathLength /
|
|
4028
|
+
max(round(vDashPathLength / max(restoredDashUnitLength, 0.0001)), 1.0);
|
|
4029
|
+
vDashOffset = restoredDashPeriod > 0.0
|
|
4030
|
+
? mod(dashOffsetAndLength.x * offsetWidth, restoredDashPeriod)
|
|
4031
|
+
: 0.0;
|
|
4032
|
+
#else
|
|
4033
|
+
vDashOffset *= offsetWidth;
|
|
4034
|
+
#endif
|
|
4035
|
+
#endif
|
|
3820
4036
|
`,
|
|
3821
|
-
"fs:#main-
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
if (isInside == 0.0) {
|
|
4037
|
+
"fs:#main-end": `
|
|
4038
|
+
#ifndef ANTIALIASING
|
|
4039
|
+
if (abs(vPathPosition.x) > 1.0) {
|
|
3825
4040
|
discard;
|
|
3826
4041
|
}
|
|
4042
|
+
#endif
|
|
3827
4043
|
`
|
|
3828
4044
|
}
|
|
3829
4045
|
};
|
|
@@ -3833,11 +4049,56 @@ var defaultProps3 = {
|
|
|
3833
4049
|
getDashArray: { type: "accessor", value: [0, 0] },
|
|
3834
4050
|
getOffset: { type: "accessor", value: 0 },
|
|
3835
4051
|
dashJustified: false,
|
|
3836
|
-
dashGapPickable: false
|
|
4052
|
+
dashGapPickable: false,
|
|
4053
|
+
dashUnits: "widths"
|
|
3837
4054
|
};
|
|
4055
|
+
var DASH_UNITS = {
|
|
4056
|
+
widths: 0,
|
|
4057
|
+
pixels: 1,
|
|
4058
|
+
meters: 2,
|
|
4059
|
+
common: 3
|
|
4060
|
+
};
|
|
4061
|
+
var PATH_STYLE_ATTRIBUTES = ["instanceDashArrays", "instanceDashOffsets", "instanceOffsets"];
|
|
4062
|
+
function dashMetricsProjectionPropsChanged({ props, oldProps }) {
|
|
4063
|
+
return !deepEqual(props.modelMatrix, oldProps.modelMatrix, 2) || props.coordinateSystem !== oldProps.coordinateSystem || !deepEqual(props.coordinateOrigin, oldProps.coordinateOrigin, 1);
|
|
4064
|
+
}
|
|
4065
|
+
function projectRenderedPathPosition(layer, position, projectUniforms) {
|
|
4066
|
+
const viewport = layer.context.viewport;
|
|
4067
|
+
if (!(viewport instanceof WebMercatorViewport) || viewport.zoom < 12) {
|
|
4068
|
+
return layer.projectPosition(position, { autoOffset: false });
|
|
4069
|
+
}
|
|
4070
|
+
const positionWorld = import_core13.vec4.transformMat4([], [position[0], position[1], position[2] || 0, 1], projectUniforms.modelMatrix);
|
|
4071
|
+
const coordinateSystem = layer.props.coordinateSystem === "default" ? "lnglat" : layer.props.coordinateSystem;
|
|
4072
|
+
if (coordinateSystem === "lnglat") {
|
|
4073
|
+
if (Math.abs(positionWorld[1] - projectUniforms.coordinateOrigin[1]) > 0.25) {
|
|
4074
|
+
let longitude = positionWorld[0];
|
|
4075
|
+
if (projectUniforms.wrapLongitude) {
|
|
4076
|
+
longitude = ((longitude + 180) % 360 + 360) % 360 - 180;
|
|
4077
|
+
}
|
|
4078
|
+
const commonPosition = viewport.projectPosition([longitude, positionWorld[1], 0]);
|
|
4079
|
+
return [
|
|
4080
|
+
commonPosition[0] - projectUniforms.commonOrigin[0],
|
|
4081
|
+
commonPosition[1] - projectUniforms.commonOrigin[1],
|
|
4082
|
+
positionWorld[2] * projectUniforms.commonUnitsPerMeter[2]
|
|
4083
|
+
];
|
|
4084
|
+
}
|
|
4085
|
+
import_core13.vec3.sub(positionWorld, positionWorld, projectUniforms.coordinateOrigin);
|
|
4086
|
+
} else if (coordinateSystem === "cartesian") {
|
|
4087
|
+
import_core13.vec3.sub(positionWorld, positionWorld, projectUniforms.coordinateOrigin);
|
|
4088
|
+
}
|
|
4089
|
+
const deltaLatitude = positionWorld[1];
|
|
4090
|
+
const scale = import_core13.vec3.scaleAndAdd([], projectUniforms.commonUnitsPerWorldUnit, projectUniforms.commonUnitsPerWorldUnit2, deltaLatitude);
|
|
4091
|
+
return import_core13.vec3.multiply([], positionWorld, scale);
|
|
4092
|
+
}
|
|
3838
4093
|
var PathStyleExtension = class extends LayerExtension {
|
|
3839
|
-
constructor({ dash = false, offset = false, highPrecisionDash = false } = {}) {
|
|
3840
|
-
|
|
4094
|
+
constructor({ dash = false, offset = false, dashMode, highPrecisionDash = false } = {}) {
|
|
4095
|
+
const resolvedDashMode = dashMode ?? (highPrecisionDash ? "path" : "segment");
|
|
4096
|
+
super({
|
|
4097
|
+
dash: dash || highPrecisionDash || dashMode !== void 0,
|
|
4098
|
+
offset,
|
|
4099
|
+
dashMode: resolvedDashMode,
|
|
4100
|
+
highPrecisionDash: resolvedDashMode === "path"
|
|
4101
|
+
});
|
|
3841
4102
|
}
|
|
3842
4103
|
getLayerType(layer) {
|
|
3843
4104
|
if ("pathTesselator" in layer.state) {
|
|
@@ -3852,6 +4113,59 @@ var PathStyleExtension = class extends LayerExtension {
|
|
|
3852
4113
|
}
|
|
3853
4114
|
return null;
|
|
3854
4115
|
}
|
|
4116
|
+
synchronizeAttributes(layer) {
|
|
4117
|
+
const attributeManager = layer.getAttributeManager();
|
|
4118
|
+
const layerType = this.getLayerType(layer);
|
|
4119
|
+
if (!attributeManager || !layerType) {
|
|
4120
|
+
return false;
|
|
4121
|
+
}
|
|
4122
|
+
const attributes = attributeManager.getAttributes();
|
|
4123
|
+
const desiredAttributes = /* @__PURE__ */ new Set();
|
|
4124
|
+
if (this.opts.dash) {
|
|
4125
|
+
desiredAttributes.add("instanceDashArrays");
|
|
4126
|
+
}
|
|
4127
|
+
if (layerType === "path" && this.opts.dash && this.opts.dashMode === "path") {
|
|
4128
|
+
desiredAttributes.add("instanceDashOffsets");
|
|
4129
|
+
}
|
|
4130
|
+
if (layerType === "path" && this.opts.offset) {
|
|
4131
|
+
desiredAttributes.add("instanceOffsets");
|
|
4132
|
+
}
|
|
4133
|
+
let topologyChanged = false;
|
|
4134
|
+
for (const attributeName of PATH_STYLE_ATTRIBUTES) {
|
|
4135
|
+
if (attributes[attributeName] && !desiredAttributes.has(attributeName)) {
|
|
4136
|
+
attributeManager.remove([attributeName]);
|
|
4137
|
+
topologyChanged = true;
|
|
4138
|
+
}
|
|
4139
|
+
}
|
|
4140
|
+
if (desiredAttributes.has("instanceDashArrays") && !attributes.instanceDashArrays) {
|
|
4141
|
+
attributeManager.addInstanced({
|
|
4142
|
+
instanceDashArrays: { size: 2, accessor: "getDashArray" }
|
|
4143
|
+
});
|
|
4144
|
+
topologyChanged = true;
|
|
4145
|
+
}
|
|
4146
|
+
if (desiredAttributes.has("instanceDashOffsets") && !attributes.instanceDashOffsets) {
|
|
4147
|
+
attributeManager.addInstanced({
|
|
4148
|
+
instanceDashOffsets: {
|
|
4149
|
+
// [distance from the start of the path, total length of the path]
|
|
4150
|
+
size: 2,
|
|
4151
|
+
// Recalculate from rendered geometry when getPath changes. A binary getPath buffer
|
|
4152
|
+
// contains positions, not dash metrics, so keep it as an update trigger rather than
|
|
4153
|
+
// binding it directly to this attribute.
|
|
4154
|
+
accessor: ["getPath"],
|
|
4155
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
4156
|
+
update: this.calculateDashMetrics
|
|
4157
|
+
}
|
|
4158
|
+
});
|
|
4159
|
+
topologyChanged = true;
|
|
4160
|
+
}
|
|
4161
|
+
if (desiredAttributes.has("instanceOffsets") && !attributes.instanceOffsets) {
|
|
4162
|
+
attributeManager.addInstanced({
|
|
4163
|
+
instanceOffsets: { size: 1, accessor: "getOffset" }
|
|
4164
|
+
});
|
|
4165
|
+
topologyChanged = true;
|
|
4166
|
+
}
|
|
4167
|
+
return topologyChanged;
|
|
4168
|
+
}
|
|
3855
4169
|
isEnabled(layer) {
|
|
3856
4170
|
return this.getLayerType(layer) !== null;
|
|
3857
4171
|
}
|
|
@@ -3878,57 +4192,55 @@ var PathStyleExtension = class extends LayerExtension {
|
|
|
3878
4192
|
const defines2 = {};
|
|
3879
4193
|
if (extension.opts.dash) {
|
|
3880
4194
|
result = mergeShaders(result, dashShaders);
|
|
3881
|
-
|
|
4195
|
+
defines2.DASH_ENABLED = true;
|
|
4196
|
+
if (extension.opts.dashMode === "path") {
|
|
3882
4197
|
defines2.HIGH_PRECISION_DASH = true;
|
|
3883
4198
|
}
|
|
3884
4199
|
}
|
|
3885
4200
|
if (extension.opts.offset) {
|
|
3886
4201
|
result = mergeShaders(result, offsetShaders);
|
|
4202
|
+
defines2.PATH_STYLE_OFFSET = true;
|
|
3887
4203
|
}
|
|
3888
4204
|
const { inject: inject6 } = result;
|
|
3889
4205
|
const pathStyle = {
|
|
3890
4206
|
name: "pathStyle",
|
|
3891
|
-
inject: inject6
|
|
3892
|
-
uniformTypes: {
|
|
3893
|
-
dashAlignMode: "f32",
|
|
3894
|
-
dashGapPickable: "i32"
|
|
3895
|
-
}
|
|
4207
|
+
inject: inject6
|
|
3896
4208
|
};
|
|
4209
|
+
if (extension.opts.dash) {
|
|
4210
|
+
pathStyle.uniformTypes = {
|
|
4211
|
+
dashAlignMode: "f32",
|
|
4212
|
+
dashGapPickable: "i32",
|
|
4213
|
+
dashUnits: "i32"
|
|
4214
|
+
};
|
|
4215
|
+
}
|
|
3897
4216
|
return {
|
|
3898
4217
|
modules: [pathStyle],
|
|
3899
4218
|
defines: defines2
|
|
3900
4219
|
};
|
|
3901
4220
|
}
|
|
3902
4221
|
initializeState(context, extension) {
|
|
3903
|
-
|
|
3904
|
-
const layerType = extension.getLayerType(this);
|
|
3905
|
-
if (!attributeManager || !layerType) {
|
|
3906
|
-
return;
|
|
3907
|
-
}
|
|
3908
|
-
if (extension.opts.dash) {
|
|
3909
|
-
attributeManager.addInstanced({
|
|
3910
|
-
instanceDashArrays: { size: 2, accessor: "getDashArray" },
|
|
3911
|
-
...layerType === "path" && extension.opts.highPrecisionDash ? {
|
|
3912
|
-
instanceDashOffsets: {
|
|
3913
|
-
size: 1,
|
|
3914
|
-
accessor: "getPath",
|
|
3915
|
-
transform: extension.getDashOffsets.bind(this)
|
|
3916
|
-
}
|
|
3917
|
-
} : {}
|
|
3918
|
-
});
|
|
3919
|
-
}
|
|
3920
|
-
if (layerType === "path" && extension.opts.offset) {
|
|
3921
|
-
attributeManager.addInstanced({
|
|
3922
|
-
instanceOffsets: { size: 1, accessor: "getOffset" }
|
|
3923
|
-
});
|
|
3924
|
-
}
|
|
4222
|
+
extension.synchronizeAttributes(this);
|
|
3925
4223
|
}
|
|
3926
4224
|
updateState(params, extension) {
|
|
4225
|
+
var _a;
|
|
3927
4226
|
if (!extension.isEnabled(this)) {
|
|
3928
4227
|
return;
|
|
3929
4228
|
}
|
|
4229
|
+
if (params.changeFlags.extensionsChanged) {
|
|
4230
|
+
const topologyChanged = extension.synchronizeAttributes(this);
|
|
4231
|
+
const attributeManager = this.getAttributeManager();
|
|
4232
|
+
if (attributeManager && topologyChanged) {
|
|
4233
|
+
attributeManager.invalidateAll();
|
|
4234
|
+
for (const model of this.getModels()) {
|
|
4235
|
+
model.setBufferLayout(attributeManager.getBufferLayouts(model));
|
|
4236
|
+
}
|
|
4237
|
+
}
|
|
4238
|
+
}
|
|
3930
4239
|
if (extension.opts.dash) {
|
|
3931
4240
|
const layerType = extension.getLayerType(this);
|
|
4241
|
+
if (layerType === "path" && extension.opts.dashMode === "path" && dashMetricsProjectionPropsChanged(params)) {
|
|
4242
|
+
(_a = this.getAttributeManager()) == null ? void 0 : _a.invalidate("instanceDashOffsets");
|
|
4243
|
+
}
|
|
3932
4244
|
if (layerType === "scatterplot" || layerType === "textBackground") {
|
|
3933
4245
|
const pathStyleProps = {
|
|
3934
4246
|
dashGapPickable: Boolean(this.props.dashGapPickable)
|
|
@@ -3937,12 +4249,96 @@ var PathStyleExtension = class extends LayerExtension {
|
|
|
3937
4249
|
} else {
|
|
3938
4250
|
const pathStyleProps = {
|
|
3939
4251
|
dashAlignMode: this.props.dashJustified ? 1 : 0,
|
|
3940
|
-
dashGapPickable: Boolean(this.props.dashGapPickable)
|
|
4252
|
+
dashGapPickable: Boolean(this.props.dashGapPickable),
|
|
4253
|
+
dashUnits: DASH_UNITS[this.props.dashUnits ?? "widths"]
|
|
3941
4254
|
};
|
|
3942
4255
|
this.setShaderModuleProps({ pathStyle: pathStyleProps });
|
|
3943
4256
|
}
|
|
3944
4257
|
}
|
|
3945
4258
|
}
|
|
4259
|
+
calculateDashMetrics(attribute, { startRow, endRow }) {
|
|
4260
|
+
var _a, _b, _c;
|
|
4261
|
+
const pathTesselator = this.state.pathTesselator;
|
|
4262
|
+
const vertexStarts = pathTesselator == null ? void 0 : pathTesselator.vertexStarts;
|
|
4263
|
+
const instanceCount = pathTesselator == null ? void 0 : pathTesselator.instanceCount;
|
|
4264
|
+
const packedPositions = pathTesselator == null ? void 0 : pathTesselator.get("positions");
|
|
4265
|
+
if (!vertexStarts || instanceCount === void 0 || typeof (pathTesselator == null ? void 0 : pathTesselator.getPathSegmentIndices) !== "function") {
|
|
4266
|
+
throw new Error("PathStyleExtension requires PathLayer tessellation data for path dashes.");
|
|
4267
|
+
}
|
|
4268
|
+
const binaryPath = (_b = (_a = this.props.data) == null ? void 0 : _a.attributes) == null ? void 0 : _b.getPath;
|
|
4269
|
+
const binaryValue = ArrayBuffer.isView(binaryPath) ? binaryPath : binaryPath == null ? void 0 : binaryPath.value;
|
|
4270
|
+
const hasReadableBinaryPath = ArrayBuffer.isView(binaryValue);
|
|
4271
|
+
const usePackedPositions = packedPositions && (!binaryPath || pathTesselator.normalize || ((_c = pathTesselator.opts) == null ? void 0 : _c.isWebGPU));
|
|
4272
|
+
if (binaryPath && !hasReadableBinaryPath || !usePackedPositions && !hasReadableBinaryPath) {
|
|
4273
|
+
throw new Error("PathStyleExtension cannot calculate whole-path dash metrics from GPU-only getPath data; supply data.attributes.instanceDashOffsets.");
|
|
4274
|
+
}
|
|
4275
|
+
const output = attribute.value;
|
|
4276
|
+
const metricSize = attribute.size;
|
|
4277
|
+
const firstRow = Math.max(0, startRow);
|
|
4278
|
+
const lastRow = Math.min(endRow, vertexStarts.length - 1);
|
|
4279
|
+
let binarySize = 3;
|
|
4280
|
+
let binaryStride = 3;
|
|
4281
|
+
let binaryOffset = 0;
|
|
4282
|
+
if (!usePackedPositions) {
|
|
4283
|
+
const bytesPerElement = binaryValue.BYTES_PER_ELEMENT;
|
|
4284
|
+
binarySize = (binaryPath == null ? void 0 : binaryPath.size) || (this.props.positionFormat === "XY" ? 2 : 3);
|
|
4285
|
+
binaryStride = (binaryPath == null ? void 0 : binaryPath.stride) ? binaryPath.stride / bytesPerElement : binarySize;
|
|
4286
|
+
binaryOffset = (binaryPath == null ? void 0 : binaryPath.offset) ? binaryPath.offset / bytesPerElement : 0;
|
|
4287
|
+
}
|
|
4288
|
+
const sourcePosition = new Array(3);
|
|
4289
|
+
const projectUniforms = project_default.getUniforms({
|
|
4290
|
+
viewport: this.context.viewport,
|
|
4291
|
+
modelMatrix: this.props.modelMatrix,
|
|
4292
|
+
coordinateSystem: this.props.coordinateSystem,
|
|
4293
|
+
coordinateOrigin: this.props.coordinateOrigin,
|
|
4294
|
+
// PathLayer normalizes/cuts wrapped paths on the CPU; its shader never wraps again.
|
|
4295
|
+
autoWrapLongitude: this.wrapLongitude
|
|
4296
|
+
});
|
|
4297
|
+
const readPosition = (vertexIndex) => {
|
|
4298
|
+
if (usePackedPositions) {
|
|
4299
|
+
sourcePosition[0] = packedPositions[vertexIndex * 3];
|
|
4300
|
+
sourcePosition[1] = packedPositions[vertexIndex * 3 + 1];
|
|
4301
|
+
sourcePosition[2] = packedPositions[vertexIndex * 3 + 2];
|
|
4302
|
+
} else {
|
|
4303
|
+
const sourceIndex = binaryOffset + vertexIndex * binaryStride;
|
|
4304
|
+
sourcePosition[0] = binaryValue[sourceIndex];
|
|
4305
|
+
sourcePosition[1] = binaryValue[sourceIndex + 1];
|
|
4306
|
+
sourcePosition[2] = binarySize === 3 ? binaryValue[sourceIndex + 2] : 0;
|
|
4307
|
+
}
|
|
4308
|
+
return sourcePosition;
|
|
4309
|
+
};
|
|
4310
|
+
attribute.startIndices = vertexStarts;
|
|
4311
|
+
for (let row = firstRow; row < lastRow; row++) {
|
|
4312
|
+
const rowStart = vertexStarts[row];
|
|
4313
|
+
const rowEnd = Math.min(vertexStarts[row + 1] ?? instanceCount, instanceCount);
|
|
4314
|
+
output.fill(0, rowStart * metricSize, rowEnd * metricSize);
|
|
4315
|
+
const validSegments = pathTesselator.getPathSegmentIndices(row);
|
|
4316
|
+
let phase = 0;
|
|
4317
|
+
let previousSegment = -2;
|
|
4318
|
+
let previousEnd = null;
|
|
4319
|
+
for (const segmentIndex of validSegments) {
|
|
4320
|
+
const outputIndex = segmentIndex * metricSize;
|
|
4321
|
+
output[outputIndex] = phase;
|
|
4322
|
+
const start = segmentIndex === previousSegment + 1 && previousEnd ? previousEnd : projectRenderedPathPosition(this, readPosition(segmentIndex), projectUniforms);
|
|
4323
|
+
const end = projectRenderedPathPosition(this, readPosition(segmentIndex + 1), projectUniforms);
|
|
4324
|
+
phase += import_core13.vec3.dist(start, end);
|
|
4325
|
+
previousSegment = segmentIndex;
|
|
4326
|
+
previousEnd = end;
|
|
4327
|
+
}
|
|
4328
|
+
if (metricSize > 1) {
|
|
4329
|
+
for (let vertexIndex = rowStart; vertexIndex < rowEnd; vertexIndex++) {
|
|
4330
|
+
output[vertexIndex * metricSize + 1] = phase;
|
|
4331
|
+
}
|
|
4332
|
+
}
|
|
4333
|
+
}
|
|
4334
|
+
}
|
|
4335
|
+
/**
|
|
4336
|
+
* Calculates the distance from the start of a path to each rendered segment.
|
|
4337
|
+
*
|
|
4338
|
+
* The final entry is zero because PathLayer reserves the final vertex as invalid padding.
|
|
4339
|
+
* This scalar return shape is retained for compatibility; path-mode rendering uses an
|
|
4340
|
+
* internal attribute containing both each segment offset and the total path length.
|
|
4341
|
+
*/
|
|
3946
4342
|
getDashOffsets(path) {
|
|
3947
4343
|
const result = [0];
|
|
3948
4344
|
const positionSize = this.props.positionFormat === "XY" ? 2 : 3;
|
|
@@ -3952,9 +4348,9 @@ var PathStyleExtension = class extends LayerExtension {
|
|
|
3952
4348
|
let prevP;
|
|
3953
4349
|
for (let i = 0; i < geometrySize - 1; i++) {
|
|
3954
4350
|
p = isNested ? path[i] : path.slice(i * positionSize, i * positionSize + positionSize);
|
|
3955
|
-
p = this.projectPosition(p);
|
|
4351
|
+
p = this.projectPosition(p, { autoOffset: false });
|
|
3956
4352
|
if (i > 0) {
|
|
3957
|
-
result[i] = result[i - 1] +
|
|
4353
|
+
result[i] = result[i - 1] + import_core13.vec3.dist(prevP, p);
|
|
3958
4354
|
}
|
|
3959
4355
|
prevP = p;
|
|
3960
4356
|
}
|
|
@@ -3967,12 +4363,26 @@ PathStyleExtension.extensionName = "PathStyleExtension";
|
|
|
3967
4363
|
var path_style_extension_default = PathStyleExtension;
|
|
3968
4364
|
|
|
3969
4365
|
// dist/fill-style/shader-module.js
|
|
4366
|
+
var FILL_UV_SCALE = 512 / 4e7;
|
|
4367
|
+
function getPatternUnitScale(sizeUnits, viewport) {
|
|
4368
|
+
switch (sizeUnits) {
|
|
4369
|
+
case "pixels":
|
|
4370
|
+
return 2 ** -Math.round(viewport.zoom);
|
|
4371
|
+
case "common":
|
|
4372
|
+
return 1;
|
|
4373
|
+
default:
|
|
4374
|
+
return FILL_UV_SCALE;
|
|
4375
|
+
}
|
|
4376
|
+
}
|
|
3970
4377
|
var uniformBlock3 = (
|
|
3971
4378
|
/* glsl */
|
|
3972
4379
|
`layout(std140) uniform fillUniforms {
|
|
3973
4380
|
vec2 patternTextureSize;
|
|
4381
|
+
float patternUnitScale;
|
|
3974
4382
|
bool patternEnabled;
|
|
3975
4383
|
bool patternMask;
|
|
4384
|
+
bool procedural;
|
|
4385
|
+
bool flipY;
|
|
3976
4386
|
vec2 uvCoordinateOrigin;
|
|
3977
4387
|
vec2 uvCoordinateOrigin64Low;
|
|
3978
4388
|
} fill;
|
|
@@ -3981,13 +4391,20 @@ var uniformBlock3 = (
|
|
|
3981
4391
|
var patternVs = (
|
|
3982
4392
|
/* glsl */
|
|
3983
4393
|
`
|
|
4394
|
+
uniform sampler2D fill_patternTexture;
|
|
4395
|
+
|
|
3984
4396
|
in vec4 fillPatternFrames;
|
|
3985
4397
|
in float fillPatternScales;
|
|
3986
4398
|
in vec2 fillPatternOffsets;
|
|
4399
|
+
in vec4 fillPatternBackgroundColors;
|
|
3987
4400
|
|
|
3988
4401
|
out vec2 fill_uv;
|
|
3989
4402
|
out vec4 fill_patternBounds;
|
|
3990
4403
|
out vec4 fill_patternPlacement;
|
|
4404
|
+
out vec4 fill_backgroundColor;
|
|
4405
|
+
out float fill_patternCoordinateScale;
|
|
4406
|
+
flat out vec4 fill_patternParams0;
|
|
4407
|
+
flat out vec4 fill_patternParams1;
|
|
3991
4408
|
`
|
|
3992
4409
|
);
|
|
3993
4410
|
var vs4 = `
|
|
@@ -4001,9 +4418,136 @@ uniform sampler2D fill_patternTexture;
|
|
|
4001
4418
|
|
|
4002
4419
|
in vec4 fill_patternBounds;
|
|
4003
4420
|
in vec4 fill_patternPlacement;
|
|
4421
|
+
in vec4 fill_backgroundColor;
|
|
4004
4422
|
in vec2 fill_uv;
|
|
4423
|
+
in float fill_patternCoordinateScale;
|
|
4424
|
+
flat in vec4 fill_patternParams0;
|
|
4425
|
+
flat in vec4 fill_patternParams1;
|
|
4426
|
+
|
|
4427
|
+
const float FILL_PATTERN_HATCH = 1.0;
|
|
4428
|
+
const float FILL_PATTERN_CROSS_HATCH = 2.0;
|
|
4429
|
+
const float FILL_PATTERN_DOTS = 3.0;
|
|
4430
|
+
|
|
4431
|
+
float fill_getPatternCoordinate(vec2 axis, float period, float offset) {
|
|
4432
|
+
float coordinateScale = max(abs(fill_patternCoordinateScale), 1.0e-20);
|
|
4433
|
+
vec2 coordinateOrigin = fill.uvCoordinateOrigin;
|
|
4434
|
+
vec2 coordinateOffset = fill.uvCoordinateOrigin64Low + fill_uv;
|
|
4435
|
+
float yDirection = fill.flipY ? 1.0 : -1.0;
|
|
4436
|
+
coordinateOrigin.y *= yDirection;
|
|
4437
|
+
coordinateOffset.y *= yDirection;
|
|
4438
|
+
|
|
4439
|
+
// Reduce the high part before adding the local offset to retain precision in large coordinates.
|
|
4440
|
+
float highPart = mod(dot(coordinateOrigin, axis) / coordinateScale, period);
|
|
4441
|
+
float lowPart = dot(coordinateOffset, axis) / coordinateScale;
|
|
4442
|
+
return mod(highPart + lowPart + offset * period, period);
|
|
4443
|
+
}
|
|
4444
|
+
|
|
4445
|
+
vec2 fill_getPatternCoords(
|
|
4446
|
+
vec2 axis0,
|
|
4447
|
+
vec2 axis1,
|
|
4448
|
+
vec2 period,
|
|
4449
|
+
vec2 offset
|
|
4450
|
+
) {
|
|
4451
|
+
return vec2(
|
|
4452
|
+
fill_getPatternCoordinate(axis0, period.x, offset.x),
|
|
4453
|
+
fill_getPatternCoordinate(axis1, period.y, offset.y)
|
|
4454
|
+
);
|
|
4455
|
+
}
|
|
4456
|
+
|
|
4457
|
+
float fill_getScreenSpaceAlpha(float signedDistance) {
|
|
4458
|
+
float distanceDerivative = fwidth(signedDistance);
|
|
4459
|
+
if (distanceDerivative == 0.0) {
|
|
4460
|
+
return signedDistance <= 0.0 ? 1.0 : 0.0;
|
|
4461
|
+
}
|
|
4462
|
+
// Normalize the SDF to screen pixels so the coverage ramp is independent of pattern units.
|
|
4463
|
+
float distanceInPixels = signedDistance / distanceDerivative;
|
|
4464
|
+
return 1.0 - smoothstep(-0.5, 0.5, distanceInPixels);
|
|
4465
|
+
}
|
|
4466
|
+
|
|
4467
|
+
float fill_getLineAlpha(float position, float center, float period, float strokeWidth) {
|
|
4468
|
+
float distanceToLine = abs(mod(position - center + period * 0.5, period) - period * 0.5);
|
|
4469
|
+
return fill_getScreenSpaceAlpha(distanceToLine - strokeWidth * 0.5);
|
|
4470
|
+
}
|
|
4471
|
+
|
|
4472
|
+
float fill_getHatchAlpha(float angle, float strokeWidth, vec2 gaps, bool alternating) {
|
|
4473
|
+
vec2 lineDirection = vec2(cos(angle), sin(angle));
|
|
4474
|
+
vec2 lineNormal = vec2(-lineDirection.y, lineDirection.x);
|
|
4475
|
+
float period = alternating
|
|
4476
|
+
? strokeWidth * 2.0 + gaps.x + gaps.y
|
|
4477
|
+
: strokeWidth + gaps.x;
|
|
4478
|
+
float offset = dot(fill_patternPlacement.xy, lineNormal);
|
|
4479
|
+
float position = fill_getPatternCoordinate(lineNormal, period, offset);
|
|
4480
|
+
float alpha = fill_getLineAlpha(position, 0.0, period, strokeWidth);
|
|
4481
|
+
if (alternating) {
|
|
4482
|
+
alpha = max(
|
|
4483
|
+
alpha,
|
|
4484
|
+
fill_getLineAlpha(position, strokeWidth + gaps.x, period, strokeWidth)
|
|
4485
|
+
);
|
|
4486
|
+
}
|
|
4487
|
+
return alpha;
|
|
4488
|
+
}
|
|
4489
|
+
|
|
4490
|
+
float fill_getDotAlpha(float angle, float skew, float radius, float gap) {
|
|
4491
|
+
vec2 axis0 = vec2(cos(angle), sin(angle));
|
|
4492
|
+
float axis1Angle = angle + 1.5707963267948966 - skew;
|
|
4493
|
+
vec2 axis1 = vec2(cos(axis1Angle), sin(axis1Angle));
|
|
4494
|
+
float determinant = axis0.x * axis1.y - axis0.y * axis1.x;
|
|
4005
4495
|
|
|
4006
|
-
|
|
4496
|
+
// The reciprocal basis maps common coordinates into the skewed dot lattice.
|
|
4497
|
+
vec2 reciprocal0 = vec2(axis1.y, -axis1.x) / determinant;
|
|
4498
|
+
vec2 reciprocal1 = vec2(-axis0.y, axis0.x) / determinant;
|
|
4499
|
+
float period = radius * 2.0 + gap;
|
|
4500
|
+
vec2 latticeCoords = fill_getPatternCoords(
|
|
4501
|
+
reciprocal0,
|
|
4502
|
+
reciprocal1,
|
|
4503
|
+
vec2(period),
|
|
4504
|
+
fill_patternPlacement.xy
|
|
4505
|
+
);
|
|
4506
|
+
vec2 cellOffset = mod(latticeCoords + period * 0.5, period) - period * 0.5;
|
|
4507
|
+
float distanceToDotSquared = 1.0e20;
|
|
4508
|
+
// In a skewed lattice the closest dot is not necessarily in the independently wrapped cell.
|
|
4509
|
+
// Include adjacent cells to keep the repeated distance field continuous at cell boundaries.
|
|
4510
|
+
for (int x = -1; x <= 1; x++) {
|
|
4511
|
+
for (int y = -1; y <= 1; y++) {
|
|
4512
|
+
vec2 neighborOffset = cellOffset + vec2(float(x), float(y)) * period;
|
|
4513
|
+
vec2 dotOffset = axis0 * neighborOffset.x + axis1 * neighborOffset.y;
|
|
4514
|
+
distanceToDotSquared = min(distanceToDotSquared, dot(dotOffset, dotOffset));
|
|
4515
|
+
}
|
|
4516
|
+
}
|
|
4517
|
+
float distanceToDot = sqrt(distanceToDotSquared);
|
|
4518
|
+
return fill_getScreenSpaceAlpha(distanceToDot - radius);
|
|
4519
|
+
}
|
|
4520
|
+
|
|
4521
|
+
float fill_getProceduralPatternAlpha() {
|
|
4522
|
+
float patternType = fill_patternParams0.x;
|
|
4523
|
+
float size = fill_patternParams0.y;
|
|
4524
|
+
vec2 gaps = fill_patternParams0.zw;
|
|
4525
|
+
vec2 angles = fill_patternParams1.xy;
|
|
4526
|
+
float elementCount = fill_patternParams1.z;
|
|
4527
|
+
|
|
4528
|
+
if (patternType == FILL_PATTERN_HATCH) {
|
|
4529
|
+
return fill_getHatchAlpha(angles.x, size, gaps, elementCount == 2.0);
|
|
4530
|
+
}
|
|
4531
|
+
if (patternType == FILL_PATTERN_CROSS_HATCH) {
|
|
4532
|
+
return max(
|
|
4533
|
+
fill_getHatchAlpha(angles.x, size, gaps, false),
|
|
4534
|
+
fill_getHatchAlpha(angles.y, size, gaps, false)
|
|
4535
|
+
);
|
|
4536
|
+
}
|
|
4537
|
+
if (patternType == FILL_PATTERN_DOTS) {
|
|
4538
|
+
return fill_getDotAlpha(angles.x, angles.y, size, gaps.x);
|
|
4539
|
+
}
|
|
4540
|
+
return 1.0;
|
|
4541
|
+
}
|
|
4542
|
+
|
|
4543
|
+
// Draw the pattern over the background fill (Porter-Duff source-over)
|
|
4544
|
+
vec4 fill_blendOverBackground(vec4 pattern, vec4 background) {
|
|
4545
|
+
if (background.a == 0.0 || layer.opacity == 0.0) return pattern;
|
|
4546
|
+
float patternAlpha = pattern.a / layer.opacity;
|
|
4547
|
+
float blendedAlpha = patternAlpha + background.a * (1.0 - patternAlpha);
|
|
4548
|
+
vec3 blendedRGB = mix(background.rgb, pattern.rgb, patternAlpha / blendedAlpha);
|
|
4549
|
+
return vec4(blendedRGB, blendedAlpha * layer.opacity);
|
|
4550
|
+
}
|
|
4007
4551
|
`
|
|
4008
4552
|
);
|
|
4009
4553
|
var fs4 = `
|
|
@@ -4012,18 +4556,34 @@ ${patternFs}
|
|
|
4012
4556
|
`;
|
|
4013
4557
|
var inject3 = {
|
|
4014
4558
|
"vs:DECKGL_FILTER_GL_POSITION": (
|
|
4015
|
-
/* glsl */
|
|
4016
|
-
`
|
|
4017
|
-
fill_uv = geometry.position.xy;
|
|
4018
|
-
`
|
|
4019
|
-
),
|
|
4020
|
-
"vs:DECKGL_FILTER_COLOR": (
|
|
4021
4559
|
/* glsl */
|
|
4022
4560
|
`
|
|
4023
4561
|
if (fill.patternEnabled) {
|
|
4024
|
-
fill_patternBounds = fillPatternFrames / vec4(fill.patternTextureSize, fill.patternTextureSize);
|
|
4025
4562
|
fill_patternPlacement.xy = fillPatternOffsets;
|
|
4026
|
-
|
|
4563
|
+
fill_backgroundColor = fillPatternBackgroundColors;
|
|
4564
|
+
if (fill.procedural) {
|
|
4565
|
+
fill_uv = geometry.position.xy;
|
|
4566
|
+
fill_patternCoordinateScale = fill.patternUnitScale * fillPatternScales;
|
|
4567
|
+
int texelIndex = int(fillPatternFrames.x) * 4;
|
|
4568
|
+
fill_patternParams0 = vec4(
|
|
4569
|
+
texelFetch(fill_patternTexture, ivec2(texelIndex, 0), 0).rg,
|
|
4570
|
+
texelFetch(fill_patternTexture, ivec2(texelIndex + 1, 0), 0).rg
|
|
4571
|
+
);
|
|
4572
|
+
fill_patternParams1 = vec4(
|
|
4573
|
+
texelFetch(fill_patternTexture, ivec2(texelIndex + 2, 0), 0).rg,
|
|
4574
|
+
texelFetch(fill_patternTexture, ivec2(texelIndex + 3, 0), 0).rg
|
|
4575
|
+
);
|
|
4576
|
+
} else {
|
|
4577
|
+
fill_patternBounds = fillPatternFrames / vec4(fill.patternTextureSize, fill.patternTextureSize);
|
|
4578
|
+
vec2 patternFrameCommon = fill.patternUnitScale * fillPatternScales * fillPatternFrames.zw;
|
|
4579
|
+
// Reduce the coordinate origin to within one tile before adding the vertex position. The
|
|
4580
|
+
// origin is large in common space, and fp32 cannot carry the sum at full precision.
|
|
4581
|
+
vec2 origin = mod(fill.uvCoordinateOrigin, patternFrameCommon) + fill.uvCoordinateOrigin64Low;
|
|
4582
|
+
fill_uv = (origin + geometry.position.xy) / patternFrameCommon;
|
|
4583
|
+
// Pattern atlases use top-left coordinates, so reverse common-space Y in bottom-left views.
|
|
4584
|
+
fill_uv.y *= fill.flipY ? 1.0 : -1.0;
|
|
4585
|
+
fill_uv += fillPatternOffsets;
|
|
4586
|
+
}
|
|
4027
4587
|
}
|
|
4028
4588
|
`
|
|
4029
4589
|
),
|
|
@@ -4031,22 +4591,31 @@ var inject3 = {
|
|
|
4031
4591
|
/* glsl */
|
|
4032
4592
|
`
|
|
4033
4593
|
if (fill.patternEnabled) {
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4594
|
+
if (fill.procedural) {
|
|
4595
|
+
color.a *= fill_getProceduralPatternAlpha();
|
|
4596
|
+
} else {
|
|
4597
|
+
vec2 patternUV = fract(fill_uv);
|
|
4598
|
+
vec2 texCoords = fill_patternBounds.xy + fill_patternBounds.zw * patternUV;
|
|
4599
|
+
|
|
4600
|
+
// Tiling is emulated by wrapping the coordinate, so texCoords jumps from the end of the
|
|
4601
|
+
// frame back to its start once per tile, leading to the wrong mip level being selected,
|
|
4602
|
+
// which leads to artifacts at pattern edges. fill_uv is continuous across the primitive,
|
|
4603
|
+
// meaning that the correct mip level is always selected
|
|
4604
|
+
vec4 grad = fill_patternBounds.zwzw * vec4(dFdx(fill_uv), dFdy(fill_uv));
|
|
4605
|
+
vec4 patternColor = textureGrad(fill_patternTexture, texCoords, grad.xy, grad.zw);
|
|
4606
|
+
|
|
4607
|
+
color.a *= patternColor.a;
|
|
4608
|
+
if (!fill.patternMask) {
|
|
4609
|
+
color.rgb = patternColor.rgb;
|
|
4610
|
+
}
|
|
4044
4611
|
}
|
|
4612
|
+
color = fill_blendOverBackground(color, fill_backgroundColor);
|
|
4045
4613
|
}
|
|
4046
4614
|
`
|
|
4047
4615
|
)
|
|
4048
4616
|
};
|
|
4049
4617
|
function getPatternUniforms(opts) {
|
|
4618
|
+
var _a;
|
|
4050
4619
|
if (!opts) {
|
|
4051
4620
|
return {};
|
|
4052
4621
|
}
|
|
@@ -4057,17 +4626,22 @@ function getPatternUniforms(opts) {
|
|
|
4057
4626
|
uniforms.patternTextureSize = [fillPatternTexture.width, fillPatternTexture.height];
|
|
4058
4627
|
}
|
|
4059
4628
|
if ("project" in opts) {
|
|
4060
|
-
const { fillPatternMask = true, fillPatternEnabled = true } = opts;
|
|
4629
|
+
const { fillPatternMask = true, fillPatternEnabled = true, fillPatternSizeUnits = "meters", fillPatternCommonFrame = null, procedural = false } = opts;
|
|
4061
4630
|
const projectUniforms = project_default.getUniforms(opts.project);
|
|
4062
4631
|
const { commonOrigin: coordinateOriginCommon } = projectUniforms;
|
|
4063
|
-
const
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4632
|
+
const unitScale = getPatternUnitScale(fillPatternSizeUnits, opts.project.viewport);
|
|
4633
|
+
const origin = [coordinateOriginCommon[0], coordinateOriginCommon[1]];
|
|
4634
|
+
if (fillPatternCommonFrame) {
|
|
4635
|
+
origin[0] %= unitScale * fillPatternCommonFrame[0];
|
|
4636
|
+
origin[1] %= unitScale * fillPatternCommonFrame[1];
|
|
4637
|
+
}
|
|
4638
|
+
uniforms.uvCoordinateOrigin = origin;
|
|
4639
|
+
uniforms.uvCoordinateOrigin64Low = [fp64LowPart(origin[0]), fp64LowPart(origin[1])];
|
|
4640
|
+
uniforms.patternUnitScale = unitScale;
|
|
4069
4641
|
uniforms.patternMask = fillPatternMask;
|
|
4070
4642
|
uniforms.patternEnabled = fillPatternEnabled;
|
|
4643
|
+
uniforms.procedural = procedural;
|
|
4644
|
+
uniforms.flipY = ((_a = opts.project.viewport) == null ? void 0 : _a.flipY) ?? false;
|
|
4071
4645
|
}
|
|
4072
4646
|
return uniforms;
|
|
4073
4647
|
}
|
|
@@ -4080,31 +4654,172 @@ var patternShaders = {
|
|
|
4080
4654
|
getUniforms: getPatternUniforms,
|
|
4081
4655
|
uniformTypes: {
|
|
4082
4656
|
patternTextureSize: "vec2<f32>",
|
|
4657
|
+
patternUnitScale: "f32",
|
|
4083
4658
|
patternEnabled: "i32",
|
|
4084
4659
|
patternMask: "i32",
|
|
4660
|
+
procedural: "i32",
|
|
4661
|
+
flipY: "i32",
|
|
4085
4662
|
uvCoordinateOrigin: "vec2<f32>",
|
|
4086
4663
|
uvCoordinateOrigin64Low: "vec2<f32>"
|
|
4087
4664
|
}
|
|
4088
4665
|
};
|
|
4089
4666
|
|
|
4667
|
+
// dist/fill-style/procedural-pattern.js
|
|
4668
|
+
var PROCEDURAL_PATTERN_TEXTURE_FORMAT = "rg32float";
|
|
4669
|
+
var PROCEDURAL_PATTERN_COMPONENTS_PER_TEXEL = 2;
|
|
4670
|
+
var PROCEDURAL_PATTERN_TEXELS_PER_PATTERN = 4;
|
|
4671
|
+
var PROCEDURAL_PATTERN_TYPES = {
|
|
4672
|
+
none: 0,
|
|
4673
|
+
hatch: 1,
|
|
4674
|
+
crossHatch: 2,
|
|
4675
|
+
dots: 3
|
|
4676
|
+
};
|
|
4677
|
+
var PROCEDURAL_PATTERN_OFFSETS = {
|
|
4678
|
+
type: 0,
|
|
4679
|
+
size: 1,
|
|
4680
|
+
gap0: 2,
|
|
4681
|
+
gap1: 3,
|
|
4682
|
+
angle0: 4,
|
|
4683
|
+
angle1: 5,
|
|
4684
|
+
/** Number of alternating gaps, hatch directions, or dot-grid axes, depending on type. */
|
|
4685
|
+
elementCount: 6
|
|
4686
|
+
};
|
|
4687
|
+
var COMPONENTS_PER_PATTERN = PROCEDURAL_PATTERN_COMPONENTS_PER_TEXEL * PROCEDURAL_PATTERN_TEXELS_PER_PATTERN;
|
|
4688
|
+
var DEGREES_TO_RADIANS3 = Math.PI / 180;
|
|
4689
|
+
var DEFAULT_SIZE = 1;
|
|
4690
|
+
var DEFAULT_GAP = 1;
|
|
4691
|
+
var DEFAULT_HATCH_ANGLE = 0;
|
|
4692
|
+
var DEFAULT_CROSS_HATCH_ANGLES = [45, 135];
|
|
4693
|
+
var DEFAULT_DOT_ANGLE = 0;
|
|
4694
|
+
var DEFAULT_DOT_SKEW = 0;
|
|
4695
|
+
function packProceduralPatterns(mapping) {
|
|
4696
|
+
const entries = Object.entries(mapping);
|
|
4697
|
+
const data = new Float32Array((entries.length + 1) * COMPONENTS_PER_PATTERN);
|
|
4698
|
+
const patternIndices = /* @__PURE__ */ new Map();
|
|
4699
|
+
entries.forEach(([id, config], entryIndex) => {
|
|
4700
|
+
const patternIndex = entryIndex + 1;
|
|
4701
|
+
const offset = patternIndex * COMPONENTS_PER_PATTERN;
|
|
4702
|
+
patternIndices.set(id, patternIndex);
|
|
4703
|
+
switch (config.type) {
|
|
4704
|
+
case "hatch": {
|
|
4705
|
+
const gap = config.gap === void 0 ? DEFAULT_GAP : config.gap;
|
|
4706
|
+
const strokeWidth = config.strokeWidth === void 0 ? DEFAULT_SIZE : config.strokeWidth;
|
|
4707
|
+
const angle = config.angle === void 0 ? DEFAULT_HATCH_ANGLE : config.angle;
|
|
4708
|
+
if (Array.isArray(gap) && gap.length !== 2) {
|
|
4709
|
+
throw new Error(`${id}.gap must be a number or a two-element array`);
|
|
4710
|
+
}
|
|
4711
|
+
const gaps = Array.isArray(gap) ? gap : [gap, gap];
|
|
4712
|
+
validatePositive(strokeWidth, `${id}.strokeWidth`);
|
|
4713
|
+
validateNonNegative(gaps[0], `${id}.gap[0]`);
|
|
4714
|
+
validateNonNegative(gaps[1], `${id}.gap[1]`);
|
|
4715
|
+
validateAngle(angle, `${id}.angle`);
|
|
4716
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.type] = PROCEDURAL_PATTERN_TYPES.hatch;
|
|
4717
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.size] = strokeWidth;
|
|
4718
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.gap0] = gaps[0];
|
|
4719
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.gap1] = gaps[1];
|
|
4720
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.angle0] = angle * DEGREES_TO_RADIANS3;
|
|
4721
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.elementCount] = Array.isArray(gap) ? 2 : 1;
|
|
4722
|
+
break;
|
|
4723
|
+
}
|
|
4724
|
+
case "cross-hatch": {
|
|
4725
|
+
const angles = config.angles === void 0 ? DEFAULT_CROSS_HATCH_ANGLES : config.angles;
|
|
4726
|
+
const strokeWidth = config.strokeWidth === void 0 ? DEFAULT_SIZE : config.strokeWidth;
|
|
4727
|
+
const gap = config.gap === void 0 ? DEFAULT_GAP : config.gap;
|
|
4728
|
+
if (!Array.isArray(angles) || angles.length !== 2) {
|
|
4729
|
+
throw new Error(`${id}.angles must be a two-element array`);
|
|
4730
|
+
}
|
|
4731
|
+
validatePositive(strokeWidth, `${id}.strokeWidth`);
|
|
4732
|
+
validateNonNegative(gap, `${id}.gap`);
|
|
4733
|
+
validateAngle(angles[0], `${id}.angles[0]`);
|
|
4734
|
+
validateAngle(angles[1], `${id}.angles[1]`);
|
|
4735
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.type] = PROCEDURAL_PATTERN_TYPES.crossHatch;
|
|
4736
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.size] = strokeWidth;
|
|
4737
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.gap0] = gap;
|
|
4738
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.gap1] = gap;
|
|
4739
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.angle0] = angles[0] * DEGREES_TO_RADIANS3;
|
|
4740
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.angle1] = angles[1] * DEGREES_TO_RADIANS3;
|
|
4741
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.elementCount] = 2;
|
|
4742
|
+
break;
|
|
4743
|
+
}
|
|
4744
|
+
case "dots": {
|
|
4745
|
+
const radius = config.radius === void 0 ? DEFAULT_SIZE : config.radius;
|
|
4746
|
+
const gap = config.gap === void 0 ? DEFAULT_GAP : config.gap;
|
|
4747
|
+
const angle = config.angle === void 0 ? DEFAULT_DOT_ANGLE : config.angle;
|
|
4748
|
+
const skew = config.skew === void 0 ? DEFAULT_DOT_SKEW : config.skew;
|
|
4749
|
+
validatePositive(radius, `${id}.radius`);
|
|
4750
|
+
validateNonNegative(gap, `${id}.gap`);
|
|
4751
|
+
validateAngle(angle, `${id}.angle`);
|
|
4752
|
+
validateSkew(skew, `${id}.skew`);
|
|
4753
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.type] = PROCEDURAL_PATTERN_TYPES.dots;
|
|
4754
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.size] = radius;
|
|
4755
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.gap0] = gap;
|
|
4756
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.gap1] = gap;
|
|
4757
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.angle0] = angle * DEGREES_TO_RADIANS3;
|
|
4758
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.angle1] = skew * DEGREES_TO_RADIANS3;
|
|
4759
|
+
data[offset + PROCEDURAL_PATTERN_OFFSETS.elementCount] = 2;
|
|
4760
|
+
break;
|
|
4761
|
+
}
|
|
4762
|
+
default:
|
|
4763
|
+
throw new Error(`${id}.type is not a supported procedural pattern type`);
|
|
4764
|
+
}
|
|
4765
|
+
});
|
|
4766
|
+
return {
|
|
4767
|
+
data,
|
|
4768
|
+
width: data.length / PROCEDURAL_PATTERN_COMPONENTS_PER_TEXEL,
|
|
4769
|
+
height: 1,
|
|
4770
|
+
patternIndices
|
|
4771
|
+
};
|
|
4772
|
+
}
|
|
4773
|
+
function validatePositive(value, name) {
|
|
4774
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
4775
|
+
throw new Error(`${name} must be a finite number greater than 0`);
|
|
4776
|
+
}
|
|
4777
|
+
}
|
|
4778
|
+
function validateNonNegative(value, name) {
|
|
4779
|
+
if (!Number.isFinite(value) || value < 0) {
|
|
4780
|
+
throw new Error(`${name} must be a finite number greater than or equal to 0`);
|
|
4781
|
+
}
|
|
4782
|
+
}
|
|
4783
|
+
function validateAngle(value, name) {
|
|
4784
|
+
if (!Number.isFinite(value)) {
|
|
4785
|
+
throw new Error(`${name} must be a finite number`);
|
|
4786
|
+
}
|
|
4787
|
+
}
|
|
4788
|
+
function validateSkew(value, name) {
|
|
4789
|
+
if (!Number.isFinite(value) || value <= -90 || value >= 90) {
|
|
4790
|
+
throw new Error(`${name} must be a finite number greater than -90 and less than 90`);
|
|
4791
|
+
}
|
|
4792
|
+
}
|
|
4793
|
+
|
|
4090
4794
|
// dist/fill-style/fill-style-extension.js
|
|
4795
|
+
function leastCommonMultiple(a, b) {
|
|
4796
|
+
if (!Number.isInteger(b) || b <= 0)
|
|
4797
|
+
return 0;
|
|
4798
|
+
if (a === 0)
|
|
4799
|
+
return b;
|
|
4800
|
+
let [x, y] = [a, b];
|
|
4801
|
+
while (y > 0)
|
|
4802
|
+
[x, y] = [y, x % y];
|
|
4803
|
+
return a / x * b;
|
|
4804
|
+
}
|
|
4091
4805
|
var defaultProps4 = {
|
|
4092
4806
|
fillPatternEnabled: true,
|
|
4093
4807
|
fillPatternAtlas: {
|
|
4094
4808
|
type: "image",
|
|
4095
4809
|
value: null,
|
|
4096
|
-
async: true
|
|
4097
|
-
parameters: { lodMaxClamp: 0 }
|
|
4810
|
+
async: true
|
|
4098
4811
|
},
|
|
4099
4812
|
fillPatternMapping: { type: "object", value: {}, async: true },
|
|
4100
4813
|
fillPatternMask: true,
|
|
4814
|
+
fillPatternSizeUnits: "meters",
|
|
4101
4815
|
getFillPattern: { type: "accessor", value: (d) => d.pattern },
|
|
4102
4816
|
getFillPatternScale: { type: "accessor", value: 1 },
|
|
4103
|
-
getFillPatternOffset: { type: "accessor", value: [0, 0] }
|
|
4817
|
+
getFillPatternOffset: { type: "accessor", value: [0, 0] },
|
|
4818
|
+
getFillPatternBackgroundColor: { type: "accessor", value: [0, 0, 0, 0] }
|
|
4104
4819
|
};
|
|
4105
4820
|
var FillStyleExtension = class extends LayerExtension {
|
|
4106
|
-
constructor({ pattern = false } = {}) {
|
|
4107
|
-
super({ pattern });
|
|
4821
|
+
constructor({ pattern = false, proceduralPattern = false } = {}) {
|
|
4822
|
+
super({ pattern: pattern || proceduralPattern, proceduralPattern });
|
|
4108
4823
|
}
|
|
4109
4824
|
isEnabled(layer) {
|
|
4110
4825
|
return layer.getAttributeManager() !== null && !("pathTesselator" in layer.state);
|
|
@@ -4128,7 +4843,7 @@ var FillStyleExtension = class extends LayerExtension {
|
|
|
4128
4843
|
size: 4,
|
|
4129
4844
|
stepMode: "dynamic",
|
|
4130
4845
|
accessor: "getFillPattern",
|
|
4131
|
-
transform: extension.getPatternFrame.bind(this)
|
|
4846
|
+
transform: extension.opts.proceduralPattern ? extension.getProceduralPatternIndex.bind(this) : extension.getPatternFrame.bind(this)
|
|
4132
4847
|
},
|
|
4133
4848
|
fillPatternScales: {
|
|
4134
4849
|
size: 1,
|
|
@@ -4140,6 +4855,13 @@ var FillStyleExtension = class extends LayerExtension {
|
|
|
4140
4855
|
size: 2,
|
|
4141
4856
|
stepMode: "dynamic",
|
|
4142
4857
|
accessor: "getFillPatternOffset"
|
|
4858
|
+
},
|
|
4859
|
+
fillPatternBackgroundColors: {
|
|
4860
|
+
size: 4,
|
|
4861
|
+
type: "unorm8",
|
|
4862
|
+
stepMode: "dynamic",
|
|
4863
|
+
accessor: "getFillPatternBackgroundColor",
|
|
4864
|
+
defaultValue: [0, 0, 0, 255]
|
|
4143
4865
|
}
|
|
4144
4866
|
});
|
|
4145
4867
|
}
|
|
@@ -4148,7 +4870,8 @@ var FillStyleExtension = class extends LayerExtension {
|
|
|
4148
4870
|
data: new Uint8Array(4),
|
|
4149
4871
|
width: 1,
|
|
4150
4872
|
height: 1
|
|
4151
|
-
})
|
|
4873
|
+
}),
|
|
4874
|
+
...extension.opts.proceduralPattern && extension.createProceduralPatternTexture.call(this, {})
|
|
4152
4875
|
});
|
|
4153
4876
|
}
|
|
4154
4877
|
updateState({ props, oldProps }, extension) {
|
|
@@ -4156,30 +4879,81 @@ var FillStyleExtension = class extends LayerExtension {
|
|
|
4156
4879
|
return;
|
|
4157
4880
|
}
|
|
4158
4881
|
if (props.fillPatternMapping && props.fillPatternMapping !== oldProps.fillPatternMapping) {
|
|
4882
|
+
if (extension.opts.proceduralPattern && typeof props.fillPatternMapping !== "string") {
|
|
4883
|
+
const oldTexture = this.state.proceduralPatternTexture;
|
|
4884
|
+
this.setState(extension.createProceduralPatternTexture.call(this, props.fillPatternMapping));
|
|
4885
|
+
oldTexture == null ? void 0 : oldTexture.delete();
|
|
4886
|
+
}
|
|
4159
4887
|
this.getAttributeManager().invalidate("getFillPattern");
|
|
4160
4888
|
}
|
|
4889
|
+
if (props.fillPatternMapping !== oldProps.fillPatternMapping || props.getFillPatternScale !== oldProps.getFillPatternScale) {
|
|
4890
|
+
this.setState({ commonFrame: extension.getCommonFrame(props) });
|
|
4891
|
+
}
|
|
4161
4892
|
}
|
|
4162
4893
|
draw(params, extension) {
|
|
4163
4894
|
if (!extension.isEnabled(this)) {
|
|
4164
4895
|
return;
|
|
4165
4896
|
}
|
|
4166
|
-
const { fillPatternAtlas, fillPatternEnabled, fillPatternMask } = this.props;
|
|
4897
|
+
const { fillPatternAtlas, fillPatternEnabled, fillPatternMask, fillPatternSizeUnits } = this.props;
|
|
4167
4898
|
const fillProps = {
|
|
4168
4899
|
project: params.shaderModuleProps.project,
|
|
4169
4900
|
fillPatternEnabled,
|
|
4170
4901
|
fillPatternMask,
|
|
4171
|
-
|
|
4902
|
+
fillPatternSizeUnits,
|
|
4903
|
+
procedural: extension.opts.proceduralPattern,
|
|
4904
|
+
fillPatternTexture: extension.opts.proceduralPattern ? this.state.proceduralPatternTexture || this.state.emptyTexture : fillPatternAtlas || this.state.emptyTexture,
|
|
4905
|
+
fillPatternCommonFrame: this.state.commonFrame
|
|
4172
4906
|
};
|
|
4173
4907
|
this.setShaderModuleProps({ fill: fillProps });
|
|
4174
4908
|
}
|
|
4175
4909
|
finalizeState() {
|
|
4176
4910
|
const emptyTexture = this.state.emptyTexture;
|
|
4177
4911
|
emptyTexture == null ? void 0 : emptyTexture.delete();
|
|
4912
|
+
const proceduralPatternTexture = this.state.proceduralPatternTexture;
|
|
4913
|
+
proceduralPatternTexture == null ? void 0 : proceduralPatternTexture.delete();
|
|
4178
4914
|
}
|
|
4179
4915
|
getPatternFrame(name) {
|
|
4180
4916
|
const { fillPatternMapping } = this.getCurrentLayer().props;
|
|
4181
4917
|
const def = fillPatternMapping && fillPatternMapping[name];
|
|
4182
|
-
return def ? [def.x, def.y, def.width, def.height] : [0, 0, 0, 0];
|
|
4918
|
+
return def && "x" in def ? [def.x, def.y, def.width, def.height] : [0, 0, 0, 0];
|
|
4919
|
+
}
|
|
4920
|
+
/**
|
|
4921
|
+
* Returns common frame into which all patterns fit as integer multiples
|
|
4922
|
+
*/
|
|
4923
|
+
getCommonFrame(props) {
|
|
4924
|
+
const { fillPatternMapping, getFillPatternScale: scale } = props;
|
|
4925
|
+
if (typeof scale !== "number" || !(scale > 0) || typeof fillPatternMapping !== "object") {
|
|
4926
|
+
return null;
|
|
4927
|
+
}
|
|
4928
|
+
let width = 0;
|
|
4929
|
+
let height = 0;
|
|
4930
|
+
for (const name in fillPatternMapping) {
|
|
4931
|
+
const frame = fillPatternMapping[name];
|
|
4932
|
+
if (!("width" in frame))
|
|
4933
|
+
return null;
|
|
4934
|
+
width = leastCommonMultiple(width, frame.width);
|
|
4935
|
+
height = leastCommonMultiple(height, frame.height);
|
|
4936
|
+
if (!width || !height)
|
|
4937
|
+
return null;
|
|
4938
|
+
}
|
|
4939
|
+
return width ? [scale * width, scale * height] : null;
|
|
4940
|
+
}
|
|
4941
|
+
getProceduralPatternIndex(name) {
|
|
4942
|
+
const patternIndices = this.state.proceduralPatternIndices;
|
|
4943
|
+
return [(patternIndices == null ? void 0 : patternIndices.get(name)) ?? 0, 0, 0, 0];
|
|
4944
|
+
}
|
|
4945
|
+
createProceduralPatternTexture(mapping) {
|
|
4946
|
+
const packedPatterns = packProceduralPatterns(mapping);
|
|
4947
|
+
return {
|
|
4948
|
+
proceduralPatternIndices: packedPatterns.patternIndices,
|
|
4949
|
+
proceduralPatternTexture: this.context.device.createTexture({
|
|
4950
|
+
data: packedPatterns.data,
|
|
4951
|
+
width: packedPatterns.width,
|
|
4952
|
+
height: packedPatterns.height,
|
|
4953
|
+
format: PROCEDURAL_PATTERN_TEXTURE_FORMAT,
|
|
4954
|
+
sampler: { minFilter: "nearest", magFilter: "nearest" }
|
|
4955
|
+
})
|
|
4956
|
+
};
|
|
4183
4957
|
}
|
|
4184
4958
|
};
|
|
4185
4959
|
FillStyleExtension.defaultProps = defaultProps4;
|
|
@@ -4424,7 +5198,7 @@ var shader_module_default2 = {
|
|
|
4424
5198
|
};
|
|
4425
5199
|
|
|
4426
5200
|
// dist/collision-filter/collision-filter-effect.js
|
|
4427
|
-
var
|
|
5201
|
+
var import_core19 = require("@math.gl/core");
|
|
4428
5202
|
|
|
4429
5203
|
// dist/collision-filter/collision-filter-pass.js
|
|
4430
5204
|
var CollisionFilterPass = class extends LayersPass {
|
|
@@ -4519,7 +5293,7 @@ var CollisionFilterEffect = class {
|
|
|
4519
5293
|
const needsRender = viewportChanged || // If render info is new
|
|
4520
5294
|
renderInfo === oldRenderInfo || // If sublayers have changed
|
|
4521
5295
|
!deepEqual(oldRenderInfo.layers, renderInfo.layers, 1) || // If a sublayer's bounds have been updated
|
|
4522
|
-
renderInfo.layerBounds.some((b, i) => !(0,
|
|
5296
|
+
renderInfo.layerBounds.some((b, i) => !(0, import_core19.equals)(b, oldRenderInfo.layerBounds[i])) || // If a sublayer's isLoaded state has been updated
|
|
4523
5297
|
renderInfo.allLayersLoaded !== oldRenderInfo.allLayersLoaded || // Some prop is in transition
|
|
4524
5298
|
renderInfo.layers.some((layer) => layer.props.transitions);
|
|
4525
5299
|
this.channels[collisionGroup] = renderInfo;
|
|
@@ -4807,7 +5581,7 @@ var shader_module_default3 = {
|
|
|
4807
5581
|
};
|
|
4808
5582
|
|
|
4809
5583
|
// dist/mask/mask-effect.js
|
|
4810
|
-
var
|
|
5584
|
+
var import_core26 = require("@math.gl/core");
|
|
4811
5585
|
|
|
4812
5586
|
// dist/mask/mask-pass.js
|
|
4813
5587
|
var MASK_BLENDING = {
|
|
@@ -5071,7 +5845,7 @@ var MaskEffect = class {
|
|
|
5071
5845
|
this.lastViewport = viewport;
|
|
5072
5846
|
const layerBounds = joinLayerBounds(channelInfo.layers, viewport);
|
|
5073
5847
|
channelInfo.bounds = layerBounds && getRenderBounds(layerBounds, viewport);
|
|
5074
|
-
if (maskChanged || !(0,
|
|
5848
|
+
if (maskChanged || !(0, import_core26.equals)(channelInfo.bounds, oldChannelInfo.bounds)) {
|
|
5075
5849
|
const { maskPass, maskMap } = this;
|
|
5076
5850
|
const maskViewport = layerBounds && makeViewport({
|
|
5077
5851
|
bounds: channelInfo.bounds,
|