@genome-spy/core 0.43.3 → 0.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/bundle/index.es.js +5525 -5259
  2. package/dist/bundle/index.js +153 -104
  3. package/dist/schema.json +412 -43
  4. package/dist/src/data/sources/lazy/axisTickSource.d.ts +1 -1
  5. package/dist/src/data/sources/lazy/axisTickSource.d.ts.map +1 -1
  6. package/dist/src/data/sources/lazy/axisTickSource.js +2 -2
  7. package/dist/src/data/sources/lazy/bigWigSource.d.ts +6 -0
  8. package/dist/src/data/sources/lazy/bigWigSource.d.ts.map +1 -1
  9. package/dist/src/data/sources/lazy/bigWigSource.js +3 -5
  10. package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts +1 -1
  11. package/dist/src/data/sources/lazy/singleAxisLazySource.d.ts.map +1 -1
  12. package/dist/src/data/sources/lazy/singleAxisLazySource.js +1 -1
  13. package/dist/src/data/sources/lazy/singleAxisWindowedSource.d.ts +7 -12
  14. package/dist/src/data/sources/lazy/singleAxisWindowedSource.d.ts.map +1 -1
  15. package/dist/src/data/sources/lazy/singleAxisWindowedSource.js +33 -29
  16. package/dist/src/data/transforms/filterScoredLabels.js +1 -1
  17. package/dist/src/encoder/encoder.d.ts.map +1 -1
  18. package/dist/src/encoder/encoder.js +16 -6
  19. package/dist/src/genomeSpy.d.ts +1 -0
  20. package/dist/src/genomeSpy.d.ts.map +1 -1
  21. package/dist/src/genomeSpy.js +108 -6
  22. package/dist/src/gl/glslScaleGenerator.d.ts +23 -3
  23. package/dist/src/gl/glslScaleGenerator.d.ts.map +1 -1
  24. package/dist/src/gl/glslScaleGenerator.js +137 -42
  25. package/dist/src/gl/webGLHelper.d.ts.map +1 -1
  26. package/dist/src/gl/webGLHelper.js +5 -7
  27. package/dist/src/marks/link.common.glsl.js +2 -0
  28. package/dist/src/marks/link.d.ts.map +1 -1
  29. package/dist/src/marks/link.js +19 -9
  30. package/dist/src/marks/link.vertex.glsl.js +1 -1
  31. package/dist/src/marks/mark.d.ts +19 -17
  32. package/dist/src/marks/mark.d.ts.map +1 -1
  33. package/dist/src/marks/mark.js +181 -120
  34. package/dist/src/marks/point.common.glsl.js +1 -1
  35. package/dist/src/marks/rect.common.glsl.js +2 -0
  36. package/dist/src/marks/rect.d.ts.map +1 -1
  37. package/dist/src/marks/rect.js +12 -12
  38. package/dist/src/marks/rect.vertex.glsl.js +1 -1
  39. package/dist/src/marks/rule.common.glsl.js +1 -1
  40. package/dist/src/marks/rule.js +2 -2
  41. package/dist/src/marks/text.common.glsl.js +1 -1
  42. package/dist/src/marks/text.js +2 -2
  43. package/dist/src/paramBroker.d.ts +19 -3
  44. package/dist/src/paramBroker.d.ts.map +1 -1
  45. package/dist/src/paramBroker.js +18 -2
  46. package/dist/src/spec/channel.d.ts +4 -3
  47. package/dist/src/spec/mark.d.ts +17 -25
  48. package/dist/src/spec/parameter.d.ts +123 -0
  49. package/dist/src/spec/root.d.ts +9 -0
  50. package/dist/src/spec/scale.d.ts +2 -1
  51. package/dist/src/spec/view.d.ts +1 -1
  52. package/dist/src/types/scaleResolutionApi.d.ts +7 -3
  53. package/dist/src/utils/expression.d.ts +2 -2
  54. package/dist/src/utils/expression.d.ts.map +1 -1
  55. package/dist/src/utils/expression.js +3 -3
  56. package/dist/src/view/axisView.js +3 -3
  57. package/dist/src/view/scaleResolution.d.ts +8 -18
  58. package/dist/src/view/scaleResolution.d.ts.map +1 -1
  59. package/dist/src/view/scaleResolution.js +220 -126
  60. package/dist/src/view/scaleResolution.test.js +7 -7
  61. package/dist/src/view/unitView.d.ts.map +1 -1
  62. package/dist/src/view/unitView.js +10 -3
  63. package/dist/src/view/view.js +2 -2
  64. package/package.json +2 -2
@@ -18,6 +18,8 @@ import {
18
18
  } from "../encoder/encoder.js";
19
19
  import { asArray, peek } from "../utils/arrayUtils.js";
20
20
  import { InternMap } from "internmap";
21
+ import { isExprRef } from "../marks/mark.js";
22
+ import scaleNull from "../utils/scaleNull.js";
21
23
 
22
24
  export const ATTRIBUTE_PREFIX = "attr_";
23
25
  export const DOMAIN_PREFIX = "uDomain_";
@@ -50,11 +52,12 @@ function splitScaleType(type) {
50
52
  }
51
53
 
52
54
  /**
55
+ * Generates GLSL code for a constant value.
53
56
  *
54
57
  * @param {Channel} channel
55
58
  * @param {number | number[] | string | boolean} value
56
59
  */
57
- export function generateValueGlsl(channel, value) {
60
+ export function generateConstantValueGlsl(channel, value) {
58
61
  /** @type {VectorizedValue} */
59
62
  let vec;
60
63
  if (isDiscreteChannel(channel)) {
@@ -81,8 +84,6 @@ export function generateValueGlsl(channel, value) {
81
84
  vec = vectorize(value);
82
85
  }
83
86
 
84
- // These could also be passed as uniforms because GPU drivers often handle
85
- // uniforms as constants and recompile the shader to eliminate dead code etc.
86
87
  let glsl = `
87
88
  #define ${channel}_DEFINED
88
89
  ${vec.type} ${SCALED_FUNCTION_PREFIX}${channel}() {
@@ -93,16 +94,52 @@ ${vec.type} ${SCALED_FUNCTION_PREFIX}${channel}() {
93
94
  }
94
95
 
95
96
  /**
97
+ * Generates GLSL code for a dynamic, parameter-driven values. These are mainly
98
+ * used as dynamic mark properties that map to encoding channels.
96
99
  *
97
100
  * @param {Channel} channel
98
- * @param {any} scale TODO: typing
101
+ */
102
+ export function generateDynamicValueGlslAndUniform(channel) {
103
+ let dataType = "float";
104
+ /** @type {(x: any) => any} */
105
+ let adjuster = (x) => x;
106
+
107
+ if (isColorChannel(channel)) {
108
+ dataType = "vec3";
109
+ adjuster = (x) => cssColorToArray(x);
110
+ }
111
+
112
+ const uniformName = `u${capitalize(channel)}`;
113
+
114
+ const uniformGlsl = ` // Dynamic value\n uniform ${dataType} ${uniformName};`;
115
+
116
+ let scaleGlsl = `
117
+ #define ${channel}_DEFINED
118
+ ${dataType} ${SCALED_FUNCTION_PREFIX}${channel}() {
119
+ // Dynamic value
120
+ return ${uniformName};
121
+ }`;
122
+
123
+ return {
124
+ channel,
125
+ uniformName,
126
+ uniformGlsl,
127
+ scaleGlsl,
128
+ adjuster,
129
+ };
130
+ }
131
+
132
+ /**
133
+ *
134
+ * @param {Channel} channel
135
+ * @param {import("../view/scaleResolution.js").default} scaleResolution TODO: typing
99
136
  * @param {import("../spec/channel.js").ChannelDef} channelDef
100
137
  * @param {Channel[]} [sharedQuantitativeChannels] Channels that share the same quantitative field
101
138
  */
102
139
  // eslint-disable-next-line complexity
103
140
  export function generateScaleGlsl(
104
141
  channel,
105
- scale,
142
+ scaleResolution,
106
143
  channelDef,
107
144
  sharedQuantitativeChannels = [channel]
108
145
  ) {
@@ -112,9 +149,11 @@ export function generateScaleGlsl(
112
149
  );
113
150
  }
114
151
 
115
- if (!scale) {
116
- throw new Error("Scale is undefined");
117
- }
152
+ /**
153
+ * Typecast to any to make it easier to handle all the different scale variants
154
+ * @type {any}
155
+ */
156
+ const scale = scaleResolution ? scaleResolution.scale : scaleNull();
118
157
 
119
158
  const primary = getPrimaryChannel(channel);
120
159
  const attributeName =
@@ -243,24 +282,35 @@ export function generateScaleGlsl(
243
282
  );
244
283
  }
245
284
 
246
- // N.B. Interpolating scales require unit range
247
- // TODO: Reverse
248
- const range =
249
- isInterpolating(scale.type) ||
250
- (isContinuous(scale.type) && isColorChannel(channel))
251
- ? [0, 1]
252
- : scale.range
253
- ? scale.range()
254
- : undefined;
255
-
256
- if (range && channel == primary && range.length && range.every(isNumber)) {
257
- const vectorizedRange = vectorizeRange(range);
258
-
259
- // Range needs no runtime adjustment (at least for now). Thus, pass it as a constant that the
260
- // GLSL compiler can optimize away in the case of unit ranges.
261
- glsl.push(
262
- `const ${vectorizedRange.type} ${rangeName} = ${vectorizedRange};`
263
- );
285
+ const range = getRangeForGlsl(scale, channel);
286
+
287
+ /** @type {string} */
288
+ let rangeUniform;
289
+
290
+ if (range && channel == primary) {
291
+ const rangeProp = scale.props.range ?? [];
292
+ // Maybe the scale could be annotated with a "dynamicRange" property or something
293
+ if (isExprRef(rangeProp) || rangeProp.some(isExprRef)) {
294
+ // TODO: should check that we don't have an ordinal range here as it should be
295
+ // handled using a texture.
296
+ if (range.length < 1 || range.length > 4) {
297
+ // TODO: Use an array instead of (float|vec[234]). This is likely to be a rare case, however.
298
+ throw new Error(
299
+ `A range with ExprRefs must have 1-4 elements, not ${
300
+ range.length
301
+ }! Range: ${JSON.stringify(range)}`
302
+ );
303
+ }
304
+ rangeUniform = ` uniform ${getFloatVectorType(
305
+ range.length
306
+ )} ${rangeName};`;
307
+ } else if (range.length && range.every(isNumber)) {
308
+ const vectorizedRange = vectorizeRange(range);
309
+
310
+ glsl.push(
311
+ `const ${vectorizedRange.type} ${rangeName} = ${vectorizedRange};`
312
+ );
313
+ }
264
314
  }
265
315
 
266
316
  const returnType = isColorChannel(channel) ? "vec3" : "float";
@@ -290,9 +340,9 @@ export function generateScaleGlsl(
290
340
  interpolate = `getDiscreteColor(${textureUniformName}, int(transformed)).r`;
291
341
  }
292
342
 
293
- const attributeGlsl = isDatumDef(channelDef)
294
- ? `uniform highp ${attributeType} ${attributeName};`
295
- : `in highp ${attributeType} ${attributeName};`;
343
+ const [attributeGlsl, markUniformGlsl] = isDatumDef(channelDef)
344
+ ? [undefined, ` uniform highp ${attributeType} ${attributeName};`]
345
+ : [`in highp ${attributeType} ${attributeName};`, undefined];
296
346
 
297
347
  /** @type {string[]} Channel's scale function*/
298
348
  const scaleBody = [];
@@ -374,14 +424,20 @@ ${returnType} ${SCALED_FUNCTION_PREFIX}${channel}() {
374
424
  ? domainLength
375
425
  : 2;
376
426
  domainUniform = hp
377
- ? `highp vec3 ${domainUniformName};`
378
- : `mediump float ${domainUniformName}[${length}];`;
427
+ ? ` highp vec3 ${domainUniformName};`
428
+ : ` mediump float ${domainUniformName}[${length}];`;
379
429
  }
380
430
 
381
431
  return {
432
+ attributeName,
382
433
  attributeGlsl,
434
+ // Ends up in the Mark uniform block
435
+ markUniformGlsl,
383
436
  glsl: concatenated,
437
+ domainUniformName,
384
438
  domainUniform,
439
+ rangeName,
440
+ rangeUniform,
385
441
  };
386
442
  }
387
443
 
@@ -426,26 +482,43 @@ function vectorize(value) {
426
482
  throw new Error("Invalid number of components: " + numComponents);
427
483
  }
428
484
 
429
- let type;
430
- let str;
485
+ const type = getFloatVectorType(numComponents);
486
+ const str = `${type}(${value.map(toDecimal).join(", ")})`;
431
487
 
432
- if (numComponents > 1) {
433
- type = `vec${numComponents}`;
434
- str = `${type}(${value.map(toDecimal).join(", ")})`;
435
- } else {
436
- type = "float";
437
- str = toDecimal(value[0]);
488
+ return Object.assign(str, { type, numComponents });
489
+ }
490
+
491
+ /**
492
+ * @param {number} numComponents
493
+ */
494
+ function getFloatVectorType(numComponents) {
495
+ switch (numComponents) {
496
+ case 1:
497
+ return "float";
498
+ case 2:
499
+ return "vec2";
500
+ case 3:
501
+ return "vec3";
502
+ case 4:
503
+ return "vec4";
504
+ default:
505
+ throw new Error("Invalid number of components: " + numComponents);
438
506
  }
507
+ }
439
508
 
440
- return Object.assign(str, { type, numComponents });
509
+ /**
510
+ * @param {string} color
511
+ */
512
+ function cssColorToArray(color) {
513
+ const rgb = d3color(color).rgb();
514
+ return [rgb.r, rgb.g, rgb.b].map((x) => x / 255);
441
515
  }
442
516
 
443
517
  /**
444
518
  * @param {string} color
445
519
  */
446
520
  function vectorizeCssColor(color) {
447
- const rgb = d3color(color).rgb();
448
- return vectorize([rgb.r, rgb.g, rgb.b].map((x) => x / 255));
521
+ return vectorize(cssColorToArray(color));
449
522
  }
450
523
 
451
524
  /**
@@ -591,3 +664,25 @@ export function dedupeEncodingFields(encoders) {
591
664
  export function makeAttributeName(channel) {
592
665
  return asArray(channel).join("_");
593
666
  }
667
+
668
+ /**
669
+ * @param {string} str
670
+ */
671
+ function capitalize(str) {
672
+ return str[0].toUpperCase() + str.slice(1);
673
+ }
674
+
675
+ /**
676
+ * N.B. Interpolating scales require unit range
677
+ * TODO: Reverse
678
+ * @param {any} scale
679
+ * @param {Channel} channel
680
+ * @returns {number[]}
681
+ */
682
+ export const getRangeForGlsl = (scale, channel) =>
683
+ isInterpolating(scale.type) ||
684
+ (isContinuous(scale.type) && isColorChannel(channel))
685
+ ? [0, 1]
686
+ : scale.range
687
+ ? scale.range()
688
+ : undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"webGLHelper.d.ts","sourceRoot":"","sources":["../../../src/gl/webGLHelper.js"],"names":[],"mappings":"AA8ZA;;;;GAIG;AACH,kCAJW,sBAAsB,gBACtB,WAAW,kBACX,WAAW;;;;;;EA8CrB;AAED;;;;;GAKG;AACH,0CALW,qBAAqB,WACrB,KAAK,OAAO,SAAS,EAAE,cAAc,EAAE,KAAK,CAAC,OAC7C,MAAM,EAAE,GAAG,eAAe,YAC1B,YAAY,gBAYtB;AAncD;IACI;;;;;;;OAOG;IACH,uBANW,WAAW,eACX,MAAM;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,eAGrC,MAAM,EAmFhB;IAhFG,wBAA2B;IAC3B;;;MAKO;IAEP,uCAAuC;IACvC,cADW,IAAI,MAAM,EAAE,WAAW,CAAC,CACN;IAE7B,kFAAkF;IAClF,eADW,QAAQ,OAAO,4BAA4B,EAAE,OAAO,EAAE,YAAY,CAAC,CAC5C;IAuClC,0BAAoB;IACpB,2BAAY;IAGZ,oDAAoD;IACpD,2BADW,OAAO,SAAS,EAAE,iBAAiB,EAAE,CAQ/C;IACD,sDAGC;IAOD,+CAA+C;IAC/C,aADW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CACZ;IAOnC,uBAIC;IAHG;;;MAAmC;IAKvC,mBAEC;IADG,YAAkC;IAGtC;;;;;OAKG;IACH,oBAHW,MAAM,QACN,MAAM,GAAG,MAAM,EAAE,eA2B3B;IAED,iBAcC;IAED,iBAEC;IAED;;;;OAIG;IACH,oCAFW;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;;;MAQ3C;IAED;;OAEG;IACH;;;MAuBC;IAED;;;;OAIG;IACH,oBAHW,MAAM,KACN,MAAM,cAwBhB;IAED,iBAOC;IAED;;;;;;;;;OASG;IACH,+BAHW,OAAO,4BAA4B,EAAE,OAAO,WAC5C,OAAO,QA4GjB;CACJ"}
1
+ {"version":3,"file":"webGLHelper.d.ts","sourceRoot":"","sources":["../../../src/gl/webGLHelper.js"],"names":[],"mappings":"AA4ZA;;;;GAIG;AACH,kCAJW,sBAAsB,gBACtB,WAAW,kBACX,WAAW;;;;;;EA8CrB;AAED;;;;;GAKG;AACH,0CALW,qBAAqB,WACrB,KAAK,OAAO,SAAS,EAAE,cAAc,EAAE,KAAK,CAAC,OAC7C,MAAM,EAAE,GAAG,eAAe,YAC1B,YAAY,gBAYtB;AAjcD;IACI;;;;;;;OAOG;IACH,uBANW,WAAW,eACX,MAAM;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,eAGrC,MAAM,EAmFhB;IAhFG,wBAA2B;IAC3B;;;MAKO;IAEP,uCAAuC;IACvC,cADW,IAAI,MAAM,EAAE,WAAW,CAAC,CACN;IAE7B,kFAAkF;IAClF,eADW,QAAQ,OAAO,4BAA4B,EAAE,OAAO,EAAE,YAAY,CAAC,CAC5C;IAuClC,0BAAoB;IACpB,2BAAY;IAGZ,oDAAoD;IACpD,2BADW,OAAO,SAAS,EAAE,iBAAiB,EAAE,CAQ/C;IACD,sDAGC;IAOD,+CAA+C;IAC/C,aADW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CACZ;IAOnC,uBAIC;IAHG;;;MAAmC;IAKvC,mBAEC;IADG,YAAkC;IAGtC;;;;;OAKG;IACH,oBAHW,MAAM,QACN,MAAM,GAAG,MAAM,EAAE,eA2B3B;IAED,iBAcC;IAED,iBAEC;IAED;;;;OAIG;IACH,oCAFW;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;;;MAQ3C;IAED;;OAEG;IACH;;;MAuBC;IAED;;;;OAIG;IACH,oBAHW,MAAM,KACN,MAAM,cAwBhB;IAED,iBAOC;IAED;;;;;;;;;OASG;IACH,+BAHW,OAAO,4BAA4B,EAAE,OAAO,WAC5C,OAAO,QA0GjB;CACJ"}
@@ -301,9 +301,9 @@ export default class WebGLHelper {
301
301
  const channel = resolution.channel;
302
302
 
303
303
  if (isColorChannel(channel)) {
304
- const props = resolution.getScaleProps();
304
+ const scale = resolution.scale;
305
+ const props = scale.props;
305
306
 
306
- const scale = resolution.getScale();
307
307
  const range = /** @type {any[]} */ (scale.range());
308
308
 
309
309
  /** @type {WebGLTexture} */
@@ -336,7 +336,7 @@ export default class WebGLHelper {
336
336
  // Interpolating
337
337
  isInterpolating(scale.type) ||
338
338
  // Or piecewise
339
- (isContinuous(scale.type) && range.length > 2)
339
+ (isContinuous(scale.type) && range.length > 1)
340
340
  ) {
341
341
  texture = createInterpolatedColorTexture(
342
342
  range,
@@ -355,7 +355,7 @@ export default class WebGLHelper {
355
355
 
356
356
  this.rangeTextures.set(resolution, texture);
357
357
  } else {
358
- const scale = resolution.getScale();
358
+ const scale = resolution.scale;
359
359
 
360
360
  if (scale.type === "ordinal" || isDiscretizing(scale.type)) {
361
361
  /** @type {function(any):number} Handle "shape" etc */
@@ -363,9 +363,7 @@ export default class WebGLHelper {
363
363
  ? getDiscreteRangeMapper(channel)
364
364
  : (x) => x;
365
365
 
366
- const range = /** @type {any[]} */ (
367
- resolution.getScale().range()
368
- );
366
+ const range = /** @type {any[]} */ (scale.range());
369
367
 
370
368
  this.rangeTextures.set(
371
369
  resolution,
@@ -0,0 +1,2 @@
1
+ const shader = "layout(std140)uniform Mark{uniform float uArcHeightFactor;uniform float uMinArcHeight;uniform float uMinPickingSize;uniform int uShape;uniform int uOrient;uniform bool uClampApex;uniform float uMaxChordLength;uniform vec2 uArcFadingDistance;\n#pragma markUniforms\n};";
2
+ export default shader;
@@ -1 +1 @@
1
- {"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../../src/marks/link.js"],"names":[],"mappings":"AAWA;IA+BQ;;;;;OAKG;IACH,yBAEC;IAmGD;;;;;;MAKC;CAoFR;iBAzOgB,WAAW"}
1
+ {"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../../src/marks/link.js"],"names":[],"mappings":"AAYA;IA+BQ;;;;;OAKG;IACH,yBAEC;IA4GD;;;;;;MAKC;CAoFR;iBAlPgB,WAAW"}
@@ -1,6 +1,7 @@
1
1
  import { setBuffersAndAttributes } from "twgl.js";
2
2
  import VERTEX_SHADER from "./link.vertex.glsl.js";
3
3
  import FRAGMENT_SHADER from "./link.fragment.glsl.js";
4
+ import COMMON_SHADER from "./link.common.glsl.js";
4
5
  import { LinkVertexBuilder } from "../gl/dataToVertices.js";
5
6
 
6
7
  import Mark from "./mark.js";
@@ -98,7 +99,9 @@ export default class LinkMark extends Mark {
98
99
  async initializeGraphics() {
99
100
  await super.initializeGraphics();
100
101
 
101
- this.createAndLinkShaders(VERTEX_SHADER, FRAGMENT_SHADER);
102
+ this.createAndLinkShaders(VERTEX_SHADER, FRAGMENT_SHADER, [
103
+ COMMON_SHADER,
104
+ ]);
102
105
  }
103
106
 
104
107
  finalizeGraphicsInitialization() {
@@ -107,22 +110,29 @@ export default class LinkMark extends Mark {
107
110
 
108
111
  const props = this.properties;
109
112
 
110
- this.registerMarkUniform(
113
+ this.registerMarkUniformValue(
111
114
  "uArcFadingDistance",
112
115
  props.arcFadingDistance,
113
116
  (x) => x || /** @type {[number, number]} */ ([0, 0])
114
117
  );
115
- this.registerMarkUniform("uArcHeightFactor", props.arcHeightFactor);
116
- this.registerMarkUniform("uMinArcHeight", props.minArcHeight);
117
- this.registerMarkUniform("uMinPickingSize", props.minPickingSize);
118
- this.registerMarkUniform("uShape", props.linkShape, (linkShape) =>
118
+ this.registerMarkUniformValue(
119
+ "uArcHeightFactor",
120
+ props.arcHeightFactor
121
+ );
122
+ this.registerMarkUniformValue("uMinArcHeight", props.minArcHeight);
123
+ this.registerMarkUniformValue("uMinPickingSize", props.minPickingSize);
124
+ this.registerMarkUniformValue("uShape", props.linkShape, (linkShape) =>
119
125
  LINK_SHAPES.indexOf(linkShape)
120
126
  );
121
- this.registerMarkUniform("uOrient", props.orient, (orient) =>
127
+ this.registerMarkUniformValue("uOrient", props.orient, (orient) =>
122
128
  ORIENTS.indexOf(orient)
123
129
  );
124
- this.registerMarkUniform("uClampApex", props.clampApex, (x) => !!x);
125
- this.registerMarkUniform("uMaxChordLength", props.maxChordLength);
130
+ this.registerMarkUniformValue(
131
+ "uClampApex",
132
+ props.clampApex,
133
+ (x) => !!x
134
+ );
135
+ this.registerMarkUniformValue("uMaxChordLength", props.maxChordLength);
126
136
  }
127
137
 
128
138
  updateGraphicsData() {
@@ -1,2 +1,2 @@
1
- const shader = "uniform Mark{uniform float uArcHeightFactor;uniform float uMinArcHeight;uniform float uMinPickingSize;uniform int uShape;uniform int uOrient;uniform bool uClampApex;uniform float uMaxChordLength;uniform vec2 uArcFadingDistance;};in vec2 strip;out vec4 vColor;out float vSize;out float vNormalLengthInPixels;const int SHAPE_ARC=0;const int SHAPE_DOME=1;const int SHAPE_DIAGONAL=2;const int SHAPE_LINE=3;const int ORIENT_VERTICAL=0;const int ORIENT_HORIZONTAL=1;float distanceFromLine(vec2 pointOnLine1,vec2 pointOnLine2,vec2 point){vec2 a=point-pointOnLine1;vec2 b=pointOnLine2-pointOnLine1;vec2 proj=dot(a,b)/dot(b,b)*b;return length(a-proj);}bool isInsideViewport(vec2 point,float marginFactor){vec2 margin=uViewportSize*vec2(marginFactor);return point.x>=-margin.x&&point.x<=uViewportSize.x+margin.x&&point.y>=-margin.y&&point.y<=uViewportSize.y+margin.y;}void main(void){float pixelSize=1.0/uDevicePixelRatio;float opacity=getScaled_opacity()*uViewOpacity;vec2 p1,p2,p3,p4;vec2 a=applySampleFacet(vec2(getScaled_x(),getScaled_y()))*uViewportSize;vec2 b=applySampleFacet(vec2(getScaled_x2(),getScaled_y2()))*uViewportSize;if(uShape<=SHAPE_DOME){if(uShape==SHAPE_DOME){vec2 height=vec2(0.0);if(uOrient==ORIENT_VERTICAL){p1=vec2(min(a.x,b.x),b.y);p4=vec2(max(a.x,b.x),b.y);height=vec2(0.0,a.y-b.y);if(uClampApex){if(p4.x>0.0){p1.x=max(p1.x,-p4.x);}if(p1.x<uViewportSize.x){p4.x=min(p4.x,2.0*uViewportSize.x-p1.x);}}}else{p1=vec2(b.x,min(a.y,b.y));p4=vec2(b.x,max(a.y,b.y));height=vec2(a.x-b.x,0.0);if(uClampApex){if(p4.y>0.0){p1.y=max(p1.y,-p4.y);}if(p1.y<uViewportSize.y){p4.y=min(p4.y,2.0*uViewportSize.y-p1.y);}}}vec2 controlOffset=height/0.75;p2=p1+controlOffset;p3=p4+controlOffset;}if(uShape==SHAPE_ARC){p1=a;p4=b;vec2 chordVector=p4-p1;vec2 unitChordVector=normalize(chordVector);vec2 chordNormal=vec2(-unitChordVector.y,unitChordVector.x);float chordLength=length(chordVector);if(chordLength>uMaxChordLength){if(isInsideViewport(p1,2.0)){chordLength=uMaxChordLength;p4=p1+unitChordVector*uMaxChordLength;}else if(isInsideViewport(p4,2.0)){chordLength=uMaxChordLength;p1=p4-unitChordVector*uMaxChordLength;}}float height=max(chordLength/2.0*uArcHeightFactor,uMinArcHeight);vec2 controlOffset=chordNormal*height/0.75;p2=p1+controlOffset;p3=p4+controlOffset;}}else if(uShape==SHAPE_DIAGONAL){if(uOrient==ORIENT_VERTICAL){p1=a;p2=vec2(a.x,(a.y+b.y)/2.0);p3=vec2(b.x,(a.y+b.y)/2.0);p4=b;}else{p1=a;p2=vec2((a.x+b.x)/2.0,a.y);p3=vec2((a.x+b.x)/2.0,b.y);p4=b;}}else if(uShape==SHAPE_LINE){p1=a;p2=(a+b)/2.0;p3=p2;p4=b;}float t=smoothstep(0.0,1.0,strip.x);vec2 C1=p4-3.0*p3+3.0*p2-p1;vec2 C2=3.0*p3-6.0*p2+3.0*p1;vec2 C3=3.0*p2-3.0*p1;vec2 C4=p1;vec2 p;if(t==0.0){p=p1;}else if(t==1.0){p=p4;}else{p=C1*t*t*t+C2*t*t+C3*t+C4;}vec2 tangent=normalize(3.0*C1*t*t+2.0*C2*t+C3);vec2 normal=vec2(-tangent.y,tangent.x);float size=getScaled_size();if(size<pixelSize){opacity*=size/pixelSize;size=pixelSize;}float paddedSize=uPickingEnabled? max(size,uMinPickingSize): size+pixelSize;vNormalLengthInPixels=strip.y*paddedSize;if(uShape==SHAPE_ARC&&uArcFadingDistance[0]>0.0&&uArcFadingDistance[1]>0.0){float d=distanceFromLine(p1,p4,p);float distanceOpacity=smoothstep(uArcFadingDistance[1],uArcFadingDistance[0],d);opacity*=distanceOpacity;if(distanceOpacity<=0.0){vNormalLengthInPixels=0.0;}}p+=normal*vNormalLengthInPixels;gl_Position=pixelsToNdc(p);vec3 color=getScaled_color();vColor=vec4(color*opacity,opacity);vSize=paddedSize;setupPicking();}";
1
+ const shader = "in vec2 strip;out vec4 vColor;out float vSize;out float vNormalLengthInPixels;const int SHAPE_ARC=0;const int SHAPE_DOME=1;const int SHAPE_DIAGONAL=2;const int SHAPE_LINE=3;const int ORIENT_VERTICAL=0;const int ORIENT_HORIZONTAL=1;float distanceFromLine(vec2 pointOnLine1,vec2 pointOnLine2,vec2 point){vec2 a=point-pointOnLine1;vec2 b=pointOnLine2-pointOnLine1;vec2 proj=dot(a,b)/dot(b,b)*b;return length(a-proj);}bool isInsideViewport(vec2 point,float marginFactor){vec2 margin=uViewportSize*vec2(marginFactor);return point.x>=-margin.x&&point.x<=uViewportSize.x+margin.x&&point.y>=-margin.y&&point.y<=uViewportSize.y+margin.y;}void main(void){float pixelSize=1.0/uDevicePixelRatio;float opacity=getScaled_opacity()*uViewOpacity;vec2 p1,p2,p3,p4;vec2 a=applySampleFacet(vec2(getScaled_x(),getScaled_y()))*uViewportSize;vec2 b=applySampleFacet(vec2(getScaled_x2(),getScaled_y2()))*uViewportSize;if(uShape<=SHAPE_DOME){if(uShape==SHAPE_DOME){vec2 height=vec2(0.0);if(uOrient==ORIENT_VERTICAL){p1=vec2(min(a.x,b.x),b.y);p4=vec2(max(a.x,b.x),b.y);height=vec2(0.0,a.y-b.y);if(uClampApex){if(p4.x>0.0){p1.x=max(p1.x,-p4.x);}if(p1.x<uViewportSize.x){p4.x=min(p4.x,2.0*uViewportSize.x-p1.x);}}}else{p1=vec2(b.x,min(a.y,b.y));p4=vec2(b.x,max(a.y,b.y));height=vec2(a.x-b.x,0.0);if(uClampApex){if(p4.y>0.0){p1.y=max(p1.y,-p4.y);}if(p1.y<uViewportSize.y){p4.y=min(p4.y,2.0*uViewportSize.y-p1.y);}}}vec2 controlOffset=height/0.75;p2=p1+controlOffset;p3=p4+controlOffset;}if(uShape==SHAPE_ARC){p1=a;p4=b;vec2 chordVector=p4-p1;vec2 unitChordVector=normalize(chordVector);vec2 chordNormal=vec2(-unitChordVector.y,unitChordVector.x);float chordLength=length(chordVector);if(chordLength>uMaxChordLength){if(isInsideViewport(p1,2.0)){chordLength=uMaxChordLength;p4=p1+unitChordVector*uMaxChordLength;}else if(isInsideViewport(p4,2.0)){chordLength=uMaxChordLength;p1=p4-unitChordVector*uMaxChordLength;}}float height=max(chordLength/2.0*uArcHeightFactor,uMinArcHeight);vec2 controlOffset=chordNormal*height/0.75;p2=p1+controlOffset;p3=p4+controlOffset;}}else if(uShape==SHAPE_DIAGONAL){if(uOrient==ORIENT_VERTICAL){p1=a;p2=vec2(a.x,(a.y+b.y)/2.0);p3=vec2(b.x,(a.y+b.y)/2.0);p4=b;}else{p1=a;p2=vec2((a.x+b.x)/2.0,a.y);p3=vec2((a.x+b.x)/2.0,b.y);p4=b;}}else if(uShape==SHAPE_LINE){p1=a;p2=(a+b)/2.0;p3=p2;p4=b;}float t=smoothstep(0.0,1.0,strip.x);vec2 C1=p4-3.0*p3+3.0*p2-p1;vec2 C2=3.0*p3-6.0*p2+3.0*p1;vec2 C3=3.0*p2-3.0*p1;vec2 C4=p1;vec2 p;if(t==0.0){p=p1;}else if(t==1.0){p=p4;}else{p=C1*t*t*t+C2*t*t+C3*t+C4;}vec2 tangent=normalize(3.0*C1*t*t+2.0*C2*t+C3);vec2 normal=vec2(-tangent.y,tangent.x);float size=getScaled_size();if(size<pixelSize){opacity*=size/pixelSize;size=pixelSize;}float paddedSize=uPickingEnabled? max(size,uMinPickingSize): size+pixelSize;vNormalLengthInPixels=strip.y*paddedSize;if(uShape==SHAPE_ARC&&uArcFadingDistance[0]>0.0&&uArcFadingDistance[1]>0.0){float d=distanceFromLine(p1,p4,p);float distanceOpacity=smoothstep(uArcFadingDistance[1],uArcFadingDistance[0],d);opacity*=distanceOpacity;if(distanceOpacity<=0.0){vNormalLengthInPixels=0.0;}}p+=normal*vNormalLengthInPixels;gl_Position=pixelsToNdc(p);vec3 color=getScaled_color();vColor=vec4(color*opacity,opacity);vSize=paddedSize;setupPicking();}";
2
2
  export default shader;
@@ -1,9 +1,9 @@
1
1
  /// <reference types="external-typings/internmap.js" />
2
2
  /**
3
3
  * @param {any} x
4
- * @returns {x is import("../spec/mark.js").ExprRef}
4
+ * @returns {x is import("../spec/parameter.js").ExprRef}
5
5
  */
6
- export function isExprRef(x: any): x is import("../spec/mark.js").ExprRef;
6
+ export function isExprRef(x: any): x is import("../spec/parameter.js").ExprRef;
7
7
  export const SAMPLE_FACET_UNIFORM: "SAMPLE_FACET_UNIFORM";
8
8
  export const SAMPLE_FACET_TEXTURE: "SAMPLE_FACET_TEXTURE";
9
9
  /**
@@ -20,13 +20,6 @@ export const SAMPLE_FACET_TEXTURE: "SAMPLE_FACET_TEXTURE";
20
20
  *
21
21
  */
22
22
  export default class Mark {
23
- /**
24
- * @typedef {import("../spec/mark.js").MarkConfig} MarkConfig
25
- * @typedef {import("../spec/channel.js").Channel} Channel
26
- * @typedef {import("../spec/channel.js").Encoding} Encoding
27
- * @typedef {import("../spec/channel.js").ValueDef} ValueDef
28
- * @typedef {import("../spec/mark.js").ExprRef} ExprRef
29
- */
30
23
  /**
31
24
  * @param {import("../view/unitView.js").default} unitView
32
25
  */
@@ -60,18 +53,18 @@ export default class Mark {
60
53
  protected markUniformsAltered: boolean;
61
54
  /** @type {RangeMap<any>} keep track of facet locations within the vertex array */
62
55
  rangeMap: RangeMap<any>;
63
- /** @type {MarkConfig} */
64
- defaultProperties: import("../spec/mark.js").MarkConfig;
56
+ /** @type {MarkProps} */
57
+ defaultProperties: import("../spec/mark.js").MarkProps;
65
58
  /**
66
59
  * A properties object that contains the configured mark properties or
67
60
  * default values as fallback.
68
61
  *
69
62
  * TODO: Proper and comprehensive typings for mark properties
70
63
  *
71
- * @type {Partial<MarkConfig>}
64
+ * @type {Partial<MarkProps>}
72
65
  * @readonly
73
66
  */
74
- readonly properties: Partial<import("../spec/mark.js").MarkConfig>;
67
+ readonly properties: Partial<import("../spec/mark.js").MarkProps>;
75
68
  get opaque(): boolean;
76
69
  /**
77
70
  * Returns attribute info for WebGL attributes that match visual channels.
@@ -128,8 +121,6 @@ export default class Mark {
128
121
  * @protected
129
122
  */
130
123
  protected createAndLinkShaders(vertexShader: string, fragmentShader: string, extraHeaders?: string[]): void;
131
- /** @type {string[]} */
132
- domainUniforms: string[];
133
124
  programStatus: {
134
125
  program: WebGLProgram;
135
126
  getProgramErrors: () => {
@@ -140,8 +131,19 @@ export default class Mark {
140
131
  /**
141
132
  * Check WebGL shader/program compilation/linking status and finalize
142
133
  * initialization.
134
+ *
135
+ * This is done as a separate step after all shader compilations have been
136
+ * initiated. The idea is to allow for parallel background compilation.
143
137
  */
144
138
  finalizeGraphicsInitialization(): void;
139
+ /**
140
+ * Sets a uniform in the Mark block. Requests a render from the animator.
141
+ *
142
+ * @protected
143
+ * @param {string} uniformName
144
+ * @returns {function(any):void}
145
+ */
146
+ protected createMarkUniformSetter(uniformName: string): (arg0: any) => void;
145
147
  /**
146
148
  * Set a uniform based on a mark property. If the property is an expression,
147
149
  * register a listener to update the uniform when the params referenced by the
@@ -153,8 +155,7 @@ export default class Mark {
153
155
  * @param {T} propValue
154
156
  * @param {(x: Exclude<T, ExprRef>) => any} adjuster
155
157
  */
156
- protected registerMarkUniform<T>(uniformName: string, propValue: T, adjuster?: (x: Exclude<T, import("../spec/mark.js").ExprRef>) => any): void;
157
- _setDatums(): void;
158
+ protected registerMarkUniformValue<T>(uniformName: string, propValue: T, adjuster?: (x: Exclude<T, import("../spec/parameter.js").ExprRef>) => any): void;
158
159
  /**
159
160
  * Delete WebGL buffers etc.
160
161
  */
@@ -233,6 +234,7 @@ export default class Mark {
233
234
  * @returns {any}
234
235
  */
235
236
  findDatumAt(facetId: string, x: import("../spec/channel.js").Scalar): any;
237
+ #private;
236
238
  }
237
239
  export type RenderingOptions = import("../types/rendering.js").RenderingOptions;
238
240
  export type _MarkRenderingOptions = {
@@ -1 +1 @@
1
- {"version":3,"file":"mark.d.ts","sourceRoot":"","sources":["../../../src/marks/mark.js"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mark.d.ts","sourceRoot":"","sources":["../../../src/marks/mark.js"],"names":[],"mappings":"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"}