@genome-spy/core 0.48.2 → 0.50.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 (244) hide show
  1. package/dist/bundle/index.es.js +7434 -7107
  2. package/dist/bundle/index.js +116 -103
  3. package/dist/schema.json +3975 -2819
  4. package/dist/src/data/collector.test.d.ts +2 -0
  5. package/dist/src/data/collector.test.d.ts.map +1 -0
  6. package/dist/src/data/dataFlow.test.d.ts +2 -0
  7. package/dist/src/data/dataFlow.test.d.ts.map +1 -0
  8. package/dist/src/data/flow.test.d.ts +2 -0
  9. package/dist/src/data/flow.test.d.ts.map +1 -0
  10. package/dist/src/data/flow.test.js +19 -14
  11. package/dist/src/data/flowNode.test.d.ts +2 -0
  12. package/dist/src/data/flowNode.test.d.ts.map +1 -0
  13. package/dist/src/data/flowOptimizer.test.d.ts +2 -0
  14. package/dist/src/data/flowOptimizer.test.d.ts.map +1 -0
  15. package/dist/src/data/flowOptimizer.test.js +9 -10
  16. package/dist/src/data/formats/fasta.test.d.ts +2 -0
  17. package/dist/src/data/formats/fasta.test.d.ts.map +1 -0
  18. package/dist/src/data/sources/inlineSource.test.d.ts +2 -0
  19. package/dist/src/data/sources/inlineSource.test.d.ts.map +1 -0
  20. package/dist/src/data/sources/inlineSource.test.js +23 -16
  21. package/dist/src/data/sources/sequenceSource.test.d.ts +2 -0
  22. package/dist/src/data/sources/sequenceSource.test.d.ts.map +1 -0
  23. package/dist/src/data/sources/sequenceSource.test.js +59 -42
  24. package/dist/src/data/transforms/clone.test.d.ts +2 -0
  25. package/dist/src/data/transforms/clone.test.d.ts.map +1 -0
  26. package/dist/src/data/transforms/coverage.test.d.ts +2 -0
  27. package/dist/src/data/transforms/coverage.test.d.ts.map +1 -0
  28. package/dist/src/data/transforms/coverage.test.js +1 -1
  29. package/dist/src/data/transforms/filter.d.ts +10 -0
  30. package/dist/src/data/transforms/filter.d.ts.map +1 -1
  31. package/dist/src/data/transforms/filter.js +30 -1
  32. package/dist/src/data/transforms/filter.test.d.ts +2 -0
  33. package/dist/src/data/transforms/filter.test.d.ts.map +1 -0
  34. package/dist/src/data/transforms/flatten.test.d.ts +2 -0
  35. package/dist/src/data/transforms/flatten.test.d.ts.map +1 -0
  36. package/dist/src/data/transforms/flatten.test.js +10 -7
  37. package/dist/src/data/transforms/flattenDelimited.test.d.ts +2 -0
  38. package/dist/src/data/transforms/flattenDelimited.test.d.ts.map +1 -0
  39. package/dist/src/data/transforms/flattenDelimited.test.js +16 -13
  40. package/dist/src/data/transforms/flattenSequence.test.d.ts +2 -0
  41. package/dist/src/data/transforms/flattenSequence.test.d.ts.map +1 -0
  42. package/dist/src/data/transforms/flattenSequence.test.js +1 -1
  43. package/dist/src/data/transforms/formula.test.d.ts +2 -0
  44. package/dist/src/data/transforms/formula.test.d.ts.map +1 -0
  45. package/dist/src/data/transforms/formula.test.js +1 -1
  46. package/dist/src/data/transforms/identifier.test.d.ts +2 -0
  47. package/dist/src/data/transforms/identifier.test.d.ts.map +1 -0
  48. package/dist/src/data/transforms/pileup.test.d.ts +2 -0
  49. package/dist/src/data/transforms/pileup.test.d.ts.map +1 -0
  50. package/dist/src/data/transforms/project.test.d.ts +2 -0
  51. package/dist/src/data/transforms/project.test.d.ts.map +1 -0
  52. package/dist/src/data/transforms/project.test.js +1 -1
  53. package/dist/src/data/transforms/regexExtract.test.d.ts +2 -0
  54. package/dist/src/data/transforms/regexExtract.test.d.ts.map +1 -0
  55. package/dist/src/data/transforms/regexExtract.test.js +6 -3
  56. package/dist/src/data/transforms/regexFold.test.d.ts +2 -0
  57. package/dist/src/data/transforms/regexFold.test.d.ts.map +1 -0
  58. package/dist/src/data/transforms/sample.test.d.ts +2 -0
  59. package/dist/src/data/transforms/sample.test.d.ts.map +1 -0
  60. package/dist/src/data/transforms/stack.test.d.ts +2 -0
  61. package/dist/src/data/transforms/stack.test.d.ts.map +1 -0
  62. package/dist/src/data/transforms/stack.test.js +8 -8
  63. package/dist/src/encoder/accessor.d.ts +17 -14
  64. package/dist/src/encoder/accessor.d.ts.map +1 -1
  65. package/dist/src/encoder/accessor.js +127 -56
  66. package/dist/src/encoder/accessor.test.d.ts +2 -0
  67. package/dist/src/encoder/accessor.test.d.ts.map +1 -0
  68. package/dist/src/encoder/accessor.test.js +145 -31
  69. package/dist/src/encoder/encoder.d.ts +26 -13
  70. package/dist/src/encoder/encoder.d.ts.map +1 -1
  71. package/dist/src/encoder/encoder.js +98 -114
  72. package/dist/src/encoder/encoder.test.d.ts +2 -0
  73. package/dist/src/encoder/encoder.test.d.ts.map +1 -0
  74. package/dist/src/encoder/encoder.test.js +85 -82
  75. package/dist/src/fonts/bmFontManager.d.ts.map +1 -1
  76. package/dist/src/fonts/bmFontManager.js +10 -4
  77. package/dist/src/genome/genome.test.d.ts +2 -0
  78. package/dist/src/genome/genome.test.d.ts.map +1 -0
  79. package/dist/src/genome/scaleIndex.test.d.ts +2 -0
  80. package/dist/src/genome/scaleIndex.test.d.ts.map +1 -0
  81. package/dist/src/genome/scaleLocus.test.d.ts +2 -0
  82. package/dist/src/genome/scaleLocus.test.d.ts.map +1 -0
  83. package/dist/src/genomeSpy.d.ts +3 -2
  84. package/dist/src/genomeSpy.d.ts.map +1 -1
  85. package/dist/src/genomeSpy.js +15 -6
  86. package/dist/src/gl/dataToVertices.d.ts +6 -8
  87. package/dist/src/gl/dataToVertices.d.ts.map +1 -1
  88. package/dist/src/gl/dataToVertices.js +42 -33
  89. package/dist/src/gl/glslScaleGenerator.d.ts +84 -15
  90. package/dist/src/gl/glslScaleGenerator.d.ts.map +1 -1
  91. package/dist/src/gl/glslScaleGenerator.js +260 -73
  92. package/dist/src/gl/includes/common.glsl.js +1 -1
  93. package/dist/src/marks/link.common.glsl.js +1 -1
  94. package/dist/src/marks/link.d.ts +8 -1
  95. package/dist/src/marks/link.d.ts.map +1 -1
  96. package/dist/src/marks/link.fragment.glsl.js +1 -1
  97. package/dist/src/marks/link.js +47 -31
  98. package/dist/src/marks/link.vertex.glsl.js +1 -1
  99. package/dist/src/marks/mark.d.ts +24 -25
  100. package/dist/src/marks/mark.d.ts.map +1 -1
  101. package/dist/src/marks/mark.js +246 -118
  102. package/dist/src/marks/markUtils.d.ts +25 -0
  103. package/dist/src/marks/markUtils.d.ts.map +1 -1
  104. package/dist/src/marks/markUtils.js +41 -1
  105. package/dist/src/marks/point.common.glsl.js +1 -1
  106. package/dist/src/marks/point.d.ts +8 -1
  107. package/dist/src/marks/point.d.ts.map +1 -1
  108. package/dist/src/marks/point.js +34 -25
  109. package/dist/src/marks/point.vertex.glsl.js +1 -1
  110. package/dist/src/marks/rect.d.ts +8 -1
  111. package/dist/src/marks/rect.d.ts.map +1 -1
  112. package/dist/src/marks/rect.js +28 -23
  113. package/dist/src/marks/rule.d.ts +8 -1
  114. package/dist/src/marks/rule.d.ts.map +1 -1
  115. package/dist/src/marks/rule.js +23 -16
  116. package/dist/src/marks/text.d.ts +10 -1
  117. package/dist/src/marks/text.d.ts.map +1 -1
  118. package/dist/src/marks/text.fragment.glsl.js +1 -1
  119. package/dist/src/marks/text.js +53 -47
  120. package/dist/src/marks/text.vertex.glsl.js +1 -1
  121. package/dist/src/scale/scale.test.d.ts +2 -0
  122. package/dist/src/scale/scale.test.d.ts.map +1 -0
  123. package/dist/src/scale/scale.test.js +2 -0
  124. package/dist/src/scale/ticks.test.d.ts +2 -0
  125. package/dist/src/scale/ticks.test.d.ts.map +1 -0
  126. package/dist/src/scale/ticks.test.js +6 -0
  127. package/dist/src/selection/selection.d.ts +39 -0
  128. package/dist/src/selection/selection.d.ts.map +1 -0
  129. package/dist/src/selection/selection.js +78 -0
  130. package/dist/src/spec/channel.d.ts +150 -83
  131. package/dist/src/spec/mark.d.ts +133 -78
  132. package/dist/src/spec/parameter.d.ts +112 -3
  133. package/dist/src/spec/root.d.ts +0 -1
  134. package/dist/src/spec/transform.d.ts +19 -1
  135. package/dist/src/spec/view.d.ts +5 -10
  136. package/dist/src/tooltip/dataTooltipHandler.d.ts +1 -1
  137. package/dist/src/tooltip/dataTooltipHandler.d.ts.map +1 -1
  138. package/dist/src/tooltip/dataTooltipHandler.js +1 -1
  139. package/dist/src/tooltip/refseqGeneTooltipHandler.d.ts +1 -1
  140. package/dist/src/tooltip/refseqGeneTooltipHandler.d.ts.map +1 -1
  141. package/dist/src/types/encoder.d.ts +80 -26
  142. package/dist/src/types/rendering.d.ts +1 -0
  143. package/dist/src/types/selectionTypes.d.ts +44 -0
  144. package/dist/src/types/viewContext.d.ts +1 -4
  145. package/dist/src/utils/addBaseUrl.test.d.ts +2 -0
  146. package/dist/src/utils/addBaseUrl.test.d.ts.map +1 -0
  147. package/dist/src/utils/binnedIndex.test.d.ts +2 -0
  148. package/dist/src/utils/binnedIndex.test.d.ts.map +1 -0
  149. package/dist/src/utils/cloner.test.d.ts +2 -0
  150. package/dist/src/utils/cloner.test.d.ts.map +1 -0
  151. package/dist/src/utils/coalesce.test.d.ts +2 -0
  152. package/dist/src/utils/coalesce.test.d.ts.map +1 -0
  153. package/dist/src/utils/concatIterables.test.d.ts +2 -0
  154. package/dist/src/utils/concatIterables.test.d.ts.map +1 -0
  155. package/dist/src/utils/domainArray.test.d.ts +2 -0
  156. package/dist/src/utils/domainArray.test.d.ts.map +1 -0
  157. package/dist/src/utils/expression.d.ts +2 -2
  158. package/dist/src/utils/expression.d.ts.map +1 -1
  159. package/dist/src/utils/expression.js +11 -2
  160. package/dist/src/utils/indexer.test.d.ts +2 -0
  161. package/dist/src/utils/indexer.test.d.ts.map +1 -0
  162. package/dist/src/utils/inputBinding.d.ts.map +1 -1
  163. package/dist/src/utils/inputBinding.js +4 -0
  164. package/dist/src/utils/iterateNestedMaps.test.d.ts +2 -0
  165. package/dist/src/utils/iterateNestedMaps.test.d.ts.map +1 -0
  166. package/dist/src/utils/kWayMerge.test.d.ts +2 -0
  167. package/dist/src/utils/kWayMerge.test.d.ts.map +1 -0
  168. package/dist/src/utils/mergeObjects.test.d.ts +2 -0
  169. package/dist/src/utils/mergeObjects.test.d.ts.map +1 -0
  170. package/dist/src/utils/numberExtractor.test.d.ts +2 -0
  171. package/dist/src/utils/numberExtractor.test.d.ts.map +1 -0
  172. package/dist/src/utils/propertyCacher.test.d.ts +2 -0
  173. package/dist/src/utils/propertyCacher.test.d.ts.map +1 -0
  174. package/dist/src/utils/propertyCoalescer.test.d.ts +2 -0
  175. package/dist/src/utils/propertyCoalescer.test.d.ts.map +1 -0
  176. package/dist/src/utils/propertyCoalescer.test.js +3 -0
  177. package/dist/src/utils/radixSort.test.d.ts +2 -0
  178. package/dist/src/utils/radixSort.test.d.ts.map +1 -0
  179. package/dist/src/utils/reservationMap.test.d.ts +2 -0
  180. package/dist/src/utils/reservationMap.test.d.ts.map +1 -0
  181. package/dist/src/utils/ringBuffer.test.d.ts +2 -0
  182. package/dist/src/utils/ringBuffer.test.d.ts.map +1 -0
  183. package/dist/src/utils/topK.test.d.ts +2 -0
  184. package/dist/src/utils/topK.test.d.ts.map +1 -0
  185. package/dist/src/utils/trees.test.d.ts +2 -0
  186. package/dist/src/utils/trees.test.d.ts.map +1 -0
  187. package/dist/src/utils/trees.test.js +8 -3
  188. package/dist/src/utils/variableTools.test.d.ts +2 -0
  189. package/dist/src/utils/variableTools.test.d.ts.map +1 -0
  190. package/dist/src/view/axisResolution.d.ts +19 -6
  191. package/dist/src/view/axisResolution.d.ts.map +1 -1
  192. package/dist/src/view/axisResolution.js +16 -7
  193. package/dist/src/view/axisResolution.test.d.ts +2 -0
  194. package/dist/src/view/axisResolution.test.d.ts.map +1 -0
  195. package/dist/src/view/axisResolution.test.js +16 -11
  196. package/dist/src/view/axisView.js +2 -2
  197. package/dist/src/view/facetView.d.ts +1 -1
  198. package/dist/src/view/facetView.d.ts.map +1 -1
  199. package/dist/src/view/flowBuilder.d.ts +1 -1
  200. package/dist/src/view/flowBuilder.d.ts.map +1 -1
  201. package/dist/src/view/flowBuilder.js +34 -5
  202. package/dist/src/view/flowBuilder.test.d.ts +2 -0
  203. package/dist/src/view/flowBuilder.test.d.ts.map +1 -0
  204. package/dist/src/view/flowBuilder.test.js +1 -1
  205. package/dist/src/view/gridView.d.ts +0 -6
  206. package/dist/src/view/gridView.d.ts.map +1 -1
  207. package/dist/src/view/gridView.js +1 -1
  208. package/dist/src/view/layerView.d.ts +0 -6
  209. package/dist/src/view/layerView.d.ts.map +1 -1
  210. package/dist/src/view/layout/flexLayout.test.d.ts +2 -0
  211. package/dist/src/view/layout/flexLayout.test.d.ts.map +1 -0
  212. package/dist/src/view/layout/grid.test.d.ts +2 -0
  213. package/dist/src/view/layout/grid.test.d.ts.map +1 -0
  214. package/dist/src/view/layout/rectangle.test.d.ts +2 -0
  215. package/dist/src/view/layout/rectangle.test.d.ts.map +1 -0
  216. package/dist/src/view/paramMediator.d.ts +39 -5
  217. package/dist/src/view/paramMediator.d.ts.map +1 -1
  218. package/dist/src/view/paramMediator.js +120 -9
  219. package/dist/src/view/paramMediator.test.d.ts +2 -0
  220. package/dist/src/view/paramMediator.test.d.ts.map +1 -0
  221. package/dist/src/view/paramMediator.test.js +37 -1
  222. package/dist/src/view/scaleResolution.d.ts +17 -15
  223. package/dist/src/view/scaleResolution.d.ts.map +1 -1
  224. package/dist/src/view/scaleResolution.js +70 -68
  225. package/dist/src/view/scaleResolution.test.d.ts +2 -0
  226. package/dist/src/view/scaleResolution.test.d.ts.map +1 -0
  227. package/dist/src/view/scaleResolution.test.js +2 -0
  228. package/dist/src/view/testUtils.d.ts.map +1 -1
  229. package/dist/src/view/testUtils.js +15 -3
  230. package/dist/src/view/unitView.d.ts +8 -20
  231. package/dist/src/view/unitView.d.ts.map +1 -1
  232. package/dist/src/view/unitView.js +100 -102
  233. package/dist/src/view/view.d.ts +1 -1
  234. package/dist/src/view/view.d.ts.map +1 -1
  235. package/dist/src/view/view.test.d.ts +2 -0
  236. package/dist/src/view/view.test.d.ts.map +1 -0
  237. package/dist/src/view/view.test.js +73 -55
  238. package/dist/src/view/viewFactory.test.d.ts +2 -0
  239. package/dist/src/view/viewFactory.test.d.ts.map +1 -0
  240. package/dist/src/view/viewFactory.test.js +2 -2
  241. package/dist/src/view/viewUtils.d.ts +1 -1
  242. package/dist/src/view/viewUtils.d.ts.map +1 -1
  243. package/dist/src/view/zoom.js +2 -2
  244. package/package.json +5 -2
@@ -10,23 +10,23 @@ import { color as d3color } from "d3-color";
10
10
  import {
11
11
  getDiscreteRangeMapper,
12
12
  isColorChannel,
13
- isDatumDef,
14
13
  isDiscreteChannel,
15
14
  getPrimaryChannel,
16
- isValueDef,
17
15
  isFieldDef,
18
16
  } from "../encoder/encoder.js";
19
17
  import { asArray, peek } from "../utils/arrayUtils.js";
20
18
  import { InternMap } from "internmap";
21
- import { isExprRef } from "../view/paramMediator.js";
19
+ import { isExprRef, validateParameterName } from "../view/paramMediator.js";
22
20
  import scaleNull from "../utils/scaleNull.js";
23
21
 
24
22
  export const ATTRIBUTE_PREFIX = "attr_";
25
23
  export const DOMAIN_PREFIX = "uDomain_";
26
24
  export const RANGE_PREFIX = "range_";
25
+ export const ACCESSOR_FUNCTION_PREFIX = "accessor_";
27
26
  export const SCALE_FUNCTION_PREFIX = "scale_";
28
27
  export const SCALED_FUNCTION_PREFIX = "getScaled_";
29
28
  export const RANGE_TEXTURE_PREFIX = "uRangeTexture_";
29
+ export const PARAM_PREFIX = "uParam_";
30
30
 
31
31
  // https://stackoverflow.com/a/47543127
32
32
  const FLT_MAX = 3.402823466e38;
@@ -51,13 +51,37 @@ function splitScaleType(type) {
51
51
  };
52
52
  }
53
53
 
54
+ /**
55
+ *
56
+ * @param {Channel} channel
57
+ * @param {number} conditionNumber
58
+ * @returns {string}
59
+ */
60
+ export function makeAccessorFunctionName(channel, conditionNumber) {
61
+ return `${ACCESSOR_FUNCTION_PREFIX}${channel}_${conditionNumber}`;
62
+ }
63
+
64
+ /**
65
+ * @typedef {object} AccessorParts
66
+ * @prop {Channel} channel
67
+ * @prop {string} accessorGlsl
68
+ * @prop {string} accessorFunctionName
69
+ * @prop {string} [attributeName]
70
+ * @prop {string} [attributeGlsl]
71
+ * @prop {string} [uniformName]
72
+ * @prop {string} [uniformGlsl]
73
+ * @prop {(x: any) => any} [adjuster]
74
+ */
75
+
54
76
  /**
55
77
  * Generates GLSL code for a constant value.
56
78
  *
57
79
  * @param {Channel} channel
80
+ * @param {number} conditionNumber
58
81
  * @param {number | number[] | string | boolean} value
82
+ * @returns {AccessorParts}
59
83
  */
60
- export function generateConstantValueGlsl(channel, value) {
84
+ export function generateConstantValueGlsl(channel, conditionNumber, value) {
61
85
  /** @type {VectorizedValue} */
62
86
  let vec;
63
87
  if (isDiscreteChannel(channel)) {
@@ -84,13 +108,21 @@ export function generateConstantValueGlsl(channel, value) {
84
108
  vec = vectorize(value);
85
109
  }
86
110
 
87
- let glsl = `
88
- #define ${channel}_DEFINED
89
- ${vec.type} ${SCALED_FUNCTION_PREFIX}${channel}() {
111
+ const accessorFunctionName = makeAccessorFunctionName(
112
+ channel,
113
+ conditionNumber
114
+ );
115
+ const accessorGlsl = `
116
+ ${vec.type} ${accessorFunctionName}() {
90
117
  // Constant value
91
118
  return ${vec};
92
119
  }`;
93
- return glsl;
120
+
121
+ return {
122
+ channel,
123
+ accessorGlsl,
124
+ accessorFunctionName,
125
+ };
94
126
  }
95
127
 
96
128
  /**
@@ -98,8 +130,10 @@ ${vec.type} ${SCALED_FUNCTION_PREFIX}${channel}() {
98
130
  * used as dynamic mark properties that map to encoding channels.
99
131
  *
100
132
  * @param {Channel} channel
133
+ * @param {number} conditionNumber
134
+ * @returns {AccessorParts}
101
135
  */
102
- export function generateDynamicValueGlslAndUniform(channel) {
136
+ export function generateDynamicValueGlslAndUniform(channel, conditionNumber) {
103
137
  let dataType = "float";
104
138
  /** @type {(x: any) => any} */
105
139
  let adjuster = (x) => x;
@@ -109,13 +143,16 @@ export function generateDynamicValueGlslAndUniform(channel) {
109
143
  adjuster = (x) => cssColorToArray(x);
110
144
  }
111
145
 
112
- const uniformName = `u${capitalize(channel)}`;
146
+ const uniformName = `u${capitalize(channel)}_${conditionNumber}`;
113
147
 
114
148
  const uniformGlsl = ` // Dynamic value\n uniform ${dataType} ${uniformName};`;
115
149
 
116
- let scaleGlsl = `
117
- #define ${channel}_DEFINED
118
- ${dataType} ${SCALED_FUNCTION_PREFIX}${channel}() {
150
+ const accessorFunctionName = makeAccessorFunctionName(
151
+ channel,
152
+ conditionNumber
153
+ );
154
+ let accessorGlsl = `
155
+ ${dataType} ${accessorFunctionName}() {
119
156
  // Dynamic value
120
157
  return ${uniformName};
121
158
  }`;
@@ -124,56 +161,95 @@ ${dataType} ${SCALED_FUNCTION_PREFIX}${channel}() {
124
161
  channel,
125
162
  uniformName,
126
163
  uniformGlsl,
127
- scaleGlsl,
164
+ accessorGlsl,
165
+ accessorFunctionName,
128
166
  adjuster,
129
167
  };
130
168
  }
131
169
 
132
170
  /**
133
- *
134
171
  * @param {Channel} channel
135
- * @param {import("../view/scaleResolution.js").default} scaleResolution TODO: typing
136
- * @param {import("../spec/channel.js").ChannelDef} channelDef
172
+ * @param {any} scale
173
+ * @param {number} conditionNumber
137
174
  * @param {Channel[]} [sharedQuantitativeChannels] Channels that share the same quantitative field
175
+ * @returns {AccessorParts}
138
176
  */
139
- // eslint-disable-next-line complexity
140
- export function generateScaleGlsl(
177
+ export function generateDataGlsl(
141
178
  channel,
142
- scaleResolution,
143
- channelDef,
179
+ scale,
180
+ conditionNumber,
144
181
  sharedQuantitativeChannels = [channel]
145
182
  ) {
146
- if (isValueDef(channelDef)) {
147
- throw new Error(
148
- `Cannot create scale for "value": ${JSON.stringify(channelDef)}`
149
- );
150
- }
151
-
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();
157
-
158
- const primary = getPrimaryChannel(channel);
183
+ const { attributeType } = getAttributeAndArrayTypes(scale, channel);
159
184
  const attributeName =
160
185
  ATTRIBUTE_PREFIX + makeAttributeName(sharedQuantitativeChannels);
161
- const domainUniformName = DOMAIN_PREFIX + primary;
162
- const rangeName = RANGE_PREFIX + primary;
163
186
 
164
- // The attribute has discrete values
165
- const discrete = isDiscrete(scale.type);
187
+ const attributeGlsl = `in highp ${attributeType} ${attributeName};`;
166
188
 
167
- const hp = isHighPrecisionScale(scale.type);
168
- const largeHp = hp && isLargeGenome(scale.domain());
189
+ const accessorFunctionName = makeAccessorFunctionName(
190
+ channel,
191
+ conditionNumber
192
+ );
169
193
 
170
- const attributeType = largeHp
171
- ? "uvec2"
172
- : hp
173
- ? "uint"
174
- : discrete || channel == "uniqueId"
175
- ? "uint"
176
- : "float";
194
+ const accessorGlsl = `
195
+ ${attributeType} ${accessorFunctionName}() {
196
+ return ${attributeName};
197
+ }`;
198
+
199
+ return {
200
+ channel,
201
+ attributeName,
202
+ attributeGlsl,
203
+ accessorGlsl,
204
+ accessorFunctionName,
205
+ };
206
+ }
207
+ /**
208
+ * @param {Channel} channel
209
+ * @param {any} scale
210
+ * @param {number} conditionNumber
211
+ * @returns {AccessorParts}
212
+ */
213
+ export function generateDatumGlslAndUniform(channel, scale, conditionNumber) {
214
+ const { attributeType } = getAttributeAndArrayTypes(scale, channel);
215
+
216
+ // TODO: Use uniform prefix
217
+ const uniformName = ATTRIBUTE_PREFIX + makeAttributeName(channel);
218
+ const uniformGlsl = ` uniform highp ${attributeType} ${uniformName};`;
219
+
220
+ const accessorFunctionName = makeAccessorFunctionName(
221
+ channel,
222
+ conditionNumber
223
+ );
224
+ const accessorGlsl = `
225
+ ${attributeType} ${accessorFunctionName}() {
226
+ return ${uniformName};
227
+ }`;
228
+
229
+ return {
230
+ channel,
231
+ uniformName,
232
+ uniformGlsl,
233
+ accessorGlsl,
234
+ accessorFunctionName,
235
+ };
236
+ }
237
+
238
+ /**
239
+ *
240
+ * @param {Channel} channel
241
+ * @param {any} scale
242
+ * @param {import("../spec/channel.js").ChannelDef} channelDef
243
+ */
244
+ // eslint-disable-next-line complexity
245
+ export function generateScaleGlsl(channel, scale, channelDef) {
246
+ scale ??= scaleNull();
247
+
248
+ const primary = getPrimaryChannel(channel);
249
+ const domainUniformName = DOMAIN_PREFIX + primary;
250
+ const rangeUniformName = RANGE_PREFIX + primary;
251
+
252
+ const { hp, attributeType } = getAttributeAndArrayTypes(scale, channel);
177
253
 
178
254
  const domainLength = scale.domain ? scale.domain().length : undefined;
179
255
 
@@ -189,8 +265,6 @@ export function generateScaleGlsl(
189
265
  glsl.push(`// Channel: ${channel}`);
190
266
  glsl.push("");
191
267
 
192
- glsl.push(`#define ${channel}_DEFINED`);
193
-
194
268
  const { transform } = splitScaleType(scale.type);
195
269
 
196
270
  /**
@@ -204,14 +278,18 @@ export function generateScaleGlsl(
204
278
  let functionCall;
205
279
  switch (transform) {
206
280
  case "linear":
207
- functionCall = makeScaleCall("scaleLinear", "domain", rangeName);
281
+ functionCall = makeScaleCall(
282
+ "scaleLinear",
283
+ "domain",
284
+ rangeUniformName
285
+ );
208
286
  break;
209
287
 
210
288
  case "log":
211
289
  functionCall = makeScaleCall(
212
290
  "scaleLog",
213
291
  "domain",
214
- rangeName,
292
+ rangeUniformName,
215
293
  scale.base()
216
294
  );
217
295
  break;
@@ -220,7 +298,7 @@ export function generateScaleGlsl(
220
298
  functionCall = makeScaleCall(
221
299
  "scaleSymlog",
222
300
  "domain",
223
- rangeName,
301
+ rangeUniformName,
224
302
  scale.constant()
225
303
  );
226
304
  break;
@@ -230,7 +308,7 @@ export function generateScaleGlsl(
230
308
  functionCall = makeScaleCall(
231
309
  "scalePow",
232
310
  "domain",
233
- rangeName,
311
+ rangeUniformName,
234
312
  scale.exponent()
235
313
  );
236
314
  break;
@@ -240,7 +318,7 @@ export function generateScaleGlsl(
240
318
  functionCall = makeScaleCall(
241
319
  "scaleBandHp",
242
320
  "domain",
243
- rangeName,
321
+ rangeUniformName,
244
322
  scale.paddingInner(),
245
323
  scale.paddingOuter(),
246
324
  scale.align(),
@@ -253,7 +331,7 @@ export function generateScaleGlsl(
253
331
  functionCall = makeScaleCall(
254
332
  "scaleBand",
255
333
  "domain",
256
- rangeName,
334
+ rangeUniformName,
257
335
  scale.paddingInner(),
258
336
  scale.paddingOuter(),
259
337
  scale.align(),
@@ -303,17 +381,17 @@ export function generateScaleGlsl(
303
381
  }
304
382
  rangeUniform = ` uniform ${getFloatVectorType(
305
383
  range.length
306
- )} ${rangeName};`;
384
+ )} ${rangeUniformName};`;
307
385
  } else if (range.length && range.every(isNumber)) {
308
386
  const vectorizedRange = vectorizeRange(range);
309
387
 
310
388
  glsl.push(
311
- `const ${vectorizedRange.type} ${rangeName} = ${vectorizedRange};`
389
+ `const ${vectorizedRange.type} ${rangeUniformName} = ${vectorizedRange};`
312
390
  );
313
391
  }
314
392
  }
315
393
 
316
- const returnType = isColorChannel(channel) ? "vec3" : "float";
394
+ const returnType = getScaledDataTypeForChannel(channel);
317
395
 
318
396
  /**
319
397
  * An optional interpolator function that maps the transformed value to the range.
@@ -340,10 +418,6 @@ export function generateScaleGlsl(
340
418
  interpolate = `getDiscreteColor(${textureUniformName}, int(transformed)).r`;
341
419
  }
342
420
 
343
- const [attributeGlsl, markUniformGlsl] = isDatumDef(channelDef)
344
- ? [undefined, ` uniform highp ${attributeType} ${attributeName};`]
345
- : [`in highp ${attributeType} ${attributeName};`, undefined];
346
-
347
421
  /** @type {string[]} Channel's scale function*/
348
422
  const scaleBody = [];
349
423
 
@@ -409,12 +483,6 @@ ${returnType} ${SCALE_FUNCTION_PREFIX}${channel}(${attributeType} value) {
409
483
  ${scaleBody.map((x) => ` ${x}\n`).join("")}
410
484
  }`);
411
485
 
412
- // A convenience getter for the scaled value
413
- glsl.push(`
414
- ${returnType} ${SCALED_FUNCTION_PREFIX}${channel}() {
415
- return ${SCALE_FUNCTION_PREFIX}${channel}(${attributeName});
416
- }`);
417
-
418
486
  const concatenated = glsl.join("\n");
419
487
 
420
488
  if (usesDomain && channel == primary) {
@@ -429,18 +497,58 @@ ${returnType} ${SCALED_FUNCTION_PREFIX}${channel}() {
429
497
  }
430
498
 
431
499
  return {
432
- attributeName,
433
- attributeGlsl,
434
- // Ends up in the Mark uniform block
435
- markUniformGlsl,
436
500
  glsl: concatenated,
437
501
  domainUniformName,
438
502
  domainUniform,
439
- rangeName,
503
+ rangeUniformName,
440
504
  rangeUniform,
441
505
  };
442
506
  }
443
507
 
508
+ /**
509
+ *
510
+ * @param {Channel} channel
511
+ * @param {import("../types/encoder.js").Accessor[]} accessors
512
+ */
513
+ export function generateConditionalEncoderGlsl(channel, accessors) {
514
+ const type = getScaledDataTypeForChannel(channel);
515
+
516
+ /** @type {string[]} */
517
+ const conditions = [];
518
+ /** @type {string[]} */
519
+ const statements = [];
520
+
521
+ for (let i = 0; i < accessors.length; i++) {
522
+ const accessor = accessors[i];
523
+ const accessorFunctionName = makeAccessorFunctionName(channel, i);
524
+ const { param, empty } = accessor.predicate;
525
+
526
+ const paramUniform = PARAM_PREFIX + validateParameterName(param);
527
+ const idAttribute = ATTRIBUTE_PREFIX + "uniqueId";
528
+
529
+ // Hardcoded condition for single point selection ... for now.
530
+ conditions.push(
531
+ param
532
+ ? `${idAttribute} == ${paramUniform}${
533
+ empty ? ` || ${paramUniform} == uint(0)` : ""
534
+ }`
535
+ : null
536
+ );
537
+
538
+ statements.push(
539
+ accessor.scaleChannel
540
+ ? `return ${SCALE_FUNCTION_PREFIX}${channel}(${accessorFunctionName}());`
541
+ : `return ${accessorFunctionName}();`
542
+ );
543
+ }
544
+
545
+ return `${type} ${SCALED_FUNCTION_PREFIX}${channel}() {
546
+ ${ifElseGlsl(conditions, statements)}
547
+ }
548
+
549
+ #define ${channel}_DEFINED`;
550
+ }
551
+
444
552
  /**
445
553
  * Adds a trailing decimal zero so that GLSL is happy.
446
554
  *
@@ -506,6 +614,17 @@ function getFloatVectorType(numComponents) {
506
614
  }
507
615
  }
508
616
 
617
+ /**
618
+ * @param {Channel} channel
619
+ */
620
+ export function getScaledDataTypeForChannel(channel) {
621
+ return isColorChannel(channel)
622
+ ? "vec3"
623
+ : channel == "uniqueId"
624
+ ? "uint"
625
+ : "float";
626
+ }
627
+
509
628
  /**
510
629
  * @param {string} color
511
630
  */
@@ -551,6 +670,37 @@ function makeFunctionCall(name, ...args) {
551
670
  return `${name}(${fixedArgs.join(", ")})`;
552
671
  }
553
672
 
673
+ /**
674
+ *
675
+ * @param {import("../types/encoder.js").VegaScale} scale
676
+ * @param {import("../spec/channel.js").Channel} channel
677
+ */
678
+ export function getAttributeAndArrayTypes(scale, channel) {
679
+ const discrete = scale && isDiscrete(scale.type);
680
+ const hp = scale && isHighPrecisionScale(scale.type);
681
+ const largeHp = hp && isLargeGenome(scale.domain());
682
+
683
+ /**
684
+ * @type {{attributeType: string, arrayConstructor: Uint32ArrayConstructor | Uint16ArrayConstructor | Float32ArrayConstructor}}
685
+ */
686
+ const props = largeHp
687
+ ? { attributeType: "uvec2", arrayConstructor: Uint32Array }
688
+ : hp
689
+ ? { attributeType: "uint", arrayConstructor: Uint32Array }
690
+ : discrete
691
+ ? { attributeType: "uint", arrayConstructor: Uint16Array }
692
+ : channel == "uniqueId"
693
+ ? { attributeType: "uint", arrayConstructor: Uint32Array }
694
+ : { attributeType: "float", arrayConstructor: Float32Array };
695
+
696
+ return Object.assign(props, {
697
+ numComponents: +(props.attributeType.match(/^vec([234])$/)?.[1] ?? 1),
698
+ discrete,
699
+ hp,
700
+ largeHp,
701
+ });
702
+ }
703
+
554
704
  /**
555
705
  * True if scale needs more than 24 bits (float32) of precision.
556
706
  *
@@ -686,3 +836,40 @@ export const getRangeForGlsl = (scale, channel) =>
686
836
  : scale.range
687
837
  ? scale.range()
688
838
  : undefined;
839
+
840
+ /**
841
+ * @param {string[]} conditions
842
+ * @param {string[]} statements
843
+ * @returns {string}
844
+ */
845
+ export function ifElseGlsl(conditions, statements) {
846
+ if (conditions.length != statements.length) {
847
+ throw new Error("Unequal array lengths");
848
+ }
849
+
850
+ const n = conditions.length;
851
+
852
+ if (n == 0) {
853
+ return "";
854
+ } else if (n == 1 && conditions[0] == null) {
855
+ return statements[0];
856
+ }
857
+
858
+ const parts = [];
859
+ for (let i = 0; i < n; i++) {
860
+ const condition = conditions[i];
861
+ const ifelse =
862
+ i == 0
863
+ ? `if (${condition})`
864
+ : condition == null && i == n - 1
865
+ ? `else`
866
+ : `else if (${condition})`;
867
+ parts.push(
868
+ ` ${ifelse} {
869
+ ${statements[i]}
870
+ }`
871
+ );
872
+ }
873
+
874
+ return parts.join("\n");
875
+ }
@@ -1,2 +1,2 @@
1
- const shader = "#define PI 3.141593\nuniform View{mediump vec2 uViewOffset;mediump vec2 uViewScale;mediump vec2 uViewportSize;lowp float uDevicePixelRatio;lowp float uViewOpacity;bool uPickingEnabled;};/***Maps a coordinate on the unit scale to a normalized device coordinate.*(0,0)is at the bottom left corner.*/vec4 unitToNdc(vec2 coord){return vec4((coord*uViewScale+uViewOffset)*2.0-1.0,0.0,1.0);}vec4 unitToNdc(float x,float y){return unitToNdc(vec2(x,y));}vec4 pixelsToNdc(vec2 coord){return unitToNdc(coord/uViewportSize);}vec4 pixelsToNdc(float x,float y){return pixelsToNdc(vec2(x,y));}float linearstep(float edge0,float edge1,float x){return clamp((x-edge0)/(edge1-edge0),0.0,1.0);}/***Specialized linearstep for doing antialiasing*/float distanceToRatio(float d){return clamp(d*uDevicePixelRatio+0.5,0.0,1.0);}vec4 distanceToColor(float d,vec4 fill,vec4 stroke,float halfStrokeWidth){if(halfStrokeWidth>0.0){float sd=abs(d)-halfStrokeWidth;return mix(stroke,d<=0.0 ? fill : vec4(0.0),distanceToRatio(sd));}else{return fill*distanceToRatio(-d);}}";
1
+ const shader = "#define PI 3.141593\nuniform View{mediump vec2 uViewOffset;mediump vec2 uViewScale;mediump vec2 uViewportSize;lowp float uDevicePixelRatio;lowp float uViewOpacity;bool uPickingEnabled;};/***Maps a coordinate on the unit scale to a normalized device coordinate.*(0,0)is at the bottom left corner.*/vec4 unitToNdc(vec2 coord){return vec4((coord*uViewScale+uViewOffset)*2.0-1.0,0.0,1.0);}vec4 unitToNdc(float x,float y){return unitToNdc(vec2(x,y));}vec4 pixelsToNdc(vec2 coord){return unitToNdc(coord/uViewportSize);}vec4 pixelsToNdc(float x,float y){return pixelsToNdc(vec2(x,y));}float linearstep(float edge0,float edge1,float x){return clamp((x-edge0)/(edge1-edge0),0.0,1.0);}/***Calculates a gamma for antialiasing opacity based on the color.*/float getGammaForColor(vec3 rgb){return mix(1.25,0.75,smoothstep(0.0,1.0,dot(rgb,vec3(0.299,0.587,0.114))));}/***Specialized linearstep for doing antialiasing*/float distanceToRatio(float d){return clamp(d*uDevicePixelRatio+0.5,0.0,1.0);}vec4 distanceToColor(float d,vec4 fill,vec4 stroke,float halfStrokeWidth){if(halfStrokeWidth>0.0){float sd=abs(d)-halfStrokeWidth;return mix(stroke,d<=0.0 ? fill : vec4(0.0),distanceToRatio(sd));}else{return fill*distanceToRatio(-d);}}";
2
2
  export default shader;
@@ -1,2 +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;uniform int uSegmentBreaks;\n#pragma markUniforms\n};";
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;uniform bool uNoFadingOnPointSelection;uniform int uSegmentBreaks;\n#pragma markUniforms\n};";
2
2
  export default shader;
@@ -1,4 +1,11 @@
1
- export default class LinkMark extends Mark {
1
+ /**
2
+ * @extends {Mark<import("../spec/mark.js").LinkProps>}
3
+ */
4
+ export default class LinkMark extends Mark<import("../spec/mark.js").LinkProps> {
5
+ /**
6
+ * @param {import("../view/unitView.js").default} unitView
7
+ */
8
+ constructor(unitView: import("../view/unitView.js").default);
2
9
  /**
3
10
  * Only available if "WebGL Draft Extensions" is enabled in chrome://flags
4
11
  * But seems to work.
@@ -1 +1 @@
1
- {"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../../src/marks/link.js"],"names":[],"mappings":"AAYA;IA+BQ;;;;;OAKG;IACH,yBAEC;IA2GD;;;;;;MAKC;CAwFR;iBArPgB,WAAW"}
1
+ {"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../../src/marks/link.js"],"names":[],"mappings":"AAYA;;GAEG;AACH;IACI;;OAEG;IACH,sBAFW,OAAO,qBAAqB,EAAE,OAAO,EAoC/C;IATG;;;;;OAKG;IACH,yBAEC;IAsHD;;;;;;MAKC;CA4FR;iBArQgB,WAAW"}
@@ -1,2 +1,2 @@
1
- const shader = "in vec4 vColor;in float vSize;in float vNormalLengthInPixels;out lowp vec4 fragColor;void main(void){float dpr=uDevicePixelRatio;float distance=abs(vNormalLengthInPixels);float opacity=clamp(((vSize/2.0-distance)*dpr),0.0,1.0);fragColor=vColor*opacity;if(uPickingEnabled){fragColor=vPickingColor;}}";
1
+ const shader = "in vec4 vColor;in float vSize;in float vNormalLengthInPixels;in float vGamma;out lowp vec4 fragColor;void main(void){float dpr=uDevicePixelRatio;float distance=abs(vNormalLengthInPixels);float opacity=clamp(((vSize/2.0-distance)*dpr),0.0,1.0);opacity=pow(opacity,vGamma);fragColor=vColor*opacity;if(uPickingEnabled){fragColor=vPickingColor;}}";
2
2
  export default shader;