q5 2.14.4 → 2.14.5

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.
@@ -1,638 +0,0 @@
1
- Q5.renderers.webgpu.drawing = ($, q) => {
2
- let c = $.canvas,
3
- drawStack = $.drawStack,
4
- vertexStack = new Float32Array(1e7),
5
- vertIndex = 0;
6
- const TAU = Math.PI * 2;
7
- const HALF_PI = Math.PI / 2;
8
-
9
- let drawingShader = Q5.device.createShaderModule({
10
- label: 'drawingShader',
11
- code: `
12
- struct Uniforms {
13
- halfWidth: f32,
14
- halfHeight: f32
15
- }
16
- struct VertexParams {
17
- @location(0) pos: vec2f,
18
- @location(1) colorIndex: f32,
19
- @location(2) matrixIndex: f32
20
- }
21
- struct FragmentParams {
22
- @builtin(position) position: vec4f,
23
- @location(0) color: vec4f
24
- }
25
-
26
- @group(0) @binding(0) var<uniform> uniforms: Uniforms;
27
- @group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;
28
- @group(0) @binding(2) var<storage> colors : array<vec4f>;
29
-
30
- @vertex
31
- fn vertexMain(v: VertexParams) -> FragmentParams {
32
- var vert = vec4f(v.pos, 0.0, 1.0);
33
- vert = transforms[i32(v.matrixIndex)] * vert;
34
- vert.x /= uniforms.halfWidth;
35
- vert.y /= uniforms.halfHeight;
36
-
37
- var f: FragmentParams;
38
- f.position = vert;
39
- f.color = colors[i32(v.colorIndex)];
40
- return f;
41
- }
42
-
43
- @fragment
44
- fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {
45
- return color;
46
- }
47
- `
48
- });
49
-
50
- let vertexBufferLayout = {
51
- arrayStride: 16, // 4 floats * 4 bytes
52
- attributes: [
53
- { format: 'float32x2', offset: 0, shaderLocation: 0 }, // position
54
- { format: 'float32', offset: 8, shaderLocation: 1 }, // colorIndex
55
- { format: 'float32', offset: 12, shaderLocation: 2 } // matrixIndex
56
- ]
57
- };
58
-
59
- let pipelineLayout = Q5.device.createPipelineLayout({
60
- label: 'drawingPipelineLayout',
61
- bindGroupLayouts: $.bindGroupLayouts
62
- });
63
-
64
- $._pipelineConfigs[0] = {
65
- label: 'drawingPipeline',
66
- layout: pipelineLayout,
67
- vertex: {
68
- module: drawingShader,
69
- entryPoint: 'vertexMain',
70
- buffers: [vertexBufferLayout]
71
- },
72
- fragment: {
73
- module: drawingShader,
74
- entryPoint: 'fragmentMain',
75
- targets: [{ format: 'bgra8unorm', blend: $.blendConfigs.normal }]
76
- },
77
- primitive: { topology: 'triangle-strip', stripIndexFormat: 'uint32' },
78
- multisample: { count: 4 }
79
- };
80
-
81
- $._pipelines[0] = Q5.device.createRenderPipeline($._pipelineConfigs[0]);
82
-
83
- const addVert = (x, y, ci, ti) => {
84
- let v = vertexStack,
85
- i = vertIndex;
86
- v[i++] = x;
87
- v[i++] = y;
88
- v[i++] = ci;
89
- v[i++] = ti;
90
- vertIndex = i;
91
- };
92
-
93
- const addRect = (x1, y1, x2, y2, x3, y3, x4, y4, ci, ti) => {
94
- let v = vertexStack,
95
- i = vertIndex;
96
-
97
- v[i++] = x1;
98
- v[i++] = y1;
99
- v[i++] = ci;
100
- v[i++] = ti;
101
-
102
- v[i++] = x2;
103
- v[i++] = y2;
104
- v[i++] = ci;
105
- v[i++] = ti;
106
-
107
- v[i++] = x4;
108
- v[i++] = y4;
109
- v[i++] = ci;
110
- v[i++] = ti;
111
-
112
- v[i++] = x3;
113
- v[i++] = y3;
114
- v[i++] = ci;
115
- v[i++] = ti;
116
-
117
- vertIndex = i;
118
- drawStack.push(0, 4);
119
- };
120
-
121
- const addArc = (x, y, a, b, startAngle, endAngle, n, ci, ti) => {
122
- let angleRange = endAngle - startAngle;
123
- let angleIncrement = angleRange / n;
124
- let t = startAngle;
125
-
126
- let v = vertexStack,
127
- i = vertIndex;
128
-
129
- for (let j = 0; j <= n; j++) {
130
- // add center vertex
131
- v[i++] = x;
132
- v[i++] = y;
133
- v[i++] = ci;
134
- v[i++] = ti;
135
-
136
- // calculate perimeter vertex
137
- let vx = x + a * Math.cos(t);
138
- let vy = y + b * Math.sin(t);
139
-
140
- // add perimeter vertex
141
- v[i++] = vx;
142
- v[i++] = vy;
143
- v[i++] = ci;
144
- v[i++] = ti;
145
-
146
- t += angleIncrement;
147
- }
148
-
149
- vertIndex = i;
150
- drawStack.push(0, (n + 1) * 2);
151
- };
152
-
153
- const addArcStroke = (x, y, outerA, outerB, innerA, innerB, startAngle, endAngle, n, ci, ti) => {
154
- let angleRange = endAngle - startAngle;
155
- let angleIncrement = angleRange / n;
156
- let t = startAngle;
157
-
158
- let v = vertexStack,
159
- i = vertIndex;
160
-
161
- for (let j = 0; j <= n; j++) {
162
- // Outer vertex
163
- let vxOuter = x + outerA * Math.cos(t);
164
- let vyOuter = y + outerB * Math.sin(t);
165
-
166
- // Inner vertex
167
- let vxInner = x + innerA * Math.cos(t);
168
- let vyInner = y + innerB * Math.sin(t);
169
-
170
- // Add vertices for triangle strip
171
- v[i++] = vxOuter;
172
- v[i++] = vyOuter;
173
- v[i++] = ci;
174
- v[i++] = ti;
175
-
176
- v[i++] = vxInner;
177
- v[i++] = vyInner;
178
- v[i++] = ci;
179
- v[i++] = ti;
180
-
181
- t += angleIncrement;
182
- }
183
-
184
- vertIndex = i;
185
- drawStack.push(0, (n + 1) * 2);
186
- };
187
-
188
- $.rectMode = (x) => ($._rectMode = x);
189
-
190
- $.rect = (x, y, w, h, rr = 0) => {
191
- let [l, r, t, b] = $._calcBox(x, y, w, h, $._rectMode);
192
- let ci, ti;
193
- if ($._matrixDirty) $._saveMatrix();
194
- ti = $._matrixIndex;
195
-
196
- if (!rr) {
197
- if ($._doFill) {
198
- ci = $._fill;
199
- addRect(l, t, r, t, r, b, l, b, ci, ti);
200
- }
201
-
202
- if ($._doStroke) {
203
- ci = $._stroke;
204
- let sw = $._strokeWeight / 2;
205
-
206
- // Calculate stroke positions
207
- let lsw = l - sw,
208
- rsw = r + sw,
209
- tsw = t + sw,
210
- bsw = b - sw,
211
- lpsw = l + sw,
212
- rpsw = r - sw,
213
- tpsw = t - sw,
214
- bpsw = b + sw;
215
-
216
- addRect(lsw, tpsw, rsw, tpsw, rsw, tsw, lsw, tsw, ci, ti); // Top
217
- addRect(lsw, bsw, rsw, bsw, rsw, bpsw, lsw, bpsw, ci, ti); // Bottom
218
-
219
- // Adjust side strokes to avoid overlapping corners
220
- tsw = t - sw;
221
- bsw = b + sw;
222
-
223
- addRect(lsw, tsw, lpsw, tsw, lpsw, bsw, lsw, bsw, ci, ti); // Left
224
- addRect(rpsw, tsw, rsw, tsw, rsw, bsw, rpsw, bsw, ci, ti); // Right
225
- }
226
- return;
227
- }
228
-
229
- l += rr;
230
- r -= rr;
231
- t -= rr;
232
- b += rr;
233
-
234
- // Clamp radius
235
- rr = Math.min(rr, Math.min(w, h) / 2);
236
-
237
- let n = getArcSegments(rr * $._scale);
238
-
239
- let trr = t + rr,
240
- brr = b - rr,
241
- lrr = l - rr,
242
- rrr = r + rr;
243
-
244
- if ($._doFill) {
245
- ci = $._fill;
246
- // Corner arcs
247
- addArc(r, b, rr, rr, -HALF_PI, 0, n, ci, ti);
248
- addArc(l, b, rr, rr, -Math.PI, -HALF_PI, n, ci, ti);
249
- addArc(l, t, rr, rr, Math.PI, HALF_PI, n, ci, ti);
250
- addArc(r, t, rr, rr, 0, HALF_PI, n, ci, ti);
251
-
252
- addRect(l, trr, r, trr, r, brr, l, brr, ci, ti); // center
253
- addRect(l, t, lrr, t, lrr, b, l, b, ci, ti); // Left
254
- addRect(rrr, t, r, t, r, b, rrr, b, ci, ti); // Right
255
- }
256
-
257
- if ($._doStroke) {
258
- ci = $._stroke;
259
- let hsw = $._hsw;
260
-
261
- let outerA = rr + hsw,
262
- outerB = rr + hsw,
263
- innerA = rr - hsw,
264
- innerB = rr - hsw;
265
- // Corner arc strokes
266
- addArcStroke(r, b, outerA, outerB, innerA, innerB, -HALF_PI, 0, n, ci, ti);
267
- addArcStroke(l, b, outerA, outerB, innerA, innerB, -Math.PI, -HALF_PI, n, ci, ti);
268
- addArcStroke(l, t, outerA, outerB, innerA, innerB, Math.PI, HALF_PI, n, ci, ti);
269
- addArcStroke(r, t, outerA, outerB, innerA, innerB, 0, HALF_PI, n, ci, ti);
270
-
271
- let lrrMin = lrr - hsw,
272
- lrrMax = lrr + hsw,
273
- rrrMin = rrr - hsw,
274
- rrrMax = rrr + hsw,
275
- trrMin = trr - hsw,
276
- trrMax = trr + hsw,
277
- brrMin = brr - hsw,
278
- brrMax = brr + hsw;
279
-
280
- // Side strokes - positioned outside
281
- addRect(lrrMin, t, lrrMax, t, lrrMax, b, lrrMin, b, ci, ti); // Left
282
- addRect(rrrMin, t, rrrMax, t, rrrMax, b, rrrMin, b, ci, ti); // Right
283
- addRect(l, trrMin, r, trrMin, r, trrMax, l, trrMax, ci, ti); // Top
284
- addRect(l, brrMin, r, brrMin, r, brrMax, l, brrMax, ci, ti); // Bottom
285
- }
286
- };
287
-
288
- $.square = (x, y, s) => $.rect(x, y, s, s);
289
-
290
- // prettier-ignore
291
- const getArcSegments = (d) =>
292
- d < 4 ? 6 :
293
- d < 6 ? 8 :
294
- d < 10 ? 10 :
295
- d < 16 ? 12 :
296
- d < 20 ? 14 :
297
- d < 22 ? 16 :
298
- d < 24 ? 18 :
299
- d < 28 ? 20 :
300
- d < 34 ? 22 :
301
- d < 42 ? 24 :
302
- d < 48 ? 26 :
303
- d < 56 ? 28 :
304
- d < 64 ? 30 :
305
- d < 72 ? 32 :
306
- d < 84 ? 34 :
307
- d < 96 ? 36 :
308
- d < 98 ? 38 :
309
- d < 113 ? 40 :
310
- d < 149 ? 44 :
311
- d < 199 ? 48 :
312
- d < 261 ? 52 :
313
- d < 353 ? 56 :
314
- d < 461 ? 60 :
315
- d < 585 ? 64 :
316
- d < 1200 ? 70 :
317
- d < 1800 ? 80 :
318
- d < 2400 ? 90 :
319
- 100;
320
-
321
- $._ellipseMode = Q5.CENTER;
322
- $.ellipseMode = (x) => ($._ellipseMode = x);
323
-
324
- $.ellipse = (x, y, w, h) => {
325
- let n = getArcSegments(Math.max(Math.abs(w), Math.abs(h)) * $._scale);
326
- let a = w / 2;
327
- let b = w == h ? a : h / 2;
328
-
329
- if ($._matrixDirty) $._saveMatrix();
330
- let ti = $._matrixIndex;
331
-
332
- if ($._doFill) {
333
- addArc(x, -y, a, b, 0, TAU, n, $._fill, ti);
334
- }
335
- if ($._doStroke) {
336
- let sw = $._strokeWeight / 2;
337
- // Draw the stroke as a ring using triangle strips
338
- addArcStroke(x, -y, a + sw, b + sw, a - sw, b - sw, 0, TAU, n, $._stroke, ti);
339
- }
340
- };
341
-
342
- $.circle = (x, y, d) => $.ellipse(x, y, d, d);
343
-
344
- $.arc = (x, y, w, h, start, stop) => {
345
- if (start === stop) return $.ellipse(x, y, w, h);
346
-
347
- // Convert angles if needed
348
- if ($._angleMode) {
349
- start = $.radians(start);
350
- stop = $.radians(stop);
351
- }
352
-
353
- // Normalize angles
354
- start %= TAU;
355
- stop %= TAU;
356
- if (start < 0) start += TAU;
357
- if (stop < 0) stop += TAU;
358
- if (start > stop) stop += TAU;
359
- if (start == stop) return $.ellipse(x, y, w, h);
360
-
361
- // Calculate position based on ellipseMode
362
- let a, b;
363
- if ($._ellipseMode == $.CENTER) {
364
- a = w / 2;
365
- b = h / 2;
366
- } else if ($._ellipseMode == $.RADIUS) {
367
- a = w;
368
- b = h;
369
- } else if ($._ellipseMode == $.CORNER) {
370
- x += w / 2;
371
- y += h / 2;
372
- a = w / 2;
373
- b = h / 2;
374
- } else if ($._ellipseMode == $.CORNERS) {
375
- x = (x + w) / 2;
376
- y = (y + h) / 2;
377
- a = (w - x) / 2;
378
- b = (h - y) / 2;
379
- }
380
-
381
- let ti = $._matrixIndex;
382
- if ($._matrixDirty) $._saveMatrix();
383
- let n = getArcSegments(Math.max(Math.abs(w), Math.abs(h)) * $._scale);
384
-
385
- // Draw fill
386
- if ($._doFill) {
387
- addArc(x, -y, a, b, start, stop, n, $._fill, ti);
388
- }
389
-
390
- // Draw stroke
391
- if ($._doStroke) {
392
- let sw = $._strokeWeight;
393
- addArcStroke(x, -y, a + sw, b + sw, a - sw, b - sw, start, stop, n, $._stroke, ti);
394
- }
395
- };
396
-
397
- $.point = (x, y) => {
398
- if ($._matrixDirty) $._saveMatrix();
399
- let ti = $._matrixIndex,
400
- ci = $._stroke,
401
- sw = $._strokeWeight;
402
-
403
- if ($._scaledSW < 2) {
404
- let [l, r, t, b] = $._calcBox(x, y, sw, sw, 'corner');
405
- addRect(l, t, r, t, r, b, l, b, ci, ti);
406
- } else {
407
- let n = getArcSegments($._scaledSW);
408
- sw /= 2;
409
- addArc(x, -y, sw, sw, 0, TAU, n, ci, ti);
410
- }
411
- };
412
-
413
- $._strokeJoin = 'round';
414
-
415
- $.strokeJoin = (x) => {
416
- $._strokeJoin = x;
417
- };
418
-
419
- $.line = (x1, y1, x2, y2) => {
420
- if ($._matrixDirty) $._saveMatrix();
421
- let ti = $._matrixIndex,
422
- ci = $._stroke,
423
- sw = $._strokeWeight,
424
- hsw = $._hsw;
425
-
426
- // calculate the direction vector and length
427
- let dx = x2 - x1,
428
- dy = y2 - y1,
429
- length = Math.hypot(dx, dy);
430
-
431
- // calculate the perpendicular vector for line thickness
432
- let px = -(dy / length) * hsw,
433
- py = (dx / length) * hsw;
434
-
435
- addRect(x1 + px, -y1 - py, x1 - px, -y1 + py, x2 - px, -y2 + py, x2 + px, -y2 - py, ci, ti);
436
-
437
- if ($._scaledSW > 2 && $._strokeJoin != 'none') {
438
- let n = getArcSegments($._scaledSW);
439
- addArc(x1, -y1, hsw, hsw, 0, TAU, n, ci, ti);
440
- addArc(x2, -y2, hsw, hsw, 0, TAU, n, ci, ti);
441
- }
442
- };
443
-
444
- let shapeVertCount;
445
- let sv = []; // shape vertices
446
- let curveVertices = []; // curve vertices
447
-
448
- $.beginShape = () => {
449
- shapeVertCount = 0;
450
- sv = [];
451
- curveVertices = [];
452
- };
453
-
454
- $.vertex = (x, y) => {
455
- if ($._matrixDirty) $._saveMatrix();
456
- sv.push(x, -y, $._fill, $._matrixIndex);
457
- shapeVertCount++;
458
- };
459
-
460
- $.curveVertex = (x, y) => {
461
- if ($._matrixDirty) $._saveMatrix();
462
- curveVertices.push({ x: x, y: -y });
463
- };
464
-
465
- $.endShape = (close) => {
466
- if (curveVertices.length > 0) {
467
- // duplicate start and end points if necessary
468
- let points = [...curveVertices];
469
- if (points.length < 4) {
470
- // duplicate first and last points
471
- while (points.length < 4) {
472
- points.unshift(points[0]);
473
- points.push(points[points.length - 1]);
474
- }
475
- }
476
-
477
- // calculate catmull-rom spline curve points
478
- for (let i = 0; i < points.length - 3; i++) {
479
- let p0 = points[i];
480
- let p1 = points[i + 1];
481
- let p2 = points[i + 2];
482
- let p3 = points[i + 3];
483
-
484
- for (let t = 0; t <= 1; t += 0.1) {
485
- let t2 = t * t;
486
- let t3 = t2 * t;
487
-
488
- let x =
489
- 0.5 *
490
- (2 * p1.x +
491
- (-p0.x + p2.x) * t +
492
- (2 * p0.x - 5 * p1.x + 4 * p2.x - p3.x) * t2 +
493
- (-p0.x + 3 * p1.x - 3 * p2.x + p3.x) * t3);
494
-
495
- let y =
496
- 0.5 *
497
- (2 * p1.y +
498
- (-p0.y + p2.y) * t +
499
- (2 * p0.y - 5 * p1.y + 4 * p2.y - p3.y) * t2 +
500
- (-p0.y + 3 * p1.y - 3 * p2.y + p3.y) * t3);
501
-
502
- sv.push(x, y, $._fill, $._matrixIndex);
503
- shapeVertCount++;
504
- }
505
- }
506
- }
507
-
508
- if (shapeVertCount < 3) {
509
- throw new Error('A shape must have at least 3 vertices.');
510
- }
511
-
512
- // close the shape if requested
513
- if (close) {
514
- let firstIndex = 0;
515
- let lastIndex = (shapeVertCount - 1) * 4;
516
-
517
- let firstX = sv[firstIndex];
518
- let firstY = sv[firstIndex + 1];
519
- let lastX = sv[lastIndex];
520
- let lastY = sv[lastIndex + 1];
521
-
522
- if (firstX !== lastX || firstY !== lastY) {
523
- sv.push(firstX, firstY, sv[firstIndex + 2], sv[firstIndex + 3]);
524
- shapeVertCount++;
525
- }
526
- }
527
-
528
- if ($._doFill) {
529
- if (shapeVertCount == 5) {
530
- // for quads, draw two triangles
531
- addVert(sv[0], sv[1], sv[2], sv[3]); // v0
532
- addVert(sv[4], sv[5], sv[6], sv[7]); // v1
533
- addVert(sv[12], sv[13], sv[14], sv[15]); // v3
534
- addVert(sv[8], sv[9], sv[10], sv[11]); // v2
535
- drawStack.push(0, 4);
536
- } else {
537
- // triangulate the shape
538
- for (let i = 1; i < shapeVertCount - 1; i++) {
539
- let v0 = 0;
540
- let v1 = i * 4;
541
- let v2 = (i + 1) * 4;
542
-
543
- addVert(sv[v0], sv[v0 + 1], sv[v0 + 2], sv[v0 + 3]);
544
- addVert(sv[v1], sv[v1 + 1], sv[v1 + 2], sv[v1 + 3]);
545
- addVert(sv[v2], sv[v2 + 1], sv[v2 + 2], sv[v2 + 3]);
546
- }
547
- drawStack.push(0, (shapeVertCount - 2) * 3);
548
- }
549
- }
550
-
551
- if ($._doStroke) {
552
- let hsw = $._hsw,
553
- n = getArcSegments($._scaledSW),
554
- ti = $._matrixIndex,
555
- ogStrokeJoin = $._strokeJoin;
556
- $._strokeJoin = 'none';
557
- // draw lines between vertices
558
- for (let i = 0; i < shapeVertCount - 1; i++) {
559
- let v1 = i * 4;
560
- let v2 = (i + 1) * 4;
561
- $.line(sv[v1], -sv[v1 + 1], sv[v2], -sv[v2 + 1]);
562
-
563
- addArc(sv[v1], sv[v1 + 1], hsw, hsw, 0, TAU, n, $._stroke, ti);
564
- }
565
- if (close) {
566
- let v1 = (shapeVertCount - 1) * 4;
567
- let v2 = 0;
568
- $.line(sv[v1], -sv[v1 + 1], sv[v2], -sv[v2 + 1]);
569
- }
570
- $._strokeJoin = ogStrokeJoin;
571
- }
572
-
573
- // reset for the next shape
574
- shapeVertCount = 0;
575
- sv = [];
576
- curveVertices = [];
577
- };
578
-
579
- $.triangle = (x1, y1, x2, y2, x3, y3) => {
580
- $.beginShape();
581
- $.vertex(x1, y1);
582
- $.vertex(x2, y2);
583
- $.vertex(x3, y3);
584
- $.endShape(true);
585
- };
586
-
587
- $.quad = (x1, y1, x2, y2, x3, y3, x4, y4) => {
588
- $.beginShape();
589
- $.vertex(x1, y1);
590
- $.vertex(x2, y2);
591
- $.vertex(x3, y3);
592
- $.vertex(x4, y4);
593
- $.endShape(true);
594
- };
595
-
596
- $.background = (r, g, b, a) => {
597
- let mi = $._matrixIndex;
598
- $._matrixIndex = 0;
599
- $._doStroke = false;
600
- if (r.src) {
601
- let img = r;
602
- let im = $._imageMode;
603
- $._imageMode = 'corner';
604
- $.image(img, -c.hw, -c.hh, c.w, c.h);
605
- $._imageMode = im;
606
- } else {
607
- let rm = $._rectMode;
608
- $._rectMode = 'corner';
609
- let fill = $._fill;
610
- $.fill(r, g, b, a);
611
- $.rect(-c.hw, -c.hh, c.w, c.h);
612
- $._rectMode = rm;
613
- $._fill = fill;
614
- }
615
- $._doStroke = true;
616
- $._matrixIndex = mi;
617
- };
618
-
619
- $._hooks.preRender.push(() => {
620
- $.pass.setPipeline($._pipelines[0]);
621
-
622
- let vertexBuffer = Q5.device.createBuffer({
623
- size: vertIndex * 4,
624
- usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
625
- mappedAtCreation: true
626
- });
627
-
628
- new Float32Array(vertexBuffer.getMappedRange()).set(vertexStack.slice(0, vertIndex));
629
- vertexBuffer.unmap();
630
-
631
- $.pass.setVertexBuffer(0, vertexBuffer);
632
- });
633
-
634
- $._hooks.postRender.push(() => {
635
- drawStack = $.drawStack;
636
- vertIndex = 0;
637
- });
638
- };