q5 2.0.5 → 2.0.12
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 +16 -19
- package/package.json +2 -2
- package/q5.js +59 -53
- package/q5.min.js +1 -1
- package/src/q5-2d-canvas.js +1 -1
- package/src/q5-2d-drawing.js +4 -4
- package/src/q5-2d-image.js +21 -21
- package/src/q5-2d-text.js +2 -5
- package/src/q5-ai.js +1 -1
- package/src/q5-color.js +22 -8
- package/src/q5-core.js +1 -2
- package/src/q5-input.js +5 -7
- package/src/q5-math.js +1 -3
- package/src/q5-vector.js +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# <img src="q5js_logo.webp" height="64"> <img src="q5js_brand.webp" height="64">
|
|
2
2
|
|
|
3
|
-
The sequel to p5.js is here!
|
|
3
|
+
The unsanctioned sequel to p5.js is here!
|
|
4
4
|
|
|
5
5
|
**q5.js** implements all of [p5][]'s 2D drawing, math, and user input functionality.
|
|
6
6
|
|
|
@@ -282,10 +282,16 @@ An increase in performance of even a few frames per second can make a significan
|
|
|
282
282
|
|
|
283
283
|
I was also interested in working on q5 because for a lot of p5.js users, the library itself is a black box. Even as an expert JS programmer and someone who teaches CS for a living, I still find myself scratching my head when I look at the p5.js source code. p5 was initially released 10 years ago and bad design choices were made due to JS limitations at the time. It's also become an absolutely massive library, with literally over 100,000 lines of code and documentation!
|
|
284
284
|
|
|
285
|
-
I think it'd be better if the canvas mode, webgl mode, Friendly Error System, and accessibility features of p5 were offered in separate files. Yet, the powers that be at the Processing Foundation have made it clear that they don't want to do that. So q5 is a good alternative that trims out the fat.
|
|
286
|
-
|
|
287
285
|
Thanks in large part to @LingDong-'s design, q5 is well organized, concise, and utilizes many modern JS features! I think even without inline documentation, the source code is easier for experienced JS programmers to comprehend.
|
|
288
286
|
|
|
287
|
+
I also started working on q5 because unfortunately I had a bad experience with The Processing Foundation. Simple bug fixes I contributed to p5.js all took over 5 months to be released. That's unacceptable given how well funded TPF is. I began to see p5play solely relying on p5.js as a liability. So being able to provide q5 as an alternative became a priority for me.
|
|
288
|
+
|
|
289
|
+
I think the problem is that management takes exorbitant salaries, 76% of the [annual budget](https://processingfoundation.report/), yet many of them still work [other full time jobs](https://www.linkedin.com/in/edsaber/). They seem to expect that just because p5.js is open source that volunteers will do most of the dev work. 🕵️
|
|
290
|
+
|
|
291
|
+
When criticized, TPF staff play the victim, silence dissent, and badmouth former contributors, regardless of how much time and effort they've donated to TPF projects. This behavior is inexcusable. Its driving away the people who made Processing and p5 great. 🚪
|
|
292
|
+
|
|
293
|
+
In October 2023, The Processing Foundation's co-founder, Ben Fry, resigned and publicly criticized management for [squandering millions of dollars in donations](https://x.com/ben_fry/status/1709400641456501020). I agree with Ben and I hope that TPF will hire full time developers to work on p5.js in the future. The summer 2024 pro5 grants are a great step in the right direction.
|
|
294
|
+
|
|
289
295
|
## More exclusive features
|
|
290
296
|
|
|
291
297
|
Features added by @quinton-ashley:
|
|
@@ -307,9 +313,10 @@ Features added by @LingDong-:
|
|
|
307
313
|
|
|
308
314
|
## Porting from p5.js
|
|
309
315
|
|
|
310
|
-
- `createCanvas` must be run before any rendering functions are called. If it's not run before the draw loop starts, then q5 will run `createCanvas(100, 100)` automatically.
|
|
311
|
-
- `
|
|
312
|
-
- `
|
|
316
|
+
- `createCanvas` must be run before any rendering functions are called. It can be run in `preload`. If it's not run before the draw loop starts, then q5 will run `createCanvas(100, 100)` automatically.
|
|
317
|
+
- `colorMode` supports 'rgb', 'srgb', and 'oklch'. Color modes like hsv are outdated, OKLCH is superior.
|
|
318
|
+
- `color` function only accepts numeric input, hex, and common named colors. It doesn't parse strings like `color('hsl(160, 100%, 50%)')`.
|
|
319
|
+
- `fill`, `stroke`, and `background` can accept any CSS color string.
|
|
313
320
|
- `colorMode` function only accepts "rgb", "srgb", or "oklch" because other formats that p5 still supports like hsv are obsolete.
|
|
314
321
|
- `noise` function's default noise algorithm is perlin noise. p5's default noise is called "blocky" noise in q5 and using it requires loading the src/q5-noisier.js module.
|
|
315
322
|
|
|
@@ -364,25 +371,15 @@ Higher FPS (frames per second) is better.
|
|
|
364
371
|
|
|
365
372
|
<sub>\* Only for browsers that support CanvasRenderingContext2D.filter ([75% of all](https://caniuse.com/#feat=mdn-api_canvasrenderingcontext2d_filter) as of Aug 2020, including Chrome, Firefox and Edge). For those that don't, performance is similar to p5.js, as identical implementations are usually used as fallbacks.</sub>
|
|
366
373
|
|
|
367
|
-
##
|
|
368
|
-
|
|
369
|
-
We aim to make contributing to the q5 project more approachable for non-experts by using modern JavaScript without any complicated build tools or frameworks.
|
|
370
|
-
|
|
371
|
-
All contributors are required to check their ego at the door and be open to feedback. Critique of code is not a critique of the person who wrote it. We're all here to learn and work with others to collectively write the best code possible.
|
|
372
|
-
|
|
373
|
-
Code is a language art that can be subjectively judged by its effectiveness at communicating its functionality to humans. Code can also be objectively measured by its performance. Since JavaScript is served over a network, size is a factor as well. Therefore, the q5 team strives to balance code readability with brevity and performance.
|
|
374
|
-
|
|
375
|
-
Check out the [q5 planning board](https://github.com/orgs/q5js/projects/1/views/1).
|
|
376
|
-
|
|
377
|
-
## Organization
|
|
374
|
+
## Contributing
|
|
378
375
|
|
|
379
|
-
|
|
376
|
+
See the [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) and [CONTRIBUTING.md](CONTRIBUTING.md) files for more information.
|
|
380
377
|
|
|
381
378
|
## Licensing
|
|
382
379
|
|
|
383
380
|
q5.js was created by the q5 team and is licensed under the LGPLv3. q5 is not affiliated with The Processing Foundation.
|
|
384
381
|
|
|
385
|
-
@LingDong- created the original q5xjs library which is
|
|
382
|
+
@LingDong- created the original q5xjs library which is Unlicense licensed.
|
|
386
383
|
|
|
387
384
|
p5.js is licensed under the LGPLv2, the two small sections of p5' code directly copied into q5 are credited below. The rest of q5 is a new implementation of part of the p5 API. APIs are not copyrightable in the United States, as decided by the Supreme Court in the Google v Oracle case.
|
|
388
385
|
|
package/package.json
CHANGED
package/q5.js
CHANGED
|
@@ -81,7 +81,6 @@ function Q5(scope, parent) {
|
|
|
81
81
|
p.frameCount++;
|
|
82
82
|
let pre = performance.now();
|
|
83
83
|
for (let m of Q5.prototype._methods.pre) m.call($);
|
|
84
|
-
firstVertex = true;
|
|
85
84
|
if ($.ctx) $.ctx.save();
|
|
86
85
|
$.draw();
|
|
87
86
|
for (let m of Q5.prototype._methods.post) m.call($);
|
|
@@ -264,7 +263,7 @@ Q5.prototype.registerPreloadMethod = (n, fn) => (Q5.prototype[n] = fn[n]);
|
|
|
264
263
|
|
|
265
264
|
if (Q5._nodejs) global.p5 ??= global.Q5 = Q5;
|
|
266
265
|
else if (typeof window == 'object') window.p5 ??= window.Q5 = Q5;
|
|
267
|
-
else window = 0;
|
|
266
|
+
else global.window = 0;
|
|
268
267
|
|
|
269
268
|
if (typeof document == 'object') {
|
|
270
269
|
document.addEventListener('DOMContentLoaded', () => {
|
|
@@ -535,6 +534,7 @@ Q5.modules.q2d_canvas = ($, p) => {
|
|
|
535
534
|
let g = new Q5('graphics');
|
|
536
535
|
opt ??= {};
|
|
537
536
|
opt.alpha ??= true;
|
|
537
|
+
opt.colorSpace ??= $.canvas.colorSpace;
|
|
538
538
|
g._createCanvas.call($, w, h, opt);
|
|
539
539
|
return g;
|
|
540
540
|
};
|
|
@@ -551,7 +551,6 @@ Q5.modules.q2d_canvas = ($, p) => {
|
|
|
551
551
|
|
|
552
552
|
Q5.canvasOptions = {
|
|
553
553
|
alpha: false,
|
|
554
|
-
desynchronized: false,
|
|
555
554
|
colorSpace: 'display-p3'
|
|
556
555
|
};
|
|
557
556
|
|
|
@@ -630,7 +629,7 @@ Q5.modules.q2d_drawing = ($) => {
|
|
|
630
629
|
$._strokeSet = true;
|
|
631
630
|
if (Q5.Color) {
|
|
632
631
|
if (!c._q5Color && typeof c != 'string') c = $.color(...arguments);
|
|
633
|
-
else if ($.
|
|
632
|
+
else if ($._namedColors[c]) c = $.color(...$._namedColors[c]);
|
|
634
633
|
if (c.a <= 0) return ($._doStroke = false);
|
|
635
634
|
}
|
|
636
635
|
$.ctx.strokeStyle = c.toString();
|
|
@@ -641,7 +640,7 @@ Q5.modules.q2d_drawing = ($) => {
|
|
|
641
640
|
$._fillSet = true;
|
|
642
641
|
if (Q5.Color) {
|
|
643
642
|
if (!c._q5Color && typeof c != 'string') c = $.color(...arguments);
|
|
644
|
-
else if ($.
|
|
643
|
+
else if ($._namedColors[c]) c = $.color(...$._namedColors[c]);
|
|
645
644
|
if (c.a <= 0) return ($._doFill = false);
|
|
646
645
|
}
|
|
647
646
|
$.ctx.fillStyle = c.toString();
|
|
@@ -668,7 +667,7 @@ Q5.modules.q2d_drawing = ($) => {
|
|
|
668
667
|
$.ctx.resetTransform();
|
|
669
668
|
if (Q5.Color) {
|
|
670
669
|
if (!c._q5Color && typeof c != 'string') c = $.color(...arguments);
|
|
671
|
-
else if ($.
|
|
670
|
+
else if ($._namedColors[c]) c = $.color(...$._namedColors[c]);
|
|
672
671
|
}
|
|
673
672
|
$.ctx.fillStyle = c.toString();
|
|
674
673
|
$.ctx.fillRect(0, 0, $.canvas.width, $.canvas.height);
|
|
@@ -1072,12 +1071,15 @@ Q5.modules.q2d_drawing = ($) => {
|
|
|
1072
1071
|
};
|
|
1073
1072
|
|
|
1074
1073
|
$.inStroke = (x, y) => {
|
|
1075
|
-
const pd =
|
|
1074
|
+
const pd = $._pixelDensity;
|
|
1076
1075
|
return $.ctx.isPointInStroke(x * pd, y * pd);
|
|
1077
1076
|
};
|
|
1078
1077
|
};
|
|
1079
1078
|
Q5.modules.q2d_image = ($, p) => {
|
|
1080
1079
|
$.createImage = (w, h, opt) => {
|
|
1080
|
+
opt ??= {};
|
|
1081
|
+
opt.alpha ??= true;
|
|
1082
|
+
opt.colorSpace ??= $.canvas.colorSpace || Q5.canvasOptions.colorSpace;
|
|
1081
1083
|
return new Q5.Image(w, h, opt);
|
|
1082
1084
|
};
|
|
1083
1085
|
|
|
@@ -1399,22 +1401,26 @@ Q5.modules.q2d_image = ($, p) => {
|
|
|
1399
1401
|
$.loadImage = function (url, cb, opt) {
|
|
1400
1402
|
if (url.canvas) return url;
|
|
1401
1403
|
if (url.slice(-3).toLowerCase() == 'gif') {
|
|
1402
|
-
throw `
|
|
1404
|
+
throw new Error(`q5 doesn't support GIFs due to their impact on performance. Use a video or animation instead.`);
|
|
1403
1405
|
}
|
|
1404
1406
|
p._preloadCount++;
|
|
1405
1407
|
let last = [...arguments].at(-1);
|
|
1406
|
-
opt = typeof last == 'object' ? last :
|
|
1407
|
-
|
|
1408
|
-
let
|
|
1408
|
+
opt = typeof last == 'object' ? last : null;
|
|
1409
|
+
|
|
1410
|
+
let g = $.createImage(1, 1, opt);
|
|
1411
|
+
|
|
1412
|
+
function loaded(img) {
|
|
1413
|
+
let c = g.ctx;
|
|
1414
|
+
g.width = c.canvas.width = img.naturalWidth || img.width;
|
|
1415
|
+
g.height = c.canvas.height = img.naturalHeight || img.height;
|
|
1416
|
+
c.drawImage(img, 0, 0);
|
|
1417
|
+
p._preloadCount--;
|
|
1418
|
+
if (cb) cb(g);
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1409
1421
|
if (Q5._nodejs && global.CairoCanvas) {
|
|
1410
|
-
CairoCanvas.loadImage(url)
|
|
1411
|
-
.then(
|
|
1412
|
-
g.width = c.canvas.width = img.width;
|
|
1413
|
-
g.height = c.canvas.height = img.height;
|
|
1414
|
-
c.drawImage(img, 0, 0);
|
|
1415
|
-
p._preloadCount--;
|
|
1416
|
-
if (cb) cb(g);
|
|
1417
|
-
})
|
|
1422
|
+
global.CairoCanvas.loadImage(url)
|
|
1423
|
+
.then(loaded)
|
|
1418
1424
|
.catch((e) => {
|
|
1419
1425
|
p._preloadCount--;
|
|
1420
1426
|
throw e;
|
|
@@ -1424,13 +1430,7 @@ Q5.modules.q2d_image = ($, p) => {
|
|
|
1424
1430
|
img.src = url;
|
|
1425
1431
|
img.crossOrigin = 'Anonymous';
|
|
1426
1432
|
img._pixelDensity = 1;
|
|
1427
|
-
img.onload = () =>
|
|
1428
|
-
g.width = c.canvas.width = img.naturalWidth;
|
|
1429
|
-
g.height = c.canvas.height = img.naturalHeight;
|
|
1430
|
-
c.drawImage(img, 0, 0);
|
|
1431
|
-
p._preloadCount--;
|
|
1432
|
-
if (cb) cb(g);
|
|
1433
|
-
};
|
|
1433
|
+
img.onload = () => loaded(img);
|
|
1434
1434
|
img.onerror = (e) => {
|
|
1435
1435
|
p._preloadCount--;
|
|
1436
1436
|
throw e;
|
|
@@ -1454,8 +1454,7 @@ class _Q5Image {
|
|
|
1454
1454
|
Q5.modules[m]($, $);
|
|
1455
1455
|
}
|
|
1456
1456
|
delete this.createCanvas;
|
|
1457
|
-
|
|
1458
|
-
opt.alpha ??= true;
|
|
1457
|
+
|
|
1459
1458
|
this._createCanvas(w, h, '2d', opt);
|
|
1460
1459
|
this._loop = false;
|
|
1461
1460
|
}
|
|
@@ -1674,9 +1673,8 @@ Q5.modules.q2d_text = ($, p) => {
|
|
|
1674
1673
|
|
|
1675
1674
|
$.loadFont = (url, cb) => {
|
|
1676
1675
|
p._preloadCount++;
|
|
1677
|
-
let
|
|
1678
|
-
let
|
|
1679
|
-
let f = new FontFace(name, 'url(' + url + ')');
|
|
1676
|
+
let name = url.split('/').pop().split('.')[0].replace(' ', '');
|
|
1677
|
+
let f = new FontFace(name, `url(${url})`);
|
|
1680
1678
|
document.fonts.add(f);
|
|
1681
1679
|
f.load().then(() => {
|
|
1682
1680
|
p._preloadCount--;
|
|
@@ -1796,7 +1794,6 @@ Q5.modules.q2d_text = ($, p) => {
|
|
|
1796
1794
|
}
|
|
1797
1795
|
if (!$._doFill && !$._doStroke) return;
|
|
1798
1796
|
let c, ti, tg, k, cX, cY, _ascent, _descent;
|
|
1799
|
-
let pd = 1;
|
|
1800
1797
|
let t = $.ctx.getTransform();
|
|
1801
1798
|
let useCache = $._genTextImage || ($._textCache && (t.b != 0 || t.c != 0));
|
|
1802
1799
|
if (!useCache) {
|
|
@@ -1812,7 +1809,6 @@ Q5.modules.q2d_text = ($, p) => {
|
|
|
1812
1809
|
}
|
|
1813
1810
|
tg = $.createGraphics.call($, 1, 1);
|
|
1814
1811
|
c = tg.ctx;
|
|
1815
|
-
pd = $._pixelDensity;
|
|
1816
1812
|
}
|
|
1817
1813
|
c.font = `${$._textStyle} ${$._textSize}px ${$._textFont}`;
|
|
1818
1814
|
let lines = str.split('\n');
|
|
@@ -1878,7 +1874,7 @@ Q5.modules.ai = ($) => {
|
|
|
1878
1874
|
let askAI = e.message?.includes('Ask AI ✨');
|
|
1879
1875
|
if (!askAI) console.error(e);
|
|
1880
1876
|
if (Q5.disableFriendlyErrors) return;
|
|
1881
|
-
if (askAI || !Q5.errorTolerant) noLoop();
|
|
1877
|
+
if (askAI || !Q5.errorTolerant) $.noLoop();
|
|
1882
1878
|
let stackLines = e.stack?.split('\n');
|
|
1883
1879
|
if (!e.stack || stackLines.length <= 1) return;
|
|
1884
1880
|
|
|
@@ -1953,7 +1949,7 @@ Q5.modules.color = ($, p) => {
|
|
|
1953
1949
|
}
|
|
1954
1950
|
};
|
|
1955
1951
|
|
|
1956
|
-
$.
|
|
1952
|
+
$._namedColors = {
|
|
1957
1953
|
aqua: [0, 255, 255],
|
|
1958
1954
|
black: [0, 0, 0],
|
|
1959
1955
|
blue: [0, 0, 255],
|
|
@@ -1994,14 +1990,28 @@ Q5.modules.color = ($, p) => {
|
|
|
1994
1990
|
if (args.length == 1) {
|
|
1995
1991
|
if (typeof c0 == 'string') {
|
|
1996
1992
|
if (c0[0] == '#') {
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
1993
|
+
if (c0.length <= 5) {
|
|
1994
|
+
return new C(
|
|
1995
|
+
parseInt(c0[1] + c0[1], 16),
|
|
1996
|
+
parseInt(c0[2] + c0[2], 16),
|
|
1997
|
+
parseInt(c0[3] + c0[3], 16),
|
|
1998
|
+
c0.length == 4 ? null : parseInt(c0[4] + c0[4], 16)
|
|
1999
|
+
);
|
|
2000
|
+
} else {
|
|
2001
|
+
return new C(
|
|
2002
|
+
parseInt(c0.slice(1, 3), 16),
|
|
2003
|
+
parseInt(c0.slice(3, 5), 16),
|
|
2004
|
+
parseInt(c0.slice(5, 7), 16),
|
|
2005
|
+
c0.length == 7 ? null : parseInt(c0.slice(7, 9), 16)
|
|
2006
|
+
);
|
|
2007
|
+
}
|
|
2008
|
+
} else if ($._namedColors[c0]) return new C(...$._namedColors[c0]);
|
|
2009
|
+
else {
|
|
2010
|
+
console.error(
|
|
2011
|
+
"q5 can't parse color: " + c0 + '\nOnly numeric input, hex, and common named colors are supported.'
|
|
2002
2012
|
);
|
|
2003
|
-
|
|
2004
|
-
|
|
2013
|
+
return new C(0, 0, 0);
|
|
2014
|
+
}
|
|
2005
2015
|
} else if (Array.isArray(c0)) return new C(...c0);
|
|
2006
2016
|
}
|
|
2007
2017
|
if ($._colorMode == 'rgb') {
|
|
@@ -2319,24 +2329,22 @@ Q5.modules.input = ($, p) => {
|
|
|
2319
2329
|
|
|
2320
2330
|
$._onkeydown = (e) => {
|
|
2321
2331
|
if (e.repeat) return;
|
|
2322
|
-
$._startAudio;
|
|
2332
|
+
$._startAudio();
|
|
2323
2333
|
p.keyIsPressed = true;
|
|
2324
2334
|
p.key = e.key;
|
|
2325
2335
|
p.keyCode = e.keyCode;
|
|
2326
|
-
keysHeld[$.keyCode] = keysHeld[$.key] = true;
|
|
2336
|
+
keysHeld[$.keyCode] = keysHeld[$.key.toLowerCase()] = true;
|
|
2327
2337
|
$.keyPressed(e);
|
|
2328
|
-
if (e.key.length == 1)
|
|
2329
|
-
$.keyTyped(e);
|
|
2330
|
-
}
|
|
2338
|
+
if (e.key.length == 1) $.keyTyped(e);
|
|
2331
2339
|
};
|
|
2332
2340
|
$._onkeyup = (e) => {
|
|
2333
2341
|
p.keyIsPressed = false;
|
|
2334
2342
|
p.key = e.key;
|
|
2335
2343
|
p.keyCode = e.keyCode;
|
|
2336
|
-
keysHeld[$.keyCode] = keysHeld[$.key] = false;
|
|
2344
|
+
keysHeld[$.keyCode] = keysHeld[$.key.toLowerCase()] = false;
|
|
2337
2345
|
$.keyReleased(e);
|
|
2338
2346
|
};
|
|
2339
|
-
$.keyIsDown = (
|
|
2347
|
+
$.keyIsDown = (v) => !!keysHeld[typeof v == 'string' ? v.toLowerCase() : v];
|
|
2340
2348
|
|
|
2341
2349
|
function getTouchInfo(touch) {
|
|
2342
2350
|
const rect = $.canvas.getBoundingClientRect();
|
|
@@ -2693,9 +2701,7 @@ Q5.modules.math = ($, p) => {
|
|
|
2693
2701
|
};
|
|
2694
2702
|
};
|
|
2695
2703
|
|
|
2696
|
-
Q5.Noise = class {
|
|
2697
|
-
constructor() {}
|
|
2698
|
-
};
|
|
2704
|
+
Q5.Noise = class {};
|
|
2699
2705
|
|
|
2700
2706
|
Q5.PerlinNoise = class extends Q5.Noise {
|
|
2701
2707
|
constructor(seed) {
|
|
@@ -3026,7 +3032,7 @@ Q5.Vector = class {
|
|
|
3026
3032
|
lerp() {
|
|
3027
3033
|
let args = [...arguments];
|
|
3028
3034
|
let u = this._arg2v(...args.slice(0, -1));
|
|
3029
|
-
let amt = args
|
|
3035
|
+
let amt = args.at(-1);
|
|
3030
3036
|
this.x += (u.x - this.x) * amt;
|
|
3031
3037
|
this.y += (u.y - this.y) * amt;
|
|
3032
3038
|
this.z += (u.z - this.z) * amt;
|
package/q5.min.js
CHANGED
|
@@ -5,4 +5,4 @@
|
|
|
5
5
|
* @license LGPL-3.0
|
|
6
6
|
* @class Q5
|
|
7
7
|
*/
|
|
8
|
-
function Q5(e,t){let a,o=this;if(o._q5=!0,o._scope=e,o._parent=t,o._preloadCount=0,e??="global","auto"==e){if(!window.setup&&!window.draw)return;e="global"}"global"==e&&(Q5._hasGlobal=o._isGlobal=!0,a=Q5._nodejs?global:window);let n=new Proxy(o,{set:(e,t,n)=>(o[t]=n,o._isGlobal&&(a[t]=n),!0)});o.canvas=o.ctx=o.drawingContext=null,o.pixels=[];let r=null;o.frameCount=0,o.deltaTime=16,o._targetFrameRate=0,o._targetFrameDuration=16.666666666666668,o._frameRate=o._fps=60,o._loop=!0;let i=0;function s(e){let t=e||performance.now();if(o._lastFrameTime??=t-o._targetFrameDuration,o._shouldResize&&(o.windowResized(),o._shouldResize=!1),o._loop)r=l(s);else if(o.frameCount&&!o._redraw)return;if(r&&o.frameCount){if(t-o._lastFrameTime<o._targetFrameDuration-1)return}n.deltaTime=t-o._lastFrameTime,o._frameRate=1e3/o.deltaTime,n.frameCount++;let a=performance.now();for(let e of Q5.prototype._methods.pre)e.call(o);firstVertex=!0,o.ctx&&o.ctx.save(),o.draw();for(let e of Q5.prototype._methods.post)e.call(o);o.ctx&&(o.ctx.restore(),o.resetMatrix()),n.pmouseX=o.mouseX,n.pmouseY=o.mouseY,o._lastFrameTime=t;let i=performance.now();o._fps=Math.round(1e3/(i-a))}o.millis=()=>performance.now()-i,o.noCanvas=()=>{o.canvas?.remove&&o.canvas.remove(),o.canvas=0,n.ctx=n.drawingContext=0},window&&(o.windowWidth=window.innerWidth,o.windowHeight=window.innerHeight,o.deviceOrientation=window.screen?.orientation?.type),o._incrementPreload=()=>n._preloadCount++,o._decrementPreload=()=>n._preloadCount--,o.noLoop=()=>{o._loop=!1,r=null},o.loop=()=>{o._loop=!0,null==r&&s()},o.redraw=(e=1)=>{o._redraw=!0;for(let t=0;t<e;t++)s();o._redraw=!1},o.remove=()=>{o.noLoop(),o.canvas.remove()},o.frameRate=e=>(e&&(o._targetFrameRate=e,o._targetFrameDuration=1e3/e),o._frameRate),o.getTargetFrameRate=()=>o._targetFrameRate,o.getFPS=()=>o._fps,o.Element=function(e){this.elt=e},o._elements=[],o.TWO_PI=o.TAU=2*Math.PI,o.log=o.print=console.log,o.describe=()=>{};for(let e in Q5.modules)Q5.modules[e](o,n);for(let e in Q5)"_"!=e[1]&&e[1]==e[1].toUpperCase()&&(o[e]=Q5[e]);"global"==e&&(Object.assign(Q5,o),delete Q5.Q5);for(let e of Q5.prototype._methods.init)e.call(o);for(let[e,t]of Object.entries(Q5.prototype))"_"!=e[0]&&"function"==typeof o[e]&&(o[e]=t.bind(o));if("global"==e){let e=Object.getOwnPropertyNames(o);for(let t of e)"_"!=t[0]&&(a[t]=o[t])}if("function"==typeof e&&e(o),"graphics"==e)return;Q5._instanceCount++;let l=window.requestAnimationFrame||function(e){const t=o._lastFrameTime+o._targetFrameDuration;return setTimeout((()=>{e(t)}),t-performance.now())},c=a||o;o._isTouchAware=c.touchStarted||c.touchMoved||c.mouseReleased;let d=c.preload,h=["setup","draw","preload","mouseMoved","mousePressed","mouseReleased","mouseDragged","mouseClicked","keyPressed","keyReleased","keyTyped","touchStarted","touchMoved","touchEnded","windowResized"];for(let e of h)c[e]?o._isGlobal&&(o[e]=()=>{try{return c[e]()}catch(e){o._aiErrorAssistance?o._aiErrorAssistance(e):console.error(e)}}):o[e]=()=>{};async function u(){if(o._startDone=!0,o._preloadCount>0)return l(u);i=performance.now(),await o.setup(),o.frameCount||(null===o.ctx&&o.createCanvas(100,100),o._setupDone=!0,o.ctx&&o.resetMatrix(),l(s))}(o.setup||o.draw)&&(o._startDone=!1,arguments.length&&"namespace"!=e||d?(o.preload(),u()):(c.preload=o.preload=()=>{o._startDone||u()},setTimeout(o.preload,32)))}Q5.modules={},Q5._nodejs="object"==typeof process,Q5._instanceCount=0,Q5._friendlyError=(e,t)=>{throw Error(t+": "+e)},Q5._validateParameters=()=>!0,Q5.prototype._methods={init:[],pre:[],post:[],remove:[]},Q5.prototype.registerMethod=(e,t)=>Q5.prototype._methods[e].push(t),Q5.prototype.registerPreloadMethod=(e,t)=>Q5.prototype[e]=t[e],Q5._nodejs?global.p5??=global.Q5=Q5:"object"==typeof window?window.p5??=window.Q5=Q5:window=0,"object"==typeof document&&document.addEventListener("DOMContentLoaded",(()=>{Q5._hasGlobal||new Q5("auto")})),Q5.modules.q2d_canvas=(e,t)=>{e._OffscreenCanvas=window.OffscreenCanvas||function(){return document.createElement("canvas")},Q5._nodejs?Q5._createNodeJSCanvas&&(t.canvas=Q5._createNodeJSCanvas(100,100)):"image"!=e._scope&&"graphics"!=e._scope||(t.canvas=new e._OffscreenCanvas(100,100)),e.canvas||("object"==typeof document?(t.canvas=document.createElement("canvas"),e.canvas.id="q5Canvas"+Q5._instanceCount,e.canvas.classList.add("q5Canvas")):e.noCanvas());let a=e.canvas;if(a.width=e.width=100,a.height=e.height=100,a&&"graphics"!=e._scope&&"image"!=e._scope){e._setupDone=!1;let r=e._parent;function o(){r??=document.getElementsByTagName("main")[0],r||(r=document.createElement("main"),document.body.append(r)),a.parent(r)}r&&"string"==typeof r&&(r=document.getElementById(r)),a.parent=t=>{function o(){e.frameCount>1&&(e._shouldResize=!0,e._adjustDisplay())}"string"==typeof t&&(t=document.getElementById(t)),t.append(a),"function"==typeof ResizeObserver?(e._ro&&e._ro.disconnect(),e._ro=new ResizeObserver(o),e._ro.observe(r)):e.frameCount||window.addEventListener("resize",o)},document.body?o():document.addEventListener("DOMContentLoaded",o)}function n(o,n){o??=window.innerWidth,n??=window.innerHeight;let r,i=function(){let t={};for(let a in e.ctx)"function"!=typeof e.ctx[a]&&(t[a]=e.ctx[a]);return delete t.canvas,t}();if(e.frameCount){r=new e._OffscreenCanvas(a.width,a.height),r.w=a.w,r.h=a.h,r.getContext("2d").drawImage(a,0,0)}a.width=Math.ceil(o*e._pixelDensity),a.height=Math.ceil(n*e._pixelDensity),a.w=o,a.h=n,a.hw=o/2,a.hh=n/2;for(let t in i)e.ctx[t]=i[t];e.ctx.scale(e._pixelDensity,e._pixelDensity),e.frameCount&&e.ctx.drawImage(r,0,0,r.w,r.h),e._da?e.flexibleCanvas(e._dau):(t.width=o,t.height=n),0!=e.frameCount&&e._adjustDisplay()}e._adjustDisplay=()=>{a.style&&(a.style.width=a.w+"px",a.style.height=a.h+"px")},e.createCanvas=function(o,n,r,i){if("webgl"==r)throw Error("webgl renderer is not supported in q5, use '2d'");"object"==typeof r&&(i=r),t.width=a.width=a.w=o||window.innerWidth,t.height=a.height=a.h=n||window.innerHeight,a.hw=o/2,a.hh=n/2,a.renderer="2d";let s=Object.assign({},Q5.canvasOptions);if(i&&Object.assign(s,i),t.ctx=t.drawingContext=a.getContext("2d",s),Object.assign(a,s),"rgb"==e._colorMode&&e.colorMode("rgb"),"image"!=e._scope&&(e._defaultStyle(),e._da=0),e.ctx.save(),"image"!=e._scope){let t=e.displayDensity();"graphics"==e._scope?t=this._pixelDensity:window.IntersectionObserver&&new IntersectionObserver((e=>{a.visible=e[0].isIntersecting})).observe(a),e.pixelDensity(Math.ceil(t))}else this._pixelDensity=1;return e.displayMode?e.displayMode():e._adjustDisplay(),a},e._createCanvas=e.createCanvas,"image"!=e._scope&&(e._defaultStyle=()=>{e.ctx.fillStyle="white",e.ctx.strokeStyle="black",e.ctx.lineCap="round",e.ctx.lineJoin="miter",e.ctx.textAlign="left"},e.resizeCanvas=(e,t)=>{e==a.w&&t==a.h||n(e,t)},e._pixelDensity=1,e.displayDensity=()=>window.devicePixelRatio,e.pixelDensity=t=>t&&t!=e._pixelDensity?(e._pixelDensity=t,n(a.w,a.h),t):e._pixelDensity,"image"!=e._scope&&(e.fullscreen=e=>{if(void 0===e)return document.fullscreenElement;e?document.body.requestFullscreen():document.body.exitFullscreen()},e.flexibleCanvas=(o=400)=>{o?(e._da=a.width/(o*e._pixelDensity),t.width=e._dau=o,t.height=a.h/a.w*o):e._da=0},e.translate=(t,a)=>{e._da&&(t*=e._da,a*=e._da),e.ctx.translate(t,a)},e.rotate=t=>{"degrees"==e._angleMode&&(t=e.radians(t)),e.ctx.rotate(t)},e.scale=(t,a)=>{a??=t,e.ctx.scale(t,a)},e.opacity=t=>e.ctx.globalAlpha=t,e.applyMatrix=(t,a,o,n,r,i)=>e.ctx.transform(t,a,o,n,r,i),e.shearX=t=>e.ctx.transform(1,0,e.tan(t),1,0,0),e.shearY=t=>e.ctx.transform(1,e.tan(t),0,1,0,0),e.resetMatrix=()=>{e.ctx.resetTransform(),e.ctx.scale(e._pixelDensity,e._pixelDensity)},e._styleNames=["_doStroke","_doFill","_strokeSet","_fillSet","_tint","_imageMode","_rectMode","_ellipseMode","_textFont","_textLeading","_leadingSet","_textSize","_textAlign","_textBaseline","_textStyle","_textWrap"],e._styles=[],e.push=e.pushMatrix=()=>{e.ctx.save();let t={};for(let a of e._styleNames)t[a]=e[a];e._styles.push(t)},e.pop=e.popMatrix=()=>{e.ctx.restore();let t=e._styles.pop();for(let a of e._styleNames)e[a]=t[a]},e.createCapture=e=>{var t=document.createElement("video");return t.playsinline="playsinline",t.autoplay="autoplay",navigator.mediaDevices.getUserMedia(e).then((e=>{t.srcObject=e})),t.style.position="absolute",t.style.opacity=1e-5,t.style.zIndex=-1e3,document.body.append(t),t},e.createGraphics=function(t,a,o){let n=new Q5("graphics");return o??={},o.alpha??=!0,n._createCanvas.call(e,t,a,o),n},window&&"graphics"!=e._scope&&window.addEventListener("resize",(()=>{e._shouldResize=!0,t.windowWidth=window.innerWidth,t.windowHeight=window.innerHeight,t.deviceOrientation=window.screen?.orientation?.type}))))},Q5.canvasOptions={alpha:!1,desynchronized:!1,colorSpace:"display-p3"},window.matchMedia&&matchMedia("(dynamic-range: high) and (color-gamut: p3)").matches?Q5.supportsHDR=!0:Q5.canvasOptions.colorSpace="srgb",Q5.modules.q2d_drawing=e=>{e.CHORD=0,e.PIE=1,e.OPEN=2,e.RADIUS="radius",e.CORNER="corner",e.CORNERS="corners",e.ROUND="round",e.SQUARE="butt",e.PROJECT="square",e.MITER="miter",e.BEVEL="bevel",e.CLOSE=1,e.CENTER="center",e.LEFT="left",e.RIGHT="right",e.TOP="top",e.BOTTOM="bottom",e.LANDSCAPE="landscape",e.PORTRAIT="portrait",e.BLEND="source-over",e.REMOVE="destination-out",e.ADD="lighter",e.DARKEST="darken",e.LIGHTEST="lighten",e.DIFFERENCE="difference",e.SUBTRACT="subtract",e.EXCLUSION="exclusion",e.MULTIPLY="multiply",e.SCREEN="screen",e.REPLACE="copy",e.OVERLAY="overlay",e.HARD_LIGHT="hard-light",e.SOFT_LIGHT="soft-light",e.DODGE="color-dodge",e.BURN="color-burn",e._doStroke=!0,e._doFill=!0,e._strokeSet=!1,e._fillSet=!1,e._ellipseMode=e.CENTER,e._rectMode=e.CORNER,e._curveDetail=20,e._curveAlpha=0;let t=!0,a=[];function o(){e._doFill&&e.ctx.fill(),e._doStroke&&e.ctx.stroke()}function n(t,a,n,r,i,s,l,c){if(!e._doFill&&!e._doStroke)return;let d="degrees"==e._angleMode,h=d?360:e.TAU;if((i%=h)<0&&(i+=h),(s%=h)<0&&(s+=h),0!=i||0!=s){if(i>s&&([i,s]=[s,i]),e.ctx.beginPath(),n==r)d&&(i=e.radians(i),s=e.radians(s)),e.ctx.arc(t,a,n/2,i,s);else{for(let o=0;o<c+1;o++){let l=o/c,d=e.lerp(i,s,l),h=e.cos(d)*n/2,u=e.sin(d)*r/2;e.ctx[o?"lineTo":"moveTo"](t+h,a+u)}l==e.CHORD?e.ctx.closePath():l==e.PIE&&(e.ctx.lineTo(t,a),e.ctx.closePath())}o()}}function r(t,a,n,r){(e._doFill||e._doStroke)&&(e._da&&(t*=e._da,a*=e._da,n*=e._da,r*=e._da),e.ctx.beginPath(),e.ctx.ellipse(t,a,n/2,r/2,0,0,e.TAU),o())}function i(t,a,n,r,s,l,c,d){if(!e._doFill&&!e._doStroke)return;if(void 0===s)return function(t,a,n,r){e._da&&(t*=e._da,a*=e._da,n*=e._da,r*=e._da),e.ctx.beginPath(),e.ctx.rect(t,a,n,r),o()}(t,a,n,r);if(void 0===l)return i(t,a,n,r,s,s,s,s);e._da&&(t*=e._da,a*=e._da,n*=e._da,r*=e._da,s*=e._da,l*=e._da,d*=e._da,c*=e._da);const h=Math.min(Math.abs(r),Math.abs(n))/2;s=Math.min(h,s),l=Math.min(h,l),d=Math.min(h,d),c=Math.min(h,c),e.ctx.beginPath(),e.ctx.moveTo(t+s,a),e.ctx.arcTo(t+n,a,t+n,a+r,l),e.ctx.arcTo(t+n,a+r,t,a+r,c),e.ctx.arcTo(t,a+r,t,a,d),e.ctx.arcTo(t,a,t+n,a,s),e.ctx.closePath(),o()}function s(){a=[]}e.strokeWeight=t=>{t||(e._doStroke=!1),e._da&&(t*=e._da),e.ctx.lineWidth=t||1e-4},e.stroke=function(t){if(e._doStroke=!0,e._strokeSet=!0,Q5.Color&&(t._q5Color||"string"==typeof t?e._basicColors[t]&&(t=e.color(...e._basicColors[t])):t=e.color(...arguments),t.a<=0))return e._doStroke=!1;e.ctx.strokeStyle=t.toString()},e.noStroke=()=>e._doStroke=!1,e.fill=function(t){if(e._doFill=!0,e._fillSet=!0,Q5.Color&&(t._q5Color||"string"==typeof t?e._basicColors[t]&&(t=e.color(...e._basicColors[t])):t=e.color(...arguments),t.a<=0))return e._doFill=!1;e.ctx.fillStyle=t.toString()},e.noFill=()=>e._doFill=!1,e.blendMode=t=>e.ctx.globalCompositeOperation=t,e.strokeCap=t=>e.ctx.lineCap=t,e.strokeJoin=t=>e.ctx.lineJoin=t,e.ellipseMode=t=>e._ellipseMode=t,e.rectMode=t=>e._rectMode=t,e.curveDetail=t=>e._curveDetail=t,e.curveAlpha=t=>e._curveAlpha=t,e.curveTightness=t=>e._curveAlpha=t,e.clear=()=>{e.ctx.clearRect(0,0,e.canvas.width,e.canvas.height)},e.background=function(t){if(t.canvas)return e.image(t,0,0,e.width,e.height);e.ctx.save(),e.ctx.resetTransform(),Q5.Color&&(t._q5Color||"string"==typeof t?e._basicColors[t]&&(t=e.color(...e._basicColors[t])):t=e.color(...arguments)),e.ctx.fillStyle=t.toString(),e.ctx.fillRect(0,0,e.canvas.width,e.canvas.height),e.ctx.restore()},e.line=(t,a,o,n)=>{e._doStroke&&(e._da&&(t*=e._da,a*=e._da,o*=e._da,n*=e._da),e.ctx.beginPath(),e.ctx.moveTo(t,a),e.ctx.lineTo(o,n),e.ctx.stroke())},e.arc=(t,a,o,r,i,s,l,c=25)=>{if(i==s)return e.ellipse(t,a,o,r);l??=e.PIE,e._ellipseMode==e.CENTER?n(t,a,o,r,i,s,l,c):e._ellipseMode==e.RADIUS?n(t,a,2*o,2*r,i,s,l,c):e._ellipseMode==e.CORNER?n(t+o/2,a+r/2,o,r,i,s,l,c):e._ellipseMode==e.CORNERS&&n((t+o)/2,(a+r)/2,o-t,r-a,i,s,l,c)},e.ellipse=(t,a,o,n)=>{n??=o,e._ellipseMode==e.CENTER?r(t,a,o,n):e._ellipseMode==e.RADIUS?r(t,a,2*o,2*n):e._ellipseMode==e.CORNER?r(t+o/2,a+n/2,o,n):e._ellipseMode==e.CORNERS&&r((t+o)/2,(a+n)/2,o-t,n-a)},e.circle=(t,a,n)=>{e._ellipseMode==e.CENTER?(e._da&&(t*=e._da,a*=e._da,n*=e._da),e.ctx.beginPath(),e.ctx.arc(t,a,n/2,0,e.TAU),o()):e.ellipse(t,a,n,n)},e.point=(t,a)=>{t.x&&(a=t.y,t=t.x),e._da&&(t*=e._da,a*=e._da),e.ctx.save(),e.ctx.beginPath(),e.ctx.arc(t,a,e.ctx.lineWidth/2,0,e.TAU),e.ctx.fillStyle=e.ctx.strokeStyle,e.ctx.fill(),e.ctx.restore()},e.rect=(t,a,o,n=o,r,s,l,c)=>{e._rectMode==e.CENTER?i(t-o/2,a-n/2,o,n,r,s,l,c):e._rectMode==e.RADIUS?i(t-o,a-n,2*o,2*n,r,s,l,c):e._rectMode==e.CORNER?i(t,a,o,n,r,s,l,c):e._rectMode==e.CORNERS&&i(t,a,o-t,n-a,r,s,l,c)},e.square=(t,a,o,n,r,i,s)=>e.rect(t,a,o,o,n,r,i,s),e.beginShape=()=>{s(),e.ctx.beginPath(),t=!0},e.beginContour=()=>{e.ctx.closePath(),s(),t=!0},e.endContour=()=>{s(),t=!0},e.vertex=(a,o)=>{e._da&&(a*=e._da,o*=e._da),s(),t?e.ctx.moveTo(a,o):e.ctx.lineTo(a,o),t=!1},e.bezierVertex=(t,a,o,n,r,i)=>{e._da&&(t*=e._da,a*=e._da,o*=e._da,n*=e._da,r*=e._da,i*=e._da),s(),e.ctx.bezierCurveTo(t,a,o,n,r,i)},e.quadraticVertex=(t,a,o,n)=>{e._da&&(t*=e._da,a*=e._da,o*=e._da,n*=e._da),s(),e.ctx.quadraticCurveTo(t,a,o,n)},e.bezier=(t,a,o,n,r,i,s,l)=>{e.beginShape(),e.vertex(t,a),e.bezierVertex(o,n,r,i,s,l),e.endShape()},e.triangle=(t,a,o,n,r,i)=>{e.beginShape(),e.vertex(t,a),e.vertex(o,n),e.vertex(r,i),e.endShape(e.CLOSE)},e.quad=(t,a,o,n,r,i,s,l)=>{e.beginShape(),e.vertex(t,a),e.vertex(o,n),e.vertex(r,i),e.vertex(s,l),e.endShape(e.CLOSE)},e.endShape=t=>{s(),t&&e.ctx.closePath(),o()},e.curveVertex=(o,n)=>{if(e._da&&(o*=e._da,n*=e._da),a.push([o,n]),a.length<4)return;let r=function(e,t,a,o,n,r,i,s,l,c){function d(e,t,a,o,n,r){let i=Math.pow(o-t,2)+Math.pow(n-a,2);return Math.pow(i,.5*r)+e}let h=[],u=d(0,e,t,a,o,c),_=d(u,a,o,n,r,c),g=d(_,n,r,i,s,c);for(let c=0;c<l;c++){let d=u+c/(l-1)*(_-u),p=[(u-d)/(u-0),(d-0)/(u-0),(_-d)/(_-u),(d-u)/(_-u),(g-d)/(g-_),(d-_)/(g-_),(_-d)/(_-0),(d-0)/(_-0),(g-d)/(g-u),(d-u)/(g-u)];for(let e=0;e<p.length;e+=2)isNaN(p[e])&&(p[e]=1,p[e+1]=0),isFinite(p[e])||(p[e]>0?(p[e]=1,p[e+1]=0):(p[e]=0,p[e+1]=1));let x=e*p[0]+a*p[1],m=t*p[0]+o*p[1],f=a*p[2]+n*p[3],v=o*p[2]+r*p[3],y=n*p[4]+i*p[5],w=r*p[4]+s*p[5],M=x*p[6]+f*p[7],C=m*p[6]+v*p[7],b=f*p[8]+y*p[9],S=v*p[8]+w*p[9],R=M*p[2]+b*p[3],E=C*p[2]+S*p[3];h.push([R,E])}return h}(...a.at(-4),...a.at(-3),...a.at(-2),...a.at(-1),e._curveDetail,e._curveAlpha);for(let a=0;a<r.length;a++)t?e.ctx.moveTo(...r[a]):e.ctx.lineTo(...r[a]),t=!1},e.curve=(t,a,o,n,r,i,s,l)=>{e.beginShape(),e.curveVertex(t,a),e.curveVertex(o,n),e.curveVertex(r,i),e.curveVertex(s,l),e.endShape()},e.curvePoint=(e,t,a,o,n)=>{const r=n*n*n,i=n*n;return e*(-.5*r+i-.5*n)+t*(1.5*r-2.5*i+1)+a*(-1.5*r+2*i+.5*n)+o*(.5*r-.5*i)},e.bezierPoint=(e,t,a,o,n)=>{const r=1-n;return Math.pow(r,3)*e+3*Math.pow(r,2)*n*t+3*r*Math.pow(n,2)*a+Math.pow(n,3)*o},e.curveTangent=(e,t,a,o,n)=>{const r=n*n;return e*(-3*r/2+2*n-.5)+t*(9*r/2-5*n)+a*(-9*r/2+4*n+.5)+o*(3*r/2-n)},e.bezierTangent=(e,t,a,o,n)=>{const r=1-n;return 3*o*Math.pow(n,2)-3*a*Math.pow(n,2)+6*a*r*n-6*t*r*n+3*t*Math.pow(r,2)-3*e*Math.pow(r,2)},e.erase=function(t=255,a=255){e.ctx.save(),e.ctx.globalCompositeOperation="destination-out",e.ctx.fillStyle=`rgba(0, 0, 0, ${t/255})`,e.ctx.strokeStyle=`rgba(0, 0, 0, ${a/255})`},e.noErase=function(){e.ctx.globalCompositeOperation="source-over",e.ctx.restore()},e.inFill=(t,a)=>{const o=e._pixelDensity;return e.ctx.isPointInPath(t*o,a*o)},e.inStroke=(t,a)=>{const o=pixelDensity();return e.ctx.isPointInStroke(t*o,a*o)}},Q5.modules.q2d_image=(e,t)=>{e.createImage=(e,t,a)=>new Q5.Image(e,t,a),e._tint=null;let a=null,o=null,n=null;function r(t,a){a??=t||e.canvas.height,t??=e.canvas.width,null==o&&(o=new e._OffscreenCanvas(t,a).getContext("2d",{colorSpace:e.canvas.colorSpace})),o.canvas.width==t&&o.canvas.height==a||(o.canvas.width=t,o.canvas.height=a)}function i(t){o.clearRect(0,0,o.canvas.width,o.canvas.height),o.filter=t,o.drawImage(e.canvas,0,0),e.ctx.save(),e.ctx.resetTransform(),e.ctx.clearRect(0,0,e.canvas.width,e.canvas.height),e.ctx.drawImage(o.canvas,0,0),e.ctx.restore()}e._softFilter=()=>{throw"Load q5-2d-soft-filters.js to use software filters."},e.filter=(t,a)=>{if(!e.ctx.filter)return e._softFilter(t,a);if(r(),"string"==typeof t)i(t);else if(t==Q5.THRESHOLD){a??=.5,a=Math.max(a,1e-5),i(`saturate(0%) brightness(${Math.floor(.5/a*100)}%) contrast(1000000%)`)}else t==Q5.GRAY?i("saturate(0%)"):t==Q5.OPAQUE?(o.fillStyle="black",o.fillRect(0,0,o.canvas.width,o.canvas.height),o.drawImage(e.canvas,0,0),e.ctx.save(),e.ctx.resetTransform(),e.ctx.drawImage(o.canvas,0,0),e.ctx.restore()):t==Q5.INVERT?i("invert(100%)"):t==Q5.BLUR?i(`blur(${Math.ceil(a*e._pixelDensity/1)||1}px)`):e._softFilter(t,a)},e.resize=(a,n)=>{r(),o.drawImage(e.canvas,0,0),t.width=a,t.height=n,e.canvas.width=a*e._pixelDensity,e.canvas.height=n*e._pixelDensity,e.ctx.save(),e.ctx.resetTransform(),e.ctx.clearRect(0,0,e.canvas.width,e.canvas.height),e.ctx.drawImage(o.canvas,0,0,e.canvas.width,e.canvas.height),e.ctx.restore()},e.trim=()=>{let t=e._pixelDensity||1,a=e.ctx.getImageData(0,0,e.width*t,e.height*t).data,o=e.width,n=0,r=e.height,i=0;for(let s=0;s<e.height*t;s++)for(let l=0;l<e.width*t;l++){0!==a[4*(s*e.width*t+l)+3]&&(l<o&&(o=l),l>n&&(n=l),s<r&&(r=s),s>i&&(i=s))}return r=Math.floor(r/t),i=Math.floor(i/t),o=Math.floor(o/t),n=Math.floor(n/t),e.get(o,r,n-o+1,i-r+1)},e.mask=t=>{e.ctx.save(),e.ctx.resetTransform();let a=e.ctx.globalCompositeOperation;e.ctx.globalCompositeOperation="destination-in",e.ctx.drawImage(t.canvas,0,0),e.ctx.globalCompositeOperation=a,e.ctx.restore()},e._save=async(e,t,a)=>{if(t=t||"untitled","jpg"==(a=a||"png")||"png"==a||"webp"==a)if(e instanceof OffscreenCanvas){const t=await e.convertToBlob({type:"image/"+a});e=await new Promise((e=>{const a=new FileReader;a.onloadend=()=>e(a.result),a.readAsDataURL(t)}))}else e=e.toDataURL("image/"+a);else{let t="text/plain";"json"==a&&("string"!=typeof e&&(e=JSON.stringify(e)),t="text/json"),e=new Blob([e],{type:t}),e=URL.createObjectURL(e)}let o=document.createElement("a");o.href=e,o.download=t+"."+a,document.body.append(o),o.click(),document.body.removeChild(o),URL.revokeObjectURL(o.href)},e.save=(t,a,o)=>{if((!t||"string"==typeof t&&(!a||!o&&a.length<5))&&(o=a,a=t,t=e.canvas),o)return e._save(t,a,o);a?(a=a.split("."),e._save(t,a[0],a.at(-1))):e._save(t)},e.get=(t,a,o,n)=>{let r=e._pixelDensity||1;if(void 0!==t&&void 0===o){let o=e.ctx.getImageData(t*r,a*r,1,1).data;return new e.Color(o[0],o[1],o[2],o[3]/255)}t=(t||0)*r,a=(a||0)*r;let i=o=o||e.width,s=n=n||e.height;o*=r,n*=r;let l=e.createImage(o,n),c=e.ctx.getImageData(t,a,o,n);return l.ctx.putImageData(c,0,0),l._pixelDensity=r,l.width=i,l.height=s,l},e.set=(t,a,o)=>{if(o.canvas){let n=e._tint;return e._tint=null,e.image(o,t,a),void(e._tint=n)}e.pixels.length||e.loadPixels();let n=e._pixelDensity||1;for(let r=0;r<n;r++)for(let i=0;i<n;i++){let s=4*((a*n+r)*e.canvas.width+t*n+i);e.pixels[s]=o.r??o.l,e.pixels[s+1]=o.g??o.c,e.pixels[s+2]=o.b??o.h,e.pixels[s+3]=o.a}},e.loadPixels=()=>{a=e.ctx.getImageData(0,0,e.canvas.width,e.canvas.height),t.pixels=a.data},e.updatePixels=()=>{null!=a&&e.ctx.putImageData(a,0,0)},e._tinted=function(t){let a=t.a;t.a=255,r(),o.clearRect(0,0,o.canvas.width,o.canvas.height),o.fillStyle=t.toString(),o.fillRect(0,0,o.canvas.width,o.canvas.height),o.globalCompositeOperation="multiply",o.drawImage(e.ctx.canvas,0,0),o.globalCompositeOperation="source-over",e.ctx.save(),e.ctx.resetTransform();let n=e.ctx.globalCompositeOperation;e.ctx.globalCompositeOperation="source-in",e.ctx.drawImage(o.canvas,0,0),e.ctx.globalCompositeOperation=n,e.ctx.restore(),o.globalAlpha=a/255,o.clearRect(0,0,o.canvas.width,o.canvas.height),o.drawImage(e.ctx.canvas,0,0),o.globalAlpha=1,e.ctx.save(),e.ctx.resetTransform(),e.ctx.clearRect(0,0,e.ctx.canvas.width,e.ctx.canvas.height),e.ctx.drawImage(o.canvas,0,0),e.ctx.restore()},e.smooth=()=>e.ctx.imageSmoothingEnabled=!0,e.noSmooth=()=>e.ctx.imageSmoothingEnabled=!1,"image"!=e._scope&&(e.saveCanvas=e.canvas.save=e.save,e.tint=function(t){e._tint=t._q5Color?t:e.color(...arguments)},e.noTint=()=>e._tint=null,e.imageMode=t=>e._imageMode=t,e.image=(t,a,o,r,i,s=0,l=0,c,d)=>{e._da&&(a*=e._da,o*=e._da,r*=e._da,i*=e._da,s*=e._da,l*=e._da,c*=e._da,d*=e._da);let h=t.canvas||t;var u,_;Q5._createNodeJSCanvas&&(h=h.context.canvas),t.canvas&&null!=e._tint&&(u=t.canvas.width,_=t.canvas.height,_??=u||e.canvas.height,u??=e.canvas.width,null==n&&(n=new e._OffscreenCanvas(u,_).getContext("2d",{colorSpace:e.canvas.colorSpace})),n.canvas.width==u&&n.canvas.height==_||(n.canvas.width=u,n.canvas.height=_),n.drawImage(t.canvas,0,0),t._tinted(e._tint)),r??=t.width||t.videoWidth,i??=t.height||t.videoHeight,"center"==e._imageMode&&(a-=.5*r,o-=.5*i);let g=t._pixelDensity||1;c?c*=g:c=h.width||h.videoWidth,d?d*=g:d=h.height||h.videoHeight,e.ctx.drawImage(h,s*g,l*g,c,d,a,o,r,i),function(){if(!t._q5||!e._tint)return;let a=t.ctx;a.save(),a.resetTransform(),a.clearRect(0,0,a.canvas.width,a.canvas.height),a.drawImage(n.canvas,0,0),a.restore()}()},e.loadImage=function(a,o,n){if(a.canvas)return a;if("gif"==a.slice(-3).toLowerCase())throw"In q5, GIFs are not supported due to their impact on performance. Use a video or p5play animation instead.";t._preloadCount++;let r=[...arguments].at(-1);n="object"!=typeof r||r;let i=e.createImage(1,1,n.alpha),s=i.ctx;if(Q5._nodejs&&global.CairoCanvas)CairoCanvas.loadImage(a).then((e=>{i.width=s.canvas.width=e.width,i.height=s.canvas.height=e.height,s.drawImage(e,0,0),t._preloadCount--,o&&o(i)})).catch((e=>{throw t._preloadCount--,e}));else{let e=new window.Image;e.src=a,e.crossOrigin="Anonymous",e._pixelDensity=1,e.onload=()=>{i.width=s.canvas.width=e.naturalWidth,i.height=s.canvas.height=e.naturalHeight,s.drawImage(e,0,0),t._preloadCount--,o&&o(i)},e.onerror=e=>{throw t._preloadCount--,e}}return i})},Q5.imageModules=["q2d_canvas","q2d_image"];class _Q5Image{constructor(e,t,a){let o=this;o._scope="image",o.canvas=o.ctx=o.drawingContext=null,o.pixels=[];for(let e of Q5.imageModules)Q5.modules[e](o,o);delete this.createCanvas,a??={},a.alpha??=!0,this._createCanvas(e,t,"2d",a),this._loop=!1}get w(){return this.width}get h(){return this.height}}Q5.Image??=_Q5Image,Q5.THRESHOLD=1,Q5.GRAY=2,Q5.OPAQUE=3,Q5.INVERT=4,Q5.POSTERIZE=5,Q5.DILATE=6,Q5.ERODE=7,Q5.BLUR=8,Q5.modules.q2d_soft_filters=e=>{let t=null;function a(){let a=e.canvas.width*e.canvas.height*4;t&&a==t.length||(t=new Uint8ClampedArray(a))}e._softFilter=(o,n)=>{e._filters||(e._filters=[],e._filters[Q5.THRESHOLD]=(e,t)=>{void 0===t?t=127.5:t*=255;for(let a=0;a<e.length;a+=4){const o=.2126*e[a]+.7152*e[a+1]+.0722*e[a+2];e[a]=e[a+1]=e[a+2]=o>=t?255:0}},e._filters[Q5.GRAY]=e=>{for(let t=0;t<e.length;t+=4){const a=.2126*e[t]+.7152*e[t+1]+.0722*e[t+2];e[t]=e[t+1]=e[t+2]=a}},e._filters[Q5.OPAQUE]=e=>{for(let t=0;t<e.length;t+=4)e[t+3]=255},e._filters[Q5.INVERT]=e=>{for(let t=0;t<e.length;t+=4)e[t]=255-e[t],e[t+1]=255-e[t+1],e[t+2]=255-e[t+2]},e._filters[Q5.POSTERIZE]=(e,t=4)=>{let a=t-1;for(let o=0;o<e.length;o+=4)e[o]=255*(e[o]*t>>8)/a,e[o+1]=255*(e[o+1]*t>>8)/a,e[o+2]=255*(e[o+2]*t>>8)/a},e._filters[Q5.DILATE]=o=>{a(),t.set(o);let[n,r]=[e.canvas.width,e.canvas.height];for(let e=0;e<r;e++)for(let a=0;a<n;a++){let i=4*Math.max(a-1,0),s=4*Math.min(a+1,n-1),l=4*Math.max(e-1,0)*n,c=4*Math.min(e+1,r-1)*n,d=4*e*n,h=4*a;for(let e=0;e<4;e++){let a=e+l,n=e+c,r=e+d;o[d+h+e]=Math.max(t[a+h],t[r+i],t[r+h],t[r+s],t[n+h])}}},e._filters[Q5.ERODE]=o=>{a(),t.set(o);let[n,r]=[e.canvas.width,e.canvas.height];for(let e=0;e<r;e++)for(let a=0;a<n;a++){let i=4*Math.max(a-1,0),s=4*Math.min(a+1,n-1),l=4*Math.max(e-1,0)*n,c=4*Math.min(e+1,r-1)*n,d=4*e*n,h=4*a;for(let e=0;e<4;e++){let a=e+l,n=e+c,r=e+d;o[d+h+e]=Math.min(t[a+h],t[r+i],t[r+h],t[r+s],t[n+h])}}},e._filters[Q5.BLUR]=(o,n)=>{n=n||1,n=Math.floor(n*e._pixelDensity),a(),t.set(o);let r=2*n+1,i=function(e){let t=new Float32Array(e),a=.3*n+.8,o=a*a*2;for(let n=0;n<e;n++){let r=n-e/2,i=Math.exp(-r*r/o)/(2.5066282746*a);t[n]=i}return t}(r),[s,l]=[e.canvas.width,e.canvas.height];for(let e=0;e<l;e++)for(let a=0;a<s;a++){let l=0,c=0,d=0,h=0;for(let o=0;o<r;o++){let r=4*(e*s+Math.min(Math.max(a-n+o,0),s-1));l+=t[r]*i[o],c+=t[r+1]*i[o],d+=t[r+2]*i[o],h+=t[r+3]*i[o]}let u=4*(e*s+a);o[u]=l,o[u+1]=c,o[u+2]=d,o[u+3]=h}t.set(o);for(let e=0;e<l;e++)for(let a=0;a<s;a++){let c=0,d=0,h=0,u=0;for(let o=0;o<r;o++){let r=4*(Math.min(Math.max(e-n+o,0),l-1)*s+a);c+=t[r]*i[o],d+=t[r+1]*i[o],h+=t[r+2]*i[o],u+=t[r+3]*i[o]}let _=4*(e*s+a);o[_]=c,o[_+1]=d,o[_+2]=h,o[_+3]=u}});let r=e.ctx.getImageData(0,0,e.canvas.width,e.canvas.height);e._filters[o](r.data,n),e.ctx.putImageData(r,0,0)}},Q5.modules.q2d_text=(e,t)=>{e.NORMAL="normal",e.ITALIC="italic",e.BOLD="bold",e.BOLDITALIC="italic bold",e.CENTER="center",e.LEFT="left",e.RIGHT="right",e.TOP="top",e.BOTTOM="bottom",e.BASELINE="alphabetic",e._textFont="sans-serif",e._textSize=12,e._textLeading=15,e._textLeadDiff=3,e._textStyle="normal",e.loadFont=(e,a)=>{t._preloadCount++;let o=e.split("/"),n=o[o.length-1].split(".")[0].replace(" ",""),r=new FontFace(n,"url("+e+")");return document.fonts.add(r),r.load().then((()=>{t._preloadCount--,a&&a(n)})),n},e.textFont=t=>e._textFont=t,e.textSize=t=>{if(void 0===t)return e._textSize;e._da&&(t*=e._da),e._textSize=t,e._leadingSet||(e._textLeading=1.25*t,e._textLeadDiff=e._textLeading-t)},e.textLeading=t=>{if(void 0===t)return e._textLeading;e._da&&(t*=e._da),e._textLeading=t,e._textLeadDiff=t-e._textSize,e._leadingSet=!0},e.textStyle=t=>e._textStyle=t,e.textAlign=(t,a)=>{e.ctx.textAlign=t,a&&(e.ctx.textBaseline=a==e.CENTER?"middle":a)},e.textWidth=t=>(e.ctx.font=`${e._textStyle} ${e._textSize}px ${e._textFont}`,e.ctx.measureText(t).width),e.textAscent=t=>(e.ctx.font=`${e._textStyle} ${e._textSize}px ${e._textFont}`,e.ctx.measureText(t).actualBoundingBoxAscent),e.textDescent=t=>(e.ctx.font=`${e._textStyle} ${e._textSize}px ${e._textFont}`,e.ctx.measureText(t).actualBoundingBoxDescent),e._textCache=!!Q5.Image,e._TimedCache=class extends Map{constructor(){super(),this.maxSize=500}set(e,t){t.lastAccessed=Date.now(),super.set(e,t),this.size>this.maxSize&&this.gc()}get(e){const t=super.get(e);return t&&(t.lastAccessed=Date.now()),t}gc(){let e,t=1/0,a=0;for(const[o,n]of this.entries())n.lastAccessed<t&&(t=n.lastAccessed,e=a),a++;a=e;for(const t of this.keys()){if(0==a){e=t;break}a--}this.delete(e)}},e._tic=new e._TimedCache,e.textCache=(t,a)=>(a&&(e._tic.maxSize=a),void 0!==t&&(e._textCache=t),e._textCache),e._genTextImageKey=(t,a,o)=>t.slice(0,200)+e._textStyle+e._textSize+e._textFont+(e._doFill?e.ctx.fillStyle:"")+"_"+(e._doStroke&&e._strokeSet?e.ctx.lineWidth+e.ctx.strokeStyle+"_":"")+(a||"")+(o?"x"+o:""),e.createTextImage=(t,a,o)=>{let n=e._textCache;e._textCache=!0,e._genTextImage=!0,e.text(t,0,0,a,o),e._genTextImage=!1;let r=e._genTextImageKey(t,a,o);return e._textCache=n,e._tic.get(r)},e.text=(t,a,o,n,r)=>{if(void 0===t)return;if(t=t.toString(),e._da&&(a*=e._da,o*=e._da),!e._doFill&&!e._doStroke)return;let i,s,l,c,d,h,u,_,g=1,p=e.ctx.getTransform(),x=e._genTextImage||e._textCache&&(0!=p.b||0!=p.c);if(x){if(c=e._genTextImageKey(t,n,r),s=e._tic.get(c),s&&!e._genTextImage)return void e.textImage(s,a,o);l=e.createGraphics.call(e,1,1),i=l.ctx,g=e._pixelDensity}else i=e.ctx,d=a,h=o;i.font=`${e._textStyle} ${e._textSize}px ${e._textFont}`;let m=t.split("\n");if(x){d=0,h=e._textLeading*m.length;let a=i.measureText(" ");u=a.fontBoundingBoxAscent,_=a.fontBoundingBoxDescent,r??=h+_,l.resizeCanvas(Math.ceil(i.measureText(t).width),Math.ceil(r)),i.fillStyle=e.ctx.fillStyle,i.strokeStyle=e.ctx.strokeStyle,i.lineWidth=e.ctx.lineWidth}let f=i.fillStyle;e._fillSet||(i.fillStyle="black");for(let t=0;t<m.length&&(e._doStroke&&e._strokeSet&&i.strokeText(m[t],d,h),e._doFill&&i.fillText(m[t],d,h),h+=e._textLeading,!(h>r));t++);e._fillSet||(i.fillStyle=f),x&&(s=l.get(),s._ascent=u,s._descent=_,e._tic.set(c,s),e._genTextImage||e.textImage(s,a,o))},e.textImage=(t,a,o)=>{let n=e._imageMode;e._imageMode="corner","center"==e.ctx.textAlign?a-=.5*t.width:"right"==e.ctx.textAlign&&(a-=t.width),"alphabetic"==e.ctx.textBaseline&&(o-=e._textLeading),"middle"==e.ctx.textBaseline?o-=t._descent+.5*t._ascent+e._textLeadDiff:"bottom"==e.ctx.textBaseline?o-=t._ascent+t._descent+e._textLeadDiff:"top"==e.ctx.textBaseline&&(o-=t._descent+e._textLeadDiff),e.image(t,a,o),e._imageMode=n},e.nf=(e,t,a)=>{let o=e<0,n=(e=Math.abs(e)).toFixed(a).split(".");n[0]=n[0].padStart(t,"0");let r=n.join(".");return o&&(r="-"+r),r}},Q5.modules.ai=e=>{e.askAI=(e="")=>{throw Error("Ask AI ✨ "+e)},e._aiErrorAssistance=async e=>{let t=e.message?.includes("Ask AI ✨");if(t||console.error(e),Q5.disableFriendlyErrors)return;!t&&Q5.errorTolerant||noLoop();let a=e.stack?.split("\n");if(!e.stack||a.length<=1)return;let o=1,n="(";for(-1==navigator.userAgent.indexOf("Chrome")&&(o=0,n="@");a[o].indexOf("q5.js:")>=0;)o++;let r=a[o].split(n).at(-1);r=r.split(":");let i=parseInt(r.at(-2));t&&i++;let s=r.slice(0,-2).join(":"),l=s.split("/").at(-1);try{let a=(await(await fetch(s)).text()).split("\n"),o=a[i-1].trim(),n="",r=1;for(;n.length<1600&&(i-r>=0&&(n=a[i-r].trim()+"\n"+n),i+r<a.length);)n+=a[i+r].trim()+"\n",r++;let c="https://chatgpt.com/?q=q5.js+"+(t&&e.message.length>10?e.message.slice(10):"Whats+wrong+with+this+line%3F+short+answer")+(t?"":"%0A%0A"+encodeURIComponent(e.name+": "+e.message))+"%0A%0ALine%3A+"+encodeURIComponent(o)+"%0A%0AExcerpt+for+context%3A%0A%0A"+encodeURIComponent(n);t||console.log("Error in "+l+" on line "+i+":\n\n"+o),console.warn("Ask AI ✨ "+c),t&&window.open(c,"_blank")}catch(e){}}},Q5.modules.color=(e,t)=>{e.RGB=e.RGBA=e._colorMode="rgb",Q5.supportsHDR?e.Color=Q5.ColorRGBA_P3:e.Color=Q5.ColorRGBA,e.colorMode=a=>{e._colorMode=a,"oklch"==a?t.Color=Q5.ColorOKLCH:"rgb"==a?"srgb"==e.canvas.colorSpace?t.Color=Q5.ColorRGBA:t.Color=Q5.ColorRGBA_P3:"srgb"==a&&(t.Color=Q5.ColorRGBA,e._colorMode="rgb")},e._basicColors={aqua:[0,255,255],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],crimson:[220,20,60],cyan:[0,255,255],darkviolet:[148,0,211],gold:[255,215,0],green:[0,128,0],gray:[128,128,128],grey:[128,128,128],hotpink:[255,105,180],indigo:[75,0,130],khaki:[240,230,140],lightgreen:[144,238,144],lime:[0,255,0],magenta:[255,0,255],navy:[0,0,128],orange:[255,165,0],olive:[128,128,0],peachpuff:[255,218,185],pink:[255,192,203],purple:[128,0,128],red:[255,0,0],skyblue:[135,206,235],tan:[210,180,140],turquoise:[64,224,208],transparent:[0,0,0,0],white:[255,255,255],violet:[238,130,238],yellow:[255,255,0]},e.color=function(t,a,o,n){let r=e.Color;if(t._q5Color)return new r(...t.levels);let i=arguments;if(1==i.length){if("string"==typeof t)return"#"==t[0]?new r(parseInt(t.slice(1,3),16),parseInt(t.slice(3,5),16),parseInt(t.slice(5,7),16),9!=t.length?null:parseInt(t.slice(7,9),16)):e._basicColors[t]?new r(...e._basicColors[t]):new r(0,0,0);if(Array.isArray(t))return new r(...t)}if("rgb"==e._colorMode){if(1==i.length)return new r(t,t,t);if(2==i.length)return new r(t,t,t,a);if(3==i.length)return new r(t,a,o);if(4==i.length)return new r(t,a,o,n)}},e.red=e=>e.r,e.green=e=>e.g,e.blue=e=>e.b,e.alpha=e=>e.a,e.lightness=e=>100*(.2126*e.r+.7152*e.g+.0722*e.b)/255,e.lerpColor=(t,a,o)=>{if("rgb"==e._colorMode)return new e.Color(e.constrain(e.lerp(t.r,a.r,o),0,255),e.constrain(e.lerp(t.g,a.g,o),0,255),e.constrain(e.lerp(t.b,a.b,o),0,255),e.constrain(e.lerp(t.a,a.a,o),0,255));{let n=a.h-t.h;n>180&&(n-=360),n<-180&&(n+=360);let r=t.h+o*n;return r<0&&(r+=360),r>360&&(r-=360),new e.Color(e.constrain(e.lerp(t.l,a.l,o),0,100),e.constrain(e.lerp(t.c,a.c,o),0,100),r,e.constrain(e.lerp(t.a,a.a,o),0,255))}}},Q5.Color=class{constructor(){this._q5Color=!0}},Q5.ColorOKLCH=class extends Q5.Color{constructor(e,t,a,o){super(),this.l=e,this.c=t,this.h=a,this.a=o??1}toString(){return`color(oklch ${this.l} ${this.c} ${this.h} / ${this.a})`}},Q5.ColorRGBA=class extends Q5.Color{constructor(e,t,a,o){super(),this.r=e,this.g=t,this.b=a,this.a=o??255}setRed(e){this.r=e}setGreen(e){this.g=e}setBlue(e){this.b=e}setAlpha(e){this.a=e}get levels(){return[this.r,this.g,this.b,this.a]}toString(){return`rgb(${this.r} ${this.g} ${this.b} / ${this.a/255})`}},Q5.ColorRGBA_P3=class extends Q5.ColorRGBA{constructor(e,t,a,o){super(e,t,a,o),this._edited=!0}get r(){return this._r}set r(e){this._r=e,this._edited=!0}get g(){return this._g}set g(e){this._g=e,this._edited=!0}get b(){return this._b}set b(e){this._b=e,this._edited=!0}get a(){return this._a}set a(e){this._a=e,this._edited=!0}toString(){if(this._edited){let e=(this._r/255).toFixed(3),t=(this._g/255).toFixed(3),a=(this._b/255).toFixed(3),o=(this._a/255).toFixed(3);this._css=`color(display-p3 ${e} ${t} ${a} / ${o})`,this._edited=!1}return this._css}},Q5.modules.display=e=>{if(!e.canvas||"graphics"==e._scope)return;let t=e.canvas;0!=Q5._instanceCount||Q5._nodejs||document.head.insertAdjacentHTML("beforeend","<style>\nhtml, body {\n\tmargin: 0;\n\tpadding: 0;\n}\n.q5Canvas {\n\toutline: none;\n\t-webkit-touch-callout: none;\n\t-webkit-text-size-adjust: none;\n\t-webkit-user-select: none;\n\toverscroll-behavior: none;\n}\n.q5-pixelated {\n\timage-rendering: pixelated;\n\tfont-smooth: never;\n\t-webkit-font-smoothing: none;\n}\n.q5-centered,\n.q5-maxed,\n.q5-fullscreen {\n display: flex;\n\talign-items: center;\n\tjustify-content: center;\n}\nmain.q5-centered,\nmain.q5-maxed,\n.q5-fullscreen {\n\theight: 100vh;\n}\nmain {\n\toverscroll-behavior: none;\n}\n</style>"),e._adjustDisplay=()=>{let a=t.style,o=t.parentElement;a&&o&&t.displayMode&&("pixelated"==t.renderQuality&&(t.classList.add("q5-pixelated"),e.pixelDensity(1),e.noSmooth&&e.noSmooth(),e.textFont&&e.textFont("monospace")),"normal"==t.displayMode?(o.classList.remove("q5-centered","q5-maxed","q5-fullscreen"),a.width=t.w*t.displayScale+"px",a.height=t.h*t.displayScale+"px"):(o.classList.add("q5-"+t.displayMode),o=o.getBoundingClientRect(),t.w/t.h>o.width/o.height?("centered"==t.displayMode?(a.width=t.w*t.displayScale+"px",a.maxWidth="100%"):a.width="100%",a.height="auto",a.maxHeight=""):(a.width="auto",a.maxWidth="","centered"==t.displayMode?(a.height=t.h*t.displayScale+"px",a.maxHeight="100%"):a.height="100%")))},e.displayMode=(a="normal",o="default",n=1)=>{"string"==typeof n&&(n=parseFloat(n.slice(1))),Object.assign(t,{displayMode:a,renderQuality:o,displayScale:n}),e._adjustDisplay()}},Q5.modules.input=(e,t)=>{if("graphics"==e._scope)return;e.mouseX=0,e.mouseY=0,e.pmouseX=0,e.pmouseY=0,e.touches=[],e.mouseButton=null,e.keyIsPressed=!1,e.mouseIsPressed=!1,e.key=null,e.keyCode=null,e.UP_ARROW=38,e.DOWN_ARROW=40,e.LEFT_ARROW=37,e.RIGHT_ARROW=39,e.SHIFT=16,e.TAB=9,e.BACKSPACE=8,e.ENTER=e.RETURN=13,e.ALT=e.OPTION=18,e.CONTROL=17,e.DELETE=46,e.ESCAPE=27,e.ARROW="default",e.CROSS="crosshair",e.HAND="pointer",e.MOVE="move",e.TEXT="text";let a={},o=[e.LEFT,e.CENTER,e.RIGHT],n=e.canvas;function r(t){const a=e.canvas.getBoundingClientRect(),o=e.canvas.scrollWidth/e.width||1,n=e.canvas.scrollHeight/e.height||1;return{x:(t.clientX-a.left)/o,y:(t.clientY-a.top)/n,id:t.identifier}}if(e._startAudio=()=>{e.getAudioContext&&"suspended"==e.getAudioContext()?.state&&e.userStartAudio()},e._updateMouse=a=>{if(a.changedTouches)return;let o=e.canvas.getBoundingClientRect(),n=e.canvas.scrollWidth/e.width||1,r=e.canvas.scrollHeight/e.height||1;t.mouseX=(a.clientX-o.left)/n,t.mouseY=(a.clientY-o.top)/r},e._onmousedown=a=>{e._startAudio(),e._updateMouse(a),t.mouseIsPressed=!0,t.mouseButton=o[a.button],e.mousePressed(a)},e._onmousemove=t=>{e._updateMouse(t),e.mouseIsPressed?e.mouseDragged(t):e.mouseMoved(t)},e._onmouseup=a=>{e._updateMouse(a),t.mouseIsPressed=!1,e.mouseReleased(a)},e._onclick=a=>{e._updateMouse(a),t.mouseIsPressed=!0,e.mouseClicked(a),t.mouseIsPressed=!1},n.addEventListener("mousedown",(t=>e._onmousedown(t))),n.addEventListener("mouseup",(t=>e._onmouseup(t))),n.addEventListener("click",(t=>e._onclick(t))),e.cursor=(t,a,o)=>{let n="";t.includes(".")&&(t=`url("${t}")`,n=", auto"),void 0!==a&&(t+=" "+a+" "+o),e.canvas.style.cursor=t+n},e.noCursor=()=>{e.canvas.style.cursor="none"},e.requestPointerLock=document.body?.requestPointerLock,e.exitPointerLock=document.exitPointerLock,e._onkeydown=o=>{o.repeat||(e._startAudio,t.keyIsPressed=!0,t.key=o.key,t.keyCode=o.keyCode,a[e.keyCode]=a[e.key]=!0,e.keyPressed(o),1==o.key.length&&e.keyTyped(o))},e._onkeyup=o=>{t.keyIsPressed=!1,t.key=o.key,t.keyCode=o.keyCode,a[e.keyCode]=a[e.key]=!1,e.keyReleased(o)},e.keyIsDown=e=>!!a[e],e._ontouchstart=a=>{e._startAudio(),t.touches=[...a.touches].map(r),e._isTouchAware||(t.mouseX=e.touches[0].x,t.mouseY=e.touches[0].y,t.mouseIsPressed=!0,t.mouseButton=e.LEFT,e.mousePressed(a)||a.preventDefault()),e.touchStarted(a)||a.preventDefault()},e._ontouchmove=a=>{t.touches=[...a.touches].map(r),e._isTouchAware||(t.mouseX=e.touches[0].x,t.mouseY=e.touches[0].y,e.mouseDragged(a)||a.preventDefault()),e.touchMoved(a)||a.preventDefault()},e._ontouchend=a=>{t.touches=[...a.touches].map(r),e._isTouchAware||e.touches.length||(t.mouseIsPressed=!1,e.mouseReleased(a)||a.preventDefault()),e.touchEnded(a)||a.preventDefault()},n.addEventListener("touchstart",(t=>e._ontouchstart(t))),n.addEventListener("touchmove",(t=>e._ontouchmove(t))),n.addEventListener("touchcancel",(t=>e._ontouchend(t))),n.addEventListener("touchend",(t=>e._ontouchend(t))),window){let t=window.addEventListener;t("mousemove",(t=>e._onmousemove(t)),!1),t("keydown",(t=>e._onkeydown(t)),!1),t("keyup",(t=>e._onkeyup(t)),!1)}},Q5.modules.math=(e,t)=>{function a(){let e,t,a=4294967295;return{setSeed(o){e=t=(o??Math.random()*a)>>>0},getSeed:()=>t,rand:()=>(e^=e<<17,e^=e>>13,e^=e<<5,(e>>>0)/a)}}e.DEGREES="degrees",e.RADIANS="radians",e.PI=Math.PI,e.HALF_PI=Math.PI/2,e.QUARTER_PI=Math.PI/4,e.abs=Math.abs,e.ceil=Math.ceil,e.exp=Math.exp,e.floor=Math.floor,e.loge=Math.log,e.mag=Math.hypot,e.max=Math.max,e.min=Math.min,e.round=Math.round,e.pow=Math.pow,e.sqrt=Math.sqrt,e.SHR3=1,e.LCG=2,e.angleMode=t=>e._angleMode=t,e._DEGTORAD=Math.PI/180,e._RADTODEG=180/Math.PI,e.degrees=t=>t*e._RADTODEG,e.radians=t=>t*e._DEGTORAD,e.map=(e,t,a,o,n,r)=>{let i=o+1*(e-t)/(a-t)*(n-o);return r?o<n?Math.min(Math.max(i,o),n):Math.min(Math.max(i,n),o):i},e.lerp=(e,t,a)=>e*(1-a)+t*a,e.constrain=(e,t,a)=>Math.min(Math.max(e,t),a),e.dist=function(){let e=arguments;return 4==e.length?Math.hypot(e[0]-e[2],e[1]-e[3]):Math.hypot(e[0]-e[3],e[1]-e[4],e[2]-e[5])},e.norm=(t,a,o)=>e.map(t,a,o,0,1),e.sq=e=>e*e,e.fract=e=>e-Math.floor(e),e.sin=t=>("degrees"==e._angleMode&&(t=e.radians(t)),Math.sin(t)),e.cos=t=>("degrees"==e._angleMode&&(t=e.radians(t)),Math.cos(t)),e.tan=t=>("degrees"==e._angleMode&&(t=e.radians(t)),Math.tan(t)),e.asin=t=>{let a=Math.asin(t);return"degrees"==e._angleMode&&(a=e.degrees(a)),a},e.acos=t=>{let a=Math.acos(t);return"degrees"==e._angleMode&&(a=e.degrees(a)),a},e.atan=t=>{let a=Math.atan(t);return"degrees"==e._angleMode&&(a=e.degrees(a)),a},e.atan2=(t,a)=>{let o=Math.atan2(t,a);return"degrees"==e._angleMode&&(o=e.degrees(o)),o};let o=a();o.setSeed(),e.randomSeed=e=>o.setSeed(e),e.random=(e,t)=>void 0===e?o.rand():"number"==typeof e?void 0!==t?o.rand()*(t-e)+e:o.rand()*e:e[Math.trunc(e.length*o.rand())],e.randomGenerator=t=>{t==e.LCG?o=function(){const e=4294967296;let t,a;return{setSeed(o){a=t=(o??Math.random()*e)>>>0},getSeed:()=>t,rand:()=>(a=(1664525*a+1013904223)%e,a/e)}}():t==e.SHR3&&(o=a()),o.setSeed()};var n=new function(){var e,t,a,n=new Array(128),r=new Array(256),i=new Array(128),s=new Array(128),l=new Array(256),c=new Array(256),d=()=>4294967296*o.rand()-2147483648,h=()=>.5+2.328306e-10*(d()|0),u=()=>{for(var t,o,r,l,c=3.44262;;){if(t=a*i[e],0==e){do{r=h(),l=h(),t=.2904764*-Math.log(r),o=-Math.log(l)}while(o+o<t*t);return a>0?c+t:-c-t}if(s[e]+h()*(s[e-1]-s[e])<Math.exp(-.5*t*t))return t;if(a=d(),e=127&a,Math.abs(a)<n[e])return a*i[e]}},_=()=>{for(var a;;){if(0==e)return 7.69711-Math.log(h());if(a=t*l[e],c[e]+h()*(c[e-1]-c[e])<Math.exp(-a))return a;if((t=d())<r[e=255&t])return t*l[e]}};this.SHR3=d,this.UNI=h,this.RNOR=()=>(a=d(),e=127&a,Math.abs(a)<n[e]?a*i[e]:u()),this.REXP=()=>(t=d()>>>0)<n[e=255&t]?t*l[e]:_(),this.zigset=()=>{var e,t,a=2147483648,o=4294967296,d=3.442619855899,h=d,u=.00991256303526217,_=7.697117470131487,g=_,p=.003949659822581572;for(e=u/Math.exp(-.5*d*d),n[0]=Math.floor(d/e*a),n[1]=0,i[0]=e/a,i[127]=d/a,s[0]=1,s[127]=Math.exp(-.5*d*d),t=126;t>=1;t--)d=Math.sqrt(-2*Math.log(u/d+Math.exp(-.5*d*d))),n[t+1]=Math.floor(d/h*a),h=d,s[t]=Math.exp(-.5*d*d),i[t]=d/a;for(e=p/Math.exp(-_),r[0]=Math.floor(_/e*o),r[1]=0,l[0]=e/o,l[255]=_/o,c[0]=1,c[255]=Math.exp(-_),t=254;t>=1;t--)_=-Math.log(p/_+Math.exp(-_)),r[t+1]=Math.floor(_/g*o),g=_,c[t]=Math.exp(-_),l[t]=_/o}};let r;n.hasInit=!1,e.randomGaussian=(e,t)=>(n.hasInit||(n.zigset(),n.hasInit=!0),n.RNOR()*t+e),e.randomExponential=()=>(n.hasInit||(n.zigset(),n.hasInit=!0),n.REXP()),e.PERLIN="perlin",e.SIMPLEX="simplex",e.BLOCKY="blocky",e.Noise=Q5.PerlinNoise,e.noiseMode=e=>{t.Noise=Q5[e[0].toUpperCase()+e.slice(1)+"Noise"],r=null},e.noiseSeed=t=>{r=new e.Noise(t)},e.noise=(t=0,a=0,o=0)=>(r??=new e.Noise,r.noise(t,a,o)),e.noiseDetail=(t,a)=>{r??=new e.Noise,t>0&&(r.octaves=t),a>0&&(r.falloff=a)}},Q5.Noise=class{constructor(){}},Q5.PerlinNoise=class extends Q5.Noise{constructor(e){super(),this.grad3=[[1,1,0],[-1,1,0],[1,-1,0],[-1,-1,0],[1,0,1],[-1,0,1],[1,0,-1],[-1,0,-1],[0,1,1],[0,-1,1],[0,1,-1],[0,-1,-1]],this.octaves=1,this.falloff=.5,this.p=null==e?Array.from({length:256},(()=>Math.floor(256*Math.random()))):this.seedPermutation(e),this.p=this.p.concat(this.p)}seedPermutation(e){let t,a,o=[];for(let e=0;e<256;e++)o[e]=e;for(let n=255;n>0;n--)t=(e=16807*e%2147483647)%(n+1),a=o[n],o[n]=o[t],o[t]=a;return o}dot(e,t,a,o){return e[0]*t+e[1]*a+e[2]*o}mix(e,t,a){return(1-a)*e+a*t}fade(e){return e*e*e*(e*(6*e-15)+10)}noise(e,t,a){let o=this,n=0,r=1,i=1,s=0;for(let l=0;l<o.octaves;l++){const l=255&Math.floor(e*r),c=255&Math.floor(t*r),d=255&Math.floor(a*r),h=e*r-Math.floor(e*r),u=t*r-Math.floor(t*r),_=a*r-Math.floor(a*r),g=o.fade(h),p=o.fade(u),x=o.fade(_),m=o.p[l]+c,f=o.p[m]+d,v=o.p[m+1]+d,y=o.p[l+1]+c,w=o.p[y]+d,M=o.p[y+1]+d,C=o.mix(o.dot(o.grad3[o.p[f]%12],h,u,_),o.dot(o.grad3[o.p[w]%12],h-1,u,_),g),b=o.mix(o.dot(o.grad3[o.p[v]%12],h,u-1,_),o.dot(o.grad3[o.p[M]%12],h-1,u-1,_),g),S=o.mix(o.dot(o.grad3[o.p[f+1]%12],h,u,_-1),o.dot(o.grad3[o.p[w+1]%12],h-1,u,_-1),g),R=o.mix(o.dot(o.grad3[o.p[v+1]%12],h,u-1,_-1),o.dot(o.grad3[o.p[M+1]%12],h-1,u-1,_-1),g),E=o.mix(C,b,p),I=o.mix(S,R,p);n+=o.mix(E,I,x)*i,s+=i,i*=o.falloff,r*=2}return(n/s+1)/2}},Q5.modules.sound=(e,t)=>{e.loadSound=(a,o)=>{t._preloadCount++,e.aud??=new window.AudioContext;let n=new Audio(a);return n.addEventListener("canplaythrough",(()=>{t._preloadCount--,o&&o(n)})),n.load(),n.setVolume=e=>n.volume=e,n.setLoop=e=>n.loop=e,n.panner=e.aud.createStereoPanner(),n.source=e.aud.createMediaElementSource(n),n.source.connect(n.panner),n.panner.connect(e.aud.destination),Object.defineProperty(n,"pan",{get:()=>n.panner.pan.value,set:e=>n.panner.pan.value=e}),n.setPan=e=>n.pan=e,n},e.getAudioContext=()=>e.aud,e.userStartAudio=()=>e.aud.resume()},Q5.modules.util=(e,t)=>{e._loadFile=(e,a,o)=>{t._preloadCount++;let n={};return fetch(e).then((e=>"json"==o?e.json():"text"==o?e.text():void 0)).then((e=>{t._preloadCount--,Object.assign(n,e),a&&a(e)})),n},e.loadStrings=(t,a)=>e._loadFile(t,a,"text"),e.loadJSON=(t,a)=>e._loadFile(t,a,"json"),"object"==typeof localStorage&&(e.storeItem=localStorage.setItem,e.getItem=localStorage.getItem,e.removeItem=localStorage.removeItem,e.clearStorage=localStorage.clear),e.year=()=>(new Date).getFullYear(),e.day=()=>(new Date).getDay(),e.hour=()=>(new Date).getHours(),e.minute=()=>(new Date).getMinutes(),e.second=()=>(new Date).getSeconds()},Q5.modules.vector=e=>{e.createVector=(t,a,o)=>new Q5.Vector(t,a,o,e)},Q5.Vector=class{constructor(e,t,a,o){this.x=e||0,this.y=t||0,this.z=a||0,this._$=o||window,this._cn=null,this._cnsq=null}set(e,t,a){this.x=e||0,this.y=t||0,this.z=a||0}copy(){return new Q5.Vector(this.x,this.y,this.z)}_arg2v(e,t,a){return void 0!==e.x?e:void 0!==t?{x:e,y:t,z:a||0}:{x:e,y:e,z:e}}_calcNorm(){this._cnsq=this.x*this.x+this.y*this.y+this.z*this.z,this._cn=Math.sqrt(this._cnsq)}add(){let e=this._arg2v(...arguments);return this.x+=e.x,this.y+=e.y,this.z+=e.z,this}rem(){let e=this._arg2v(...arguments);return this.x%=e.x,this.y%=e.y,this.z%=e.z,this}sub(){let e=this._arg2v(...arguments);return this.x-=e.x,this.y-=e.y,this.z-=e.z,this}mult(){let e=this._arg2v(...arguments);return this.x*=e.x,this.y*=e.y,this.z*=e.z,this}div(){let e=this._arg2v(...arguments);return e.x?this.x/=e.x:this.x=0,e.y?this.y/=e.y:this.y=0,e.z?this.z/=e.z:this.z=0,this}mag(){return this._calcNorm(),this._cn}magSq(){return this._calcNorm(),this._cnsq}dot(){let e=this._arg2v(...arguments);return this.x*e.x+this.y*e.y+this.z*e.z}dist(){let e=this._arg2v(...arguments),t=this.x-e.x,a=this.y-e.y,o=this.z-e.z;return Math.sqrt(t*t+a*a+o*o)}cross(){let e=this._arg2v(...arguments),t=this.y*e.z-this.z*e.y,a=this.z*e.x-this.x*e.z,o=this.x*e.y-this.y*e.x;return this.x=t,this.y=a,this.z=o,this}normalize(){this._calcNorm();let e=this._cn;return 0!=e&&(this.x/=e,this.y/=e,this.z/=e),this._cn=1,this._cnsq=1,this}limit(e){this._calcNorm();let t=this._cn;if(t>e){let a=e/t;this.x*=a,this.y*=a,this.z*=a,this._cn=e,this._cnsq=e*e}return this}setMag(e){this._calcNorm();let t=e/this._cn;return this.x*=t,this.y*=t,this.z*=t,this._cn=e,this._cnsq=e*e,this}heading(){return this._$.atan2(this.y,this.x)}rotate(e){let t=this._$.cos(e),a=this._$.sin(e),o=this.x*t-this.y*a,n=this.x*a+this.y*t;return this.x=o,this.y=n,this}angleBetween(){let e=this._arg2v(...arguments),t=Q5.Vector.cross(this,e);return this._$.atan2(t.mag(),this.dot(e))*Math.sign(t.z||1)}lerp(){let e=[...arguments],t=this._arg2v(...e.slice(0,-1)),a=e[e.length-1];return this.x+=(t.x-this.x)*a,this.y+=(t.y-this.y)*a,this.z+=(t.z-this.z)*a,this}reflect(e){return e.normalize(),this.sub(e.mult(2*this.dot(e)))}array(){return[this.x,this.y,this.z]}equals(e,t){return t??=Number.EPSILON||0,Math.abs(e.x-this.x)<t&&Math.abs(e.y-this.y)<t&&Math.abs(e.z-this.z)<t}fromAngle(e,t){return void 0===t&&(t=1),this._cn=t,this._cnsq=t*t,this.x=t*this._$.cos(e),this.y=t*this._$.sin(e),this.z=0,this}fromAngles(e,t,a){void 0===a&&(a=1),this._cn=a,this._cnsq=a*a;const o=this._$.cos(t),n=this._$.sin(t),r=this._$.cos(e),i=this._$.sin(e);return this.x=a*i*n,this.y=-a*r,this.z=a*i*o,this}random2D(){return this._cn=this._cnsq=1,this.fromAngle(Math.random()*Math.PI*2)}random3D(){return this._cn=this._cnsq=1,this.fromAngles(Math.random()*Math.PI*2,Math.random()*Math.PI*2)}toString(){return`[${this.x}, ${this.y}, ${this.z}]`}},Q5.Vector.add=(e,t)=>e.copy().add(t),Q5.Vector.cross=(e,t)=>e.copy().cross(t),Q5.Vector.dist=(e,t)=>Math.hypot(e.x-t.x,e.y-t.y,e.z-t.z),Q5.Vector.div=(e,t)=>e.copy().div(t),Q5.Vector.dot=(e,t)=>e.copy().dot(t),Q5.Vector.equals=(e,t,a)=>e.equals(t,a),Q5.Vector.lerp=(e,t,a)=>e.copy().lerp(t,a),Q5.Vector.limit=(e,t)=>e.copy().limit(t),Q5.Vector.heading=e=>this._$.atan2(e.y,e.x),Q5.Vector.magSq=e=>e.x*e.x+e.y*e.y+e.z*e.z,Q5.Vector.mag=e=>Math.sqrt(Q5.Vector.magSq(e)),Q5.Vector.mult=(e,t)=>e.copy().mult(t),Q5.Vector.normalize=e=>e.copy().normalize(),Q5.Vector.rem=(e,t)=>e.copy().rem(t),Q5.Vector.sub=(e,t)=>e.copy().sub(t);for(let e of["fromAngle","fromAngles","random2D","random3D"])Q5.Vector[e]=(t,a,o)=>(new Q5.Vector)[e](t,a,o);
|
|
8
|
+
function Q5(e,t){let a,o=this;if(o._q5=!0,o._scope=e,o._parent=t,o._preloadCount=0,e??="global","auto"==e){if(!window.setup&&!window.draw)return;e="global"}"global"==e&&(Q5._hasGlobal=o._isGlobal=!0,a=Q5._nodejs?global:window);let n=new Proxy(o,{set:(e,t,n)=>(o[t]=n,o._isGlobal&&(a[t]=n),!0)});o.canvas=o.ctx=o.drawingContext=null,o.pixels=[];let r=null;o.frameCount=0,o.deltaTime=16,o._targetFrameRate=0,o._targetFrameDuration=16.666666666666668,o._frameRate=o._fps=60,o._loop=!0;let s=0;function i(e){let t=e||performance.now();if(o._lastFrameTime??=t-o._targetFrameDuration,o._shouldResize&&(o.windowResized(),o._shouldResize=!1),o._loop)r=l(i);else if(o.frameCount&&!o._redraw)return;if(r&&o.frameCount){if(t-o._lastFrameTime<o._targetFrameDuration-1)return}n.deltaTime=t-o._lastFrameTime,o._frameRate=1e3/o.deltaTime,n.frameCount++;let a=performance.now();for(let e of Q5.prototype._methods.pre)e.call(o);o.ctx&&o.ctx.save(),o.draw();for(let e of Q5.prototype._methods.post)e.call(o);o.ctx&&(o.ctx.restore(),o.resetMatrix()),n.pmouseX=o.mouseX,n.pmouseY=o.mouseY,o._lastFrameTime=t;let s=performance.now();o._fps=Math.round(1e3/(s-a))}o.millis=()=>performance.now()-s,o.noCanvas=()=>{o.canvas?.remove&&o.canvas.remove(),o.canvas=0,n.ctx=n.drawingContext=0},window&&(o.windowWidth=window.innerWidth,o.windowHeight=window.innerHeight,o.deviceOrientation=window.screen?.orientation?.type),o._incrementPreload=()=>n._preloadCount++,o._decrementPreload=()=>n._preloadCount--,o.noLoop=()=>{o._loop=!1,r=null},o.loop=()=>{o._loop=!0,null==r&&i()},o.redraw=(e=1)=>{o._redraw=!0;for(let t=0;t<e;t++)i();o._redraw=!1},o.remove=()=>{o.noLoop(),o.canvas.remove()},o.frameRate=e=>(e&&(o._targetFrameRate=e,o._targetFrameDuration=1e3/e),o._frameRate),o.getTargetFrameRate=()=>o._targetFrameRate,o.getFPS=()=>o._fps,o.Element=function(e){this.elt=e},o._elements=[],o.TWO_PI=o.TAU=2*Math.PI,o.log=o.print=console.log,o.describe=()=>{};for(let e in Q5.modules)Q5.modules[e](o,n);for(let e in Q5)"_"!=e[1]&&e[1]==e[1].toUpperCase()&&(o[e]=Q5[e]);"global"==e&&(Object.assign(Q5,o),delete Q5.Q5);for(let e of Q5.prototype._methods.init)e.call(o);for(let[e,t]of Object.entries(Q5.prototype))"_"!=e[0]&&"function"==typeof o[e]&&(o[e]=t.bind(o));if("global"==e){let e=Object.getOwnPropertyNames(o);for(let t of e)"_"!=t[0]&&(a[t]=o[t])}if("function"==typeof e&&e(o),"graphics"==e)return;Q5._instanceCount++;let l=window.requestAnimationFrame||function(e){const t=o._lastFrameTime+o._targetFrameDuration;return setTimeout((()=>{e(t)}),t-performance.now())},c=a||o;o._isTouchAware=c.touchStarted||c.touchMoved||c.mouseReleased;let d=c.preload,h=["setup","draw","preload","mouseMoved","mousePressed","mouseReleased","mouseDragged","mouseClicked","keyPressed","keyReleased","keyTyped","touchStarted","touchMoved","touchEnded","windowResized"];for(let e of h)c[e]?o._isGlobal&&(o[e]=()=>{try{return c[e]()}catch(e){o._aiErrorAssistance?o._aiErrorAssistance(e):console.error(e)}}):o[e]=()=>{};async function u(){if(o._startDone=!0,o._preloadCount>0)return l(u);s=performance.now(),await o.setup(),o.frameCount||(null===o.ctx&&o.createCanvas(100,100),o._setupDone=!0,o.ctx&&o.resetMatrix(),l(i))}(o.setup||o.draw)&&(o._startDone=!1,arguments.length&&"namespace"!=e||d?(o.preload(),u()):(c.preload=o.preload=()=>{o._startDone||u()},setTimeout(o.preload,32)))}Q5.modules={},Q5._nodejs="object"==typeof process,Q5._instanceCount=0,Q5._friendlyError=(e,t)=>{throw Error(t+": "+e)},Q5._validateParameters=()=>!0,Q5.prototype._methods={init:[],pre:[],post:[],remove:[]},Q5.prototype.registerMethod=(e,t)=>Q5.prototype._methods[e].push(t),Q5.prototype.registerPreloadMethod=(e,t)=>Q5.prototype[e]=t[e],Q5._nodejs?global.p5??=global.Q5=Q5:"object"==typeof window?window.p5??=window.Q5=Q5:global.window=0,"object"==typeof document&&document.addEventListener("DOMContentLoaded",(()=>{Q5._hasGlobal||new Q5("auto")})),Q5.modules.q2d_canvas=(e,t)=>{e._OffscreenCanvas=window.OffscreenCanvas||function(){return document.createElement("canvas")},Q5._nodejs?Q5._createNodeJSCanvas&&(t.canvas=Q5._createNodeJSCanvas(100,100)):"image"!=e._scope&&"graphics"!=e._scope||(t.canvas=new e._OffscreenCanvas(100,100)),e.canvas||("object"==typeof document?(t.canvas=document.createElement("canvas"),e.canvas.id="q5Canvas"+Q5._instanceCount,e.canvas.classList.add("q5Canvas")):e.noCanvas());let a=e.canvas;if(a.width=e.width=100,a.height=e.height=100,a&&"graphics"!=e._scope&&"image"!=e._scope){e._setupDone=!1;let r=e._parent;function o(){r??=document.getElementsByTagName("main")[0],r||(r=document.createElement("main"),document.body.append(r)),a.parent(r)}r&&"string"==typeof r&&(r=document.getElementById(r)),a.parent=t=>{function o(){e.frameCount>1&&(e._shouldResize=!0,e._adjustDisplay())}"string"==typeof t&&(t=document.getElementById(t)),t.append(a),"function"==typeof ResizeObserver?(e._ro&&e._ro.disconnect(),e._ro=new ResizeObserver(o),e._ro.observe(r)):e.frameCount||window.addEventListener("resize",o)},document.body?o():document.addEventListener("DOMContentLoaded",o)}function n(o,n){o??=window.innerWidth,n??=window.innerHeight;let r,s=function(){let t={};for(let a in e.ctx)"function"!=typeof e.ctx[a]&&(t[a]=e.ctx[a]);return delete t.canvas,t}();if(e.frameCount){r=new e._OffscreenCanvas(a.width,a.height),r.w=a.w,r.h=a.h,r.getContext("2d").drawImage(a,0,0)}a.width=Math.ceil(o*e._pixelDensity),a.height=Math.ceil(n*e._pixelDensity),a.w=o,a.h=n,a.hw=o/2,a.hh=n/2;for(let t in s)e.ctx[t]=s[t];e.ctx.scale(e._pixelDensity,e._pixelDensity),e.frameCount&&e.ctx.drawImage(r,0,0,r.w,r.h),e._da?e.flexibleCanvas(e._dau):(t.width=o,t.height=n),0!=e.frameCount&&e._adjustDisplay()}e._adjustDisplay=()=>{a.style&&(a.style.width=a.w+"px",a.style.height=a.h+"px")},e.createCanvas=function(o,n,r,s){if("webgl"==r)throw Error("webgl renderer is not supported in q5, use '2d'");"object"==typeof r&&(s=r),t.width=a.width=a.w=o||window.innerWidth,t.height=a.height=a.h=n||window.innerHeight,a.hw=o/2,a.hh=n/2,a.renderer="2d";let i=Object.assign({},Q5.canvasOptions);if(s&&Object.assign(i,s),t.ctx=t.drawingContext=a.getContext("2d",i),Object.assign(a,i),"rgb"==e._colorMode&&e.colorMode("rgb"),"image"!=e._scope&&(e._defaultStyle(),e._da=0),e.ctx.save(),"image"!=e._scope){let t=e.displayDensity();"graphics"==e._scope?t=this._pixelDensity:window.IntersectionObserver&&new IntersectionObserver((e=>{a.visible=e[0].isIntersecting})).observe(a),e.pixelDensity(Math.ceil(t))}else this._pixelDensity=1;return e.displayMode?e.displayMode():e._adjustDisplay(),a},e._createCanvas=e.createCanvas,"image"!=e._scope&&(e._defaultStyle=()=>{e.ctx.fillStyle="white",e.ctx.strokeStyle="black",e.ctx.lineCap="round",e.ctx.lineJoin="miter",e.ctx.textAlign="left"},e.resizeCanvas=(e,t)=>{e==a.w&&t==a.h||n(e,t)},e._pixelDensity=1,e.displayDensity=()=>window.devicePixelRatio,e.pixelDensity=t=>t&&t!=e._pixelDensity?(e._pixelDensity=t,n(a.w,a.h),t):e._pixelDensity,"image"!=e._scope&&(e.fullscreen=e=>{if(void 0===e)return document.fullscreenElement;e?document.body.requestFullscreen():document.body.exitFullscreen()},e.flexibleCanvas=(o=400)=>{o?(e._da=a.width/(o*e._pixelDensity),t.width=e._dau=o,t.height=a.h/a.w*o):e._da=0},e.translate=(t,a)=>{e._da&&(t*=e._da,a*=e._da),e.ctx.translate(t,a)},e.rotate=t=>{"degrees"==e._angleMode&&(t=e.radians(t)),e.ctx.rotate(t)},e.scale=(t,a)=>{a??=t,e.ctx.scale(t,a)},e.opacity=t=>e.ctx.globalAlpha=t,e.applyMatrix=(t,a,o,n,r,s)=>e.ctx.transform(t,a,o,n,r,s),e.shearX=t=>e.ctx.transform(1,0,e.tan(t),1,0,0),e.shearY=t=>e.ctx.transform(1,e.tan(t),0,1,0,0),e.resetMatrix=()=>{e.ctx.resetTransform(),e.ctx.scale(e._pixelDensity,e._pixelDensity)},e._styleNames=["_doStroke","_doFill","_strokeSet","_fillSet","_tint","_imageMode","_rectMode","_ellipseMode","_textFont","_textLeading","_leadingSet","_textSize","_textAlign","_textBaseline","_textStyle","_textWrap"],e._styles=[],e.push=e.pushMatrix=()=>{e.ctx.save();let t={};for(let a of e._styleNames)t[a]=e[a];e._styles.push(t)},e.pop=e.popMatrix=()=>{e.ctx.restore();let t=e._styles.pop();for(let a of e._styleNames)e[a]=t[a]},e.createCapture=e=>{var t=document.createElement("video");return t.playsinline="playsinline",t.autoplay="autoplay",navigator.mediaDevices.getUserMedia(e).then((e=>{t.srcObject=e})),t.style.position="absolute",t.style.opacity=1e-5,t.style.zIndex=-1e3,document.body.append(t),t},e.createGraphics=function(t,a,o){let n=new Q5("graphics");return o??={},o.alpha??=!0,o.colorSpace??=e.canvas.colorSpace,n._createCanvas.call(e,t,a,o),n},window&&"graphics"!=e._scope&&window.addEventListener("resize",(()=>{e._shouldResize=!0,t.windowWidth=window.innerWidth,t.windowHeight=window.innerHeight,t.deviceOrientation=window.screen?.orientation?.type}))))},Q5.canvasOptions={alpha:!1,colorSpace:"display-p3"},window.matchMedia&&matchMedia("(dynamic-range: high) and (color-gamut: p3)").matches?Q5.supportsHDR=!0:Q5.canvasOptions.colorSpace="srgb",Q5.modules.q2d_drawing=e=>{e.CHORD=0,e.PIE=1,e.OPEN=2,e.RADIUS="radius",e.CORNER="corner",e.CORNERS="corners",e.ROUND="round",e.SQUARE="butt",e.PROJECT="square",e.MITER="miter",e.BEVEL="bevel",e.CLOSE=1,e.CENTER="center",e.LEFT="left",e.RIGHT="right",e.TOP="top",e.BOTTOM="bottom",e.LANDSCAPE="landscape",e.PORTRAIT="portrait",e.BLEND="source-over",e.REMOVE="destination-out",e.ADD="lighter",e.DARKEST="darken",e.LIGHTEST="lighten",e.DIFFERENCE="difference",e.SUBTRACT="subtract",e.EXCLUSION="exclusion",e.MULTIPLY="multiply",e.SCREEN="screen",e.REPLACE="copy",e.OVERLAY="overlay",e.HARD_LIGHT="hard-light",e.SOFT_LIGHT="soft-light",e.DODGE="color-dodge",e.BURN="color-burn",e._doStroke=!0,e._doFill=!0,e._strokeSet=!1,e._fillSet=!1,e._ellipseMode=e.CENTER,e._rectMode=e.CORNER,e._curveDetail=20,e._curveAlpha=0;let t=!0,a=[];function o(){e._doFill&&e.ctx.fill(),e._doStroke&&e.ctx.stroke()}function n(t,a,n,r,s,i,l,c){if(!e._doFill&&!e._doStroke)return;let d="degrees"==e._angleMode,h=d?360:e.TAU;if((s%=h)<0&&(s+=h),(i%=h)<0&&(i+=h),0!=s||0!=i){if(s>i&&([s,i]=[i,s]),e.ctx.beginPath(),n==r)d&&(s=e.radians(s),i=e.radians(i)),e.ctx.arc(t,a,n/2,s,i);else{for(let o=0;o<c+1;o++){let l=o/c,d=e.lerp(s,i,l),h=e.cos(d)*n/2,u=e.sin(d)*r/2;e.ctx[o?"lineTo":"moveTo"](t+h,a+u)}l==e.CHORD?e.ctx.closePath():l==e.PIE&&(e.ctx.lineTo(t,a),e.ctx.closePath())}o()}}function r(t,a,n,r){(e._doFill||e._doStroke)&&(e._da&&(t*=e._da,a*=e._da,n*=e._da,r*=e._da),e.ctx.beginPath(),e.ctx.ellipse(t,a,n/2,r/2,0,0,e.TAU),o())}function s(t,a,n,r,i,l,c,d){if(!e._doFill&&!e._doStroke)return;if(void 0===i)return function(t,a,n,r){e._da&&(t*=e._da,a*=e._da,n*=e._da,r*=e._da),e.ctx.beginPath(),e.ctx.rect(t,a,n,r),o()}(t,a,n,r);if(void 0===l)return s(t,a,n,r,i,i,i,i);e._da&&(t*=e._da,a*=e._da,n*=e._da,r*=e._da,i*=e._da,l*=e._da,d*=e._da,c*=e._da);const h=Math.min(Math.abs(r),Math.abs(n))/2;i=Math.min(h,i),l=Math.min(h,l),d=Math.min(h,d),c=Math.min(h,c),e.ctx.beginPath(),e.ctx.moveTo(t+i,a),e.ctx.arcTo(t+n,a,t+n,a+r,l),e.ctx.arcTo(t+n,a+r,t,a+r,c),e.ctx.arcTo(t,a+r,t,a,d),e.ctx.arcTo(t,a,t+n,a,i),e.ctx.closePath(),o()}function i(){a=[]}e.strokeWeight=t=>{t||(e._doStroke=!1),e._da&&(t*=e._da),e.ctx.lineWidth=t||1e-4},e.stroke=function(t){if(e._doStroke=!0,e._strokeSet=!0,Q5.Color&&(t._q5Color||"string"==typeof t?e._namedColors[t]&&(t=e.color(...e._namedColors[t])):t=e.color(...arguments),t.a<=0))return e._doStroke=!1;e.ctx.strokeStyle=t.toString()},e.noStroke=()=>e._doStroke=!1,e.fill=function(t){if(e._doFill=!0,e._fillSet=!0,Q5.Color&&(t._q5Color||"string"==typeof t?e._namedColors[t]&&(t=e.color(...e._namedColors[t])):t=e.color(...arguments),t.a<=0))return e._doFill=!1;e.ctx.fillStyle=t.toString()},e.noFill=()=>e._doFill=!1,e.blendMode=t=>e.ctx.globalCompositeOperation=t,e.strokeCap=t=>e.ctx.lineCap=t,e.strokeJoin=t=>e.ctx.lineJoin=t,e.ellipseMode=t=>e._ellipseMode=t,e.rectMode=t=>e._rectMode=t,e.curveDetail=t=>e._curveDetail=t,e.curveAlpha=t=>e._curveAlpha=t,e.curveTightness=t=>e._curveAlpha=t,e.clear=()=>{e.ctx.clearRect(0,0,e.canvas.width,e.canvas.height)},e.background=function(t){if(t.canvas)return e.image(t,0,0,e.width,e.height);e.ctx.save(),e.ctx.resetTransform(),Q5.Color&&(t._q5Color||"string"==typeof t?e._namedColors[t]&&(t=e.color(...e._namedColors[t])):t=e.color(...arguments)),e.ctx.fillStyle=t.toString(),e.ctx.fillRect(0,0,e.canvas.width,e.canvas.height),e.ctx.restore()},e.line=(t,a,o,n)=>{e._doStroke&&(e._da&&(t*=e._da,a*=e._da,o*=e._da,n*=e._da),e.ctx.beginPath(),e.ctx.moveTo(t,a),e.ctx.lineTo(o,n),e.ctx.stroke())},e.arc=(t,a,o,r,s,i,l,c=25)=>{if(s==i)return e.ellipse(t,a,o,r);l??=e.PIE,e._ellipseMode==e.CENTER?n(t,a,o,r,s,i,l,c):e._ellipseMode==e.RADIUS?n(t,a,2*o,2*r,s,i,l,c):e._ellipseMode==e.CORNER?n(t+o/2,a+r/2,o,r,s,i,l,c):e._ellipseMode==e.CORNERS&&n((t+o)/2,(a+r)/2,o-t,r-a,s,i,l,c)},e.ellipse=(t,a,o,n)=>{n??=o,e._ellipseMode==e.CENTER?r(t,a,o,n):e._ellipseMode==e.RADIUS?r(t,a,2*o,2*n):e._ellipseMode==e.CORNER?r(t+o/2,a+n/2,o,n):e._ellipseMode==e.CORNERS&&r((t+o)/2,(a+n)/2,o-t,n-a)},e.circle=(t,a,n)=>{e._ellipseMode==e.CENTER?(e._da&&(t*=e._da,a*=e._da,n*=e._da),e.ctx.beginPath(),e.ctx.arc(t,a,n/2,0,e.TAU),o()):e.ellipse(t,a,n,n)},e.point=(t,a)=>{t.x&&(a=t.y,t=t.x),e._da&&(t*=e._da,a*=e._da),e.ctx.save(),e.ctx.beginPath(),e.ctx.arc(t,a,e.ctx.lineWidth/2,0,e.TAU),e.ctx.fillStyle=e.ctx.strokeStyle,e.ctx.fill(),e.ctx.restore()},e.rect=(t,a,o,n=o,r,i,l,c)=>{e._rectMode==e.CENTER?s(t-o/2,a-n/2,o,n,r,i,l,c):e._rectMode==e.RADIUS?s(t-o,a-n,2*o,2*n,r,i,l,c):e._rectMode==e.CORNER?s(t,a,o,n,r,i,l,c):e._rectMode==e.CORNERS&&s(t,a,o-t,n-a,r,i,l,c)},e.square=(t,a,o,n,r,s,i)=>e.rect(t,a,o,o,n,r,s,i),e.beginShape=()=>{i(),e.ctx.beginPath(),t=!0},e.beginContour=()=>{e.ctx.closePath(),i(),t=!0},e.endContour=()=>{i(),t=!0},e.vertex=(a,o)=>{e._da&&(a*=e._da,o*=e._da),i(),t?e.ctx.moveTo(a,o):e.ctx.lineTo(a,o),t=!1},e.bezierVertex=(t,a,o,n,r,s)=>{e._da&&(t*=e._da,a*=e._da,o*=e._da,n*=e._da,r*=e._da,s*=e._da),i(),e.ctx.bezierCurveTo(t,a,o,n,r,s)},e.quadraticVertex=(t,a,o,n)=>{e._da&&(t*=e._da,a*=e._da,o*=e._da,n*=e._da),i(),e.ctx.quadraticCurveTo(t,a,o,n)},e.bezier=(t,a,o,n,r,s,i,l)=>{e.beginShape(),e.vertex(t,a),e.bezierVertex(o,n,r,s,i,l),e.endShape()},e.triangle=(t,a,o,n,r,s)=>{e.beginShape(),e.vertex(t,a),e.vertex(o,n),e.vertex(r,s),e.endShape(e.CLOSE)},e.quad=(t,a,o,n,r,s,i,l)=>{e.beginShape(),e.vertex(t,a),e.vertex(o,n),e.vertex(r,s),e.vertex(i,l),e.endShape(e.CLOSE)},e.endShape=t=>{i(),t&&e.ctx.closePath(),o()},e.curveVertex=(o,n)=>{if(e._da&&(o*=e._da,n*=e._da),a.push([o,n]),a.length<4)return;let r=function(e,t,a,o,n,r,s,i,l,c){function d(e,t,a,o,n,r){let s=Math.pow(o-t,2)+Math.pow(n-a,2);return Math.pow(s,.5*r)+e}let h=[],u=d(0,e,t,a,o,c),_=d(u,a,o,n,r,c),p=d(_,n,r,s,i,c);for(let c=0;c<l;c++){let d=u+c/(l-1)*(_-u),g=[(u-d)/(u-0),(d-0)/(u-0),(_-d)/(_-u),(d-u)/(_-u),(p-d)/(p-_),(d-_)/(p-_),(_-d)/(_-0),(d-0)/(_-0),(p-d)/(p-u),(d-u)/(p-u)];for(let e=0;e<g.length;e+=2)isNaN(g[e])&&(g[e]=1,g[e+1]=0),isFinite(g[e])||(g[e]>0?(g[e]=1,g[e+1]=0):(g[e]=0,g[e+1]=1));let x=e*g[0]+a*g[1],m=t*g[0]+o*g[1],f=a*g[2]+n*g[3],v=o*g[2]+r*g[3],y=n*g[4]+s*g[5],w=r*g[4]+i*g[5],M=x*g[6]+f*g[7],C=m*g[6]+v*g[7],S=f*g[8]+y*g[9],b=v*g[8]+w*g[9],R=M*g[2]+S*g[3],E=C*g[2]+b*g[3];h.push([R,E])}return h}(...a.at(-4),...a.at(-3),...a.at(-2),...a.at(-1),e._curveDetail,e._curveAlpha);for(let a=0;a<r.length;a++)t?e.ctx.moveTo(...r[a]):e.ctx.lineTo(...r[a]),t=!1},e.curve=(t,a,o,n,r,s,i,l)=>{e.beginShape(),e.curveVertex(t,a),e.curveVertex(o,n),e.curveVertex(r,s),e.curveVertex(i,l),e.endShape()},e.curvePoint=(e,t,a,o,n)=>{const r=n*n*n,s=n*n;return e*(-.5*r+s-.5*n)+t*(1.5*r-2.5*s+1)+a*(-1.5*r+2*s+.5*n)+o*(.5*r-.5*s)},e.bezierPoint=(e,t,a,o,n)=>{const r=1-n;return Math.pow(r,3)*e+3*Math.pow(r,2)*n*t+3*r*Math.pow(n,2)*a+Math.pow(n,3)*o},e.curveTangent=(e,t,a,o,n)=>{const r=n*n;return e*(-3*r/2+2*n-.5)+t*(9*r/2-5*n)+a*(-9*r/2+4*n+.5)+o*(3*r/2-n)},e.bezierTangent=(e,t,a,o,n)=>{const r=1-n;return 3*o*Math.pow(n,2)-3*a*Math.pow(n,2)+6*a*r*n-6*t*r*n+3*t*Math.pow(r,2)-3*e*Math.pow(r,2)},e.erase=function(t=255,a=255){e.ctx.save(),e.ctx.globalCompositeOperation="destination-out",e.ctx.fillStyle=`rgba(0, 0, 0, ${t/255})`,e.ctx.strokeStyle=`rgba(0, 0, 0, ${a/255})`},e.noErase=function(){e.ctx.globalCompositeOperation="source-over",e.ctx.restore()},e.inFill=(t,a)=>{const o=e._pixelDensity;return e.ctx.isPointInPath(t*o,a*o)},e.inStroke=(t,a)=>{const o=e._pixelDensity;return e.ctx.isPointInStroke(t*o,a*o)}},Q5.modules.q2d_image=(e,t)=>{e.createImage=(t,a,o)=>(o??={},o.alpha??=!0,o.colorSpace??=e.canvas.colorSpace||Q5.canvasOptions.colorSpace,new Q5.Image(t,a,o)),e._tint=null;let a=null,o=null,n=null;function r(t,a){a??=t||e.canvas.height,t??=e.canvas.width,null==o&&(o=new e._OffscreenCanvas(t,a).getContext("2d",{colorSpace:e.canvas.colorSpace})),o.canvas.width==t&&o.canvas.height==a||(o.canvas.width=t,o.canvas.height=a)}function s(t){o.clearRect(0,0,o.canvas.width,o.canvas.height),o.filter=t,o.drawImage(e.canvas,0,0),e.ctx.save(),e.ctx.resetTransform(),e.ctx.clearRect(0,0,e.canvas.width,e.canvas.height),e.ctx.drawImage(o.canvas,0,0),e.ctx.restore()}e._softFilter=()=>{throw"Load q5-2d-soft-filters.js to use software filters."},e.filter=(t,a)=>{if(!e.ctx.filter)return e._softFilter(t,a);if(r(),"string"==typeof t)s(t);else if(t==Q5.THRESHOLD){a??=.5,a=Math.max(a,1e-5),s(`saturate(0%) brightness(${Math.floor(.5/a*100)}%) contrast(1000000%)`)}else t==Q5.GRAY?s("saturate(0%)"):t==Q5.OPAQUE?(o.fillStyle="black",o.fillRect(0,0,o.canvas.width,o.canvas.height),o.drawImage(e.canvas,0,0),e.ctx.save(),e.ctx.resetTransform(),e.ctx.drawImage(o.canvas,0,0),e.ctx.restore()):t==Q5.INVERT?s("invert(100%)"):t==Q5.BLUR?s(`blur(${Math.ceil(a*e._pixelDensity/1)||1}px)`):e._softFilter(t,a)},e.resize=(a,n)=>{r(),o.drawImage(e.canvas,0,0),t.width=a,t.height=n,e.canvas.width=a*e._pixelDensity,e.canvas.height=n*e._pixelDensity,e.ctx.save(),e.ctx.resetTransform(),e.ctx.clearRect(0,0,e.canvas.width,e.canvas.height),e.ctx.drawImage(o.canvas,0,0,e.canvas.width,e.canvas.height),e.ctx.restore()},e.trim=()=>{let t=e._pixelDensity||1,a=e.ctx.getImageData(0,0,e.width*t,e.height*t).data,o=e.width,n=0,r=e.height,s=0;for(let i=0;i<e.height*t;i++)for(let l=0;l<e.width*t;l++){0!==a[4*(i*e.width*t+l)+3]&&(l<o&&(o=l),l>n&&(n=l),i<r&&(r=i),i>s&&(s=i))}return r=Math.floor(r/t),s=Math.floor(s/t),o=Math.floor(o/t),n=Math.floor(n/t),e.get(o,r,n-o+1,s-r+1)},e.mask=t=>{e.ctx.save(),e.ctx.resetTransform();let a=e.ctx.globalCompositeOperation;e.ctx.globalCompositeOperation="destination-in",e.ctx.drawImage(t.canvas,0,0),e.ctx.globalCompositeOperation=a,e.ctx.restore()},e._save=async(e,t,a)=>{if(t=t||"untitled","jpg"==(a=a||"png")||"png"==a||"webp"==a)if(e instanceof OffscreenCanvas){const t=await e.convertToBlob({type:"image/"+a});e=await new Promise((e=>{const a=new FileReader;a.onloadend=()=>e(a.result),a.readAsDataURL(t)}))}else e=e.toDataURL("image/"+a);else{let t="text/plain";"json"==a&&("string"!=typeof e&&(e=JSON.stringify(e)),t="text/json"),e=new Blob([e],{type:t}),e=URL.createObjectURL(e)}let o=document.createElement("a");o.href=e,o.download=t+"."+a,document.body.append(o),o.click(),document.body.removeChild(o),URL.revokeObjectURL(o.href)},e.save=(t,a,o)=>{if((!t||"string"==typeof t&&(!a||!o&&a.length<5))&&(o=a,a=t,t=e.canvas),o)return e._save(t,a,o);a?(a=a.split("."),e._save(t,a[0],a.at(-1))):e._save(t)},e.get=(t,a,o,n)=>{let r=e._pixelDensity||1;if(void 0!==t&&void 0===o){let o=e.ctx.getImageData(t*r,a*r,1,1).data;return new e.Color(o[0],o[1],o[2],o[3]/255)}t=(t||0)*r,a=(a||0)*r;let s=o=o||e.width,i=n=n||e.height;o*=r,n*=r;let l=e.createImage(o,n),c=e.ctx.getImageData(t,a,o,n);return l.ctx.putImageData(c,0,0),l._pixelDensity=r,l.width=s,l.height=i,l},e.set=(t,a,o)=>{if(o.canvas){let n=e._tint;return e._tint=null,e.image(o,t,a),void(e._tint=n)}e.pixels.length||e.loadPixels();let n=e._pixelDensity||1;for(let r=0;r<n;r++)for(let s=0;s<n;s++){let i=4*((a*n+r)*e.canvas.width+t*n+s);e.pixels[i]=o.r??o.l,e.pixels[i+1]=o.g??o.c,e.pixels[i+2]=o.b??o.h,e.pixels[i+3]=o.a}},e.loadPixels=()=>{a=e.ctx.getImageData(0,0,e.canvas.width,e.canvas.height),t.pixels=a.data},e.updatePixels=()=>{null!=a&&e.ctx.putImageData(a,0,0)},e._tinted=function(t){let a=t.a;t.a=255,r(),o.clearRect(0,0,o.canvas.width,o.canvas.height),o.fillStyle=t.toString(),o.fillRect(0,0,o.canvas.width,o.canvas.height),o.globalCompositeOperation="multiply",o.drawImage(e.ctx.canvas,0,0),o.globalCompositeOperation="source-over",e.ctx.save(),e.ctx.resetTransform();let n=e.ctx.globalCompositeOperation;e.ctx.globalCompositeOperation="source-in",e.ctx.drawImage(o.canvas,0,0),e.ctx.globalCompositeOperation=n,e.ctx.restore(),o.globalAlpha=a/255,o.clearRect(0,0,o.canvas.width,o.canvas.height),o.drawImage(e.ctx.canvas,0,0),o.globalAlpha=1,e.ctx.save(),e.ctx.resetTransform(),e.ctx.clearRect(0,0,e.ctx.canvas.width,e.ctx.canvas.height),e.ctx.drawImage(o.canvas,0,0),e.ctx.restore()},e.smooth=()=>e.ctx.imageSmoothingEnabled=!0,e.noSmooth=()=>e.ctx.imageSmoothingEnabled=!1,"image"!=e._scope&&(e.saveCanvas=e.canvas.save=e.save,e.tint=function(t){e._tint=t._q5Color?t:e.color(...arguments)},e.noTint=()=>e._tint=null,e.imageMode=t=>e._imageMode=t,e.image=(t,a,o,r,s,i=0,l=0,c,d)=>{e._da&&(a*=e._da,o*=e._da,r*=e._da,s*=e._da,i*=e._da,l*=e._da,c*=e._da,d*=e._da);let h=t.canvas||t;var u,_;Q5._createNodeJSCanvas&&(h=h.context.canvas),t.canvas&&null!=e._tint&&(u=t.canvas.width,_=t.canvas.height,_??=u||e.canvas.height,u??=e.canvas.width,null==n&&(n=new e._OffscreenCanvas(u,_).getContext("2d",{colorSpace:e.canvas.colorSpace})),n.canvas.width==u&&n.canvas.height==_||(n.canvas.width=u,n.canvas.height=_),n.drawImage(t.canvas,0,0),t._tinted(e._tint)),r??=t.width||t.videoWidth,s??=t.height||t.videoHeight,"center"==e._imageMode&&(a-=.5*r,o-=.5*s);let p=t._pixelDensity||1;c?c*=p:c=h.width||h.videoWidth,d?d*=p:d=h.height||h.videoHeight,e.ctx.drawImage(h,i*p,l*p,c,d,a,o,r,s),function(){if(!t._q5||!e._tint)return;let a=t.ctx;a.save(),a.resetTransform(),a.clearRect(0,0,a.canvas.width,a.canvas.height),a.drawImage(n.canvas,0,0),a.restore()}()},e.loadImage=function(a,o,n){if(a.canvas)return a;if("gif"==a.slice(-3).toLowerCase())throw new Error("q5 doesn't support GIFs due to their impact on performance. Use a video or animation instead.");t._preloadCount++;let r=[...arguments].at(-1);n="object"==typeof r?r:null;let s=e.createImage(1,1,n);function i(e){let a=s.ctx;s.width=a.canvas.width=e.naturalWidth||e.width,s.height=a.canvas.height=e.naturalHeight||e.height,a.drawImage(e,0,0),t._preloadCount--,o&&o(s)}if(Q5._nodejs&&global.CairoCanvas)global.CairoCanvas.loadImage(a).then(i).catch((e=>{throw t._preloadCount--,e}));else{let e=new window.Image;e.src=a,e.crossOrigin="Anonymous",e._pixelDensity=1,e.onload=()=>i(e),e.onerror=e=>{throw t._preloadCount--,e}}return s})},Q5.imageModules=["q2d_canvas","q2d_image"];class _Q5Image{constructor(e,t,a){let o=this;o._scope="image",o.canvas=o.ctx=o.drawingContext=null,o.pixels=[];for(let e of Q5.imageModules)Q5.modules[e](o,o);delete this.createCanvas,this._createCanvas(e,t,"2d",a),this._loop=!1}get w(){return this.width}get h(){return this.height}}Q5.Image??=_Q5Image,Q5.THRESHOLD=1,Q5.GRAY=2,Q5.OPAQUE=3,Q5.INVERT=4,Q5.POSTERIZE=5,Q5.DILATE=6,Q5.ERODE=7,Q5.BLUR=8,Q5.modules.q2d_soft_filters=e=>{let t=null;function a(){let a=e.canvas.width*e.canvas.height*4;t&&a==t.length||(t=new Uint8ClampedArray(a))}e._softFilter=(o,n)=>{e._filters||(e._filters=[],e._filters[Q5.THRESHOLD]=(e,t)=>{void 0===t?t=127.5:t*=255;for(let a=0;a<e.length;a+=4){const o=.2126*e[a]+.7152*e[a+1]+.0722*e[a+2];e[a]=e[a+1]=e[a+2]=o>=t?255:0}},e._filters[Q5.GRAY]=e=>{for(let t=0;t<e.length;t+=4){const a=.2126*e[t]+.7152*e[t+1]+.0722*e[t+2];e[t]=e[t+1]=e[t+2]=a}},e._filters[Q5.OPAQUE]=e=>{for(let t=0;t<e.length;t+=4)e[t+3]=255},e._filters[Q5.INVERT]=e=>{for(let t=0;t<e.length;t+=4)e[t]=255-e[t],e[t+1]=255-e[t+1],e[t+2]=255-e[t+2]},e._filters[Q5.POSTERIZE]=(e,t=4)=>{let a=t-1;for(let o=0;o<e.length;o+=4)e[o]=255*(e[o]*t>>8)/a,e[o+1]=255*(e[o+1]*t>>8)/a,e[o+2]=255*(e[o+2]*t>>8)/a},e._filters[Q5.DILATE]=o=>{a(),t.set(o);let[n,r]=[e.canvas.width,e.canvas.height];for(let e=0;e<r;e++)for(let a=0;a<n;a++){let s=4*Math.max(a-1,0),i=4*Math.min(a+1,n-1),l=4*Math.max(e-1,0)*n,c=4*Math.min(e+1,r-1)*n,d=4*e*n,h=4*a;for(let e=0;e<4;e++){let a=e+l,n=e+c,r=e+d;o[d+h+e]=Math.max(t[a+h],t[r+s],t[r+h],t[r+i],t[n+h])}}},e._filters[Q5.ERODE]=o=>{a(),t.set(o);let[n,r]=[e.canvas.width,e.canvas.height];for(let e=0;e<r;e++)for(let a=0;a<n;a++){let s=4*Math.max(a-1,0),i=4*Math.min(a+1,n-1),l=4*Math.max(e-1,0)*n,c=4*Math.min(e+1,r-1)*n,d=4*e*n,h=4*a;for(let e=0;e<4;e++){let a=e+l,n=e+c,r=e+d;o[d+h+e]=Math.min(t[a+h],t[r+s],t[r+h],t[r+i],t[n+h])}}},e._filters[Q5.BLUR]=(o,n)=>{n=n||1,n=Math.floor(n*e._pixelDensity),a(),t.set(o);let r=2*n+1,s=function(e){let t=new Float32Array(e),a=.3*n+.8,o=a*a*2;for(let n=0;n<e;n++){let r=n-e/2,s=Math.exp(-r*r/o)/(2.5066282746*a);t[n]=s}return t}(r),[i,l]=[e.canvas.width,e.canvas.height];for(let e=0;e<l;e++)for(let a=0;a<i;a++){let l=0,c=0,d=0,h=0;for(let o=0;o<r;o++){let r=4*(e*i+Math.min(Math.max(a-n+o,0),i-1));l+=t[r]*s[o],c+=t[r+1]*s[o],d+=t[r+2]*s[o],h+=t[r+3]*s[o]}let u=4*(e*i+a);o[u]=l,o[u+1]=c,o[u+2]=d,o[u+3]=h}t.set(o);for(let e=0;e<l;e++)for(let a=0;a<i;a++){let c=0,d=0,h=0,u=0;for(let o=0;o<r;o++){let r=4*(Math.min(Math.max(e-n+o,0),l-1)*i+a);c+=t[r]*s[o],d+=t[r+1]*s[o],h+=t[r+2]*s[o],u+=t[r+3]*s[o]}let _=4*(e*i+a);o[_]=c,o[_+1]=d,o[_+2]=h,o[_+3]=u}});let r=e.ctx.getImageData(0,0,e.canvas.width,e.canvas.height);e._filters[o](r.data,n),e.ctx.putImageData(r,0,0)}},Q5.modules.q2d_text=(e,t)=>{e.NORMAL="normal",e.ITALIC="italic",e.BOLD="bold",e.BOLDITALIC="italic bold",e.CENTER="center",e.LEFT="left",e.RIGHT="right",e.TOP="top",e.BOTTOM="bottom",e.BASELINE="alphabetic",e._textFont="sans-serif",e._textSize=12,e._textLeading=15,e._textLeadDiff=3,e._textStyle="normal",e.loadFont=(e,a)=>{t._preloadCount++;let o=e.split("/").pop().split(".")[0].replace(" ",""),n=new FontFace(o,`url(${e})`);return document.fonts.add(n),n.load().then((()=>{t._preloadCount--,a&&a(o)})),o},e.textFont=t=>e._textFont=t,e.textSize=t=>{if(void 0===t)return e._textSize;e._da&&(t*=e._da),e._textSize=t,e._leadingSet||(e._textLeading=1.25*t,e._textLeadDiff=e._textLeading-t)},e.textLeading=t=>{if(void 0===t)return e._textLeading;e._da&&(t*=e._da),e._textLeading=t,e._textLeadDiff=t-e._textSize,e._leadingSet=!0},e.textStyle=t=>e._textStyle=t,e.textAlign=(t,a)=>{e.ctx.textAlign=t,a&&(e.ctx.textBaseline=a==e.CENTER?"middle":a)},e.textWidth=t=>(e.ctx.font=`${e._textStyle} ${e._textSize}px ${e._textFont}`,e.ctx.measureText(t).width),e.textAscent=t=>(e.ctx.font=`${e._textStyle} ${e._textSize}px ${e._textFont}`,e.ctx.measureText(t).actualBoundingBoxAscent),e.textDescent=t=>(e.ctx.font=`${e._textStyle} ${e._textSize}px ${e._textFont}`,e.ctx.measureText(t).actualBoundingBoxDescent),e._textCache=!!Q5.Image,e._TimedCache=class extends Map{constructor(){super(),this.maxSize=500}set(e,t){t.lastAccessed=Date.now(),super.set(e,t),this.size>this.maxSize&&this.gc()}get(e){const t=super.get(e);return t&&(t.lastAccessed=Date.now()),t}gc(){let e,t=1/0,a=0;for(const[o,n]of this.entries())n.lastAccessed<t&&(t=n.lastAccessed,e=a),a++;a=e;for(const t of this.keys()){if(0==a){e=t;break}a--}this.delete(e)}},e._tic=new e._TimedCache,e.textCache=(t,a)=>(a&&(e._tic.maxSize=a),void 0!==t&&(e._textCache=t),e._textCache),e._genTextImageKey=(t,a,o)=>t.slice(0,200)+e._textStyle+e._textSize+e._textFont+(e._doFill?e.ctx.fillStyle:"")+"_"+(e._doStroke&&e._strokeSet?e.ctx.lineWidth+e.ctx.strokeStyle+"_":"")+(a||"")+(o?"x"+o:""),e.createTextImage=(t,a,o)=>{let n=e._textCache;e._textCache=!0,e._genTextImage=!0,e.text(t,0,0,a,o),e._genTextImage=!1;let r=e._genTextImageKey(t,a,o);return e._textCache=n,e._tic.get(r)},e.text=(t,a,o,n,r)=>{if(void 0===t)return;if(t=t.toString(),e._da&&(a*=e._da,o*=e._da),!e._doFill&&!e._doStroke)return;let s,i,l,c,d,h,u,_,p=e.ctx.getTransform(),g=e._genTextImage||e._textCache&&(0!=p.b||0!=p.c);if(g){if(c=e._genTextImageKey(t,n,r),i=e._tic.get(c),i&&!e._genTextImage)return void e.textImage(i,a,o);l=e.createGraphics.call(e,1,1),s=l.ctx}else s=e.ctx,d=a,h=o;s.font=`${e._textStyle} ${e._textSize}px ${e._textFont}`;let x=t.split("\n");if(g){d=0,h=e._textLeading*x.length;let a=s.measureText(" ");u=a.fontBoundingBoxAscent,_=a.fontBoundingBoxDescent,r??=h+_,l.resizeCanvas(Math.ceil(s.measureText(t).width),Math.ceil(r)),s.fillStyle=e.ctx.fillStyle,s.strokeStyle=e.ctx.strokeStyle,s.lineWidth=e.ctx.lineWidth}let m=s.fillStyle;e._fillSet||(s.fillStyle="black");for(let t=0;t<x.length&&(e._doStroke&&e._strokeSet&&s.strokeText(x[t],d,h),e._doFill&&s.fillText(x[t],d,h),h+=e._textLeading,!(h>r));t++);e._fillSet||(s.fillStyle=m),g&&(i=l.get(),i._ascent=u,i._descent=_,e._tic.set(c,i),e._genTextImage||e.textImage(i,a,o))},e.textImage=(t,a,o)=>{let n=e._imageMode;e._imageMode="corner","center"==e.ctx.textAlign?a-=.5*t.width:"right"==e.ctx.textAlign&&(a-=t.width),"alphabetic"==e.ctx.textBaseline&&(o-=e._textLeading),"middle"==e.ctx.textBaseline?o-=t._descent+.5*t._ascent+e._textLeadDiff:"bottom"==e.ctx.textBaseline?o-=t._ascent+t._descent+e._textLeadDiff:"top"==e.ctx.textBaseline&&(o-=t._descent+e._textLeadDiff),e.image(t,a,o),e._imageMode=n},e.nf=(e,t,a)=>{let o=e<0,n=(e=Math.abs(e)).toFixed(a).split(".");n[0]=n[0].padStart(t,"0");let r=n.join(".");return o&&(r="-"+r),r}},Q5.modules.ai=e=>{e.askAI=(e="")=>{throw Error("Ask AI ✨ "+e)},e._aiErrorAssistance=async t=>{let a=t.message?.includes("Ask AI ✨");if(a||console.error(t),Q5.disableFriendlyErrors)return;!a&&Q5.errorTolerant||e.noLoop();let o=t.stack?.split("\n");if(!t.stack||o.length<=1)return;let n=1,r="(";for(-1==navigator.userAgent.indexOf("Chrome")&&(n=0,r="@");o[n].indexOf("q5.js:")>=0;)n++;let s=o[n].split(r).at(-1);s=s.split(":");let i=parseInt(s.at(-2));a&&i++;let l=s.slice(0,-2).join(":"),c=l.split("/").at(-1);try{let e=(await(await fetch(l)).text()).split("\n"),o=e[i-1].trim(),n="",r=1;for(;n.length<1600&&(i-r>=0&&(n=e[i-r].trim()+"\n"+n),i+r<e.length);)n+=e[i+r].trim()+"\n",r++;let s="https://chatgpt.com/?q=q5.js+"+(a&&t.message.length>10?t.message.slice(10):"Whats+wrong+with+this+line%3F+short+answer")+(a?"":"%0A%0A"+encodeURIComponent(t.name+": "+t.message))+"%0A%0ALine%3A+"+encodeURIComponent(o)+"%0A%0AExcerpt+for+context%3A%0A%0A"+encodeURIComponent(n);a||console.log("Error in "+c+" on line "+i+":\n\n"+o),console.warn("Ask AI ✨ "+s),a&&window.open(s,"_blank")}catch(e){}}},Q5.modules.color=(e,t)=>{e.RGB=e.RGBA=e._colorMode="rgb",Q5.supportsHDR?e.Color=Q5.ColorRGBA_P3:e.Color=Q5.ColorRGBA,e.colorMode=a=>{e._colorMode=a,"oklch"==a?t.Color=Q5.ColorOKLCH:"rgb"==a?"srgb"==e.canvas.colorSpace?t.Color=Q5.ColorRGBA:t.Color=Q5.ColorRGBA_P3:"srgb"==a&&(t.Color=Q5.ColorRGBA,e._colorMode="rgb")},e._namedColors={aqua:[0,255,255],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],crimson:[220,20,60],cyan:[0,255,255],darkviolet:[148,0,211],gold:[255,215,0],green:[0,128,0],gray:[128,128,128],grey:[128,128,128],hotpink:[255,105,180],indigo:[75,0,130],khaki:[240,230,140],lightgreen:[144,238,144],lime:[0,255,0],magenta:[255,0,255],navy:[0,0,128],orange:[255,165,0],olive:[128,128,0],peachpuff:[255,218,185],pink:[255,192,203],purple:[128,0,128],red:[255,0,0],skyblue:[135,206,235],tan:[210,180,140],turquoise:[64,224,208],transparent:[0,0,0,0],white:[255,255,255],violet:[238,130,238],yellow:[255,255,0]},e.color=function(t,a,o,n){let r=e.Color;if(t._q5Color)return new r(...t.levels);let s=arguments;if(1==s.length){if("string"==typeof t)return"#"==t[0]?t.length<=5?new r(parseInt(t[1]+t[1],16),parseInt(t[2]+t[2],16),parseInt(t[3]+t[3],16),4==t.length?null:parseInt(t[4]+t[4],16)):new r(parseInt(t.slice(1,3),16),parseInt(t.slice(3,5),16),parseInt(t.slice(5,7),16),7==t.length?null:parseInt(t.slice(7,9),16)):e._namedColors[t]?new r(...e._namedColors[t]):(console.error("q5 can't parse color: "+t+"\nOnly numeric input, hex, and common named colors are supported."),new r(0,0,0));if(Array.isArray(t))return new r(...t)}if("rgb"==e._colorMode){if(1==s.length)return new r(t,t,t);if(2==s.length)return new r(t,t,t,a);if(3==s.length)return new r(t,a,o);if(4==s.length)return new r(t,a,o,n)}},e.red=e=>e.r,e.green=e=>e.g,e.blue=e=>e.b,e.alpha=e=>e.a,e.lightness=e=>100*(.2126*e.r+.7152*e.g+.0722*e.b)/255,e.lerpColor=(t,a,o)=>{if("rgb"==e._colorMode)return new e.Color(e.constrain(e.lerp(t.r,a.r,o),0,255),e.constrain(e.lerp(t.g,a.g,o),0,255),e.constrain(e.lerp(t.b,a.b,o),0,255),e.constrain(e.lerp(t.a,a.a,o),0,255));{let n=a.h-t.h;n>180&&(n-=360),n<-180&&(n+=360);let r=t.h+o*n;return r<0&&(r+=360),r>360&&(r-=360),new e.Color(e.constrain(e.lerp(t.l,a.l,o),0,100),e.constrain(e.lerp(t.c,a.c,o),0,100),r,e.constrain(e.lerp(t.a,a.a,o),0,255))}}},Q5.Color=class{constructor(){this._q5Color=!0}},Q5.ColorOKLCH=class extends Q5.Color{constructor(e,t,a,o){super(),this.l=e,this.c=t,this.h=a,this.a=o??1}toString(){return`color(oklch ${this.l} ${this.c} ${this.h} / ${this.a})`}},Q5.ColorRGBA=class extends Q5.Color{constructor(e,t,a,o){super(),this.r=e,this.g=t,this.b=a,this.a=o??255}setRed(e){this.r=e}setGreen(e){this.g=e}setBlue(e){this.b=e}setAlpha(e){this.a=e}get levels(){return[this.r,this.g,this.b,this.a]}toString(){return`rgb(${this.r} ${this.g} ${this.b} / ${this.a/255})`}},Q5.ColorRGBA_P3=class extends Q5.ColorRGBA{constructor(e,t,a,o){super(e,t,a,o),this._edited=!0}get r(){return this._r}set r(e){this._r=e,this._edited=!0}get g(){return this._g}set g(e){this._g=e,this._edited=!0}get b(){return this._b}set b(e){this._b=e,this._edited=!0}get a(){return this._a}set a(e){this._a=e,this._edited=!0}toString(){if(this._edited){let e=(this._r/255).toFixed(3),t=(this._g/255).toFixed(3),a=(this._b/255).toFixed(3),o=(this._a/255).toFixed(3);this._css=`color(display-p3 ${e} ${t} ${a} / ${o})`,this._edited=!1}return this._css}},Q5.modules.display=e=>{if(!e.canvas||"graphics"==e._scope)return;let t=e.canvas;0!=Q5._instanceCount||Q5._nodejs||document.head.insertAdjacentHTML("beforeend","<style>\nhtml, body {\n\tmargin: 0;\n\tpadding: 0;\n}\n.q5Canvas {\n\toutline: none;\n\t-webkit-touch-callout: none;\n\t-webkit-text-size-adjust: none;\n\t-webkit-user-select: none;\n\toverscroll-behavior: none;\n}\n.q5-pixelated {\n\timage-rendering: pixelated;\n\tfont-smooth: never;\n\t-webkit-font-smoothing: none;\n}\n.q5-centered,\n.q5-maxed,\n.q5-fullscreen {\n display: flex;\n\talign-items: center;\n\tjustify-content: center;\n}\nmain.q5-centered,\nmain.q5-maxed,\n.q5-fullscreen {\n\theight: 100vh;\n}\nmain {\n\toverscroll-behavior: none;\n}\n</style>"),e._adjustDisplay=()=>{let a=t.style,o=t.parentElement;a&&o&&t.displayMode&&("pixelated"==t.renderQuality&&(t.classList.add("q5-pixelated"),e.pixelDensity(1),e.noSmooth&&e.noSmooth(),e.textFont&&e.textFont("monospace")),"normal"==t.displayMode?(o.classList.remove("q5-centered","q5-maxed","q5-fullscreen"),a.width=t.w*t.displayScale+"px",a.height=t.h*t.displayScale+"px"):(o.classList.add("q5-"+t.displayMode),o=o.getBoundingClientRect(),t.w/t.h>o.width/o.height?("centered"==t.displayMode?(a.width=t.w*t.displayScale+"px",a.maxWidth="100%"):a.width="100%",a.height="auto",a.maxHeight=""):(a.width="auto",a.maxWidth="","centered"==t.displayMode?(a.height=t.h*t.displayScale+"px",a.maxHeight="100%"):a.height="100%")))},e.displayMode=(a="normal",o="default",n=1)=>{"string"==typeof n&&(n=parseFloat(n.slice(1))),Object.assign(t,{displayMode:a,renderQuality:o,displayScale:n}),e._adjustDisplay()}},Q5.modules.input=(e,t)=>{if("graphics"==e._scope)return;e.mouseX=0,e.mouseY=0,e.pmouseX=0,e.pmouseY=0,e.touches=[],e.mouseButton=null,e.keyIsPressed=!1,e.mouseIsPressed=!1,e.key=null,e.keyCode=null,e.UP_ARROW=38,e.DOWN_ARROW=40,e.LEFT_ARROW=37,e.RIGHT_ARROW=39,e.SHIFT=16,e.TAB=9,e.BACKSPACE=8,e.ENTER=e.RETURN=13,e.ALT=e.OPTION=18,e.CONTROL=17,e.DELETE=46,e.ESCAPE=27,e.ARROW="default",e.CROSS="crosshair",e.HAND="pointer",e.MOVE="move",e.TEXT="text";let a={},o=[e.LEFT,e.CENTER,e.RIGHT],n=e.canvas;function r(t){const a=e.canvas.getBoundingClientRect(),o=e.canvas.scrollWidth/e.width||1,n=e.canvas.scrollHeight/e.height||1;return{x:(t.clientX-a.left)/o,y:(t.clientY-a.top)/n,id:t.identifier}}if(e._startAudio=()=>{e.getAudioContext&&"suspended"==e.getAudioContext()?.state&&e.userStartAudio()},e._updateMouse=a=>{if(a.changedTouches)return;let o=e.canvas.getBoundingClientRect(),n=e.canvas.scrollWidth/e.width||1,r=e.canvas.scrollHeight/e.height||1;t.mouseX=(a.clientX-o.left)/n,t.mouseY=(a.clientY-o.top)/r},e._onmousedown=a=>{e._startAudio(),e._updateMouse(a),t.mouseIsPressed=!0,t.mouseButton=o[a.button],e.mousePressed(a)},e._onmousemove=t=>{e._updateMouse(t),e.mouseIsPressed?e.mouseDragged(t):e.mouseMoved(t)},e._onmouseup=a=>{e._updateMouse(a),t.mouseIsPressed=!1,e.mouseReleased(a)},e._onclick=a=>{e._updateMouse(a),t.mouseIsPressed=!0,e.mouseClicked(a),t.mouseIsPressed=!1},n.addEventListener("mousedown",(t=>e._onmousedown(t))),n.addEventListener("mouseup",(t=>e._onmouseup(t))),n.addEventListener("click",(t=>e._onclick(t))),e.cursor=(t,a,o)=>{let n="";t.includes(".")&&(t=`url("${t}")`,n=", auto"),void 0!==a&&(t+=" "+a+" "+o),e.canvas.style.cursor=t+n},e.noCursor=()=>{e.canvas.style.cursor="none"},e.requestPointerLock=document.body?.requestPointerLock,e.exitPointerLock=document.exitPointerLock,e._onkeydown=o=>{o.repeat||(e._startAudio(),t.keyIsPressed=!0,t.key=o.key,t.keyCode=o.keyCode,a[e.keyCode]=a[e.key.toLowerCase()]=!0,e.keyPressed(o),1==o.key.length&&e.keyTyped(o))},e._onkeyup=o=>{t.keyIsPressed=!1,t.key=o.key,t.keyCode=o.keyCode,a[e.keyCode]=a[e.key.toLowerCase()]=!1,e.keyReleased(o)},e.keyIsDown=e=>!!a["string"==typeof e?e.toLowerCase():e],e._ontouchstart=a=>{e._startAudio(),t.touches=[...a.touches].map(r),e._isTouchAware||(t.mouseX=e.touches[0].x,t.mouseY=e.touches[0].y,t.mouseIsPressed=!0,t.mouseButton=e.LEFT,e.mousePressed(a)||a.preventDefault()),e.touchStarted(a)||a.preventDefault()},e._ontouchmove=a=>{t.touches=[...a.touches].map(r),e._isTouchAware||(t.mouseX=e.touches[0].x,t.mouseY=e.touches[0].y,e.mouseDragged(a)||a.preventDefault()),e.touchMoved(a)||a.preventDefault()},e._ontouchend=a=>{t.touches=[...a.touches].map(r),e._isTouchAware||e.touches.length||(t.mouseIsPressed=!1,e.mouseReleased(a)||a.preventDefault()),e.touchEnded(a)||a.preventDefault()},n.addEventListener("touchstart",(t=>e._ontouchstart(t))),n.addEventListener("touchmove",(t=>e._ontouchmove(t))),n.addEventListener("touchcancel",(t=>e._ontouchend(t))),n.addEventListener("touchend",(t=>e._ontouchend(t))),window){let t=window.addEventListener;t("mousemove",(t=>e._onmousemove(t)),!1),t("keydown",(t=>e._onkeydown(t)),!1),t("keyup",(t=>e._onkeyup(t)),!1)}},Q5.modules.math=(e,t)=>{function a(){let e,t,a=4294967295;return{setSeed(o){e=t=(o??Math.random()*a)>>>0},getSeed:()=>t,rand:()=>(e^=e<<17,e^=e>>13,e^=e<<5,(e>>>0)/a)}}e.DEGREES="degrees",e.RADIANS="radians",e.PI=Math.PI,e.HALF_PI=Math.PI/2,e.QUARTER_PI=Math.PI/4,e.abs=Math.abs,e.ceil=Math.ceil,e.exp=Math.exp,e.floor=Math.floor,e.loge=Math.log,e.mag=Math.hypot,e.max=Math.max,e.min=Math.min,e.round=Math.round,e.pow=Math.pow,e.sqrt=Math.sqrt,e.SHR3=1,e.LCG=2,e.angleMode=t=>e._angleMode=t,e._DEGTORAD=Math.PI/180,e._RADTODEG=180/Math.PI,e.degrees=t=>t*e._RADTODEG,e.radians=t=>t*e._DEGTORAD,e.map=(e,t,a,o,n,r)=>{let s=o+1*(e-t)/(a-t)*(n-o);return r?o<n?Math.min(Math.max(s,o),n):Math.min(Math.max(s,n),o):s},e.lerp=(e,t,a)=>e*(1-a)+t*a,e.constrain=(e,t,a)=>Math.min(Math.max(e,t),a),e.dist=function(){let e=arguments;return 4==e.length?Math.hypot(e[0]-e[2],e[1]-e[3]):Math.hypot(e[0]-e[3],e[1]-e[4],e[2]-e[5])},e.norm=(t,a,o)=>e.map(t,a,o,0,1),e.sq=e=>e*e,e.fract=e=>e-Math.floor(e),e.sin=t=>("degrees"==e._angleMode&&(t=e.radians(t)),Math.sin(t)),e.cos=t=>("degrees"==e._angleMode&&(t=e.radians(t)),Math.cos(t)),e.tan=t=>("degrees"==e._angleMode&&(t=e.radians(t)),Math.tan(t)),e.asin=t=>{let a=Math.asin(t);return"degrees"==e._angleMode&&(a=e.degrees(a)),a},e.acos=t=>{let a=Math.acos(t);return"degrees"==e._angleMode&&(a=e.degrees(a)),a},e.atan=t=>{let a=Math.atan(t);return"degrees"==e._angleMode&&(a=e.degrees(a)),a},e.atan2=(t,a)=>{let o=Math.atan2(t,a);return"degrees"==e._angleMode&&(o=e.degrees(o)),o};let o=a();o.setSeed(),e.randomSeed=e=>o.setSeed(e),e.random=(e,t)=>void 0===e?o.rand():"number"==typeof e?void 0!==t?o.rand()*(t-e)+e:o.rand()*e:e[Math.trunc(e.length*o.rand())],e.randomGenerator=t=>{t==e.LCG?o=function(){const e=4294967296;let t,a;return{setSeed(o){a=t=(o??Math.random()*e)>>>0},getSeed:()=>t,rand:()=>(a=(1664525*a+1013904223)%e,a/e)}}():t==e.SHR3&&(o=a()),o.setSeed()};var n=new function(){var e,t,a,n=new Array(128),r=new Array(256),s=new Array(128),i=new Array(128),l=new Array(256),c=new Array(256),d=()=>4294967296*o.rand()-2147483648,h=()=>.5+2.328306e-10*(d()|0),u=()=>{for(var t,o,r,l,c=3.44262;;){if(t=a*s[e],0==e){do{r=h(),l=h(),t=.2904764*-Math.log(r),o=-Math.log(l)}while(o+o<t*t);return a>0?c+t:-c-t}if(i[e]+h()*(i[e-1]-i[e])<Math.exp(-.5*t*t))return t;if(a=d(),e=127&a,Math.abs(a)<n[e])return a*s[e]}},_=()=>{for(var a;;){if(0==e)return 7.69711-Math.log(h());if(a=t*l[e],c[e]+h()*(c[e-1]-c[e])<Math.exp(-a))return a;if((t=d())<r[e=255&t])return t*l[e]}};this.SHR3=d,this.UNI=h,this.RNOR=()=>(a=d(),e=127&a,Math.abs(a)<n[e]?a*s[e]:u()),this.REXP=()=>(t=d()>>>0)<n[e=255&t]?t*l[e]:_(),this.zigset=()=>{var e,t,a=2147483648,o=4294967296,d=3.442619855899,h=d,u=.00991256303526217,_=7.697117470131487,p=_,g=.003949659822581572;for(e=u/Math.exp(-.5*d*d),n[0]=Math.floor(d/e*a),n[1]=0,s[0]=e/a,s[127]=d/a,i[0]=1,i[127]=Math.exp(-.5*d*d),t=126;t>=1;t--)d=Math.sqrt(-2*Math.log(u/d+Math.exp(-.5*d*d))),n[t+1]=Math.floor(d/h*a),h=d,i[t]=Math.exp(-.5*d*d),s[t]=d/a;for(e=g/Math.exp(-_),r[0]=Math.floor(_/e*o),r[1]=0,l[0]=e/o,l[255]=_/o,c[0]=1,c[255]=Math.exp(-_),t=254;t>=1;t--)_=-Math.log(g/_+Math.exp(-_)),r[t+1]=Math.floor(_/p*o),p=_,c[t]=Math.exp(-_),l[t]=_/o}};let r;n.hasInit=!1,e.randomGaussian=(e,t)=>(n.hasInit||(n.zigset(),n.hasInit=!0),n.RNOR()*t+e),e.randomExponential=()=>(n.hasInit||(n.zigset(),n.hasInit=!0),n.REXP()),e.PERLIN="perlin",e.SIMPLEX="simplex",e.BLOCKY="blocky",e.Noise=Q5.PerlinNoise,e.noiseMode=e=>{t.Noise=Q5[e[0].toUpperCase()+e.slice(1)+"Noise"],r=null},e.noiseSeed=t=>{r=new e.Noise(t)},e.noise=(t=0,a=0,o=0)=>(r??=new e.Noise,r.noise(t,a,o)),e.noiseDetail=(t,a)=>{r??=new e.Noise,t>0&&(r.octaves=t),a>0&&(r.falloff=a)}},Q5.Noise=class{},Q5.PerlinNoise=class extends Q5.Noise{constructor(e){super(),this.grad3=[[1,1,0],[-1,1,0],[1,-1,0],[-1,-1,0],[1,0,1],[-1,0,1],[1,0,-1],[-1,0,-1],[0,1,1],[0,-1,1],[0,1,-1],[0,-1,-1]],this.octaves=1,this.falloff=.5,this.p=null==e?Array.from({length:256},(()=>Math.floor(256*Math.random()))):this.seedPermutation(e),this.p=this.p.concat(this.p)}seedPermutation(e){let t,a,o=[];for(let e=0;e<256;e++)o[e]=e;for(let n=255;n>0;n--)t=(e=16807*e%2147483647)%(n+1),a=o[n],o[n]=o[t],o[t]=a;return o}dot(e,t,a,o){return e[0]*t+e[1]*a+e[2]*o}mix(e,t,a){return(1-a)*e+a*t}fade(e){return e*e*e*(e*(6*e-15)+10)}noise(e,t,a){let o=this,n=0,r=1,s=1,i=0;for(let l=0;l<o.octaves;l++){const l=255&Math.floor(e*r),c=255&Math.floor(t*r),d=255&Math.floor(a*r),h=e*r-Math.floor(e*r),u=t*r-Math.floor(t*r),_=a*r-Math.floor(a*r),p=o.fade(h),g=o.fade(u),x=o.fade(_),m=o.p[l]+c,f=o.p[m]+d,v=o.p[m+1]+d,y=o.p[l+1]+c,w=o.p[y]+d,M=o.p[y+1]+d,C=o.mix(o.dot(o.grad3[o.p[f]%12],h,u,_),o.dot(o.grad3[o.p[w]%12],h-1,u,_),p),S=o.mix(o.dot(o.grad3[o.p[v]%12],h,u-1,_),o.dot(o.grad3[o.p[M]%12],h-1,u-1,_),p),b=o.mix(o.dot(o.grad3[o.p[f+1]%12],h,u,_-1),o.dot(o.grad3[o.p[w+1]%12],h-1,u,_-1),p),R=o.mix(o.dot(o.grad3[o.p[v+1]%12],h,u-1,_-1),o.dot(o.grad3[o.p[M+1]%12],h-1,u-1,_-1),p),E=o.mix(C,S,g),I=o.mix(b,R,g);n+=o.mix(E,I,x)*s,i+=s,s*=o.falloff,r*=2}return(n/i+1)/2}},Q5.modules.sound=(e,t)=>{e.loadSound=(a,o)=>{t._preloadCount++,e.aud??=new window.AudioContext;let n=new Audio(a);return n.addEventListener("canplaythrough",(()=>{t._preloadCount--,o&&o(n)})),n.load(),n.setVolume=e=>n.volume=e,n.setLoop=e=>n.loop=e,n.panner=e.aud.createStereoPanner(),n.source=e.aud.createMediaElementSource(n),n.source.connect(n.panner),n.panner.connect(e.aud.destination),Object.defineProperty(n,"pan",{get:()=>n.panner.pan.value,set:e=>n.panner.pan.value=e}),n.setPan=e=>n.pan=e,n},e.getAudioContext=()=>e.aud,e.userStartAudio=()=>e.aud.resume()},Q5.modules.util=(e,t)=>{e._loadFile=(e,a,o)=>{t._preloadCount++;let n={};return fetch(e).then((e=>"json"==o?e.json():"text"==o?e.text():void 0)).then((e=>{t._preloadCount--,Object.assign(n,e),a&&a(e)})),n},e.loadStrings=(t,a)=>e._loadFile(t,a,"text"),e.loadJSON=(t,a)=>e._loadFile(t,a,"json"),"object"==typeof localStorage&&(e.storeItem=localStorage.setItem,e.getItem=localStorage.getItem,e.removeItem=localStorage.removeItem,e.clearStorage=localStorage.clear),e.year=()=>(new Date).getFullYear(),e.day=()=>(new Date).getDay(),e.hour=()=>(new Date).getHours(),e.minute=()=>(new Date).getMinutes(),e.second=()=>(new Date).getSeconds()},Q5.modules.vector=e=>{e.createVector=(t,a,o)=>new Q5.Vector(t,a,o,e)},Q5.Vector=class{constructor(e,t,a,o){this.x=e||0,this.y=t||0,this.z=a||0,this._$=o||window,this._cn=null,this._cnsq=null}set(e,t,a){this.x=e||0,this.y=t||0,this.z=a||0}copy(){return new Q5.Vector(this.x,this.y,this.z)}_arg2v(e,t,a){return void 0!==e.x?e:void 0!==t?{x:e,y:t,z:a||0}:{x:e,y:e,z:e}}_calcNorm(){this._cnsq=this.x*this.x+this.y*this.y+this.z*this.z,this._cn=Math.sqrt(this._cnsq)}add(){let e=this._arg2v(...arguments);return this.x+=e.x,this.y+=e.y,this.z+=e.z,this}rem(){let e=this._arg2v(...arguments);return this.x%=e.x,this.y%=e.y,this.z%=e.z,this}sub(){let e=this._arg2v(...arguments);return this.x-=e.x,this.y-=e.y,this.z-=e.z,this}mult(){let e=this._arg2v(...arguments);return this.x*=e.x,this.y*=e.y,this.z*=e.z,this}div(){let e=this._arg2v(...arguments);return e.x?this.x/=e.x:this.x=0,e.y?this.y/=e.y:this.y=0,e.z?this.z/=e.z:this.z=0,this}mag(){return this._calcNorm(),this._cn}magSq(){return this._calcNorm(),this._cnsq}dot(){let e=this._arg2v(...arguments);return this.x*e.x+this.y*e.y+this.z*e.z}dist(){let e=this._arg2v(...arguments),t=this.x-e.x,a=this.y-e.y,o=this.z-e.z;return Math.sqrt(t*t+a*a+o*o)}cross(){let e=this._arg2v(...arguments),t=this.y*e.z-this.z*e.y,a=this.z*e.x-this.x*e.z,o=this.x*e.y-this.y*e.x;return this.x=t,this.y=a,this.z=o,this}normalize(){this._calcNorm();let e=this._cn;return 0!=e&&(this.x/=e,this.y/=e,this.z/=e),this._cn=1,this._cnsq=1,this}limit(e){this._calcNorm();let t=this._cn;if(t>e){let a=e/t;this.x*=a,this.y*=a,this.z*=a,this._cn=e,this._cnsq=e*e}return this}setMag(e){this._calcNorm();let t=e/this._cn;return this.x*=t,this.y*=t,this.z*=t,this._cn=e,this._cnsq=e*e,this}heading(){return this._$.atan2(this.y,this.x)}rotate(e){let t=this._$.cos(e),a=this._$.sin(e),o=this.x*t-this.y*a,n=this.x*a+this.y*t;return this.x=o,this.y=n,this}angleBetween(){let e=this._arg2v(...arguments),t=Q5.Vector.cross(this,e);return this._$.atan2(t.mag(),this.dot(e))*Math.sign(t.z||1)}lerp(){let e=[...arguments],t=this._arg2v(...e.slice(0,-1)),a=e.at(-1);return this.x+=(t.x-this.x)*a,this.y+=(t.y-this.y)*a,this.z+=(t.z-this.z)*a,this}reflect(e){return e.normalize(),this.sub(e.mult(2*this.dot(e)))}array(){return[this.x,this.y,this.z]}equals(e,t){return t??=Number.EPSILON||0,Math.abs(e.x-this.x)<t&&Math.abs(e.y-this.y)<t&&Math.abs(e.z-this.z)<t}fromAngle(e,t){return void 0===t&&(t=1),this._cn=t,this._cnsq=t*t,this.x=t*this._$.cos(e),this.y=t*this._$.sin(e),this.z=0,this}fromAngles(e,t,a){void 0===a&&(a=1),this._cn=a,this._cnsq=a*a;const o=this._$.cos(t),n=this._$.sin(t),r=this._$.cos(e),s=this._$.sin(e);return this.x=a*s*n,this.y=-a*r,this.z=a*s*o,this}random2D(){return this._cn=this._cnsq=1,this.fromAngle(Math.random()*Math.PI*2)}random3D(){return this._cn=this._cnsq=1,this.fromAngles(Math.random()*Math.PI*2,Math.random()*Math.PI*2)}toString(){return`[${this.x}, ${this.y}, ${this.z}]`}},Q5.Vector.add=(e,t)=>e.copy().add(t),Q5.Vector.cross=(e,t)=>e.copy().cross(t),Q5.Vector.dist=(e,t)=>Math.hypot(e.x-t.x,e.y-t.y,e.z-t.z),Q5.Vector.div=(e,t)=>e.copy().div(t),Q5.Vector.dot=(e,t)=>e.copy().dot(t),Q5.Vector.equals=(e,t,a)=>e.equals(t,a),Q5.Vector.lerp=(e,t,a)=>e.copy().lerp(t,a),Q5.Vector.limit=(e,t)=>e.copy().limit(t),Q5.Vector.heading=e=>this._$.atan2(e.y,e.x),Q5.Vector.magSq=e=>e.x*e.x+e.y*e.y+e.z*e.z,Q5.Vector.mag=e=>Math.sqrt(Q5.Vector.magSq(e)),Q5.Vector.mult=(e,t)=>e.copy().mult(t),Q5.Vector.normalize=e=>e.copy().normalize(),Q5.Vector.rem=(e,t)=>e.copy().rem(t),Q5.Vector.sub=(e,t)=>e.copy().sub(t);for(let e of["fromAngle","fromAngles","random2D","random3D"])Q5.Vector[e]=(t,a,o)=>(new Q5.Vector)[e](t,a,o);
|
package/src/q5-2d-canvas.js
CHANGED
|
@@ -262,6 +262,7 @@ Q5.modules.q2d_canvas = ($, p) => {
|
|
|
262
262
|
let g = new Q5('graphics');
|
|
263
263
|
opt ??= {};
|
|
264
264
|
opt.alpha ??= true;
|
|
265
|
+
opt.colorSpace ??= $.canvas.colorSpace;
|
|
265
266
|
g._createCanvas.call($, w, h, opt);
|
|
266
267
|
return g;
|
|
267
268
|
};
|
|
@@ -278,7 +279,6 @@ Q5.modules.q2d_canvas = ($, p) => {
|
|
|
278
279
|
|
|
279
280
|
Q5.canvasOptions = {
|
|
280
281
|
alpha: false,
|
|
281
|
-
desynchronized: false,
|
|
282
282
|
colorSpace: 'display-p3'
|
|
283
283
|
};
|
|
284
284
|
|
package/src/q5-2d-drawing.js
CHANGED
|
@@ -70,7 +70,7 @@ Q5.modules.q2d_drawing = ($) => {
|
|
|
70
70
|
$._strokeSet = true;
|
|
71
71
|
if (Q5.Color) {
|
|
72
72
|
if (!c._q5Color && typeof c != 'string') c = $.color(...arguments);
|
|
73
|
-
else if ($.
|
|
73
|
+
else if ($._namedColors[c]) c = $.color(...$._namedColors[c]);
|
|
74
74
|
if (c.a <= 0) return ($._doStroke = false);
|
|
75
75
|
}
|
|
76
76
|
$.ctx.strokeStyle = c.toString();
|
|
@@ -81,7 +81,7 @@ Q5.modules.q2d_drawing = ($) => {
|
|
|
81
81
|
$._fillSet = true;
|
|
82
82
|
if (Q5.Color) {
|
|
83
83
|
if (!c._q5Color && typeof c != 'string') c = $.color(...arguments);
|
|
84
|
-
else if ($.
|
|
84
|
+
else if ($._namedColors[c]) c = $.color(...$._namedColors[c]);
|
|
85
85
|
if (c.a <= 0) return ($._doFill = false);
|
|
86
86
|
}
|
|
87
87
|
$.ctx.fillStyle = c.toString();
|
|
@@ -108,7 +108,7 @@ Q5.modules.q2d_drawing = ($) => {
|
|
|
108
108
|
$.ctx.resetTransform();
|
|
109
109
|
if (Q5.Color) {
|
|
110
110
|
if (!c._q5Color && typeof c != 'string') c = $.color(...arguments);
|
|
111
|
-
else if ($.
|
|
111
|
+
else if ($._namedColors[c]) c = $.color(...$._namedColors[c]);
|
|
112
112
|
}
|
|
113
113
|
$.ctx.fillStyle = c.toString();
|
|
114
114
|
$.ctx.fillRect(0, 0, $.canvas.width, $.canvas.height);
|
|
@@ -512,7 +512,7 @@ Q5.modules.q2d_drawing = ($) => {
|
|
|
512
512
|
};
|
|
513
513
|
|
|
514
514
|
$.inStroke = (x, y) => {
|
|
515
|
-
const pd =
|
|
515
|
+
const pd = $._pixelDensity;
|
|
516
516
|
return $.ctx.isPointInStroke(x * pd, y * pd);
|
|
517
517
|
};
|
|
518
518
|
};
|
package/src/q5-2d-image.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
Q5.modules.q2d_image = ($, p) => {
|
|
2
2
|
$.createImage = (w, h, opt) => {
|
|
3
|
+
opt ??= {};
|
|
4
|
+
opt.alpha ??= true;
|
|
5
|
+
opt.colorSpace ??= $.canvas.colorSpace || Q5.canvasOptions.colorSpace;
|
|
3
6
|
return new Q5.Image(w, h, opt);
|
|
4
7
|
};
|
|
5
8
|
|
|
@@ -321,22 +324,26 @@ Q5.modules.q2d_image = ($, p) => {
|
|
|
321
324
|
$.loadImage = function (url, cb, opt) {
|
|
322
325
|
if (url.canvas) return url;
|
|
323
326
|
if (url.slice(-3).toLowerCase() == 'gif') {
|
|
324
|
-
throw `
|
|
327
|
+
throw new Error(`q5 doesn't support GIFs due to their impact on performance. Use a video or animation instead.`);
|
|
325
328
|
}
|
|
326
329
|
p._preloadCount++;
|
|
327
330
|
let last = [...arguments].at(-1);
|
|
328
|
-
opt = typeof last == 'object' ? last :
|
|
329
|
-
|
|
330
|
-
let
|
|
331
|
+
opt = typeof last == 'object' ? last : null;
|
|
332
|
+
|
|
333
|
+
let g = $.createImage(1, 1, opt);
|
|
334
|
+
|
|
335
|
+
function loaded(img) {
|
|
336
|
+
let c = g.ctx;
|
|
337
|
+
g.width = c.canvas.width = img.naturalWidth || img.width;
|
|
338
|
+
g.height = c.canvas.height = img.naturalHeight || img.height;
|
|
339
|
+
c.drawImage(img, 0, 0);
|
|
340
|
+
p._preloadCount--;
|
|
341
|
+
if (cb) cb(g);
|
|
342
|
+
}
|
|
343
|
+
|
|
331
344
|
if (Q5._nodejs && global.CairoCanvas) {
|
|
332
|
-
CairoCanvas.loadImage(url)
|
|
333
|
-
.then(
|
|
334
|
-
g.width = c.canvas.width = img.width;
|
|
335
|
-
g.height = c.canvas.height = img.height;
|
|
336
|
-
c.drawImage(img, 0, 0);
|
|
337
|
-
p._preloadCount--;
|
|
338
|
-
if (cb) cb(g);
|
|
339
|
-
})
|
|
345
|
+
global.CairoCanvas.loadImage(url)
|
|
346
|
+
.then(loaded)
|
|
340
347
|
.catch((e) => {
|
|
341
348
|
p._preloadCount--;
|
|
342
349
|
throw e;
|
|
@@ -346,13 +353,7 @@ Q5.modules.q2d_image = ($, p) => {
|
|
|
346
353
|
img.src = url;
|
|
347
354
|
img.crossOrigin = 'Anonymous';
|
|
348
355
|
img._pixelDensity = 1;
|
|
349
|
-
img.onload = () =>
|
|
350
|
-
g.width = c.canvas.width = img.naturalWidth;
|
|
351
|
-
g.height = c.canvas.height = img.naturalHeight;
|
|
352
|
-
c.drawImage(img, 0, 0);
|
|
353
|
-
p._preloadCount--;
|
|
354
|
-
if (cb) cb(g);
|
|
355
|
-
};
|
|
356
|
+
img.onload = () => loaded(img);
|
|
356
357
|
img.onerror = (e) => {
|
|
357
358
|
p._preloadCount--;
|
|
358
359
|
throw e;
|
|
@@ -376,8 +377,7 @@ class _Q5Image {
|
|
|
376
377
|
Q5.modules[m]($, $);
|
|
377
378
|
}
|
|
378
379
|
delete this.createCanvas;
|
|
379
|
-
|
|
380
|
-
opt.alpha ??= true;
|
|
380
|
+
|
|
381
381
|
this._createCanvas(w, h, '2d', opt);
|
|
382
382
|
this._loop = false;
|
|
383
383
|
}
|
package/src/q5-2d-text.js
CHANGED
|
@@ -19,9 +19,8 @@ Q5.modules.q2d_text = ($, p) => {
|
|
|
19
19
|
|
|
20
20
|
$.loadFont = (url, cb) => {
|
|
21
21
|
p._preloadCount++;
|
|
22
|
-
let
|
|
23
|
-
let
|
|
24
|
-
let f = new FontFace(name, 'url(' + url + ')');
|
|
22
|
+
let name = url.split('/').pop().split('.')[0].replace(' ', '');
|
|
23
|
+
let f = new FontFace(name, `url(${url})`);
|
|
25
24
|
document.fonts.add(f);
|
|
26
25
|
f.load().then(() => {
|
|
27
26
|
p._preloadCount--;
|
|
@@ -141,7 +140,6 @@ Q5.modules.q2d_text = ($, p) => {
|
|
|
141
140
|
}
|
|
142
141
|
if (!$._doFill && !$._doStroke) return;
|
|
143
142
|
let c, ti, tg, k, cX, cY, _ascent, _descent;
|
|
144
|
-
let pd = 1;
|
|
145
143
|
let t = $.ctx.getTransform();
|
|
146
144
|
let useCache = $._genTextImage || ($._textCache && (t.b != 0 || t.c != 0));
|
|
147
145
|
if (!useCache) {
|
|
@@ -157,7 +155,6 @@ Q5.modules.q2d_text = ($, p) => {
|
|
|
157
155
|
}
|
|
158
156
|
tg = $.createGraphics.call($, 1, 1);
|
|
159
157
|
c = tg.ctx;
|
|
160
|
-
pd = $._pixelDensity;
|
|
161
158
|
}
|
|
162
159
|
c.font = `${$._textStyle} ${$._textSize}px ${$._textFont}`;
|
|
163
160
|
let lines = str.split('\n');
|
package/src/q5-ai.js
CHANGED
|
@@ -7,7 +7,7 @@ Q5.modules.ai = ($) => {
|
|
|
7
7
|
let askAI = e.message?.includes('Ask AI ✨');
|
|
8
8
|
if (!askAI) console.error(e);
|
|
9
9
|
if (Q5.disableFriendlyErrors) return;
|
|
10
|
-
if (askAI || !Q5.errorTolerant) noLoop();
|
|
10
|
+
if (askAI || !Q5.errorTolerant) $.noLoop();
|
|
11
11
|
let stackLines = e.stack?.split('\n');
|
|
12
12
|
if (!e.stack || stackLines.length <= 1) return;
|
|
13
13
|
|
package/src/q5-color.js
CHANGED
|
@@ -17,7 +17,7 @@ Q5.modules.color = ($, p) => {
|
|
|
17
17
|
}
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
$.
|
|
20
|
+
$._namedColors = {
|
|
21
21
|
aqua: [0, 255, 255],
|
|
22
22
|
black: [0, 0, 0],
|
|
23
23
|
blue: [0, 0, 255],
|
|
@@ -58,14 +58,28 @@ Q5.modules.color = ($, p) => {
|
|
|
58
58
|
if (args.length == 1) {
|
|
59
59
|
if (typeof c0 == 'string') {
|
|
60
60
|
if (c0[0] == '#') {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
61
|
+
if (c0.length <= 5) {
|
|
62
|
+
return new C(
|
|
63
|
+
parseInt(c0[1] + c0[1], 16),
|
|
64
|
+
parseInt(c0[2] + c0[2], 16),
|
|
65
|
+
parseInt(c0[3] + c0[3], 16),
|
|
66
|
+
c0.length == 4 ? null : parseInt(c0[4] + c0[4], 16)
|
|
67
|
+
);
|
|
68
|
+
} else {
|
|
69
|
+
return new C(
|
|
70
|
+
parseInt(c0.slice(1, 3), 16),
|
|
71
|
+
parseInt(c0.slice(3, 5), 16),
|
|
72
|
+
parseInt(c0.slice(5, 7), 16),
|
|
73
|
+
c0.length == 7 ? null : parseInt(c0.slice(7, 9), 16)
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
} else if ($._namedColors[c0]) return new C(...$._namedColors[c0]);
|
|
77
|
+
else {
|
|
78
|
+
console.error(
|
|
79
|
+
"q5 can't parse color: " + c0 + '\nOnly numeric input, hex, and common named colors are supported.'
|
|
66
80
|
);
|
|
67
|
-
|
|
68
|
-
|
|
81
|
+
return new C(0, 0, 0);
|
|
82
|
+
}
|
|
69
83
|
} else if (Array.isArray(c0)) return new C(...c0);
|
|
70
84
|
}
|
|
71
85
|
if ($._colorMode == 'rgb') {
|
package/src/q5-core.js
CHANGED
|
@@ -81,7 +81,6 @@ function Q5(scope, parent) {
|
|
|
81
81
|
p.frameCount++;
|
|
82
82
|
let pre = performance.now();
|
|
83
83
|
for (let m of Q5.prototype._methods.pre) m.call($);
|
|
84
|
-
firstVertex = true;
|
|
85
84
|
if ($.ctx) $.ctx.save();
|
|
86
85
|
$.draw();
|
|
87
86
|
for (let m of Q5.prototype._methods.post) m.call($);
|
|
@@ -264,7 +263,7 @@ Q5.prototype.registerPreloadMethod = (n, fn) => (Q5.prototype[n] = fn[n]);
|
|
|
264
263
|
|
|
265
264
|
if (Q5._nodejs) global.p5 ??= global.Q5 = Q5;
|
|
266
265
|
else if (typeof window == 'object') window.p5 ??= window.Q5 = Q5;
|
|
267
|
-
else window = 0;
|
|
266
|
+
else global.window = 0;
|
|
268
267
|
|
|
269
268
|
if (typeof document == 'object') {
|
|
270
269
|
document.addEventListener('DOMContentLoaded', () => {
|
package/src/q5-input.js
CHANGED
|
@@ -94,24 +94,22 @@ Q5.modules.input = ($, p) => {
|
|
|
94
94
|
|
|
95
95
|
$._onkeydown = (e) => {
|
|
96
96
|
if (e.repeat) return;
|
|
97
|
-
$._startAudio;
|
|
97
|
+
$._startAudio();
|
|
98
98
|
p.keyIsPressed = true;
|
|
99
99
|
p.key = e.key;
|
|
100
100
|
p.keyCode = e.keyCode;
|
|
101
|
-
keysHeld[$.keyCode] = keysHeld[$.key] = true;
|
|
101
|
+
keysHeld[$.keyCode] = keysHeld[$.key.toLowerCase()] = true;
|
|
102
102
|
$.keyPressed(e);
|
|
103
|
-
if (e.key.length == 1)
|
|
104
|
-
$.keyTyped(e);
|
|
105
|
-
}
|
|
103
|
+
if (e.key.length == 1) $.keyTyped(e);
|
|
106
104
|
};
|
|
107
105
|
$._onkeyup = (e) => {
|
|
108
106
|
p.keyIsPressed = false;
|
|
109
107
|
p.key = e.key;
|
|
110
108
|
p.keyCode = e.keyCode;
|
|
111
|
-
keysHeld[$.keyCode] = keysHeld[$.key] = false;
|
|
109
|
+
keysHeld[$.keyCode] = keysHeld[$.key.toLowerCase()] = false;
|
|
112
110
|
$.keyReleased(e);
|
|
113
111
|
};
|
|
114
|
-
$.keyIsDown = (
|
|
112
|
+
$.keyIsDown = (v) => !!keysHeld[typeof v == 'string' ? v.toLowerCase() : v];
|
|
115
113
|
|
|
116
114
|
function getTouchInfo(touch) {
|
|
117
115
|
const rect = $.canvas.getBoundingClientRect();
|
package/src/q5-math.js
CHANGED
package/src/q5-vector.js
CHANGED
|
@@ -154,7 +154,7 @@ Q5.Vector = class {
|
|
|
154
154
|
lerp() {
|
|
155
155
|
let args = [...arguments];
|
|
156
156
|
let u = this._arg2v(...args.slice(0, -1));
|
|
157
|
-
let amt = args
|
|
157
|
+
let amt = args.at(-1);
|
|
158
158
|
this.x += (u.x - this.x) * amt;
|
|
159
159
|
this.y += (u.y - this.y) * amt;
|
|
160
160
|
this.z += (u.z - this.z) * amt;
|