q5 2.21.4 → 2.22.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.
- package/README.md +10 -0
- package/deno.json +2 -2
- package/package.json +2 -2
- package/q5.d.ts +141 -49
- package/q5.js +305 -110
- package/q5.min.js +2 -2
package/q5.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* q5.js
|
|
3
|
-
* @version 2.
|
|
3
|
+
* @version 2.22
|
|
4
4
|
* @author quinton-ashley, Tezumie, and LingDong-
|
|
5
5
|
* @license LGPL-3.0
|
|
6
6
|
* @class Q5
|
|
@@ -41,7 +41,8 @@ function Q5(scope, parent, renderer) {
|
|
|
41
41
|
|
|
42
42
|
$.canvas = $.ctx = $.drawingContext = null;
|
|
43
43
|
$.pixels = [];
|
|
44
|
-
let looper = null
|
|
44
|
+
let looper = null,
|
|
45
|
+
useRAF = true;
|
|
45
46
|
|
|
46
47
|
$.frameCount = 0;
|
|
47
48
|
$.deltaTime = 16;
|
|
@@ -83,13 +84,22 @@ function Q5(scope, parent, renderer) {
|
|
|
83
84
|
$._didResize = false;
|
|
84
85
|
}
|
|
85
86
|
|
|
86
|
-
if ($._loop)
|
|
87
|
-
|
|
87
|
+
if ($._loop) {
|
|
88
|
+
if (useRAF) looper = raf($._draw);
|
|
89
|
+
else {
|
|
90
|
+
let nextTS = ts + $._targetFrameDuration;
|
|
91
|
+
let frameDelay = nextTS - performance.now();
|
|
92
|
+
while (frameDelay < 0) frameDelay += $._targetFrameDuration;
|
|
93
|
+
log(frameDelay);
|
|
94
|
+
looper = setTimeout(() => $._draw(nextTS), frameDelay);
|
|
95
|
+
}
|
|
96
|
+
} else if ($.frameCount && !$._redraw) return;
|
|
88
97
|
|
|
89
|
-
if (
|
|
90
|
-
let
|
|
91
|
-
if (
|
|
98
|
+
if ($.frameCount && useRAF) {
|
|
99
|
+
let timeSinceLast = ts - $._lastFrameTime;
|
|
100
|
+
if (timeSinceLast < $._targetFrameDuration - 4) return;
|
|
92
101
|
}
|
|
102
|
+
|
|
93
103
|
q.deltaTime = ts - $._lastFrameTime;
|
|
94
104
|
$._frameRate = 1000 / $.deltaTime;
|
|
95
105
|
q.frameCount++;
|
|
@@ -100,7 +110,6 @@ function Q5(scope, parent, renderer) {
|
|
|
100
110
|
try {
|
|
101
111
|
$.draw();
|
|
102
112
|
} catch (e) {
|
|
103
|
-
if (!Q5.disableFriendlyErrors && $._askAI) $._askAI(e);
|
|
104
113
|
if (!Q5.errorTolerant) $.noLoop();
|
|
105
114
|
throw e;
|
|
106
115
|
}
|
|
@@ -117,6 +126,10 @@ function Q5(scope, parent, renderer) {
|
|
|
117
126
|
};
|
|
118
127
|
$.noLoop = () => {
|
|
119
128
|
$._loop = false;
|
|
129
|
+
if (looper) {
|
|
130
|
+
if (useRAF) cancelAnimationFrame(looper);
|
|
131
|
+
else clearTimeout(looper);
|
|
132
|
+
}
|
|
120
133
|
looper = null;
|
|
121
134
|
};
|
|
122
135
|
$.loop = () => {
|
|
@@ -140,6 +153,14 @@ function Q5(scope, parent, renderer) {
|
|
|
140
153
|
if (hz) {
|
|
141
154
|
$._targetFrameRate = hz;
|
|
142
155
|
$._targetFrameDuration = 1000 / hz;
|
|
156
|
+
|
|
157
|
+
if ($._loop && $._setupDone && looper != null) {
|
|
158
|
+
if (useRAF) cancelAnimationFrame(looper);
|
|
159
|
+
else clearTimeout(looper);
|
|
160
|
+
looper = null;
|
|
161
|
+
}
|
|
162
|
+
useRAF = hz <= 60;
|
|
163
|
+
setTimeout(() => $._draw(), $._targetFrameDuration);
|
|
143
164
|
}
|
|
144
165
|
return $._frameRate;
|
|
145
166
|
};
|
|
@@ -243,14 +264,7 @@ function Q5(scope, parent, renderer) {
|
|
|
243
264
|
for (let k of userFns) {
|
|
244
265
|
if (!t[k]) $[k] = () => {};
|
|
245
266
|
else if ($._isGlobal) {
|
|
246
|
-
$[k] = (event) =>
|
|
247
|
-
try {
|
|
248
|
-
return t[k](event);
|
|
249
|
-
} catch (e) {
|
|
250
|
-
if ($._askAI) $._askAI(e);
|
|
251
|
-
throw e;
|
|
252
|
-
}
|
|
253
|
-
};
|
|
267
|
+
$[k] = (event) => t[k](event);
|
|
254
268
|
}
|
|
255
269
|
}
|
|
256
270
|
|
|
@@ -314,7 +328,7 @@ function createCanvas(w, h, opt) {
|
|
|
314
328
|
}
|
|
315
329
|
}
|
|
316
330
|
|
|
317
|
-
Q5.version = Q5.VERSION = '2.
|
|
331
|
+
Q5.version = Q5.VERSION = '2.22';
|
|
318
332
|
|
|
319
333
|
if (typeof document == 'object') {
|
|
320
334
|
document.addEventListener('DOMContentLoaded', () => {
|
|
@@ -407,7 +421,6 @@ Q5.modules.canvas = ($, q) => {
|
|
|
407
421
|
if ($._hooks) {
|
|
408
422
|
for (let m of $._hooks.postCanvas) m();
|
|
409
423
|
}
|
|
410
|
-
if ($._beginRender) $._beginRender();
|
|
411
424
|
|
|
412
425
|
if ($._addEventMethods) $._addEventMethods(c);
|
|
413
426
|
|
|
@@ -514,7 +527,7 @@ Q5.modules.canvas = ($, q) => {
|
|
|
514
527
|
$.pixelDensity = (v) => {
|
|
515
528
|
if (!v || v == $._pixelDensity) return $._pixelDensity;
|
|
516
529
|
$._pixelDensity = v;
|
|
517
|
-
$.
|
|
530
|
+
$._resizeCanvas(c.w, c.h);
|
|
518
531
|
return v;
|
|
519
532
|
};
|
|
520
533
|
|
|
@@ -688,6 +701,22 @@ Q5.renderers.c2d.canvas = ($, q) => {
|
|
|
688
701
|
|
|
689
702
|
if ($._scope == 'image') return;
|
|
690
703
|
|
|
704
|
+
$.background = function (c) {
|
|
705
|
+
$.ctx.save();
|
|
706
|
+
$.ctx.resetTransform();
|
|
707
|
+
$.ctx.globalAlpha = 1;
|
|
708
|
+
if (c.canvas) $.image(c, 0, 0, $.canvas.width, $.canvas.height);
|
|
709
|
+
else {
|
|
710
|
+
if (Q5.Color && !c._q5Color) {
|
|
711
|
+
if (typeof c != 'string') c = $.color(...arguments);
|
|
712
|
+
else if ($._namedColors[c]) c = $.color(...$._namedColors[c]);
|
|
713
|
+
}
|
|
714
|
+
$.ctx.fillStyle = c.toString();
|
|
715
|
+
$.ctx.fillRect(0, 0, $.canvas.width, $.canvas.height);
|
|
716
|
+
}
|
|
717
|
+
$.ctx.restore();
|
|
718
|
+
};
|
|
719
|
+
|
|
691
720
|
$._resizeCanvas = (w, h) => {
|
|
692
721
|
let t = {};
|
|
693
722
|
for (let prop in $.ctx) {
|
|
@@ -868,22 +897,6 @@ Q5.renderers.c2d.shapes = ($) => {
|
|
|
868
897
|
|
|
869
898
|
// DRAWING
|
|
870
899
|
|
|
871
|
-
$.background = function (c) {
|
|
872
|
-
$.ctx.save();
|
|
873
|
-
$.ctx.resetTransform();
|
|
874
|
-
$.ctx.globalAlpha = 1;
|
|
875
|
-
if (c.canvas) $.image(c, 0, 0, $.canvas.width, $.canvas.height);
|
|
876
|
-
else {
|
|
877
|
-
if (Q5.Color && !c._q5Color) {
|
|
878
|
-
if (typeof c != 'string') c = $.color(...arguments);
|
|
879
|
-
else if ($._namedColors[c]) c = $.color(...$._namedColors[c]);
|
|
880
|
-
}
|
|
881
|
-
$.ctx.fillStyle = c.toString();
|
|
882
|
-
$.ctx.fillRect(0, 0, $.canvas.width, $.canvas.height);
|
|
883
|
-
}
|
|
884
|
-
$.ctx.restore();
|
|
885
|
-
};
|
|
886
|
-
|
|
887
900
|
$.line = (x0, y0, x1, y1) => {
|
|
888
901
|
if ($._doStroke) {
|
|
889
902
|
$._da && ((x0 *= $._da), (y0 *= $._da), (x1 *= $._da), (y1 *= $._da));
|
|
@@ -1217,8 +1230,8 @@ Q5.renderers.c2d.shapes = ($) => {
|
|
|
1217
1230
|
$.erase = function (fillAlpha = 255, strokeAlpha = 255) {
|
|
1218
1231
|
$.ctx.save();
|
|
1219
1232
|
$.ctx.globalCompositeOperation = 'destination-out';
|
|
1220
|
-
$.ctx.fillStyle = `
|
|
1221
|
-
$.ctx.strokeStyle = `
|
|
1233
|
+
$.ctx.fillStyle = `rgb(0 0 0 / ${fillAlpha / 255})`;
|
|
1234
|
+
$.ctx.strokeStyle = `rgb(0 0 0 / ${strokeAlpha / 255})`;
|
|
1222
1235
|
};
|
|
1223
1236
|
|
|
1224
1237
|
$.noErase = function () {
|
|
@@ -2095,21 +2108,29 @@ Q5.modules.ai = ($) => {
|
|
|
2095
2108
|
};
|
|
2096
2109
|
Q5.modules.color = ($, q) => {
|
|
2097
2110
|
$.RGB = $.RGBA = $._colorMode = 'rgb';
|
|
2098
|
-
$.
|
|
2111
|
+
$.HSL = 'hsl';
|
|
2112
|
+
$.HSB = 'hsb';
|
|
2099
2113
|
$.OKLCH = 'oklch';
|
|
2100
2114
|
|
|
2101
|
-
$.
|
|
2115
|
+
$.SRGB = 'srgb';
|
|
2116
|
+
$.DISPLAY_P3 = 'display-p3';
|
|
2117
|
+
|
|
2118
|
+
$.colorMode = (mode, format, gamut) => {
|
|
2102
2119
|
$._colorMode = mode;
|
|
2103
|
-
let srgb = $.canvas.colorSpace == 'srgb' ||
|
|
2120
|
+
let srgb = $.canvas.colorSpace == 'srgb' || gamut == 'srgb';
|
|
2104
2121
|
format ??= srgb ? 'integer' : 'float';
|
|
2105
2122
|
$._colorFormat = format == 'float' || format == 1 ? 1 : 255;
|
|
2106
2123
|
if (mode == 'oklch') {
|
|
2107
2124
|
q.Color = Q5.ColorOKLCH;
|
|
2125
|
+
} else if (mode == 'hsl') {
|
|
2126
|
+
q.Color = srgb ? Q5.ColorHSL : Q5.ColorHSL_P3;
|
|
2127
|
+
} else if (mode == 'hsb') {
|
|
2128
|
+
q.Color = srgb ? Q5.ColorHSB : Q5.ColorHSB_P3;
|
|
2108
2129
|
} else {
|
|
2109
2130
|
if ($._colorFormat == 255) {
|
|
2110
|
-
q.Color = srgb ? Q5.
|
|
2131
|
+
q.Color = srgb ? Q5.ColorRGB_8 : Q5.ColorRGB_P3_8;
|
|
2111
2132
|
} else {
|
|
2112
|
-
q.Color = srgb ? Q5.
|
|
2133
|
+
q.Color = srgb ? Q5.ColorRGB : Q5.ColorRGB_P3;
|
|
2113
2134
|
}
|
|
2114
2135
|
$._colorMode = 'rgb';
|
|
2115
2136
|
}
|
|
@@ -2203,7 +2224,8 @@ Q5.modules.color = ($, q) => {
|
|
|
2203
2224
|
|
|
2204
2225
|
$.lightness = (c) => {
|
|
2205
2226
|
if (c.l) return c.l;
|
|
2206
|
-
|
|
2227
|
+
let l = (0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b) * 100;
|
|
2228
|
+
return $._colorFormat == 255 ? l / 255 : l;
|
|
2207
2229
|
};
|
|
2208
2230
|
$.hue = (c) => {
|
|
2209
2231
|
if (c.h) return c.h;
|
|
@@ -2248,6 +2270,12 @@ Q5.Color = class {
|
|
|
2248
2270
|
constructor() {
|
|
2249
2271
|
this._q5Color = true;
|
|
2250
2272
|
}
|
|
2273
|
+
get alpha() {
|
|
2274
|
+
return this.a;
|
|
2275
|
+
}
|
|
2276
|
+
set alpha(v) {
|
|
2277
|
+
this.a = v;
|
|
2278
|
+
}
|
|
2251
2279
|
};
|
|
2252
2280
|
|
|
2253
2281
|
Q5.ColorOKLCH = class extends Q5.Color {
|
|
@@ -2289,15 +2317,9 @@ Q5.ColorOKLCH = class extends Q5.Color {
|
|
|
2289
2317
|
set hue(v) {
|
|
2290
2318
|
this.h = v;
|
|
2291
2319
|
}
|
|
2292
|
-
get alpha() {
|
|
2293
|
-
return this.a;
|
|
2294
|
-
}
|
|
2295
|
-
set alpha(v) {
|
|
2296
|
-
this.a = v;
|
|
2297
|
-
}
|
|
2298
2320
|
};
|
|
2299
2321
|
|
|
2300
|
-
Q5.
|
|
2322
|
+
Q5.ColorRGB = class extends Q5.Color {
|
|
2301
2323
|
constructor(r, g, b, a) {
|
|
2302
2324
|
super();
|
|
2303
2325
|
this.r = r;
|
|
@@ -2317,6 +2339,7 @@ Q5.ColorRGBA = class extends Q5.Color {
|
|
|
2317
2339
|
toString() {
|
|
2318
2340
|
return `color(srgb ${this.r} ${this.g} ${this.b} / ${this.a})`;
|
|
2319
2341
|
}
|
|
2342
|
+
|
|
2320
2343
|
get red() {
|
|
2321
2344
|
return this.r;
|
|
2322
2345
|
}
|
|
@@ -2335,22 +2358,16 @@ Q5.ColorRGBA = class extends Q5.Color {
|
|
|
2335
2358
|
set blue(v) {
|
|
2336
2359
|
this.b = v;
|
|
2337
2360
|
}
|
|
2338
|
-
get alpha() {
|
|
2339
|
-
return this.a;
|
|
2340
|
-
}
|
|
2341
|
-
set alpha(v) {
|
|
2342
|
-
this.a = v;
|
|
2343
|
-
}
|
|
2344
2361
|
};
|
|
2345
2362
|
|
|
2346
|
-
Q5.
|
|
2363
|
+
Q5.ColorRGB_P3 = class extends Q5.ColorRGB {
|
|
2347
2364
|
toString() {
|
|
2348
2365
|
return `color(display-p3 ${this.r} ${this.g} ${this.b} / ${this.a})`;
|
|
2349
2366
|
}
|
|
2350
2367
|
};
|
|
2351
2368
|
|
|
2352
|
-
// legacy 8-bit (0-255) integer color format
|
|
2353
|
-
Q5.
|
|
2369
|
+
// legacy 8-bit (0-255) integer color format, srgb color space
|
|
2370
|
+
Q5.ColorRGB_8 = class extends Q5.ColorRGB {
|
|
2354
2371
|
constructor(r, g, b, a) {
|
|
2355
2372
|
super(r, g, b, a ?? 255);
|
|
2356
2373
|
}
|
|
@@ -2373,7 +2390,7 @@ Q5.ColorRGBA_8 = class extends Q5.ColorRGBA {
|
|
|
2373
2390
|
};
|
|
2374
2391
|
|
|
2375
2392
|
// p3 10-bit color in integer color format, for backwards compatibility
|
|
2376
|
-
Q5.
|
|
2393
|
+
Q5.ColorRGB_P3_8 = class extends Q5.ColorRGB_8 {
|
|
2377
2394
|
constructor(r, g, b, a) {
|
|
2378
2395
|
super(r, g, b, a ?? 255);
|
|
2379
2396
|
this._edited = true;
|
|
@@ -2418,6 +2435,159 @@ Q5.ColorRGBA_P3_8 = class extends Q5.ColorRGBA {
|
|
|
2418
2435
|
return this._css;
|
|
2419
2436
|
}
|
|
2420
2437
|
};
|
|
2438
|
+
|
|
2439
|
+
Q5.ColorHSL = class extends Q5.Color {
|
|
2440
|
+
constructor(h, s, l, a) {
|
|
2441
|
+
super();
|
|
2442
|
+
this.h = h;
|
|
2443
|
+
this.s = s;
|
|
2444
|
+
this.l = l;
|
|
2445
|
+
this.a = a ?? 1;
|
|
2446
|
+
}
|
|
2447
|
+
get levels() {
|
|
2448
|
+
return [this.h, this.s, this.l, this.a];
|
|
2449
|
+
}
|
|
2450
|
+
equals(c) {
|
|
2451
|
+
return c && this.h == c.h && this.s == c.s && this.l == c.l && this.a == c.a;
|
|
2452
|
+
}
|
|
2453
|
+
isSameColor(c) {
|
|
2454
|
+
return c && this.h == c.h && this.s == c.s && this.l == c.l;
|
|
2455
|
+
}
|
|
2456
|
+
toString() {
|
|
2457
|
+
return `hsl(${this.h} ${this.s} ${this.l} / ${this.a})`;
|
|
2458
|
+
}
|
|
2459
|
+
|
|
2460
|
+
get hue() {
|
|
2461
|
+
return this.h;
|
|
2462
|
+
}
|
|
2463
|
+
set hue(v) {
|
|
2464
|
+
this.h = v;
|
|
2465
|
+
}
|
|
2466
|
+
get saturation() {
|
|
2467
|
+
return this.s;
|
|
2468
|
+
}
|
|
2469
|
+
set saturation(v) {
|
|
2470
|
+
this.s = v;
|
|
2471
|
+
}
|
|
2472
|
+
get lightness() {
|
|
2473
|
+
return this.l;
|
|
2474
|
+
}
|
|
2475
|
+
set lightness(v) {
|
|
2476
|
+
this.l = v;
|
|
2477
|
+
}
|
|
2478
|
+
};
|
|
2479
|
+
|
|
2480
|
+
Q5.ColorHSL_P3 = class extends Q5.ColorHSL {
|
|
2481
|
+
toString() {
|
|
2482
|
+
let o = Q5.HSLtoRGB(this.h, this.s, this.l);
|
|
2483
|
+
return `color(display-p3 ${o.join(' ')} / ${this.a})`;
|
|
2484
|
+
}
|
|
2485
|
+
};
|
|
2486
|
+
|
|
2487
|
+
Q5.ColorHSB = class extends Q5.ColorHSL {
|
|
2488
|
+
constructor(h, s, b, a) {
|
|
2489
|
+
super(h, s, b, a);
|
|
2490
|
+
delete this.l;
|
|
2491
|
+
this.b = b;
|
|
2492
|
+
}
|
|
2493
|
+
get levels() {
|
|
2494
|
+
return [this.h, this.s, this.b, this.a];
|
|
2495
|
+
}
|
|
2496
|
+
equals(c) {
|
|
2497
|
+
return c && this.h == c.h && this.s == c.s && this.b == c.b && this.a == c.a;
|
|
2498
|
+
}
|
|
2499
|
+
isSameColor(c) {
|
|
2500
|
+
return c && this.h == c.h && this.s == c.s && this.b == c.b;
|
|
2501
|
+
}
|
|
2502
|
+
toString() {
|
|
2503
|
+
let o = Q5.HSBtoHSL(this.h, this.s, this.b);
|
|
2504
|
+
return `hsl(${o.join(' ')} / ${this.a})`;
|
|
2505
|
+
}
|
|
2506
|
+
|
|
2507
|
+
get v() {
|
|
2508
|
+
return this.b;
|
|
2509
|
+
}
|
|
2510
|
+
set v(v) {
|
|
2511
|
+
this.b = v;
|
|
2512
|
+
}
|
|
2513
|
+
get brightness() {
|
|
2514
|
+
return this.b;
|
|
2515
|
+
}
|
|
2516
|
+
set brightness(v) {
|
|
2517
|
+
this.b = v;
|
|
2518
|
+
}
|
|
2519
|
+
get value() {
|
|
2520
|
+
return this.b;
|
|
2521
|
+
}
|
|
2522
|
+
set value(v) {
|
|
2523
|
+
this.b = v;
|
|
2524
|
+
}
|
|
2525
|
+
};
|
|
2526
|
+
|
|
2527
|
+
Q5.ColorHSB_P3 = class extends Q5.ColorHSB {
|
|
2528
|
+
toString() {
|
|
2529
|
+
let o = Q5.HSLtoRGB(...Q5.HSBtoHSL(this.h, this.s, this.b));
|
|
2530
|
+
return `color(display-p3 ${o.join(' ')} / ${this.a})`;
|
|
2531
|
+
}
|
|
2532
|
+
};
|
|
2533
|
+
|
|
2534
|
+
Q5.HSLtoRGB = (h, s, l) => {
|
|
2535
|
+
l /= 100;
|
|
2536
|
+
let m = (s / 100) * Math.min(l, 1 - l);
|
|
2537
|
+
let f = (n, k = (n + h / 30) % 12) => l - m * Math.max(Math.min(k - 3, 9 - k, 1), -1);
|
|
2538
|
+
return [f(0), f(8), f(4)];
|
|
2539
|
+
};
|
|
2540
|
+
|
|
2541
|
+
Q5.HSBtoHSL = (h, s, v, l = v * (1 - s / 200)) => [h, !l || l == 100 ? 0 : ((v - l) / Math.min(l, 100 - l)) * 100, l];
|
|
2542
|
+
|
|
2543
|
+
{
|
|
2544
|
+
const multiplyMatrices = (A, B) => [
|
|
2545
|
+
A[0] * B[0] + A[1] * B[1] + A[2] * B[2],
|
|
2546
|
+
A[3] * B[0] + A[4] * B[1] + A[5] * B[2],
|
|
2547
|
+
A[6] * B[0] + A[7] * B[1] + A[8] * B[2]
|
|
2548
|
+
];
|
|
2549
|
+
|
|
2550
|
+
const oklch2oklab = (l, c, h) => [
|
|
2551
|
+
l,
|
|
2552
|
+
isNaN(h) ? 0 : c * Math.cos((h * Math.PI) / 180),
|
|
2553
|
+
isNaN(h) ? 0 : c * Math.sin((h * Math.PI) / 180)
|
|
2554
|
+
];
|
|
2555
|
+
|
|
2556
|
+
const srgbLinear2rgb = (rgb) =>
|
|
2557
|
+
rgb.map((c) =>
|
|
2558
|
+
Math.max(
|
|
2559
|
+
0,
|
|
2560
|
+
Math.min(1, Math.abs(c) > 0.0031308 ? (c < 0 ? -1 : 1) * (1.055 * Math.abs(c) ** (1 / 2.4) - 0.055) : 12.92 * c)
|
|
2561
|
+
)
|
|
2562
|
+
);
|
|
2563
|
+
|
|
2564
|
+
const oklab2xyz = (lab) => {
|
|
2565
|
+
const LMSg = multiplyMatrices(
|
|
2566
|
+
[
|
|
2567
|
+
1, 0.3963377773761749, 0.2158037573099136, 1, -0.1055613458156586, -0.0638541728258133, 1, -0.0894841775298119,
|
|
2568
|
+
-1.2914855480194092
|
|
2569
|
+
],
|
|
2570
|
+
lab
|
|
2571
|
+
);
|
|
2572
|
+
return multiplyMatrices(
|
|
2573
|
+
[
|
|
2574
|
+
1.2268798758459243, -0.5578149944602171, 0.2813910456659647, -0.0405757452148008, 1.112286803280317,
|
|
2575
|
+
-0.0717110580655164, -0.0763729366746601, -0.4214933324022432, 1.5869240198367816
|
|
2576
|
+
],
|
|
2577
|
+
LMSg.map((val) => val ** 3)
|
|
2578
|
+
);
|
|
2579
|
+
};
|
|
2580
|
+
const xyz2rgbLinear = (xyz) =>
|
|
2581
|
+
multiplyMatrices(
|
|
2582
|
+
[
|
|
2583
|
+
3.2409699419045226, -1.537383177570094, -0.4986107602930034, -0.9692436362808796, 1.8759675015077202,
|
|
2584
|
+
0.04155505740717559, 0.05563007969699366, -0.20397695888897652, 1.0569715142428786
|
|
2585
|
+
],
|
|
2586
|
+
xyz
|
|
2587
|
+
);
|
|
2588
|
+
|
|
2589
|
+
Q5.OKLCHtoRGB = (l, c, h) => srgbLinear2rgb(xyz2rgbLinear(oklab2xyz(oklch2oklab(l, c, h))));
|
|
2590
|
+
}
|
|
2421
2591
|
Q5.modules.display = ($) => {
|
|
2422
2592
|
if (!$.canvas || $._scope == 'graphics') return;
|
|
2423
2593
|
|
|
@@ -3552,13 +3722,13 @@ Q5.modules.record = ($, q) => {
|
|
|
3552
3722
|
.rec button,
|
|
3553
3723
|
.rec select,
|
|
3554
3724
|
.rec input,
|
|
3555
|
-
.rec
|
|
3725
|
+
.rec span {
|
|
3556
3726
|
font-family: sans-serif;
|
|
3557
3727
|
font-size: 14px;
|
|
3558
3728
|
padding: 2px 10px;
|
|
3559
3729
|
border-radius: 18px;
|
|
3560
3730
|
outline: none;
|
|
3561
|
-
background
|
|
3731
|
+
background: #232529;
|
|
3562
3732
|
color: #d4dae6;
|
|
3563
3733
|
box-shadow: #0000001a 0px 4px 12px;
|
|
3564
3734
|
border: 1px solid #46494e;
|
|
@@ -3567,13 +3737,28 @@ Q5.modules.record = ($, q) => {
|
|
|
3567
3737
|
transition: all 0.3s;
|
|
3568
3738
|
}
|
|
3569
3739
|
|
|
3740
|
+
.rec .bitrate input {
|
|
3741
|
+
border-radius: 18px 0 0 18px;
|
|
3742
|
+
border-right: 0;
|
|
3743
|
+
width: 40px;
|
|
3744
|
+
padding: 2px 5px 2px 10px;
|
|
3745
|
+
text-align: right;
|
|
3746
|
+
}
|
|
3747
|
+
|
|
3748
|
+
.rec .bitrate span {
|
|
3749
|
+
border-radius: 0 18px 18px 0;
|
|
3750
|
+
border-left: 0;
|
|
3751
|
+
padding: 2px 10px 2px 5px;
|
|
3752
|
+
background: #333;
|
|
3753
|
+
}
|
|
3754
|
+
|
|
3570
3755
|
.rec .record-button {
|
|
3571
3756
|
color: #cc3e44;
|
|
3572
3757
|
font-size: 18px;
|
|
3573
3758
|
}
|
|
3574
3759
|
|
|
3575
3760
|
.rec select:hover,
|
|
3576
|
-
.rec button:hover { background
|
|
3761
|
+
.rec button:hover { background: #292b30; }
|
|
3577
3762
|
|
|
3578
3763
|
.rec button:disabled {
|
|
3579
3764
|
opacity: 0.5;
|
|
@@ -3617,10 +3802,17 @@ Q5.modules.record = ($, q) => {
|
|
|
3617
3802
|
formatSelect.title = 'Video Format';
|
|
3618
3803
|
rec.append(formatSelect);
|
|
3619
3804
|
|
|
3805
|
+
let div = $.createEl('div');
|
|
3806
|
+
div.className = 'bitrate';
|
|
3807
|
+
div.style.display = 'flex';
|
|
3808
|
+
rec.append(div);
|
|
3809
|
+
|
|
3620
3810
|
bitrateInput = $.createInput();
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3811
|
+
let span = document.createElement('span');
|
|
3812
|
+
span.textContent = 'mbps';
|
|
3813
|
+
bitrateInput.title = span.title = 'Video Bitrate';
|
|
3814
|
+
div.append(bitrateInput);
|
|
3815
|
+
div.append(span);
|
|
3624
3816
|
|
|
3625
3817
|
rec.encoderSettings = {};
|
|
3626
3818
|
|
|
@@ -4534,9 +4726,11 @@ struct Q5 {
|
|
|
4534
4726
|
$._pipelineConfigs = [];
|
|
4535
4727
|
$._pipelines = [];
|
|
4536
4728
|
$._buffers = [];
|
|
4729
|
+
$._prevFramePL = 0;
|
|
4537
4730
|
$._framePL = 0;
|
|
4538
4731
|
|
|
4539
4732
|
// local variables used for slightly better performance
|
|
4733
|
+
|
|
4540
4734
|
// stores pipeline shifts and vertex counts/image indices
|
|
4541
4735
|
let drawStack = ($.drawStack = []);
|
|
4542
4736
|
|
|
@@ -4573,7 +4767,7 @@ struct Q5 {
|
|
|
4573
4767
|
$.bindGroupLayouts = [mainLayout];
|
|
4574
4768
|
|
|
4575
4769
|
let uniformBuffer = Q5.device.createBuffer({
|
|
4576
|
-
size: 64,
|
|
4770
|
+
size: 64,
|
|
4577
4771
|
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
|
|
4578
4772
|
});
|
|
4579
4773
|
|
|
@@ -4673,7 +4867,7 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
4673
4867
|
fragment: {
|
|
4674
4868
|
module: frameShader,
|
|
4675
4869
|
entryPoint: 'fragMain',
|
|
4676
|
-
targets: [{ format
|
|
4870
|
+
targets: [{ format }]
|
|
4677
4871
|
},
|
|
4678
4872
|
primitive: { topology: 'triangle-strip' },
|
|
4679
4873
|
multisample: { count: 4 }
|
|
@@ -4701,27 +4895,23 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
4701
4895
|
createMainView();
|
|
4702
4896
|
};
|
|
4703
4897
|
|
|
4704
|
-
$.pixelDensity = (v) => {
|
|
4705
|
-
if (!v || v == $._pixelDensity) return $._pixelDensity;
|
|
4706
|
-
$._pixelDensity = v;
|
|
4707
|
-
$._setCanvasSize(c.w, c.h);
|
|
4708
|
-
createMainView();
|
|
4709
|
-
return v;
|
|
4710
|
-
};
|
|
4711
|
-
|
|
4712
|
-
// current color index, used to associate a vertex with a color
|
|
4713
4898
|
let addColor = (r, g, b, a = 1) => {
|
|
4714
|
-
if (typeof r == 'string'
|
|
4715
|
-
|
|
4899
|
+
if (typeof r == 'string' || $._colorMode != 'rgb') {
|
|
4900
|
+
r = $.color(r, g, b, a);
|
|
4901
|
+
} else if (b == undefined) {
|
|
4716
4902
|
// grayscale mode `fill(1, 0.5)`
|
|
4717
4903
|
a = g ?? 1;
|
|
4718
4904
|
g = b = r;
|
|
4719
4905
|
}
|
|
4720
4906
|
if (r._q5Color) {
|
|
4721
|
-
|
|
4722
|
-
b =
|
|
4723
|
-
|
|
4724
|
-
|
|
4907
|
+
let c = r;
|
|
4908
|
+
if (c.r) ({ r, g, b, a } = c);
|
|
4909
|
+
else {
|
|
4910
|
+
if (c.c) c = Q5.OKLCHtoRGB(c.l, c.c, c.h);
|
|
4911
|
+
else if (c.l) c = Q5.HSLtoRGB(c.h, c.s, c.l);
|
|
4912
|
+
else c = Q5.HSLtoRGB(...Q5.HSBtoHSL(c.h, c.s, c.b));
|
|
4913
|
+
[r, g, b, a] = c;
|
|
4914
|
+
}
|
|
4725
4915
|
}
|
|
4726
4916
|
|
|
4727
4917
|
let cs = colorStack,
|
|
@@ -4754,7 +4944,6 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
4754
4944
|
$._tint = colorIndex;
|
|
4755
4945
|
};
|
|
4756
4946
|
$.opacity = (a) => ($._globalAlpha = a);
|
|
4757
|
-
|
|
4758
4947
|
$.noFill = () => ($._doFill = false);
|
|
4759
4948
|
$.noStroke = () => ($._doStroke = false);
|
|
4760
4949
|
$.noTint = () => ($._tint = 1);
|
|
@@ -4762,6 +4951,7 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
4762
4951
|
$._strokeWeight = 1;
|
|
4763
4952
|
$._hsw = 0.5;
|
|
4764
4953
|
$._scaledSW = 1;
|
|
4954
|
+
|
|
4765
4955
|
$.strokeWeight = (v) => {
|
|
4766
4956
|
v = Math.abs(v);
|
|
4767
4957
|
$._strokeWeight = v;
|
|
@@ -4912,7 +5102,7 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
4912
5102
|
$._matrixDirty = true;
|
|
4913
5103
|
};
|
|
4914
5104
|
|
|
4915
|
-
//
|
|
5105
|
+
// saves the current matrix state
|
|
4916
5106
|
$._saveMatrix = () => {
|
|
4917
5107
|
transforms.set(matrix, matrices.length * MATRIX_SIZE);
|
|
4918
5108
|
$._matrixIndex = matrices.length;
|
|
@@ -5044,13 +5234,28 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5044
5234
|
};
|
|
5045
5235
|
|
|
5046
5236
|
let shouldClear;
|
|
5237
|
+
|
|
5047
5238
|
$.clear = () => {
|
|
5048
5239
|
shouldClear = true;
|
|
5049
5240
|
};
|
|
5050
5241
|
|
|
5051
|
-
$.
|
|
5052
|
-
|
|
5242
|
+
$.background = (r, g, b, a) => {
|
|
5243
|
+
$.push();
|
|
5244
|
+
$.resetMatrix();
|
|
5245
|
+
if (r.canvas) {
|
|
5246
|
+
let img = r;
|
|
5247
|
+
$._imageMode = 'corner';
|
|
5248
|
+
$.image(img, -c.hw, -c.hh, c.w, c.h);
|
|
5249
|
+
} else {
|
|
5250
|
+
$._rectMode = 'corner';
|
|
5251
|
+
$.fill(r, g, b, a);
|
|
5252
|
+
$._doStroke = false;
|
|
5253
|
+
$.rect(-c.hw, -c.hh, c.w, c.h);
|
|
5254
|
+
}
|
|
5255
|
+
$.pop();
|
|
5256
|
+
};
|
|
5053
5257
|
|
|
5258
|
+
$._beginRender = () => {
|
|
5054
5259
|
// swap the frame textures
|
|
5055
5260
|
const temp = frameA;
|
|
5056
5261
|
frameA = frameB;
|
|
@@ -5081,7 +5286,7 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5081
5286
|
});
|
|
5082
5287
|
|
|
5083
5288
|
if (!shouldClear) {
|
|
5084
|
-
pass.setPipeline($._pipelines[
|
|
5289
|
+
pass.setPipeline($._pipelines[$._prevFramePL]);
|
|
5085
5290
|
pass.setBindGroup(0, frameBindGroup);
|
|
5086
5291
|
pass.draw(4);
|
|
5087
5292
|
}
|
|
@@ -5098,6 +5303,8 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5098
5303
|
new Float32Array(transformBuffer.getMappedRange()).set(transforms.slice(0, matrices.length * MATRIX_SIZE));
|
|
5099
5304
|
transformBuffer.unmap();
|
|
5100
5305
|
|
|
5306
|
+
$._buffers.push(transformBuffer);
|
|
5307
|
+
|
|
5101
5308
|
let colorsBuffer = Q5.device.createBuffer({
|
|
5102
5309
|
size: colorStackIndex * 4,
|
|
5103
5310
|
usage: GPUBufferUsage.STORAGE,
|
|
@@ -5107,6 +5314,8 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5107
5314
|
new Float32Array(colorsBuffer.getMappedRange()).set(colorStack.slice(0, colorStackIndex));
|
|
5108
5315
|
colorsBuffer.unmap();
|
|
5109
5316
|
|
|
5317
|
+
$._buffers.push(colorsBuffer);
|
|
5318
|
+
|
|
5110
5319
|
$._uniforms = [
|
|
5111
5320
|
$.width,
|
|
5112
5321
|
$.height,
|
|
@@ -5167,7 +5376,7 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5167
5376
|
pass.setBindGroup(1, $._textureBindGroups[v]);
|
|
5168
5377
|
pass.draw(4, 1, imageVertOffset);
|
|
5169
5378
|
imageVertOffset += 4;
|
|
5170
|
-
} else
|
|
5379
|
+
} else {
|
|
5171
5380
|
// draw a shape
|
|
5172
5381
|
// v is the number of vertices
|
|
5173
5382
|
pass.draw(v, 1, drawVertOffset);
|
|
@@ -5176,7 +5385,7 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5176
5385
|
}
|
|
5177
5386
|
};
|
|
5178
5387
|
|
|
5179
|
-
$._finishRender = () => {
|
|
5388
|
+
$._finishRender = async () => {
|
|
5180
5389
|
pass.end();
|
|
5181
5390
|
|
|
5182
5391
|
pass = encoder.beginRenderPass({
|
|
@@ -5206,6 +5415,7 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5206
5415
|
pass.end();
|
|
5207
5416
|
|
|
5208
5417
|
Q5.device.queue.submit([encoder.finish()]);
|
|
5418
|
+
$._pass = pass = encoder = null;
|
|
5209
5419
|
|
|
5210
5420
|
// destroy buffers
|
|
5211
5421
|
Q5.device.queue.onSubmittedWorkDone().then(() => {
|
|
@@ -5213,8 +5423,6 @@ fn fragMain(f: FragParams ) -> @location(0) vec4f {
|
|
|
5213
5423
|
$._buffers = [];
|
|
5214
5424
|
});
|
|
5215
5425
|
|
|
5216
|
-
$._pass = pass = encoder = null;
|
|
5217
|
-
|
|
5218
5426
|
// clear the stacks for the next frame
|
|
5219
5427
|
drawStack.splice(0, drawStack.length);
|
|
5220
5428
|
colorIndex = 1;
|
|
@@ -5864,22 +6072,6 @@ fn fragMain(f: FragParams) -> @location(0) vec4f {
|
|
|
5864
6072
|
$.endShape(true);
|
|
5865
6073
|
};
|
|
5866
6074
|
|
|
5867
|
-
$.background = (r, g, b, a) => {
|
|
5868
|
-
$.push();
|
|
5869
|
-
$.resetMatrix();
|
|
5870
|
-
if (r.canvas) {
|
|
5871
|
-
let img = r;
|
|
5872
|
-
$._imageMode = 'corner';
|
|
5873
|
-
$.image(img, -c.hw, -c.hh, c.w, c.h);
|
|
5874
|
-
} else {
|
|
5875
|
-
$._rectMode = 'corner';
|
|
5876
|
-
$.fill(r, g, b, a);
|
|
5877
|
-
$._doStroke = false;
|
|
5878
|
-
$.rect(-c.hw, -c.hh, c.w, c.h);
|
|
5879
|
-
}
|
|
5880
|
-
$.pop();
|
|
5881
|
-
};
|
|
5882
|
-
|
|
5883
6075
|
$._hooks.preRender.push(() => {
|
|
5884
6076
|
$._pass.setPipeline($._pipelines[1]);
|
|
5885
6077
|
|
|
@@ -7027,6 +7219,7 @@ Q5.renderers.webgpu.shaders = ($) => {
|
|
|
7027
7219
|
|
|
7028
7220
|
let pl = plCounters[type];
|
|
7029
7221
|
$._pipelines[pl] = Q5.device.createRenderPipeline(config);
|
|
7222
|
+
$._pipelines[pl].shader = shader;
|
|
7030
7223
|
shader.pipelineIndex = pl;
|
|
7031
7224
|
|
|
7032
7225
|
plCounters[type]++;
|
|
@@ -7041,15 +7234,17 @@ Q5.renderers.webgpu.shaders = ($) => {
|
|
|
7041
7234
|
$.createTextShader = (code) => $._createShader(code, 'text');
|
|
7042
7235
|
|
|
7043
7236
|
$.shader = (shader) => {
|
|
7044
|
-
|
|
7237
|
+
if (shader.applyBeforeDraw) $._prevFramePL = shader.pipelineIndex;
|
|
7238
|
+
else $['_' + shader.type + 'PL'] = shader.pipelineIndex;
|
|
7045
7239
|
};
|
|
7046
7240
|
|
|
7047
7241
|
$.resetShader = (type = 'shapes') => {
|
|
7242
|
+
if (type == 'frame') $._prevFramePL = 0;
|
|
7048
7243
|
$['_' + type + 'PL'] = pipelineTypes.indexOf(type);
|
|
7049
7244
|
};
|
|
7050
7245
|
|
|
7051
7246
|
$.resetShaders = () => {
|
|
7052
|
-
$._framePL = 0;
|
|
7247
|
+
$._prevFramePL = $._framePL = 0;
|
|
7053
7248
|
$._shapesPL = 1;
|
|
7054
7249
|
$._imagePL = 2;
|
|
7055
7250
|
$._videoPL = 3;
|