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 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
- - `color` function only accepts numeric input, hex, and simple named colors. It doesn't parse strings like `color('hsl(160, 100%, 50%)')`.
312
- - `fill` and `stroke` can accept any CSS color string.
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
- ## Contributor Code of Conduct
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
- If the q5 project is successful, all contributing developers will be paid for their work. The project will be run as a [worker co-op](https://en.wikipedia.org/wiki/Worker_cooperative).
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 MIT licensed.
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "q5",
3
- "version": "2.0.5",
4
- "description": "The sequel to p5.js that's smaller and faster",
3
+ "version": "2.0.12",
4
+ "description": "A sequel to p5.js that's smaller and faster",
5
5
  "author": "quinton-ashley",
6
6
  "contributors": [
7
7
  "Tezumie",
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 ($._basicColors[c]) c = $.color(...$._basicColors[c]);
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 ($._basicColors[c]) c = $.color(...$._basicColors[c]);
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 ($._basicColors[c]) c = $.color(...$._basicColors[c]);
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 = pixelDensity();
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 `In q5, GIFs are not supported due to their impact on performance. Use a video or p5play animation instead.`;
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 : true;
1407
- let g = $.createImage(1, 1, opt.alpha);
1408
- let c = g.ctx;
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((img) => {
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
- opt ??= {};
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 sp = url.split('/');
1678
- let name = sp[sp.length - 1].split('.')[0].replace(' ', '');
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
- $._basicColors = {
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
- return new C(
1998
- parseInt(c0.slice(1, 3), 16),
1999
- parseInt(c0.slice(3, 5), 16),
2000
- parseInt(c0.slice(5, 7), 16),
2001
- c0.length != 9 ? null : parseInt(c0.slice(7, 9), 16)
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
- } else if ($._basicColors[c0]) return new C(...$._basicColors[c0]);
2004
- else return new C(0, 0, 0);
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 = (x) => !!keysHeld[x];
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[args.length - 1];
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);
@@ -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
 
@@ -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 ($._basicColors[c]) c = $.color(...$._basicColors[c]);
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 ($._basicColors[c]) c = $.color(...$._basicColors[c]);
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 ($._basicColors[c]) c = $.color(...$._basicColors[c]);
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 = pixelDensity();
515
+ const pd = $._pixelDensity;
516
516
  return $.ctx.isPointInStroke(x * pd, y * pd);
517
517
  };
518
518
  };
@@ -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 `In q5, GIFs are not supported due to their impact on performance. Use a video or p5play animation instead.`;
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 : true;
329
- let g = $.createImage(1, 1, opt.alpha);
330
- let c = g.ctx;
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((img) => {
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
- opt ??= {};
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 sp = url.split('/');
23
- let name = sp[sp.length - 1].split('.')[0].replace(' ', '');
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
- $._basicColors = {
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
- return new C(
62
- parseInt(c0.slice(1, 3), 16),
63
- parseInt(c0.slice(3, 5), 16),
64
- parseInt(c0.slice(5, 7), 16),
65
- c0.length != 9 ? null : parseInt(c0.slice(7, 9), 16)
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
- } else if ($._basicColors[c0]) return new C(...$._basicColors[c0]);
68
- else return new C(0, 0, 0);
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 = (x) => !!keysHeld[x];
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
@@ -302,9 +302,7 @@ Q5.modules.math = ($, p) => {
302
302
  };
303
303
  };
304
304
 
305
- Q5.Noise = class {
306
- constructor() {}
307
- };
305
+ Q5.Noise = class {};
308
306
 
309
307
  Q5.PerlinNoise = class extends Q5.Noise {
310
308
  constructor(seed) {
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[args.length - 1];
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;