@deck.gl/arcgis 9.3.7 → 9.4.0-alpha.2

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 CHANGED
@@ -1478,7 +1478,7 @@ var __exports__ = (() => {
1478
1478
  setGLParameters(gl, GL_PARAMETER_DEFAULTS);
1479
1479
  }
1480
1480
  function isObjectEmpty(object) {
1481
- for (const key in object) {
1481
+ for (const _key in object) {
1482
1482
  return false;
1483
1483
  }
1484
1484
  return true;
@@ -2191,6 +2191,7 @@ var __exports__ = (() => {
2191
2191
  // 'depth32float-stencil8' // GPUTextureFormat 'depth32float-stencil8'
2192
2192
  // optional WebGL features
2193
2193
  "compilation-status-async-webgl": "KHR_parallel_shader_compile",
2194
+ "html-in-canvas": (gl) => (0, import_core5.isHTMLInCanvasSupported)() && typeof gl.texElementImage2D === "function",
2194
2195
  "polygon-mode-webgl": "WEBGL_polygon_mode",
2195
2196
  "provoking-vertex-webgl": "WEBGL_provoking_vertex",
2196
2197
  "shader-clip-cull-distance-webgl": "WEBGL_clip_cull_distance",
@@ -2246,7 +2247,7 @@ var __exports__ = (() => {
2246
2247
  /** Extract all WebGL features */
2247
2248
  getWebGLFeature(feature) {
2248
2249
  const featureInfo = WEBGL_FEATURES[feature];
2249
- const isSupported = typeof featureInfo === "string" ? Boolean(getWebGLExtension(this.gl, featureInfo, this.extensions)) : Boolean(featureInfo);
2250
+ const isSupported = typeof featureInfo === "string" ? Boolean(getWebGLExtension(this.gl, featureInfo, this.extensions)) : typeof featureInfo === "function" ? featureInfo(this.gl) : Boolean(featureInfo);
2250
2251
  return isSupported;
2251
2252
  }
2252
2253
  };
@@ -2275,6 +2276,12 @@ var __exports__ = (() => {
2275
2276
  get maxBindGroups() {
2276
2277
  return 0;
2277
2278
  }
2279
+ get maxBindGroupsPlusVertexBuffers() {
2280
+ return 0;
2281
+ }
2282
+ get maxBindingsPerBindGroup() {
2283
+ return 0;
2284
+ }
2278
2285
  get maxDynamicUniformBuffersPerPipelineLayout() {
2279
2286
  return 0;
2280
2287
  }
@@ -2294,10 +2301,22 @@ var __exports__ = (() => {
2294
2301
  return 0;
2295
2302
  }
2296
2303
  // TBD
2304
+ get maxStorageBuffersInVertexStage() {
2305
+ return 0;
2306
+ }
2307
+ get maxStorageBuffersInFragmentStage() {
2308
+ return 0;
2309
+ }
2297
2310
  get maxStorageTexturesPerShaderStage() {
2298
2311
  return 0;
2299
2312
  }
2300
2313
  // TBD
2314
+ get maxStorageTexturesInVertexStage() {
2315
+ return 0;
2316
+ }
2317
+ get maxStorageTexturesInFragmentStage() {
2318
+ return 0;
2319
+ }
2301
2320
  get maxUniformBuffersPerShaderStage() {
2302
2321
  return this.getParameter(35375);
2303
2322
  }
@@ -2307,6 +2326,9 @@ var __exports__ = (() => {
2307
2326
  get maxStorageBufferBindingSize() {
2308
2327
  return 0;
2309
2328
  }
2329
+ get maxBufferSize() {
2330
+ return Number.MAX_SAFE_INTEGER;
2331
+ }
2310
2332
  get minUniformBufferOffsetAlignment() {
2311
2333
  return this.getParameter(35380);
2312
2334
  }
@@ -2327,6 +2349,12 @@ var __exports__ = (() => {
2327
2349
  get maxInterStageShaderVariables() {
2328
2350
  return this.getParameter(35659);
2329
2351
  }
2352
+ get maxColorAttachments() {
2353
+ return this.getParameter(36063);
2354
+ }
2355
+ get maxColorAttachmentBytesPerSample() {
2356
+ return 0;
2357
+ }
2330
2358
  get maxComputeWorkgroupStorageSize() {
2331
2359
  return 0;
2332
2360
  }
@@ -2403,10 +2431,11 @@ var __exports__ = (() => {
2403
2431
  depthStencilAttachment = null;
2404
2432
  constructor(device, props) {
2405
2433
  super(device, props);
2406
- const isDefaultFramebuffer = props.handle === null;
2434
+ const suppliedHandle = props.handle;
2435
+ const isDefaultFramebuffer = suppliedHandle === null;
2407
2436
  this.device = device;
2408
2437
  this.gl = device.gl;
2409
- this.handle = this.props.handle || isDefaultFramebuffer ? this.props.handle : this.gl.createFramebuffer();
2438
+ this.handle = suppliedHandle || isDefaultFramebuffer ? suppliedHandle : this.gl.createFramebuffer();
2410
2439
  if (!isDefaultFramebuffer) {
2411
2440
  device._setWebGLDebugMetadata(this.handle, this, { spector: this.props });
2412
2441
  if (!props.handle) {
@@ -2823,6 +2852,9 @@ var __exports__ = (() => {
2823
2852
  });
2824
2853
 
2825
2854
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-shader.js
2855
+ function getFirstCompilerLogLine(shaderLog) {
2856
+ return shaderLog.split(/\r?\n/).find((line) => line.trim())?.trim();
2857
+ }
2826
2858
  var import_core11, WEBGLShader;
2827
2859
  var init_webgl_shader = __esm({
2828
2860
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-shader.js"() {
@@ -2831,15 +2863,17 @@ var __exports__ = (() => {
2831
2863
  WEBGLShader = class extends import_core11.Shader {
2832
2864
  device;
2833
2865
  handle;
2866
+ _compilationInfoLog = "";
2834
2867
  constructor(device, props) {
2835
2868
  super(device, props);
2836
2869
  this.device = device;
2870
+ const suppliedHandle = this.props.handle;
2837
2871
  switch (this.props.stage) {
2838
2872
  case "vertex":
2839
- this.handle = this.props.handle || this.device.gl.createShader(35633);
2873
+ this.handle = suppliedHandle || this.device.gl.createShader(35633);
2840
2874
  break;
2841
2875
  case "fragment":
2842
- this.handle = this.props.handle || this.device.gl.createShader(35632);
2876
+ this.handle = suppliedHandle || this.device.gl.createShader(35632);
2843
2877
  break;
2844
2878
  default:
2845
2879
  throw new Error(this.props.stage);
@@ -2871,7 +2905,7 @@ var __exports__ = (() => {
2871
2905
  return this.getCompilationInfoSync();
2872
2906
  }
2873
2907
  getCompilationInfoSync() {
2874
- const shaderLog = this.device.gl.getShaderInfoLog(this.handle);
2908
+ const shaderLog = this._getCompilationInfoLog();
2875
2909
  return shaderLog ? parseShaderCompilerLog(shaderLog) : [];
2876
2910
  }
2877
2911
  getTranslatedSource() {
@@ -2895,7 +2929,7 @@ ${source}`;
2895
2929
  this._getCompilationStatus();
2896
2930
  this.debugShader();
2897
2931
  if (this.compilationStatus === "error") {
2898
- throw new Error(`GLSL compilation errors in ${this.props.stage} shader ${this.props.id}`);
2932
+ throw new Error(this._getCompilationErrorMessage(source));
2899
2933
  }
2900
2934
  return;
2901
2935
  }
@@ -2930,6 +2964,31 @@ ${source}`;
2930
2964
  */
2931
2965
  _getCompilationStatus() {
2932
2966
  this.compilationStatus = this.device.gl.getShaderParameter(this.handle, 35713) ? "success" : "error";
2967
+ if (this.compilationStatus === "error") {
2968
+ this._getCompilationInfoLog();
2969
+ }
2970
+ }
2971
+ _getCompilationErrorMessage(source) {
2972
+ const shaderDescription = `${this.props.stage} shader ${this.props.id}`;
2973
+ const firstShaderLogLine = getFirstCompilerLogLine(this._getCompilationInfoLog());
2974
+ const compilerMessages = this.getCompilationInfoSync();
2975
+ const firstMessage = compilerMessages.find((message3) => message3.type === "error" && message3.message.trim()) || compilerMessages.find((message3) => message3.message.trim()) || compilerMessages.find((message3) => message3.type === "error") || compilerMessages[0];
2976
+ if (!firstMessage) {
2977
+ return firstShaderLogLine ? `GLSL compilation errors in ${shaderDescription}: ${firstShaderLogLine}` : `GLSL compilation errors in ${shaderDescription}: WebGL did not provide a shader compiler log`;
2978
+ }
2979
+ const sourceLine = firstMessage.lineNum ? source.split(/\r?\n/)[firstMessage.lineNum - 1]?.trim() : void 0;
2980
+ const location = firstMessage.lineNum ? ` line ${firstMessage.lineNum}` : "";
2981
+ const sourceSnippet = sourceLine ? `
2982
+ Source: ${sourceLine}` : "";
2983
+ const message2 = firstMessage.message.trim() || firstShaderLogLine || "WebGL did not provide a shader compiler log";
2984
+ return `GLSL compilation errors in ${shaderDescription}:${location}: ${message2}${sourceSnippet}`;
2985
+ }
2986
+ _getCompilationInfoLog() {
2987
+ const shaderLog = this.device.gl.getShaderInfoLog(this.handle)?.trim();
2988
+ if (shaderLog) {
2989
+ this._compilationInfoLog = shaderLog;
2990
+ }
2991
+ return this._compilationInfoLog;
2933
2992
  }
2934
2993
  };
2935
2994
  }
@@ -3160,7 +3219,7 @@ ${source}`;
3160
3219
  }
3161
3220
  function isObjectEmpty2(obj) {
3162
3221
  let isEmpty = true;
3163
- for (const key in obj) {
3222
+ for (const _key in obj) {
3164
3223
  isEmpty = false;
3165
3224
  break;
3166
3225
  }
@@ -3325,7 +3384,7 @@ ${source}`;
3325
3384
  return value;
3326
3385
  }
3327
3386
  function isObjectEmpty3(object) {
3328
- for (const key in object) {
3387
+ for (const _key in object) {
3329
3388
  return false;
3330
3389
  }
3331
3390
  return true;
@@ -3472,32 +3531,39 @@ ${source}`;
3472
3531
  this.glFormat = formatInfo.format;
3473
3532
  this.glType = formatInfo.type;
3474
3533
  this.compressed = formatInfo.compressed;
3534
+ if (this.isHandleBorrowed && this.props.handle === void 0) {
3535
+ throw new Error("Borrowed WebGL textures require a texture handle");
3536
+ }
3475
3537
  this.handle = this.props.handle || this.gl.createTexture();
3476
3538
  this.device._setWebGLDebugMetadata(this.handle, this, { spector: this.props });
3477
- this.gl.bindTexture(this.glTarget, this.handle);
3478
- const { dimension, width, height, depth, mipLevels, glTarget, glInternalFormat } = this;
3479
- if (!this.compressed) {
3480
- switch (dimension) {
3481
- case "2d":
3482
- case "cube":
3483
- this.gl.texStorage2D(glTarget, mipLevels, glInternalFormat, width, height);
3484
- break;
3485
- case "2d-array":
3486
- case "3d":
3487
- this.gl.texStorage3D(glTarget, mipLevels, glInternalFormat, width, height, depth);
3488
- break;
3489
- default:
3490
- throw new Error(dimension);
3539
+ if (!this.isHandleBorrowed) {
3540
+ this.gl.bindTexture(this.glTarget, this.handle);
3541
+ const { dimension, width, height, depth, mipLevels, glTarget, glInternalFormat } = this;
3542
+ if (!this.compressed) {
3543
+ switch (dimension) {
3544
+ case "2d":
3545
+ case "cube":
3546
+ this.gl.texStorage2D(glTarget, mipLevels, glInternalFormat, width, height);
3547
+ break;
3548
+ case "2d-array":
3549
+ case "3d":
3550
+ this.gl.texStorage3D(glTarget, mipLevels, glInternalFormat, width, height, depth);
3551
+ break;
3552
+ default:
3553
+ throw new Error(dimension);
3554
+ }
3491
3555
  }
3556
+ this.gl.bindTexture(this.glTarget, null);
3557
+ this._initializeData(props.data);
3492
3558
  }
3493
- this.gl.bindTexture(this.glTarget, null);
3494
- this._initializeData(props.data);
3495
- if (!this.props.handle) {
3559
+ if (this.ownsHandle) {
3496
3560
  this.trackAllocatedMemory(this.getAllocatedByteLength(), "Texture");
3497
3561
  } else {
3498
3562
  this.trackReferencedMemory(this.getAllocatedByteLength(), "Texture");
3499
3563
  }
3500
- this.setSampler(this.props.sampler);
3564
+ if (!this.isHandleBorrowed) {
3565
+ this.setSampler(this.props.sampler);
3566
+ }
3501
3567
  this.view = new WEBGLTextureView(this.device, { ...this.props, texture: this });
3502
3568
  Object.seal(this);
3503
3569
  }
@@ -3507,7 +3573,7 @@ ${source}`;
3507
3573
  this._framebuffer = null;
3508
3574
  this._framebufferAttachmentKey = null;
3509
3575
  this.removeStats();
3510
- if (!this.props.handle) {
3576
+ if (this.ownsHandle) {
3511
3577
  this.gl.deleteTexture(this.handle);
3512
3578
  this.trackDeallocatedMemory("Texture");
3513
3579
  } else {
@@ -3519,12 +3585,20 @@ ${source}`;
3519
3585
  createView(props) {
3520
3586
  return new WEBGLTextureView(this.device, { ...props, texture: this });
3521
3587
  }
3588
+ clone(size) {
3589
+ if (this.isHandleBorrowed && size && (size.width !== this.width || size.height !== this.height)) {
3590
+ throw new Error(`Cannot resize borrowed read-only ${this}`);
3591
+ }
3592
+ return super.clone(size);
3593
+ }
3522
3594
  setSampler(sampler = {}) {
3595
+ this._assertWritable("set sampler parameters on");
3523
3596
  super.setSampler(sampler);
3524
3597
  const parameters = convertSamplerParametersToWebGL(this.sampler.props);
3525
3598
  this._setSamplerParameters(parameters);
3526
3599
  }
3527
3600
  copyExternalImage(options_) {
3601
+ this._assertWritable("copy external image data into");
3528
3602
  const options = this._normalizeCopyExternalImageOptions(options_);
3529
3603
  if (options.sourceX || options.sourceY) {
3530
3604
  throw new Error("WebGL does not support sourceX/sourceY)");
@@ -3550,6 +3624,37 @@ ${source}`;
3550
3624
  this.gl.bindTexture(this.glTarget, null);
3551
3625
  return { width: options.width, height: options.height };
3552
3626
  }
3627
+ copyElementImage(options_) {
3628
+ this._assertWritable("copy element image data into");
3629
+ const options = this._normalizeCopyElementImageOptions(options_);
3630
+ const { glFormat } = this;
3631
+ const { element, depth, mipLevel, sourceX, sourceY, sourceWidth, sourceHeight, x, y, z, width, height } = options;
3632
+ const glTarget = getWebGLCubeFaceTarget(this.glTarget, this.dimension, z);
3633
+ const glParameters = options.flipY ? { [37440]: true } : {};
3634
+ const gl = this.gl;
3635
+ if (depth !== 1 || this.dimension !== "2d" && this.dimension !== "cube") {
3636
+ throw new Error(`${this} copyElementImage only supports 2d and cube textures on WebGL`);
3637
+ }
3638
+ if (mipLevel !== 0 || x !== 0 || y !== 0) {
3639
+ throw new Error(`${this} copyElementImage only supports full base-level uploads on WebGL`);
3640
+ }
3641
+ if (typeof gl.texElementImage2D !== "function") {
3642
+ throw new Error(`${this} copyElementImage is not supported by this WebGL implementation`);
3643
+ }
3644
+ this.gl.bindTexture(this.glTarget, this.handle);
3645
+ withGLParameters(this.gl, glParameters, () => {
3646
+ gl.texElementImage2D?.(glTarget, glFormat, element, {
3647
+ sx: sourceX,
3648
+ sy: sourceY,
3649
+ swidth: sourceWidth ?? width,
3650
+ sheight: sourceHeight ?? height,
3651
+ width,
3652
+ height
3653
+ });
3654
+ });
3655
+ this.gl.bindTexture(this.glTarget, null);
3656
+ return { width: options.width, height: options.height };
3657
+ }
3553
3658
  copyImageData(options_) {
3554
3659
  super.copyImageData(options_);
3555
3660
  }
@@ -3584,6 +3689,7 @@ ${source}`;
3584
3689
  throw new Error(`${this} readDataAsync is deprecated; use readBuffer() with an explicit destination buffer or DynamicTexture.readAsync()`);
3585
3690
  }
3586
3691
  writeBuffer(buffer, options_ = {}) {
3692
+ this._assertWritable("write buffer data into");
3587
3693
  const options = this._normalizeTextureWriteOptions(options_);
3588
3694
  const { width, height, depthOrArrayLayers, mipLevel, byteOffset, x, y, z } = options;
3589
3695
  const { glFormat, glType, compressed } = this;
@@ -3617,6 +3723,7 @@ ${source}`;
3617
3723
  this.gl.bindTexture(this.glTarget, null);
3618
3724
  }
3619
3725
  writeData(data, options_ = {}) {
3726
+ this._assertWritable("write data into");
3620
3727
  const options = this._normalizeTextureWriteOptions(options_);
3621
3728
  const typedArray = ArrayBuffer.isView(data) ? data : new Uint8Array(data);
3622
3729
  const { width, height, depthOrArrayLayers, mipLevel, x, y, z, byteOffset } = options;
@@ -3764,6 +3871,7 @@ ${source}`;
3764
3871
  * @note - this is used by the DynamicTexture class to generate mipmaps on WebGL
3765
3872
  */
3766
3873
  generateMipmapsWebGL(options) {
3874
+ this._assertWritable("generate mipmaps for");
3767
3875
  const isFilterableAndRenderable = this.device.isTextureFormatRenderable(this.props.format) && this.device.isTextureFormatFilterable(this.props.format);
3768
3876
  if (!isFilterableAndRenderable) {
3769
3877
  import_core15.log.warn(`${this} is not renderable or filterable, may not be able to generate mipmaps`)();
@@ -3838,6 +3946,11 @@ ${source}`;
3838
3946
  gl.bindTexture(this.glTarget, null);
3839
3947
  return _textureUnit;
3840
3948
  }
3949
+ _assertWritable(operation) {
3950
+ if (this.isHandleBorrowed) {
3951
+ throw new Error(`Cannot ${operation} borrowed read-only ${this}`);
3952
+ }
3953
+ }
3841
3954
  };
3842
3955
  }
3843
3956
  });
@@ -3931,44 +4044,6 @@ ${source}`;
3931
4044
  }
3932
4045
  });
3933
4046
 
3934
- // ../../node_modules/@luma.gl/webgl/dist/adapter/helpers/webgl-topology-utils.js
3935
- function getGLDrawMode(topology) {
3936
- switch (topology) {
3937
- case "point-list":
3938
- return 0;
3939
- case "line-list":
3940
- return 1;
3941
- case "line-strip":
3942
- return 3;
3943
- case "triangle-list":
3944
- return 4;
3945
- case "triangle-strip":
3946
- return 5;
3947
- default:
3948
- throw new Error(topology);
3949
- }
3950
- }
3951
- function getGLPrimitive(topology) {
3952
- switch (topology) {
3953
- case "point-list":
3954
- return 0;
3955
- case "line-list":
3956
- return 1;
3957
- case "line-strip":
3958
- return 1;
3959
- case "triangle-list":
3960
- return 4;
3961
- case "triangle-strip":
3962
- return 4;
3963
- default:
3964
- throw new Error(topology);
3965
- }
3966
- }
3967
- var init_webgl_topology_utils = __esm({
3968
- "../../node_modules/@luma.gl/webgl/dist/adapter/helpers/webgl-topology-utils.js"() {
3969
- }
3970
- });
3971
-
3972
4047
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-render-pipeline.js
3973
4048
  function mergeShaderLayout(baseLayout, overrideLayout) {
3974
4049
  const mergedLayout = {
@@ -4005,13 +4080,11 @@ ${source}`;
4005
4080
  var init_webgl_render_pipeline = __esm({
4006
4081
  "../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-render-pipeline.js"() {
4007
4082
  import_core16 = __toESM(require_core2(), 1);
4008
- init_device_parameters();
4009
4083
  init_set_uniform();
4010
4084
  init_webgl_buffer();
4011
4085
  init_webgl_framebuffer();
4012
4086
  init_webgl_texture();
4013
4087
  init_webgl_texture_view();
4014
- init_webgl_topology_utils();
4015
4088
  WEBGLRenderPipeline = class extends import_core16.RenderPipeline {
4016
4089
  /** The WebGL device that created this render pipeline */
4017
4090
  device;
@@ -4057,10 +4130,7 @@ ${source}`;
4057
4130
  }
4058
4131
  this.destroyResource();
4059
4132
  }
4060
- /**
4061
- * Compatibility shim for code paths that still set bindings on the pipeline.
4062
- * Shared-model draws pass bindings per draw and do not rely on this state.
4063
- */
4133
+ /** @deprecated Set bindings on RenderPass instead. Will be removed in the next major release. */
4064
4134
  setBindings(bindings, options) {
4065
4135
  const flatBindings = (0, import_core16.flattenBindingsByGroup)((0, import_core16.normalizeBindingsByGroup)(this.shaderLayout, bindings));
4066
4136
  for (const [name, value] of Object.entries(flatBindings)) {
@@ -4100,66 +4170,25 @@ ${source}`;
4100
4170
  * This function unifies those ways into a single call using common parameters with sane defaults
4101
4171
  */
4102
4172
  draw(options) {
4103
- this._syncLinkStatus();
4173
+ const webglRenderPass = options.renderPass;
4104
4174
  const drawBindings = options.bindGroups ? (0, import_core16.flattenBindingsByGroup)(options.bindGroups) : options.bindings || this.bindings;
4105
- const {
4106
- renderPass,
4107
- parameters = this.props.parameters,
4108
- topology = this.props.topology,
4109
- vertexArray,
4110
- vertexCount,
4111
- // indexCount,
4112
- instanceCount,
4113
- isInstanced = false,
4114
- firstVertex = 0,
4115
- // firstIndex,
4116
- // firstInstance,
4117
- // baseVertex,
4118
- transformFeedback,
4119
- uniforms = this.uniforms
4120
- } = options;
4121
- const glDrawMode = getGLDrawMode(topology);
4122
- const isIndexed = Boolean(vertexArray.indexBuffer);
4123
- const glIndexType = vertexArray.indexBuffer?.glIndexType;
4124
- if (this.linkStatus !== "success") {
4125
- import_core16.log.info(2, `RenderPipeline:${this.id}.draw() aborted - waiting for shader linking`)();
4126
- return false;
4127
- }
4128
- if (!this._areTexturesRenderable(drawBindings)) {
4129
- import_core16.log.info(2, `RenderPipeline:${this.id}.draw() aborted - textures not yet loaded`)();
4130
- return false;
4131
- }
4132
- this.device.gl.useProgram(this.handle);
4133
- vertexArray.bindBeforeRender(renderPass);
4134
- if (transformFeedback) {
4135
- transformFeedback.begin(this.props.topology);
4136
- }
4137
- this._applyBindings(drawBindings, { disableWarnings: this.props.disableWarnings });
4138
- this._applyUniforms(uniforms);
4139
- const webglRenderPass = renderPass;
4140
- withDeviceAndGLParameters(this.device, parameters, webglRenderPass.glParameters, () => {
4141
- if (isIndexed && isInstanced) {
4142
- this.device.gl.drawElementsInstanced(
4143
- glDrawMode,
4144
- vertexCount || 0,
4145
- // indexCount?
4146
- glIndexType,
4147
- firstVertex,
4148
- instanceCount || 0
4149
- );
4150
- } else if (isIndexed) {
4151
- this.device.gl.drawElements(glDrawMode, vertexCount || 0, glIndexType, firstVertex);
4152
- } else if (isInstanced) {
4153
- this.device.gl.drawArraysInstanced(glDrawMode, firstVertex, vertexCount || 0, instanceCount || 0);
4154
- } else {
4155
- this.device.gl.drawArrays(glDrawMode, firstVertex, vertexCount || 0);
4156
- }
4157
- if (transformFeedback) {
4158
- transformFeedback.end();
4159
- }
4175
+ webglRenderPass.setPipeline(this);
4176
+ webglRenderPass.setBindings(drawBindings);
4177
+ webglRenderPass.setVertexArray(options.vertexArray);
4178
+ return webglRenderPass.draw({
4179
+ parameters: options.parameters,
4180
+ topology: options.topology,
4181
+ isInstanced: options.isInstanced,
4182
+ vertexCount: options.vertexCount,
4183
+ indexCount: options.indexCount,
4184
+ instanceCount: options.instanceCount,
4185
+ firstVertex: options.firstVertex,
4186
+ firstIndex: options.firstIndex,
4187
+ firstInstance: options.firstInstance,
4188
+ baseVertex: options.baseVertex,
4189
+ transformFeedback: options.transformFeedback,
4190
+ uniforms: options.uniforms
4160
4191
  });
4161
- vertexArray.unbindAfterRender(renderPass);
4162
- return true;
4163
4192
  }
4164
4193
  /**
4165
4194
  * Checks if all texture-values uniforms are renderable (i.e. loaded)
@@ -4707,7 +4736,22 @@ ${source}`;
4707
4736
  device.gl.bindBuffer(36663, null);
4708
4737
  }
4709
4738
  function _copyBufferToTexture(_device, _options) {
4710
- throw new Error("copyBufferToTexture is not supported in WebGL");
4739
+ const { sourceBuffer, byteOffset = 0, destinationTexture, mipLevel = 0, origin = [0, 0, 0], aspect = "all", bytesPerRow, rowsPerImage, size } = _options;
4740
+ if (aspect !== "all") {
4741
+ throw new Error("copyBufferToTexture aspect is not supported in WebGL");
4742
+ }
4743
+ destinationTexture.writeBuffer(sourceBuffer, {
4744
+ byteOffset,
4745
+ bytesPerRow,
4746
+ rowsPerImage,
4747
+ mipLevel,
4748
+ x: origin[0] ?? 0,
4749
+ y: origin[1] ?? 0,
4750
+ z: origin[2] ?? 0,
4751
+ width: size[0],
4752
+ height: size[1],
4753
+ depthOrArrayLayers: size[2]
4754
+ });
4711
4755
  }
4712
4756
  function _copyTextureToBuffer(device, options) {
4713
4757
  const { sourceTexture, mipLevel = 0, aspect = "all", width = options.sourceTexture.width, height = options.sourceTexture.height, depthOrArrayLayers, origin = [0, 0, 0], destinationBuffer, byteOffset = 0, bytesPerRow, rowsPerImage } = options;
@@ -4865,6 +4909,44 @@ ${source}`;
4865
4909
  }
4866
4910
  });
4867
4911
 
4912
+ // ../../node_modules/@luma.gl/webgl/dist/adapter/helpers/webgl-topology-utils.js
4913
+ function getGLDrawMode(topology) {
4914
+ switch (topology) {
4915
+ case "point-list":
4916
+ return 0;
4917
+ case "line-list":
4918
+ return 1;
4919
+ case "line-strip":
4920
+ return 3;
4921
+ case "triangle-list":
4922
+ return 4;
4923
+ case "triangle-strip":
4924
+ return 5;
4925
+ default:
4926
+ throw new Error(topology);
4927
+ }
4928
+ }
4929
+ function getGLPrimitive(topology) {
4930
+ switch (topology) {
4931
+ case "point-list":
4932
+ return 0;
4933
+ case "line-list":
4934
+ return 1;
4935
+ case "line-strip":
4936
+ return 1;
4937
+ case "triangle-list":
4938
+ return 4;
4939
+ case "triangle-strip":
4940
+ return 4;
4941
+ default:
4942
+ throw new Error(topology);
4943
+ }
4944
+ }
4945
+ var init_webgl_topology_utils = __esm({
4946
+ "../../node_modules/@luma.gl/webgl/dist/adapter/helpers/webgl-topology-utils.js"() {
4947
+ }
4948
+ });
4949
+
4868
4950
  // ../../node_modules/@luma.gl/webgl/dist/adapter/resources/webgl-render-pass.js
4869
4951
  var import_core20, COLOR_CHANNELS, WEBGLRenderPass;
4870
4952
  var init_webgl_render_pass = __esm({
@@ -4872,12 +4954,21 @@ ${source}`;
4872
4954
  import_core20 = __toESM(require_core2(), 1);
4873
4955
  init_with_parameters();
4874
4956
  init_unified_parameter_api();
4957
+ init_webgl_topology_utils();
4958
+ init_device_parameters();
4875
4959
  COLOR_CHANNELS = [1, 2, 4, 8];
4876
4960
  WEBGLRenderPass = class extends import_core20.RenderPass {
4877
4961
  device;
4878
4962
  handle = null;
4879
4963
  /** Parameters that should be applied before each draw call */
4880
4964
  glParameters = {};
4965
+ /** Pipeline used by subsequent draw commands. */
4966
+ pipeline = null;
4967
+ /** Complete binding set used by subsequent draw commands. */
4968
+ bindings = {};
4969
+ bindingsPipeline = null;
4970
+ /** Vertex array used by subsequent draw commands. */
4971
+ vertexArray = null;
4881
4972
  constructor(device, props) {
4882
4973
  super(device, props);
4883
4974
  this.device = device;
@@ -4929,7 +5020,10 @@ ${source}`;
4929
5020
  }
4930
5021
  // beginOcclusionQuery(queryIndex: number): void;
4931
5022
  // endOcclusionQuery(): void;
4932
- // executeBundles(bundles: Iterable<GPURenderBundle>): void;
5023
+ /** @throws Always throws because WebGL does not support render bundles. */
5024
+ executeBundles(_bundles) {
5025
+ throw new Error("Render bundles are only supported in WebGPU");
5026
+ }
4933
5027
  /**
4934
5028
  * Maps RenderPass parameters to GL parameters
4935
5029
  */
@@ -4969,6 +5063,78 @@ ${source}`;
4969
5063
  this.glParameters = glParameters;
4970
5064
  setGLParameters(this.device.gl, glParameters);
4971
5065
  }
5066
+ setPipeline(pipeline) {
5067
+ this.pipeline = pipeline;
5068
+ }
5069
+ setBindings(bindings, _options) {
5070
+ if (!this.pipeline) {
5071
+ throw new Error("RenderPass.setPipeline() must be called before setBindings()");
5072
+ }
5073
+ this.bindings = (0, import_core20.flattenBindingsByGroup)((0, import_core20.normalizeBindingsByGroup)(this.pipeline.shaderLayout, bindings));
5074
+ this.bindingsPipeline = this.pipeline;
5075
+ }
5076
+ setVertexArray(vertexArray) {
5077
+ this.vertexArray = vertexArray;
5078
+ }
5079
+ draw(options) {
5080
+ const pipeline = this.pipeline;
5081
+ const vertexArray = this.vertexArray;
5082
+ if (!pipeline) {
5083
+ throw new Error("RenderPass.setPipeline() must be called before draw()");
5084
+ }
5085
+ if (!vertexArray) {
5086
+ throw new Error("RenderPass.setVertexArray() must be called before draw()");
5087
+ }
5088
+ if (pipeline.shaderLayout.bindings.length > 0 && this.bindingsPipeline !== pipeline) {
5089
+ throw new Error("RenderPass.setBindings() must be called after setPipeline() before draw()");
5090
+ }
5091
+ pipeline._syncLinkStatus();
5092
+ const { parameters = pipeline.props.parameters, topology = pipeline.props.topology, vertexCount, indexCount, instanceCount, isInstanced = false, firstVertex = 0, transformFeedback, uniforms = pipeline.uniforms } = options;
5093
+ const glDrawMode = getGLDrawMode(topology);
5094
+ const isIndexed = Boolean(vertexArray.indexBuffer);
5095
+ const glIndexType = vertexArray.indexBuffer?.glIndexType;
5096
+ const indexedDrawCount = indexCount ?? vertexCount ?? 0;
5097
+ if (pipeline.linkStatus !== "success") {
5098
+ import_core20.log.info(2, `RenderPipeline:${pipeline.id}.draw() aborted - waiting for shader linking`)();
5099
+ return false;
5100
+ }
5101
+ if (!pipeline._areTexturesRenderable(this.bindings)) {
5102
+ import_core20.log.info(2, `RenderPipeline:${pipeline.id}.draw() aborted - textures not yet loaded`)();
5103
+ return false;
5104
+ }
5105
+ this.device.gl.useProgram(pipeline.handle);
5106
+ vertexArray.bindBeforeRender(this);
5107
+ const webglTransformFeedback = transformFeedback;
5108
+ if (webglTransformFeedback) {
5109
+ webglTransformFeedback.begin(pipeline.props.topology);
5110
+ }
5111
+ pipeline._applyBindings(this.bindings, { disableWarnings: pipeline.props.disableWarnings });
5112
+ pipeline._applyUniforms(uniforms);
5113
+ withDeviceAndGLParameters(this.device, parameters, this.glParameters, () => {
5114
+ if (isIndexed && isInstanced) {
5115
+ this.device.gl.drawElementsInstanced(glDrawMode, indexedDrawCount, glIndexType, firstVertex, instanceCount || 0);
5116
+ } else if (isIndexed) {
5117
+ this.device.gl.drawElements(glDrawMode, indexedDrawCount, glIndexType, firstVertex);
5118
+ } else if (isInstanced) {
5119
+ this.device.gl.drawArraysInstanced(glDrawMode, firstVertex, vertexCount || 0, instanceCount || 0);
5120
+ } else {
5121
+ this.device.gl.drawArrays(glDrawMode, firstVertex, vertexCount || 0);
5122
+ }
5123
+ if (webglTransformFeedback) {
5124
+ webglTransformFeedback.end();
5125
+ }
5126
+ });
5127
+ vertexArray.unbindAfterRender(this);
5128
+ return true;
5129
+ }
5130
+ /** @throws Always throws because WebGL does not expose indirect drawing. */
5131
+ drawIndirect(_indirectBuffer, _indirectByteOffset = 0) {
5132
+ throw new Error("Indirect drawing is only supported in WebGPU");
5133
+ }
5134
+ /** @throws Always throws because WebGL does not expose indirect drawing. */
5135
+ drawIndexedIndirect(_indirectBuffer, _indirectByteOffset = 0) {
5136
+ throw new Error("Indirect drawing is only supported in WebGPU");
5137
+ }
4972
5138
  beginOcclusionQuery(queryIndex) {
4973
5139
  const webglQuerySet = this.props.occlusionQuerySet;
4974
5140
  webglQuerySet?.beginOcclusionQuery();
@@ -5053,17 +5219,14 @@ ${source}`;
5053
5219
  super(device, props);
5054
5220
  this.device = device;
5055
5221
  this.commandBuffer = new WEBGLCommandBuffer(device, {
5056
- id: `${this.props.id}-command-buffer`
5222
+ id: this.id,
5223
+ userData: this.userData
5057
5224
  });
5058
5225
  }
5059
5226
  destroy() {
5060
5227
  this.destroyResource();
5061
5228
  }
5062
- finish(props) {
5063
- if (props?.id && this.commandBuffer.id !== props.id) {
5064
- this.commandBuffer.id = props.id;
5065
- this.commandBuffer.props.id = props.id;
5066
- }
5229
+ finish() {
5067
5230
  this.destroy();
5068
5231
  return this.commandBuffer;
5069
5232
  }
@@ -5161,18 +5324,32 @@ ${source}`;
5161
5324
  }
5162
5325
  device;
5163
5326
  handle;
5327
+ /** Attribute accessors indexed by shader location for WebGL pointer setup. */
5328
+ attributeInfosByLocation;
5164
5329
  /** Attribute 0 buffer constant */
5165
5330
  buffer = null;
5166
5331
  bufferValue = null;
5167
- /** * Attribute 0 can not be disable on most desktop OpenGL based browsers */
5332
+ /**
5333
+ * Reports whether attribute location 0 may be disabled without fallback handling.
5334
+ * @param device The device that owns the vertex array.
5335
+ * @returns `true` when constant attribute 0 is supported on the current browser.
5336
+ */
5168
5337
  static isConstantAttributeZeroSupported(device) {
5169
5338
  return getBrowser() === "Chrome";
5170
5339
  }
5171
- // Create a VertexArray
5340
+ /**
5341
+ * Creates a WebGL vertex array and caches per-location accessor metadata.
5342
+ * @param device The device that owns the vertex array.
5343
+ * @param props Vertex-array initialization properties.
5344
+ */
5172
5345
  constructor(device, props) {
5173
5346
  super(device, props);
5174
5347
  this.device = device;
5175
5348
  this.handle = this.device.gl.createVertexArray();
5349
+ this.attributeInfosByLocation = new Array(this.maxVertexAttributes).fill(null);
5350
+ for (const attributeInfo of Object.values((0, import_core22.getAttributeInfosFromLayouts)(props.shaderLayout, props.bufferLayout))) {
5351
+ this.attributeInfosByLocation[attributeInfo.location] = attributeInfo;
5352
+ }
5176
5353
  }
5177
5354
  destroy() {
5178
5355
  super.destroy();
@@ -5200,7 +5377,11 @@ ${source}`;
5200
5377
  this.indexBuffer = buffer;
5201
5378
  this.device.gl.bindVertexArray(null);
5202
5379
  }
5203
- /** Set a location in vertex attributes array to a buffer, enables the location, sets divisor */
5380
+ /**
5381
+ * Binds a buffer to one shader attribute location and configures the WebGL pointer state.
5382
+ * @param location Shader attribute location.
5383
+ * @param attributeBuffer Buffer supplying the attribute data.
5384
+ */
5204
5385
  setBuffer(location, attributeBuffer) {
5205
5386
  const buffer = attributeBuffer;
5206
5387
  if (buffer.glTarget === 34963) {
@@ -5220,7 +5401,11 @@ ${source}`;
5220
5401
  this.attributes[location] = buffer;
5221
5402
  this.device.gl.bindVertexArray(null);
5222
5403
  }
5223
- /** Set a location in vertex attributes array to a constant value, disables the location */
5404
+ /**
5405
+ * Stores a constant value for one shader attribute location.
5406
+ * @param location Shader attribute location.
5407
+ * @param value Constant attribute value.
5408
+ */
5224
5409
  setConstantWebGL(location, value) {
5225
5410
  this._enable(location, false);
5226
5411
  this.attributes[location] = value;
@@ -5262,9 +5447,13 @@ ${source}`;
5262
5447
  // }
5263
5448
  // this.device.gl.vertexAttribDivisor(location, divisor || 0);
5264
5449
  // }
5265
- /** Get an accessor from the */
5450
+ /**
5451
+ * Returns the cached accessor description for one shader attribute location.
5452
+ * @param location Shader attribute location.
5453
+ * @returns WebGL pointer state derived from the shared attribute metadata.
5454
+ */
5266
5455
  _getAccessor(location) {
5267
- const attributeInfo = this.attributeInfos[location];
5456
+ const attributeInfo = this.attributeInfosByLocation[location];
5268
5457
  if (!attributeInfo) {
5269
5458
  throw new Error(`Unknown attribute location ${location}`);
5270
5459
  }
@@ -6126,8 +6315,9 @@ ${source}`;
6126
6315
  reason: "destroyed",
6127
6316
  message: "Entered sleep mode, or too many apps or browser tabs are using the GPU."
6128
6317
  }),
6129
- // eslint-disable-next-line no-console
6130
- onContextRestored: (event) => console.log("WebGL context restored")
6318
+ onContextRestored: (_event) => {
6319
+ console.log("WebGL context restored");
6320
+ }
6131
6321
  }, webglContextAttributes);
6132
6322
  if (!gl) {
6133
6323
  throw new Error("WebGL context creation failed");
@@ -6205,8 +6395,8 @@ ${source}`;
6205
6395
  createTexture(props) {
6206
6396
  return new WEBGLTexture(this, props);
6207
6397
  }
6208
- createExternalTexture(props) {
6209
- throw new Error("createExternalTexture() not implemented");
6398
+ createExternalTexture(_props) {
6399
+ throw new Error("ExternalTexture is not available on WebGL");
6210
6400
  }
6211
6401
  createSampler(props) {
6212
6402
  return new WEBGLSampler(this, props);
@@ -6238,6 +6428,10 @@ ${source}`;
6238
6428
  createComputePipeline(props) {
6239
6429
  throw new Error("ComputePipeline not supported in WebGL");
6240
6430
  }
6431
+ /** @throws Always throws because WebGL does not support render bundles. */
6432
+ createRenderBundleEncoder(_props) {
6433
+ throw new Error("Render bundles are only supported in WebGPU");
6434
+ }
6241
6435
  createCommandEncoder(props = {}) {
6242
6436
  return new WEBGLCommandEncoder(this, props);
6243
6437
  }
@@ -6263,6 +6457,9 @@ ${source}`;
6263
6457
  commandBuffer.destroy();
6264
6458
  }
6265
6459
  }
6460
+ writeBufferViaCommandEncoder(_commandEncoder, destinationBuffer, data, byteOffset = 0) {
6461
+ destinationBuffer.write(data, byteOffset);
6462
+ }
6266
6463
  _finalizeDefaultCommandEncoderForSubmit() {
6267
6464
  const submittedCommandEncoder = this.commandEncoder;
6268
6465
  const commandBuffer = submittedCommandEncoder.finish();
@@ -11868,19 +12065,6 @@ void main(void) {
11868
12065
  RecognizerState2[RecognizerState2["Failed"] = 32] = "Failed";
11869
12066
  })(RecognizerState || (RecognizerState = {}));
11870
12067
 
11871
- // ../../node_modules/mjolnir.js/dist/hammerjs/touchaction/touchaction-Consts.js
11872
- var TOUCH_ACTION_MANIPULATION = "manipulation";
11873
- var TOUCH_ACTION_NONE = "none";
11874
- var TOUCH_ACTION_PAN_X = "pan-x";
11875
- var TOUCH_ACTION_PAN_Y = "pan-y";
11876
-
11877
- // ../../node_modules/mjolnir.js/dist/hammerjs/input/get-distance.js
11878
- function getPointDistance(p1, p2) {
11879
- const x = p2.x - p1.x;
11880
- const y = p2.y - p1.y;
11881
- return Math.sqrt(x * x + y * y);
11882
- }
11883
-
11884
12068
  // ../../node_modules/mjolnir.js/dist/hammerjs/inputs/pointerevent.js
11885
12069
  var POINTER_INPUT_MAP = {
11886
12070
  pointerdown: InputEvent.Start,
@@ -11890,430 +12074,6 @@ void main(void) {
11890
12074
  pointerout: InputEvent.Cancel
11891
12075
  };
11892
12076
 
11893
- // ../../node_modules/mjolnir.js/dist/hammerjs/utils/unique-id.js
11894
- var _uniqueId = 1;
11895
- function uniqueId() {
11896
- return _uniqueId++;
11897
- }
11898
-
11899
- // ../../node_modules/mjolnir.js/dist/hammerjs/recognizer/state-str.js
11900
- function stateStr(state) {
11901
- if (state & RecognizerState.Cancelled) {
11902
- return "cancel";
11903
- } else if (state & RecognizerState.Ended) {
11904
- return "end";
11905
- } else if (state & RecognizerState.Changed) {
11906
- return "move";
11907
- } else if (state & RecognizerState.Began) {
11908
- return "start";
11909
- }
11910
- return "";
11911
- }
11912
-
11913
- // ../../node_modules/mjolnir.js/dist/hammerjs/recognizer/recognizer.js
11914
- var Recognizer = class {
11915
- constructor(options) {
11916
- this.options = options;
11917
- this.id = uniqueId();
11918
- this.state = RecognizerState.Possible;
11919
- this.simultaneous = {};
11920
- this.requireFail = [];
11921
- }
11922
- /**
11923
- * set options
11924
- */
11925
- set(options) {
11926
- Object.assign(this.options, options);
11927
- this.manager.touchAction.update();
11928
- return this;
11929
- }
11930
- /**
11931
- * recognize simultaneous with an other recognizer.
11932
- */
11933
- recognizeWith(recognizerOrName) {
11934
- if (Array.isArray(recognizerOrName)) {
11935
- for (const item of recognizerOrName) {
11936
- this.recognizeWith(item);
11937
- }
11938
- return this;
11939
- }
11940
- let otherRecognizer;
11941
- if (typeof recognizerOrName === "string") {
11942
- otherRecognizer = this.manager.get(recognizerOrName);
11943
- if (!otherRecognizer) {
11944
- throw new Error(`Cannot find recognizer ${recognizerOrName}`);
11945
- }
11946
- } else {
11947
- otherRecognizer = recognizerOrName;
11948
- }
11949
- const { simultaneous } = this;
11950
- if (!simultaneous[otherRecognizer.id]) {
11951
- simultaneous[otherRecognizer.id] = otherRecognizer;
11952
- otherRecognizer.recognizeWith(this);
11953
- }
11954
- return this;
11955
- }
11956
- /**
11957
- * drop the simultaneous link. it doesnt remove the link on the other recognizer.
11958
- */
11959
- dropRecognizeWith(recognizerOrName) {
11960
- if (Array.isArray(recognizerOrName)) {
11961
- for (const item of recognizerOrName) {
11962
- this.dropRecognizeWith(item);
11963
- }
11964
- return this;
11965
- }
11966
- let otherRecognizer;
11967
- if (typeof recognizerOrName === "string") {
11968
- otherRecognizer = this.manager.get(recognizerOrName);
11969
- } else {
11970
- otherRecognizer = recognizerOrName;
11971
- }
11972
- if (otherRecognizer) {
11973
- delete this.simultaneous[otherRecognizer.id];
11974
- }
11975
- return this;
11976
- }
11977
- /**
11978
- * recognizer can only run when an other is failing
11979
- */
11980
- requireFailure(recognizerOrName) {
11981
- if (Array.isArray(recognizerOrName)) {
11982
- for (const item of recognizerOrName) {
11983
- this.requireFailure(item);
11984
- }
11985
- return this;
11986
- }
11987
- let otherRecognizer;
11988
- if (typeof recognizerOrName === "string") {
11989
- otherRecognizer = this.manager.get(recognizerOrName);
11990
- if (!otherRecognizer) {
11991
- throw new Error(`Cannot find recognizer ${recognizerOrName}`);
11992
- }
11993
- } else {
11994
- otherRecognizer = recognizerOrName;
11995
- }
11996
- const { requireFail } = this;
11997
- if (requireFail.indexOf(otherRecognizer) === -1) {
11998
- requireFail.push(otherRecognizer);
11999
- otherRecognizer.requireFailure(this);
12000
- }
12001
- return this;
12002
- }
12003
- /**
12004
- * drop the requireFailure link. it does not remove the link on the other recognizer.
12005
- */
12006
- dropRequireFailure(recognizerOrName) {
12007
- if (Array.isArray(recognizerOrName)) {
12008
- for (const item of recognizerOrName) {
12009
- this.dropRequireFailure(item);
12010
- }
12011
- return this;
12012
- }
12013
- let otherRecognizer;
12014
- if (typeof recognizerOrName === "string") {
12015
- otherRecognizer = this.manager.get(recognizerOrName);
12016
- } else {
12017
- otherRecognizer = recognizerOrName;
12018
- }
12019
- if (otherRecognizer) {
12020
- const index = this.requireFail.indexOf(otherRecognizer);
12021
- if (index > -1) {
12022
- this.requireFail.splice(index, 1);
12023
- }
12024
- }
12025
- return this;
12026
- }
12027
- /**
12028
- * has require failures boolean
12029
- */
12030
- hasRequireFailures() {
12031
- return Boolean(this.requireFail.find((recognier) => recognier.options.enable));
12032
- }
12033
- /**
12034
- * if the recognizer can recognize simultaneous with an other recognizer
12035
- */
12036
- canRecognizeWith(otherRecognizer) {
12037
- return Boolean(this.simultaneous[otherRecognizer.id]);
12038
- }
12039
- /**
12040
- * You should use `tryEmit` instead of `emit` directly to check
12041
- * that all the needed recognizers has failed before emitting.
12042
- */
12043
- emit(input) {
12044
- if (!input)
12045
- return;
12046
- const { state } = this;
12047
- if (state < RecognizerState.Ended) {
12048
- this.manager.emit(this.options.event + stateStr(state), input);
12049
- }
12050
- this.manager.emit(this.options.event, input);
12051
- if (input.additionalEvent) {
12052
- this.manager.emit(input.additionalEvent, input);
12053
- }
12054
- if (state >= RecognizerState.Ended) {
12055
- this.manager.emit(this.options.event + stateStr(state), input);
12056
- }
12057
- }
12058
- /**
12059
- * Check that all the require failure recognizers has failed,
12060
- * if true, it emits a gesture event,
12061
- * otherwise, setup the state to FAILED.
12062
- */
12063
- tryEmit(input) {
12064
- if (this.canEmit()) {
12065
- this.emit(input);
12066
- } else {
12067
- this.state = RecognizerState.Failed;
12068
- }
12069
- }
12070
- /**
12071
- * can we emit?
12072
- */
12073
- canEmit() {
12074
- let i = 0;
12075
- while (i < this.requireFail.length) {
12076
- if (!(this.requireFail[i].state & (RecognizerState.Failed | RecognizerState.Possible))) {
12077
- return false;
12078
- }
12079
- i++;
12080
- }
12081
- return true;
12082
- }
12083
- /**
12084
- * update the recognizer
12085
- */
12086
- recognize(inputData) {
12087
- const inputDataClone = { ...inputData };
12088
- if (!this.options.enable) {
12089
- this.reset();
12090
- this.state = RecognizerState.Failed;
12091
- return;
12092
- }
12093
- if (this.state & (RecognizerState.Recognized | RecognizerState.Cancelled | RecognizerState.Failed)) {
12094
- this.state = RecognizerState.Possible;
12095
- }
12096
- this.state = this.process(inputDataClone);
12097
- if (this.state & (RecognizerState.Began | RecognizerState.Changed | RecognizerState.Ended | RecognizerState.Cancelled)) {
12098
- this.tryEmit(inputDataClone);
12099
- }
12100
- }
12101
- /**
12102
- * return the event names that are emitted by this recognizer
12103
- */
12104
- getEventNames() {
12105
- return [this.options.event];
12106
- }
12107
- /**
12108
- * called when the gesture isn't allowed to recognize
12109
- * like when another is being recognized or it is disabled
12110
- */
12111
- reset() {
12112
- }
12113
- };
12114
-
12115
- // ../../node_modules/mjolnir.js/dist/hammerjs/recognizers/attribute.js
12116
- var AttrRecognizer = class extends Recognizer {
12117
- /**
12118
- * Used to check if it the recognizer receives valid input, like input.distance > 10.
12119
- */
12120
- attrTest(input) {
12121
- const optionPointers = this.options.pointers;
12122
- return optionPointers === 0 || input.pointers.length === optionPointers;
12123
- }
12124
- /**
12125
- * Process the input and return the state for the recognizer
12126
- */
12127
- process(input) {
12128
- const { state } = this;
12129
- const { eventType } = input;
12130
- const isRecognized = state & (RecognizerState.Began | RecognizerState.Changed);
12131
- const isValid = this.attrTest(input);
12132
- if (isRecognized && (eventType & InputEvent.Cancel || !isValid)) {
12133
- return state | RecognizerState.Cancelled;
12134
- } else if (isRecognized || isValid) {
12135
- if (eventType & InputEvent.End) {
12136
- return state | RecognizerState.Ended;
12137
- } else if (!(state & RecognizerState.Began)) {
12138
- return RecognizerState.Began;
12139
- }
12140
- return state | RecognizerState.Changed;
12141
- }
12142
- return RecognizerState.Failed;
12143
- }
12144
- };
12145
-
12146
- // ../../node_modules/mjolnir.js/dist/hammerjs/recognizers/tap.js
12147
- var TapRecognizer = class extends Recognizer {
12148
- constructor(options = {}) {
12149
- super({
12150
- enable: true,
12151
- event: "tap",
12152
- pointers: 1,
12153
- taps: 1,
12154
- interval: 300,
12155
- time: 250,
12156
- threshold: 9,
12157
- posThreshold: 10,
12158
- ...options
12159
- });
12160
- this.pTime = null;
12161
- this.pCenter = null;
12162
- this._timer = null;
12163
- this._input = null;
12164
- this.count = 0;
12165
- }
12166
- getTouchAction() {
12167
- return [TOUCH_ACTION_MANIPULATION];
12168
- }
12169
- process(input) {
12170
- const { options } = this;
12171
- const validPointers = input.pointers.length === options.pointers;
12172
- const validMovement = input.distance < options.threshold;
12173
- const validTouchTime = input.deltaTime < options.time;
12174
- this.reset();
12175
- if (input.eventType & InputEvent.Start && this.count === 0) {
12176
- return this.failTimeout();
12177
- }
12178
- if (validMovement && validTouchTime && validPointers) {
12179
- if (input.eventType !== InputEvent.End) {
12180
- return this.failTimeout();
12181
- }
12182
- const validInterval = this.pTime ? input.timeStamp - this.pTime < options.interval : true;
12183
- const validMultiTap = !this.pCenter || getPointDistance(this.pCenter, input.center) < options.posThreshold;
12184
- this.pTime = input.timeStamp;
12185
- this.pCenter = input.center;
12186
- if (!validMultiTap || !validInterval) {
12187
- this.count = 1;
12188
- } else {
12189
- this.count += 1;
12190
- }
12191
- this._input = input;
12192
- const tapCount = this.count % options.taps;
12193
- if (tapCount === 0) {
12194
- if (!this.hasRequireFailures()) {
12195
- return RecognizerState.Recognized;
12196
- }
12197
- this._timer = setTimeout(() => {
12198
- this.state = RecognizerState.Recognized;
12199
- this.tryEmit(this._input);
12200
- }, options.interval);
12201
- return RecognizerState.Began;
12202
- }
12203
- }
12204
- return RecognizerState.Failed;
12205
- }
12206
- failTimeout() {
12207
- this._timer = setTimeout(() => {
12208
- this.state = RecognizerState.Failed;
12209
- }, this.options.interval);
12210
- return RecognizerState.Failed;
12211
- }
12212
- reset() {
12213
- clearTimeout(this._timer);
12214
- }
12215
- emit(input) {
12216
- if (this.state === RecognizerState.Recognized) {
12217
- input.tapCount = this.count;
12218
- this.manager.emit(this.options.event, input);
12219
- }
12220
- }
12221
- };
12222
-
12223
- // ../../node_modules/mjolnir.js/dist/hammerjs/recognizers/pan.js
12224
- var EVENT_NAMES = ["", "start", "move", "end", "cancel", "up", "down", "left", "right"];
12225
- var PanRecognizer = class extends AttrRecognizer {
12226
- constructor(options = {}) {
12227
- super({
12228
- enable: true,
12229
- pointers: 1,
12230
- event: "pan",
12231
- threshold: 10,
12232
- direction: InputDirection.All,
12233
- ...options
12234
- });
12235
- this.pX = null;
12236
- this.pY = null;
12237
- }
12238
- getTouchAction() {
12239
- const { options: { direction } } = this;
12240
- const actions = [];
12241
- if (direction & InputDirection.Horizontal) {
12242
- actions.push(TOUCH_ACTION_PAN_Y);
12243
- }
12244
- if (direction & InputDirection.Vertical) {
12245
- actions.push(TOUCH_ACTION_PAN_X);
12246
- }
12247
- return actions;
12248
- }
12249
- getEventNames() {
12250
- return EVENT_NAMES.map((suffix) => this.options.event + suffix);
12251
- }
12252
- directionTest(input) {
12253
- const { options } = this;
12254
- let hasMoved = true;
12255
- let { distance: distance4 } = input;
12256
- let { direction } = input;
12257
- const x = input.deltaX;
12258
- const y = input.deltaY;
12259
- if (!(direction & options.direction)) {
12260
- if (options.direction & InputDirection.Horizontal) {
12261
- direction = x === 0 ? InputDirection.None : x < 0 ? InputDirection.Left : InputDirection.Right;
12262
- hasMoved = x !== this.pX;
12263
- distance4 = Math.abs(input.deltaX);
12264
- } else {
12265
- direction = y === 0 ? InputDirection.None : y < 0 ? InputDirection.Up : InputDirection.Down;
12266
- hasMoved = y !== this.pY;
12267
- distance4 = Math.abs(input.deltaY);
12268
- }
12269
- }
12270
- input.direction = direction;
12271
- return hasMoved && distance4 > options.threshold && Boolean(direction & options.direction);
12272
- }
12273
- attrTest(input) {
12274
- return super.attrTest(input) && (Boolean(this.state & RecognizerState.Began) || !(this.state & RecognizerState.Began) && this.directionTest(input));
12275
- }
12276
- emit(input) {
12277
- this.pX = input.deltaX;
12278
- this.pY = input.deltaY;
12279
- const direction = InputDirection[input.direction].toLowerCase();
12280
- if (direction) {
12281
- input.additionalEvent = this.options.event + direction;
12282
- }
12283
- super.emit(input);
12284
- }
12285
- };
12286
-
12287
- // ../../node_modules/mjolnir.js/dist/hammerjs/recognizers/pinch.js
12288
- var EVENT_NAMES2 = ["", "start", "move", "end", "cancel", "in", "out"];
12289
- var PinchRecognizer = class extends AttrRecognizer {
12290
- constructor(options = {}) {
12291
- super({
12292
- enable: true,
12293
- event: "pinch",
12294
- threshold: 0,
12295
- pointers: 2,
12296
- ...options
12297
- });
12298
- }
12299
- getTouchAction() {
12300
- return [TOUCH_ACTION_NONE];
12301
- }
12302
- getEventNames() {
12303
- return EVENT_NAMES2.map((suffix) => this.options.event + suffix);
12304
- }
12305
- attrTest(input) {
12306
- return super.attrTest(input) && (Math.abs(input.scale - 1) > this.options.threshold || Boolean(this.state & RecognizerState.Began));
12307
- }
12308
- emit(input) {
12309
- if (input.scale !== 1) {
12310
- const inOut = input.scale < 1 ? "in" : "out";
12311
- input.additionalEvent = this.options.event + inOut;
12312
- }
12313
- super.emit(input);
12314
- }
12315
- };
12316
-
12317
12077
  // ../../node_modules/mjolnir.js/dist/utils/globals.js
12318
12078
  var userAgent = typeof navigator !== "undefined" && navigator.userAgent ? navigator.userAgent.toLowerCase() : "";
12319
12079
  var window_2 = typeof window !== "undefined" ? window : global;
@@ -12373,13 +12133,6 @@ void main(void) {
12373
12133
  */
12374
12134
  IDENTITY: 0
12375
12135
  };
12376
- var RECOGNIZERS = {
12377
- multipan: [PanRecognizer, { threshold: 10, direction: InputDirection.Vertical, pointers: 2 }],
12378
- pinch: [PinchRecognizer, {}, null, ["multipan"]],
12379
- pan: [PanRecognizer, { threshold: 1 }, ["pinch"], ["multipan"]],
12380
- dblclick: [TapRecognizer, { event: "dblclick", taps: 2 }],
12381
- click: [TapRecognizer, { event: "click" }, null, ["dblclick"]]
12382
- };
12383
12136
 
12384
12137
  // ../core/src/viewports/viewport.ts
12385
12138
  var DEGREES_TO_RADIANS4 = Math.PI / 180;
@@ -13176,6 +12929,8 @@ void main(void) {
13176
12929
  constructor(opts = {}) {
13177
12930
  const {
13178
12931
  longitude = 0,
12932
+ bearing = 0,
12933
+ pitch = 0,
13179
12934
  zoom = 0,
13180
12935
  // Matches Maplibre defaults
13181
12936
  // https://github.com/maplibre/maplibre-gl-js/blob/f8ab4b48d59ab8fe7b068b102538793bbdd4c848/src/geo/projection/globe_transform.ts#L632-L633
@@ -13184,20 +12939,19 @@ void main(void) {
13184
12939
  resolution = 10
13185
12940
  } = opts;
13186
12941
  let { latitude = 0, height, altitude = 1.5, fovy } = opts;
13187
- latitude = Math.max(Math.min(latitude, MAX_LATITUDE), -MAX_LATITUDE);
12942
+ latitude = Math.max(Math.min(latitude, 90), -90);
13188
12943
  height = height || 1;
13189
12944
  if (fovy) {
13190
12945
  altitude = fovyToAltitude(fovy);
13191
12946
  } else {
13192
12947
  fovy = altitudeToFovy(altitude);
13193
12948
  }
13194
- const scale5 = Math.pow(2, zoom - zoomAdjust(latitude));
12949
+ const scaleLatitude = Math.max(Math.min(latitude, MAX_LATITUDE), -MAX_LATITUDE);
12950
+ const scale5 = Math.pow(2, zoom - zoomAdjust(scaleLatitude));
12951
+ const pitchRadians = pitch * DEGREES_TO_RADIANS5;
13195
12952
  const nearZ = opts.nearZ ?? nearZMultiplier;
13196
- const farZ = opts.farZ ?? (altitude + GLOBE_RADIUS * 2 * scale5 / height) * farZMultiplier;
13197
- const viewMatrix = new Matrix4().lookAt({ eye: [0, -altitude, 0], up: [0, 0, 1] });
13198
- viewMatrix.rotateX(latitude * DEGREES_TO_RADIANS5);
13199
- viewMatrix.rotateZ(-longitude * DEGREES_TO_RADIANS5);
13200
- viewMatrix.scale(scale5 / height);
12953
+ const farZ = opts.farZ ?? (altitude + GLOBE_RADIUS * 2 * scale5 / height / Math.max(Math.cos(pitchRadians), 0.1)) * farZMultiplier;
12954
+ const viewMatrix = new Matrix4().lookAt({ eye: [0, -altitude, 0], up: [0, 0, 1] }).rotateX(-pitchRadians).rotateY(-bearing * DEGREES_TO_RADIANS5).rotateX(latitude * DEGREES_TO_RADIANS5).rotateZ(-longitude * DEGREES_TO_RADIANS5).scale(scale5 / height);
13201
12955
  super({
13202
12956
  ...opts,
13203
12957
  // x, y, width,
@@ -13217,6 +12971,8 @@ void main(void) {
13217
12971
  this.scale = scale5;
13218
12972
  this.latitude = latitude;
13219
12973
  this.longitude = longitude;
12974
+ this.bearing = bearing;
12975
+ this.pitch = pitch;
13220
12976
  this.fovy = fovy;
13221
12977
  this.resolution = resolution;
13222
12978
  }
@@ -13306,14 +13062,17 @@ void main(void) {
13306
13062
  const rotationSpeed = 0.25 / scale5;
13307
13063
  const longitude = startLng + rotationSpeed * (startPixel[0] - pixel[0]);
13308
13064
  let latitude = startLat - rotationSpeed * (startPixel[1] - pixel[1]);
13309
- latitude = Math.max(Math.min(latitude, MAX_LATITUDE), -MAX_LATITUDE);
13065
+ latitude = Math.max(Math.min(latitude, 90), -90);
13310
13066
  const out = { longitude, latitude, zoom: startZoom - zoomAdjust(startLat) };
13311
13067
  out.zoom += zoomAdjust(out.latitude);
13312
13068
  return out;
13313
13069
  }
13314
13070
  };
13315
13071
  GlobeViewport.displayName = "GlobeViewport";
13316
- function zoomAdjust(latitude) {
13072
+ function zoomAdjust(latitude, clampToPoles) {
13073
+ if (clampToPoles) {
13074
+ latitude = Math.max(Math.min(latitude, MAX_LATITUDE), -MAX_LATITUDE);
13075
+ }
13317
13076
  const scaleAdjust = Math.PI * Math.cos(latitude * Math.PI / 180);
13318
13077
  return Math.log2(scaleAdjust);
13319
13078
  }
@@ -13400,6 +13159,7 @@ void main(void) {
13400
13159
  PINCH: ["pinchstart", "pinchmove", "pinchend"],
13401
13160
  MULTI_PAN: ["multipanstart", "multipanmove", "multipanend"],
13402
13161
  DOUBLE_CLICK: ["dblclick"],
13162
+ DOUBLE_CLICK_DRAG: ["dblclickdragstart", "dblclickdragmove", "dblclickdragend", "dblclickdragcancel"],
13403
13163
  KEYBOARD: ["keydown"]
13404
13164
  };
13405
13165
  var pinchEventWorkaround = {};
@@ -13413,6 +13173,10 @@ void main(void) {
13413
13173
  this._customEvents = [];
13414
13174
  this._eventStartBlocked = null;
13415
13175
  this._panMove = false;
13176
+ this._multiPanMode = null;
13177
+ this._multiPanStartCenter = null;
13178
+ this._doubleClickDragAnchor = null;
13179
+ this._suppressDoubleClickUntil = 0;
13416
13180
  this.invertPan = false;
13417
13181
  this.dragMode = "rotate";
13418
13182
  this.inertia = 0;
@@ -13420,8 +13184,11 @@ void main(void) {
13420
13184
  this.dragPan = true;
13421
13185
  this.dragRotate = true;
13422
13186
  this.doubleClickZoom = true;
13187
+ this.doubleClickDragZoom = true;
13423
13188
  this.touchZoom = true;
13424
13189
  this.touchRotate = false;
13190
+ this.multiTouchDrag = null;
13191
+ this.trackpadGesture = false;
13425
13192
  this.keyboard = true;
13426
13193
  this.transitionManager = new TransitionManager({
13427
13194
  ...opts,
@@ -13468,11 +13235,11 @@ void main(void) {
13468
13235
  case "panend":
13469
13236
  return this._onPanEnd(event);
13470
13237
  case "pinchstart":
13471
- return eventStartBlocked ? false : this._onPinchStart(event);
13238
+ return eventStartBlocked || !this._isTrackpadGestureAllowed(event) ? false : this._onPinchStart(event);
13472
13239
  case "pinchmove":
13473
- return this._onPinch(event);
13240
+ return this._isTrackpadGestureAllowed(event) ? this._onPinch(event) : false;
13474
13241
  case "pinchend":
13475
- return this._onPinchEnd(event);
13242
+ return this._isTrackpadGestureAllowed(event) ? this._onPinchEnd(event) : false;
13476
13243
  case "multipanstart":
13477
13244
  return eventStartBlocked ? false : this._onMultiPanStart(event);
13478
13245
  case "multipanmove":
@@ -13481,6 +13248,13 @@ void main(void) {
13481
13248
  return this._onMultiPanEnd(event);
13482
13249
  case "dblclick":
13483
13250
  return this._onDoubleClick(event);
13251
+ case "dblclickdragstart":
13252
+ return eventStartBlocked ? false : this._onDoubleClickDragStart(event);
13253
+ case "dblclickdragmove":
13254
+ return this._onDoubleClickDrag(event);
13255
+ case "dblclickdragend":
13256
+ case "dblclickdragcancel":
13257
+ return this._onDoubleClickDragEnd(event);
13484
13258
  case "wheel":
13485
13259
  return this._onWheel(event);
13486
13260
  case "keydown":
@@ -13553,23 +13327,33 @@ void main(void) {
13553
13327
  dragPan = true,
13554
13328
  dragRotate = true,
13555
13329
  doubleClickZoom = true,
13330
+ doubleClickDragZoom = false,
13556
13331
  touchZoom = true,
13557
13332
  touchRotate = false,
13333
+ multiTouchDrag = touchRotate ? "rotate" : null,
13334
+ trackpadGesture = false,
13558
13335
  keyboard = true
13559
13336
  } = props;
13560
13337
  const isInteractive = Boolean(this.onViewStateChange);
13561
13338
  this.toggleEvents(EVENT_TYPES.WHEEL, isInteractive && scrollZoom);
13562
13339
  this.toggleEvents(EVENT_TYPES.PAN, isInteractive);
13563
- this.toggleEvents(EVENT_TYPES.PINCH, isInteractive && (touchZoom || touchRotate));
13564
- this.toggleEvents(EVENT_TYPES.MULTI_PAN, isInteractive && touchRotate);
13340
+ this.toggleEvents(
13341
+ EVENT_TYPES.PINCH,
13342
+ isInteractive && (touchZoom || multiTouchDrag === "rotate")
13343
+ );
13344
+ this.toggleEvents(EVENT_TYPES.MULTI_PAN, isInteractive && Boolean(multiTouchDrag));
13565
13345
  this.toggleEvents(EVENT_TYPES.DOUBLE_CLICK, isInteractive && doubleClickZoom);
13346
+ this.toggleEvents(EVENT_TYPES.DOUBLE_CLICK_DRAG, isInteractive && doubleClickDragZoom);
13566
13347
  this.toggleEvents(EVENT_TYPES.KEYBOARD, isInteractive && keyboard);
13567
13348
  this.scrollZoom = scrollZoom;
13568
13349
  this.dragPan = dragPan;
13569
13350
  this.dragRotate = dragRotate;
13570
13351
  this.doubleClickZoom = doubleClickZoom;
13352
+ this.doubleClickDragZoom = doubleClickDragZoom;
13571
13353
  this.touchZoom = touchZoom;
13572
- this.touchRotate = touchRotate;
13354
+ this.touchRotate = multiTouchDrag === "rotate";
13355
+ this.multiTouchDrag = multiTouchDrag;
13356
+ this.trackpadGesture = trackpadGesture;
13573
13357
  this.keyboard = keyboard;
13574
13358
  const dimensionChanged = !oldProps || oldProps.height !== props.height || oldProps.width !== props.width || oldProps.maxBounds !== props.maxBounds;
13575
13359
  if (dimensionChanged && props.maxBounds) {
@@ -13744,6 +13528,9 @@ void main(void) {
13744
13528
  if (!this.scrollZoom) {
13745
13529
  return false;
13746
13530
  }
13531
+ if (this.trackpadGesture && event.device !== "mouse") {
13532
+ return false;
13533
+ }
13747
13534
  const pos = this.getCenter(event);
13748
13535
  if (!this.isPointInBounds(pos, event)) {
13749
13536
  return false;
@@ -13771,63 +13558,77 @@ void main(void) {
13771
13558
  return true;
13772
13559
  }
13773
13560
  _onMultiPanStart(event) {
13774
- const pos = this.getCenter(event);
13775
- if (!this.isPointInBounds(pos, event)) {
13561
+ const { multiTouchDrag } = this;
13562
+ if (!multiTouchDrag || !this._isMultiPanEventAllowed(event, multiTouchDrag)) {
13563
+ return false;
13564
+ }
13565
+ const currentCenter = event.offsetCenter;
13566
+ if (!this.isPointInBounds(this.getCenter(event), event)) {
13776
13567
  return false;
13777
13568
  }
13778
- const newControllerState = this.controllerState.rotateStart({ pos });
13569
+ const isTrackpad = event.pointerType === "trackpad";
13570
+ const startCenter = {
13571
+ x: currentCenter.x - (isTrackpad ? 0 : event.deltaX),
13572
+ y: currentCenter.y - (isTrackpad ? 0 : event.deltaY)
13573
+ };
13574
+ const startEvent = { ...event, offsetCenter: startCenter };
13575
+ const pos = this.getCenter(startEvent);
13576
+ const newControllerState = multiTouchDrag === "pan" ? this.controllerState.panStart({ pos }) : this.controllerState.rotateStart({ pos });
13577
+ this._multiPanMode = multiTouchDrag;
13578
+ this._multiPanStartCenter = startCenter;
13779
13579
  this.updateViewport(newControllerState, NO_TRANSITION_PROPS, { isDragging: true });
13780
13580
  return true;
13781
13581
  }
13782
13582
  _onMultiPan(event) {
13783
- if (!this.touchRotate) {
13583
+ const { mode, event: panEvent } = this._getMultiPanEvent(event);
13584
+ if (!mode || !panEvent || !this.isDragging()) {
13784
13585
  return false;
13785
13586
  }
13786
- if (!this.isDragging()) {
13787
- return false;
13788
- }
13789
- const pos = this.getCenter(event);
13790
- pos[0] -= event.deltaX;
13791
- const newControllerState = this.controllerState.rotate({ pos });
13792
- this.updateViewport(newControllerState, NO_TRANSITION_PROPS, {
13793
- isDragging: true,
13794
- isRotating: true
13795
- });
13796
- return true;
13587
+ return mode === "pan" ? this._onPanMove(panEvent) : this._onPanRotate(panEvent);
13797
13588
  }
13798
13589
  _onMultiPanEnd(event) {
13799
- if (!this.isDragging()) {
13590
+ const { mode, event: panEvent } = this._getMultiPanEvent(event);
13591
+ if (!mode || !panEvent || !this.isDragging()) {
13592
+ this._resetMultiPan();
13800
13593
  return false;
13801
13594
  }
13802
- const { inertia } = this;
13803
- if (this.touchRotate && inertia && event.velocityY) {
13804
- const pos = this.getCenter(event);
13805
- const endPos = [pos[0], pos[1] += event.velocityY * inertia / 2];
13806
- const newControllerState = this.controllerState.rotate({ pos: endPos });
13807
- this.updateViewport(
13808
- newControllerState,
13809
- {
13810
- ...this._getTransitionProps(),
13811
- transitionDuration: inertia,
13812
- transitionEasing: INERTIA_EASING
13813
- },
13814
- {
13815
- isDragging: false,
13816
- isRotating: true
13817
- }
13818
- );
13819
- this.blockEvents(inertia);
13820
- } else {
13821
- const newControllerState = this.controllerState.rotateEnd();
13822
- this.updateViewport(newControllerState, null, {
13823
- isDragging: false,
13824
- isRotating: false
13825
- });
13595
+ const handled = mode === "pan" ? this._onPanMoveEnd(panEvent) : this._onPanRotateEnd(panEvent);
13596
+ this._resetMultiPan();
13597
+ return handled;
13598
+ }
13599
+ _isTrackpadGestureAllowed(event) {
13600
+ return event.pointerType !== "trackpad" || this.trackpadGesture;
13601
+ }
13602
+ _isMultiPanEventAllowed(event, mode) {
13603
+ if (event.pointerType === "trackpad") {
13604
+ return this.trackpadGesture && (mode === "pan" ? this.dragPan : this.dragRotate);
13826
13605
  }
13827
- return true;
13606
+ return event.pointerType === "touch" && (mode === "pan" ? this.dragPan : this.dragRotate);
13607
+ }
13608
+ _getMultiPanEvent(event) {
13609
+ const mode = this._multiPanMode;
13610
+ const startCenter = this._multiPanStartCenter;
13611
+ if (!mode || !startCenter) {
13612
+ return { mode: null, event: null };
13613
+ }
13614
+ return {
13615
+ mode,
13616
+ event: {
13617
+ ...event,
13618
+ offsetCenter: {
13619
+ x: startCenter.x + event.deltaX,
13620
+ y: startCenter.y + event.deltaY
13621
+ }
13622
+ }
13623
+ };
13624
+ }
13625
+ _resetMultiPan() {
13626
+ this._multiPanMode = null;
13627
+ this._multiPanStartCenter = null;
13828
13628
  }
13829
13629
  // Default handler for the `pinchstart` event.
13830
13630
  _onPinchStart(event) {
13631
+ this._doubleClickDragAnchor = null;
13831
13632
  const pos = this.getCenter(event);
13832
13633
  if (!this.isPointInBounds(pos, event)) {
13833
13634
  return false;
@@ -13913,6 +13714,9 @@ void main(void) {
13913
13714
  if (!this.doubleClickZoom) {
13914
13715
  return false;
13915
13716
  }
13717
+ if (Date.now() < this._suppressDoubleClickUntil) {
13718
+ return false;
13719
+ }
13916
13720
  const pos = this.getCenter(event);
13917
13721
  if (!this.isPointInBounds(pos, event)) {
13918
13722
  return false;
@@ -13926,6 +13730,56 @@ void main(void) {
13926
13730
  this.blockEvents(100);
13927
13731
  return true;
13928
13732
  }
13733
+ _onDoubleClickDragStart(event) {
13734
+ if (!this.doubleClickDragZoom) {
13735
+ this._doubleClickDragAnchor = null;
13736
+ return false;
13737
+ }
13738
+ const pos = this.getCenter(event);
13739
+ if (!this.isPointInBounds(pos, event)) {
13740
+ this._doubleClickDragAnchor = null;
13741
+ return false;
13742
+ }
13743
+ this._doubleClickDragAnchor = pos;
13744
+ let newControllerState = this.controllerState.zoomStart({ pos });
13745
+ if (event.scale !== 1) {
13746
+ newControllerState = newControllerState.zoom({ pos, scale: event.scale });
13747
+ }
13748
+ this.updateViewport(newControllerState, NO_TRANSITION_PROPS, {
13749
+ isDragging: true,
13750
+ isPanning: true,
13751
+ isZooming: true
13752
+ });
13753
+ return true;
13754
+ }
13755
+ _onDoubleClickDrag(event) {
13756
+ const pos = this._doubleClickDragAnchor;
13757
+ if (!pos) {
13758
+ return false;
13759
+ }
13760
+ const newControllerState = this.controllerState.zoom({ pos, scale: event.scale });
13761
+ this.updateViewport(newControllerState, NO_TRANSITION_PROPS, {
13762
+ isDragging: true,
13763
+ isPanning: true,
13764
+ isZooming: true
13765
+ });
13766
+ return true;
13767
+ }
13768
+ _onDoubleClickDragEnd(_event) {
13769
+ if (!this._doubleClickDragAnchor) {
13770
+ return false;
13771
+ }
13772
+ this._doubleClickDragAnchor = null;
13773
+ const newControllerState = this.controllerState.zoomEnd();
13774
+ this.updateViewport(newControllerState, null, {
13775
+ isDragging: false,
13776
+ isPanning: false,
13777
+ isZooming: false
13778
+ });
13779
+ this._suppressDoubleClickUntil = Date.now() + 100;
13780
+ this.blockEvents(100);
13781
+ return true;
13782
+ }
13929
13783
  // Default handler for the `keydown` event
13930
13784
  _onKeyDown(event) {
13931
13785
  if (!this.keyboard) {