q5 2.2.2 → 2.2.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "q5",
3
- "version": "2.2.2",
3
+ "version": "2.2.3",
4
4
  "description": "A sequel to p5.js that's smaller and faster",
5
5
  "author": "quinton-ashley",
6
6
  "contributors": [
package/q5-q2d.js CHANGED
@@ -551,7 +551,12 @@ Q5.renderers.q2d.canvas = ($, q) => {
551
551
  $.ctx.lineWidth = n || 0.0001;
552
552
  };
553
553
  $.noStroke = () => ($._doStroke = false);
554
- $.clear = () => $.ctx.clearRect(0, 0, $.canvas.width, $.canvas.height);
554
+ $.clear = () => {
555
+ $.ctx.save();
556
+ $.ctx.resetTransform();
557
+ $.ctx.clearRect(0, 0, $.canvas.width, $.canvas.height);
558
+ $.ctx.restore();
559
+ };
555
560
 
556
561
  // DRAWING MATRIX
557
562
 
@@ -717,15 +722,17 @@ Q5.renderers.q2d.drawing = ($) => {
717
722
  // DRAWING
718
723
 
719
724
  $.background = function (c) {
720
- if (c.canvas) return $.image(c, 0, 0, $.width, $.height);
721
725
  $.ctx.save();
722
726
  $.ctx.resetTransform();
723
- if (Q5.Color) {
724
- if (!c._q5Color && typeof c != 'string') c = $.color(...arguments);
725
- else if ($._namedColors[c]) c = $.color(...$._namedColors[c]);
727
+ if (c.canvas) $.image(c, 0, 0, $.width, $.height);
728
+ else {
729
+ if (Q5.Color) {
730
+ if (!c._q5Color && typeof c != 'string') c = $.color(...arguments);
731
+ else if ($._namedColors[c]) c = $.color(...$._namedColors[c]);
732
+ }
733
+ $.ctx.fillStyle = c.toString();
734
+ $.ctx.fillRect(0, 0, $.canvas.width, $.canvas.height);
726
735
  }
727
- $.ctx.fillStyle = c.toString();
728
- $.ctx.fillRect(0, 0, $.canvas.width, $.canvas.height);
729
736
  $.ctx.restore();
730
737
  };
731
738
 
@@ -1904,13 +1911,20 @@ Q5.modules.color = ($, q) => {
1904
1911
  c0 = parseInt(c0.slice(1, 3), 16);
1905
1912
  }
1906
1913
  } else if ($._namedColors[c0]) {
1907
- c0 = $._namedColors[c0];
1914
+ [c0, c1, c2, c3] = $._namedColors[c0];
1908
1915
  } else {
1909
1916
  console.error(
1910
1917
  "q5 can't parse color: " + c0 + '\nOnly numeric input, hex, and common named colors are supported.'
1911
1918
  );
1912
1919
  return new C(0, 0, 0);
1913
1920
  }
1921
+
1922
+ if ($._colorFormat == 1) {
1923
+ c0 /= 255;
1924
+ if (c1) c1 /= 255;
1925
+ if (c2) c2 /= 255;
1926
+ if (c3) c3 /= 255;
1927
+ }
1914
1928
  }
1915
1929
  if (Array.isArray(c0)) {
1916
1930
  c1 = c0[1];
@@ -1920,13 +1934,6 @@ Q5.modules.color = ($, q) => {
1920
1934
  }
1921
1935
  }
1922
1936
 
1923
- if ($._colorFormat == 1) {
1924
- c0 /= 255;
1925
- if (c1) c1 /= 255;
1926
- if (c2) c2 /= 255;
1927
- if (c3) c3 /= 255;
1928
- }
1929
-
1930
1937
  if (c2 == undefined) return new C(c0, c0, c0, c1);
1931
1938
  return new C(c0, c1, c2, c3);
1932
1939
  };
package/q5-q2d.min.js CHANGED
@@ -5,4 +5,4 @@
5
5
  * @license LGPL-3.0
6
6
  * @class Q5
7
7
  */
8
- function Q5(e,t,o){let a,r=this;if(r._q5=!0,r._parent=t,r._renderer=o||"q2d",r._preloadCount=0,e??="global","auto"==e){if(!window.setup&&!window.draw)return;e="global"}r._scope=e,"global"==e&&(Q5._hasGlobal=r._isGlobal=!0,a=Q5._nodejs?global:window);let n=new Proxy(r,{set:(e,t,o)=>(r[t]=o,r._isGlobal&&(a[t]=o),!0)});r.canvas=r.ctx=r.drawingContext=null,r.pixels=[];let s=null;r.frameCount=0,r.deltaTime=16,r._targetFrameRate=0,r._targetFrameDuration=16.666666666666668,r._frameRate=r._fps=60,r._loop=!0,r._hooks={postCanvas:[],preRender:[]};let i=0;r.millis=()=>performance.now()-i,r.noCanvas=()=>{r.canvas?.remove&&r.canvas.remove(),r.canvas=0,n.ctx=n.drawingContext=0},window&&(r.windowWidth=window.innerWidth,r.windowHeight=window.innerHeight,r.deviceOrientation=window.screen?.orientation?.type),r._incrementPreload=()=>n._preloadCount++,r._decrementPreload=()=>n._preloadCount--,r._draw=e=>{let t=e||performance.now();if(r._lastFrameTime??=t-r._targetFrameDuration,r._shouldResize&&(r.windowResized(),r._shouldResize=!1),r._loop)s=c(r._draw);else if(r.frameCount&&!r._redraw)return;if(s&&r.frameCount){if(t-r._lastFrameTime<r._targetFrameDuration-4)return}n.deltaTime=t-r._lastFrameTime,r._frameRate=1e3/r.deltaTime,n.frameCount++;let o=performance.now();r.ctx&&r.resetMatrix(),r._beginRender&&r._beginRender();for(let e of Q5.methods.pre)e.call(r);r.draw(),r._render&&r._render();for(let e of Q5.methods.post)e.call(r);r._finishRender&&r._finishRender(),n.pmouseX=r.mouseX,n.pmouseY=r.mouseY,r._lastFrameTime=t;let a=performance.now();r._fps=Math.round(1e3/(a-o))},r.noLoop=()=>{r._loop=!1,s=null},r.loop=()=>{r._loop=!0,null==s&&r._draw()},r.isLooping=()=>r._loop,r.redraw=(e=1)=>{r._redraw=!0;for(let t=0;t<e;t++)r._draw();r._redraw=!1},r.remove=()=>{r.noLoop(),r.canvas.remove()},r.frameRate=e=>(e&&(r._targetFrameRate=e,r._targetFrameDuration=1e3/e),r._frameRate),r.getTargetFrameRate=()=>r._targetFrameRate,r.getFPS=()=>r._fps,r.Element=function(e){this.elt=e},r._elements=[],r.TWO_PI=r.TAU=2*Math.PI,r.log=r.print=console.log,r.describe=()=>{};for(let e in Q5.modules)Q5.modules[e](r,n);let l=Q5.renderers[r._renderer];for(let e in l)l[e](r,n);for(let e in Q5)"_"!=e[1]&&e[1]==e[1].toUpperCase()&&(r[e]=Q5[e]);if("graphics"==e)return;"global"==e&&(Object.assign(Q5,r),delete Q5.Q5);for(let e of Q5.methods.init)e.call(r);for(let[e,t]of Object.entries(Q5.prototype))"_"!=e[0]&&"function"==typeof r[e]&&(r[e]=t.bind(r));if("global"==e){let e=Object.getOwnPropertyNames(r);for(let t of e)"_"!=t[0]&&(a[t]=r[t])}"function"==typeof e&&e(r),Q5._instanceCount++;let c=window.requestAnimationFrame||function(e){const t=r._lastFrameTime+r._targetFrameDuration;return setTimeout((()=>{e(t)}),t-performance.now())},d=a||r;r._isTouchAware=d.touchStarted||d.touchMoved||d.mouseReleased;let h=d.preload,u=["setup","draw","preload","mouseMoved","mousePressed","mouseReleased","mouseDragged","mouseClicked","keyPressed","keyReleased","keyTyped","touchStarted","touchMoved","touchEnded","windowResized"];for(let e of u)d[e]?r._isGlobal&&(r[e]=()=>{try{return d[e]()}catch(e){r._aiErrorAssistance?r._aiErrorAssistance(e):console.error(e)}}):r[e]=()=>{};async function _(){if(r._startDone=!0,r._preloadCount>0)return c(_);i=performance.now(),await r.setup(),r.frameCount||(null===r.ctx&&r.createCanvas(100,100),r._setupDone=!0,r.ctx&&r.resetMatrix(),c(r._draw))}(r.setup||r.draw)&&(arguments.length&&"namespace"!=e&&"webgpu"!=o||h?(r.preload(),_()):(d.preload=r.preload=()=>{r._startDone||_()},setTimeout(r.preload,32)))}Q5.renderers={},Q5.modules={},Q5._nodejs="object"==typeof process,Q5._instanceCount=0,Q5._friendlyError=(e,t)=>{throw Error(t+": "+e)},Q5._validateParameters=()=>!0,Q5.methods={init:[],pre:[],post:[],remove:[]},Q5.prototype.registerMethod=(e,t)=>Q5.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.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 o=e.canvas;if(o.width=e.width=100,o.height=e.height=100,"image"!=e._scope&&(o.renderer=e._renderer,o[e._renderer]=!0),e._pixelDensity=1,e._adjustDisplay=()=>{o.style&&(o.style.width=o.w+"px",o.style.height=o.h+"px")},e.createCanvas=function(t,a,r){r??=arguments[3];let n=Object.assign({},Q5.canvasOptions);if("object"==typeof r&&Object.assign(n,r),"image"!=e._scope){let t=e.displayDensity();"graphics"==e._scope?t=this._pixelDensity:window.IntersectionObserver&&new IntersectionObserver((e=>{o.visible=e[0].isIntersecting})).observe(o),e._pixelDensity=Math.ceil(t)}e._setCanvasSize(t,a),Object.assign(o,n);let s=e._createCanvas(o.w,o.h,n);if(e._hooks)for(let t of e._hooks.postCanvas)t();return s},e._save=async(e,t,o)=>{if(t=t||"untitled","jpg"==(o=o||"png")||"png"==o||"webp"==o)if(e instanceof OffscreenCanvas){const t=await e.convertToBlob({type:"image/"+o});e=await new Promise((e=>{const o=new FileReader;o.onloadend=()=>e(o.result),o.readAsDataURL(t)}))}else e=e.toDataURL("image/"+o);else{let t="text/plain";"json"==o&&("string"!=typeof e&&(e=JSON.stringify(e)),t="text/json"),e=new Blob([e],{type:t}),e=URL.createObjectURL(e)}let a=document.createElement("a");a.href=e,a.download=t+"."+o,a.click(),URL.revokeObjectURL(a.href)},e.save=(t,o,a)=>{if((!t||"string"==typeof t&&(!o||!a&&o.length<5))&&(a=o,o=t,t=e.canvas),a)return e._save(t,o,a);o?(o=o.split("."),e._save(t,o[0],o.at(-1))):e._save(t)},e._setCanvasSize=(a,r)=>{a??=window.innerWidth,r??=window.innerHeight,o.w=a=Math.ceil(a),o.h=r=Math.ceil(r),o.hw=a/2,o.hh=r/2,o.width=Math.ceil(a*e._pixelDensity),o.height=Math.ceil(r*e._pixelDensity),e._da?e.flexibleCanvas(e._dau):(t.width=a,t.height=r),e.displayMode&&!o.displayMode?e.displayMode():e._adjustDisplay()},"image"!=e._scope){if(o&&"graphics"!=e._scope){function a(){let t=e._parent;t??=document.getElementsByTagName("main")[0],t||(t=document.createElement("main"),document.body.append(t)),o.parent(t)}o.parent=t=>{function a(){e.frameCount>1&&(e._shouldResize=!0,e._adjustDisplay())}o.parentElement&&o.parentElement.removeChild(o),"string"==typeof t&&(t=document.getElementById(t)),t.append(o),"function"==typeof ResizeObserver?(e._ro&&e._ro.disconnect(),e._ro=new ResizeObserver(a),e._ro.observe(t)):e.frameCount||window.addEventListener("resize",a)},document.body?a():document.addEventListener("DOMContentLoaded",a)}e.resizeCanvas=(t,a)=>{if(!e.ctx)return e.createCanvas(t,a);t==o.w&&a==o.h||e._resizeCanvas(t,a)},e.canvas.resize=e.resizeCanvas,e.canvas.save=e.saveCanvas=e.save,e.displayDensity=()=>window.devicePixelRatio,e.pixelDensity=t=>t&&t!=e._pixelDensity?(e._pixelDensity=t,e._setCanvasSize(o.w,o.h),t):e._pixelDensity,e.flexibleCanvas=(a=400)=>{a?(e._da=o.width/(a*e._pixelDensity),t.width=e._dau=a,t.height=o.h/o.w*a):e._da=0}}},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.renderers.q2d={},Q5.renderers.q2d.canvas=(e,t)=>{let o=e.canvas;e.colorMode&&e.colorMode("rgb","integer"),e._createCanvas=function(a,r,n){return t.ctx=t.drawingContext=o.getContext("2d",n),"image"!=e._scope&&(e.ctx.fillStyle="white",e.ctx.strokeStyle="black",e.ctx.lineCap="round",e.ctx.lineJoin="miter",e.ctx.textAlign="left"),e.ctx.scale(e._pixelDensity,e._pixelDensity),e.ctx.save(),o},"image"!=e._scope&&(e._resizeCanvas=(t,a)=>{let r={};for(let t in e.ctx)"function"!=typeof e.ctx[t]&&(r[t]=e.ctx[t]);delete r.canvas;let n=new e._OffscreenCanvas(o.width,o.height);n.w=o.w,n.h=o.h,n.getContext("2d").drawImage(o,0,0),e._setCanvasSize(t,a);for(let t in r)e.ctx[t]=r[t];e.scale(e._pixelDensity),e.ctx.drawImage(n,0,0,n.w,n.h)},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.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.strokeWeight=t=>{t||(e._doStroke=!1),e._da&&(t*=e._da),e.ctx.lineWidth=t||1e-4},e.noStroke=()=>e._doStroke=!1,e.clear=()=>e.ctx.clearRect(0,0,e.canvas.width,e.canvas.height),e.translate=(t,o)=>{e._da&&(t*=e._da,o*=e._da),e.ctx.translate(t,o)},e.rotate=t=>{"degrees"==e._angleMode&&(t=e.radians(t)),e.ctx.rotate(t)},e.scale=(t,o)=>{o??=t,e.ctx.scale(t,o)},e.opacity=t=>e.ctx.globalAlpha=t,e.applyMatrix=(t,o,a,r,n,s)=>e.ctx.transform(t,o,a,r,n,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.scale(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 o of e._styleNames)t[o]=e[o];e._styles.push(t)},e.pop=e.popMatrix=()=>{e.ctx.restore();let t=e._styles.pop();for(let o of e._styleNames)e[o]=t[o]},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,o,a){let r=new Q5("graphics");return a??={},a.alpha??=!0,a.colorSpace??=e.canvas.colorSpace,r.createCanvas.call(e,t,o,a),r},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.renderers.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,o=[];function a(){e._doFill&&e.ctx.fill(),e._doStroke&&e.ctx.stroke()}function r(t,o,r,n,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(),r==n)d&&(s=e.radians(s),i=e.radians(i)),e.ctx.arc(t,o,r/2,s,i);else{for(let a=0;a<c+1;a++){let l=a/c,d=e.lerp(s,i,l),h=e.cos(d)*r/2,u=e.sin(d)*n/2;e.ctx[a?"lineTo":"moveTo"](t+h,o+u)}l==e.CHORD?e.ctx.closePath():l==e.PIE&&(e.ctx.lineTo(t,o),e.ctx.closePath())}a()}}function n(t,o,r,n){(e._doFill||e._doStroke)&&(e._da&&(t*=e._da,o*=e._da,r*=e._da,n*=e._da),e.ctx.beginPath(),e.ctx.ellipse(t,o,r/2,n/2,0,0,e.TAU),a())}function s(t,o,r,n,i,l,c,d){if(e._doFill||e._doStroke){if(void 0===i)return function(t,o,r,n){e._da&&(t*=e._da,o*=e._da,r*=e._da,n*=e._da),e.ctx.beginPath(),e.ctx.rect(t,o,r,n),a()}(t,o,r,n);if(void 0===l)return s(t,o,r,n,i,i,i,i);e._da&&(t*=e._da,o*=e._da,r*=e._da,n*=e._da,i*=e._da,l*=e._da,d*=e._da,c*=e._da),e.ctx.roundRect(t,o,r,n,[i,l,c,d]),a()}}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.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,o,a,r)=>{e._doStroke&&(e._da&&(t*=e._da,o*=e._da,a*=e._da,r*=e._da),e.ctx.beginPath(),e.ctx.moveTo(t,o),e.ctx.lineTo(a,r),e.ctx.stroke())},e.arc=(t,o,a,n,s,i,l,c=25)=>{if(s==i)return e.ellipse(t,o,a,n);l??=e.PIE,e._ellipseMode==e.CENTER?r(t,o,a,n,s,i,l,c):e._ellipseMode==e.RADIUS?r(t,o,2*a,2*n,s,i,l,c):e._ellipseMode==e.CORNER?r(t+a/2,o+n/2,a,n,s,i,l,c):e._ellipseMode==e.CORNERS&&r((t+a)/2,(o+n)/2,a-t,n-o,s,i,l,c)},e.ellipse=(t,o,a,r)=>{r??=a,e._ellipseMode==e.CENTER?n(t,o,a,r):e._ellipseMode==e.RADIUS?n(t,o,2*a,2*r):e._ellipseMode==e.CORNER?n(t+a/2,o+r/2,a,r):e._ellipseMode==e.CORNERS&&n((t+a)/2,(o+r)/2,a-t,r-o)},e.circle=(t,o,r)=>{e._ellipseMode==e.CENTER?(e._da&&(t*=e._da,o*=e._da,r*=e._da),e.ctx.beginPath(),e.ctx.arc(t,o,r/2,0,e.TAU),a()):e.ellipse(t,o,r,r)},e.point=(t,o)=>{t.x&&(o=t.y,t=t.x),e._da&&(t*=e._da,o*=e._da),e.ctx.save(),e.ctx.beginPath(),e.ctx.arc(t,o,e.ctx.lineWidth/2,0,e.TAU),e.ctx.fillStyle=e.ctx.strokeStyle,e.ctx.fill(),e.ctx.restore()},e.rect=(t,o,a,r=a,n,i,l,c)=>{e._rectMode==e.CENTER?s(t-a/2,o-r/2,a,r,n,i,l,c):e._rectMode==e.RADIUS?s(t-a,o-r,2*a,2*r,n,i,l,c):e._rectMode==e.CORNER?s(t,o,a,r,n,i,l,c):e._rectMode==e.CORNERS&&s(t,o,a-t,r-o,n,i,l,c)},e.square=(t,o,a,r,n,s,i)=>e.rect(t,o,a,a,r,n,s,i),e.beginShape=()=>{o=[],e.ctx.beginPath(),t=!0},e.beginContour=()=>{e.ctx.closePath(),o=[],t=!0},e.endContour=()=>{o=[],t=!0},e.vertex=(a,r)=>{e._da&&(a*=e._da,r*=e._da),o=[],t?e.ctx.moveTo(a,r):e.ctx.lineTo(a,r),t=!1},e.bezierVertex=(t,a,r,n,s,i)=>{e._da&&(t*=e._da,a*=e._da,r*=e._da,n*=e._da,s*=e._da,i*=e._da),o=[],e.ctx.bezierCurveTo(t,a,r,n,s,i)},e.quadraticVertex=(t,a,r,n)=>{e._da&&(t*=e._da,a*=e._da,r*=e._da,n*=e._da),o=[],e.ctx.quadraticCurveTo(t,a,r,n)},e.bezier=(t,o,a,r,n,s,i,l)=>{e.beginShape(),e.vertex(t,o),e.bezierVertex(a,r,n,s,i,l),e.endShape()},e.triangle=(t,o,a,r,n,s)=>{e.beginShape(),e.vertex(t,o),e.vertex(a,r),e.vertex(n,s),e.endShape(e.CLOSE)},e.quad=(t,o,a,r,n,s,i,l)=>{e.beginShape(),e.vertex(t,o),e.vertex(a,r),e.vertex(n,s),e.vertex(i,l),e.endShape(e.CLOSE)},e.endShape=t=>{o=[],t&&e.ctx.closePath(),a()},e.curveVertex=(a,r)=>{if(e._da&&(a*=e._da,r*=e._da),o.push([a,r]),o.length<4)return;let n=function(e,t,o,a,r,n,s,i,l,c){function d(e,t,o,a,r,n){let s=Math.pow(a-t,2)+Math.pow(r-o,2);return Math.pow(s,.5*n)+e}let h=[],u=d(0,e,t,o,a,c),_=d(u,o,a,r,n,c),p=d(_,r,n,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]+o*g[1],m=t*g[0]+a*g[1],f=o*g[2]+r*g[3],y=a*g[2]+n*g[3],v=r*g[4]+s*g[5],w=n*g[4]+i*g[5],C=x*g[6]+f*g[7],M=m*g[6]+y*g[7],S=f*g[8]+v*g[9],b=y*g[8]+w*g[9],R=C*g[2]+S*g[3],Q=M*g[2]+b*g[3];h.push([R,Q])}return h}(...o.at(-4),...o.at(-3),...o.at(-2),...o.at(-1),e._curveDetail,e._curveAlpha);for(let o=0;o<n.length;o++)t?e.ctx.moveTo(...n[o]):e.ctx.lineTo(...n[o]),t=!1},e.curve=(t,o,a,r,n,s,i,l)=>{e.beginShape(),e.curveVertex(t,o),e.curveVertex(a,r),e.curveVertex(n,s),e.curveVertex(i,l),e.endShape()},e.curvePoint=(e,t,o,a,r)=>{const n=r*r*r,s=r*r;return e*(-.5*n+s-.5*r)+t*(1.5*n-2.5*s+1)+o*(-1.5*n+2*s+.5*r)+a*(.5*n-.5*s)},e.bezierPoint=(e,t,o,a,r)=>{const n=1-r;return Math.pow(n,3)*e+3*Math.pow(n,2)*r*t+3*n*Math.pow(r,2)*o+Math.pow(r,3)*a},e.curveTangent=(e,t,o,a,r)=>{const n=r*r;return e*(-3*n/2+2*r-.5)+t*(9*n/2-5*r)+o*(-9*n/2+4*r+.5)+a*(3*n/2-r)},e.bezierTangent=(e,t,o,a,r)=>{const n=1-r;return 3*a*Math.pow(r,2)-3*o*Math.pow(r,2)+6*o*n*r-6*t*n*r+3*t*Math.pow(n,2)-3*e*Math.pow(n,2)},e.erase=function(t=255,o=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, ${o/255})`},e.noErase=function(){e.ctx.globalCompositeOperation="source-over",e.ctx.restore()},e.inFill=(t,o)=>{const a=e._pixelDensity;return e.ctx.isPointInPath(t*a,o*a)},e.inStroke=(t,o)=>{const a=e._pixelDensity;return e.ctx.isPointInStroke(t*a,o*a)}},Q5.renderers.q2d.image=(e,t)=>{Q5.Image??=class{constructor(e,t,o){let a=this;a._scope="image",a.canvas=a.ctx=a.drawingContext=null,a.pixels=[],Q5.modules.canvas(a,a);let r=Q5.renderers.q2d;for(let e of["canvas","image","soft_filters"])r[e]&&r[e](a,a);a.createCanvas(e,t,o),delete a.createCanvas,a._loop=!1}get w(){return this.width}get h(){return this.height}},e.createImage=(t,o,a)=>(a??={},a.alpha??=!0,a.colorSpace??=e.canvas.colorSpace||Q5.canvasOptions.colorSpace,new Q5.Image(t,o,a)),e.loadImage=function(o,a,r){if(o.canvas)return o;if("gif"==o.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 n=[...arguments].at(-1);r="object"==typeof n?n:null;let s=e.createImage(1,1,r);function i(e){s.resize(e.naturalWidth||e.width,e.naturalHeight||e.height),s.ctx.drawImage(e,0,0),t._preloadCount--,a&&a(s)}if(Q5._nodejs&&global.CairoCanvas)global.CairoCanvas.loadImage(o).then(i).catch((e=>{throw t._preloadCount--,e}));else{let e=new window.Image;e.src=o,e.crossOrigin="Anonymous",e._pixelDensity=1,e.onload=()=>i(e),e.onerror=e=>{throw t._preloadCount--,e}}return s},e.imageMode=t=>e._imageMode=t,e.image=(t,o,a,r,n,s=0,i=0,l,c)=>{let d=t.canvas||t;Q5._createNodeJSCanvas&&(d=d.context.canvas),r??=t.width||t.videoWidth,n??=t.height||t.videoHeight,"center"==e._imageMode&&(o-=.5*r,a-=.5*n),e._da&&(o*=e._da,a*=e._da,r*=e._da,n*=e._da,s*=e._da,i*=e._da,l*=e._da,c*=e._da);let h=t._pixelDensity||1;l?l*=h:l=d.width||d.videoWidth,c?c*=h:c=d.height||d.videoHeight,e.ctx.drawImage(d,s*h,i*h,l,c,o,a,r,n),e._tint&&(e.ctx.globalCompositeOperation="multiply",e.ctx.fillStyle=e._tint.toString(),e.ctx.fillRect(o,a,r,n),e.ctx.globalCompositeOperation="source-over")},e._tint=null;let o=null;e._softFilter=()=>{throw new Error("Load q5-2d-soft-filters.js to use software filters.")},e.filter=(t,o)=>{if(!e.ctx.filter)return e._softFilter(t,o);if("string"==typeof t)f=t;else if(t==Q5.GRAY)f="saturate(0%)";else if(t==Q5.INVERT)f="invert(100%)";else if(t==Q5.BLUR){let t=Math.ceil(o*e._pixelDensity)||1;f=`blur(${t}px)`}else{if(t!=Q5.THRESHOLD)return e._softFilter(t,o);{o??=.5;let e=Math.floor(.5/Math.max(o,1e-5)*100);f=`saturate(0%) brightness(${e}%) contrast(1000000%)`}}e.ctx.filter=f,e.ctx.drawImage(e.canvas,0,0,e.canvas.w,e.canvas.h),e.ctx.filter="none"},"image"==e._scope&&(e.resize=(t,o)=>{let a=new e._OffscreenCanvas(e.canvas.width,e.canvas.height);a.getContext("2d",{colorSpace:e.canvas.colorSpace}).drawImage(e.canvas,0,0),e._setCanvasSize(t,o),e.ctx.clearRect(0,0,e.canvas.width,e.canvas.height),e.ctx.drawImage(a,0,0,e.canvas.width,e.canvas.height)}),e.trim=()=>{let t=e._pixelDensity||1,o=e.canvas.width,a=e.canvas.height,r=e.ctx.getImageData(0,0,o,a).data,n=o,s=0,i=a,l=0,c=3;for(let e=0;e<a;e++)for(let t=0;t<o;t++)0!==r[c]&&(t<n&&(n=t),t>s&&(s=t),e<i&&(i=e),e>l&&(l=e)),c+=4;return i=Math.floor(i/t),l=Math.floor(l/t),n=Math.floor(n/t),s=Math.floor(s/t),e.get(n,i,s-n+1,l-i+1)},e.mask=t=>{e.ctx.save(),e.ctx.resetTransform();let o=e.ctx.globalCompositeOperation;e.ctx.globalCompositeOperation="destination-in",e.ctx.drawImage(t.canvas,0,0),e.ctx.globalCompositeOperation=o,e.ctx.restore()},e.get=(t,o,a,r)=>{let n=e._pixelDensity||1;if(void 0!==t&&void 0===a){let a=e.ctx.getImageData(t*n,o*n,1,1).data;return new e.Color(a[0],a[1],a[2],a[3]/255)}t=(t||0)*n,o=(o||0)*n;let s=a=a||e.width,i=r=r||e.height;a*=n,r*=n;let l=e.createImage(a,r),c=e.ctx.getImageData(t,o,a,r);return l.ctx.putImageData(c,0,0),l._pixelDensity=n,l.width=s,l.height=i,l},e.set=(t,o,a)=>{if(a.canvas){let r=e._tint;return e._tint=null,e.image(a,t,o),void(e._tint=r)}e.pixels.length||e.loadPixels();let r=e._pixelDensity||1;for(let n=0;n<r;n++)for(let s=0;s<r;s++){let i=4*((o*r+n)*e.canvas.width+t*r+s);e.pixels[i]=a.r??a.l,e.pixels[i+1]=a.g??a.c,e.pixels[i+2]=a.b??a.h,e.pixels[i+3]=a.a}},e.loadPixels=()=>{o=e.ctx.getImageData(0,0,e.canvas.width,e.canvas.height),t.pixels=o.data},e.updatePixels=()=>{null!=o&&e.ctx.putImageData(o,0,0)},e.smooth=()=>e.ctx.imageSmoothingEnabled=!0,e.noSmooth=()=>e.ctx.imageSmoothingEnabled=!1,"image"!=e._scope&&(e.tint=function(t){e._tint=t._q5Color?t:e.color(...arguments)},e.noTint=()=>e._tint=null)},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.renderers.q2d.soft_filters=e=>{let t=null;function o(){let o=e.canvas.width*e.canvas.height*4;t&&t.length==o||(t=new Uint8ClampedArray(o))}e._softFilter=(a,r)=>{e._filters||(e._filters=[],e._filters[Q5.THRESHOLD]=(e,t)=>{void 0===t?t=127.5:t*=255;for(let o=0;o<e.length;o+=4){const a=.2126*e[o]+.7152*e[o+1]+.0722*e[o+2];e[o]=e[o+1]=e[o+2]=a>=t?255:0}},e._filters[Q5.GRAY]=e=>{for(let t=0;t<e.length;t+=4){const o=.2126*e[t]+.7152*e[t+1]+.0722*e[t+2];e[t]=e[t+1]=e[t+2]=o}},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 o=t-1;for(let a=0;a<e.length;a+=4)e[a]=255*(e[a]*t>>8)/o,e[a+1]=255*(e[a+1]*t>>8)/o,e[a+2]=255*(e[a+2]*t>>8)/o},e._filters[Q5.DILATE]=a=>{o(),t.set(a);let[r,n]=[e.canvas.width,e.canvas.height];for(let e=0;e<n;e++)for(let o=0;o<r;o++){let s=4*Math.max(o-1,0),i=4*Math.min(o+1,r-1),l=4*Math.max(e-1,0)*r,c=4*Math.min(e+1,n-1)*r,d=4*e*r,h=4*o;for(let e=0;e<4;e++){let o=e+l,r=e+c,n=e+d;a[d+h+e]=Math.max(t[o+h],t[n+s],t[n+h],t[n+i],t[r+h])}}},e._filters[Q5.ERODE]=a=>{o(),t.set(a);let[r,n]=[e.canvas.width,e.canvas.height];for(let e=0;e<n;e++)for(let o=0;o<r;o++){let s=4*Math.max(o-1,0),i=4*Math.min(o+1,r-1),l=4*Math.max(e-1,0)*r,c=4*Math.min(e+1,n-1)*r,d=4*e*r,h=4*o;for(let e=0;e<4;e++){let o=e+l,r=e+c,n=e+d;a[d+h+e]=Math.min(t[o+h],t[n+s],t[n+h],t[n+i],t[r+h])}}},e._filters[Q5.BLUR]=(a,r)=>{r=r||1,r=Math.floor(r*e._pixelDensity),o(),t.set(a);let n=2*r+1,s=function(e){let t=new Float32Array(e),o=.3*r+.8,a=o*o*2;for(let r=0;r<e;r++){let n=r-e/2,s=Math.exp(-n*n/a)/(2.5066282746*o);t[r]=s}return t}(n),[i,l]=[e.canvas.width,e.canvas.height];for(let e=0;e<l;e++)for(let o=0;o<i;o++){let l=0,c=0,d=0,h=0;for(let a=0;a<n;a++){let n=4*(e*i+Math.min(Math.max(o-r+a,0),i-1));l+=t[n]*s[a],c+=t[n+1]*s[a],d+=t[n+2]*s[a],h+=t[n+3]*s[a]}let u=4*(e*i+o);a[u]=l,a[u+1]=c,a[u+2]=d,a[u+3]=h}t.set(a);for(let e=0;e<l;e++)for(let o=0;o<i;o++){let c=0,d=0,h=0,u=0;for(let a=0;a<n;a++){let n=4*(Math.min(Math.max(e-r+a,0),l-1)*i+o);c+=t[n]*s[a],d+=t[n+1]*s[a],h+=t[n+2]*s[a],u+=t[n+3]*s[a]}let _=4*(e*i+o);a[_]=c,a[_+1]=d,a[_+2]=h,a[_+3]=u}});let n=e.ctx.getImageData(0,0,e.canvas.width,e.canvas.height);e._filters[a](n.data,r),e.ctx.putImageData(n,0,0)}},Q5.renderers.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,o)=>{t._preloadCount++;let a=e.split("/").pop().split(".")[0].replace(" ",""),r=new FontFace(a,`url(${e})`);return document.fonts.add(r),r.load().then((()=>{t._preloadCount--,o&&o(a)})),a},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,o)=>{e.ctx.textAlign=t,o&&(e.ctx.textBaseline=o==e.CENTER?"middle":o)},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,o=0;for(const[a,r]of this.entries())r.lastAccessed<t&&(t=r.lastAccessed,e=o),o++;o=e;for(const t of this.keys()){if(0==o){e=t;break}o--}this.delete(e)}},e._tic=new e._TimedCache,e.textCache=(t,o)=>(o&&(e._tic.maxSize=o),void 0!==t&&(e._textCache=t),e._textCache),e._genTextImageKey=(t,o,a)=>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+"_":"")+(o||"")+(a?"x"+a:""),e.createTextImage=(t,o,a)=>{let r=e._textCache;e._textCache=!0,e._genTextImage=!0,e.text(t,0,0,o,a),e._genTextImage=!1;let n=e._genTextImageKey(t,o,a);return e._textCache=r,e._tic.get(n)},e.text=(t,o,a,r,n)=>{if(void 0===t)return;if(t=t.toString(),e._da&&(o*=e._da,a*=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,r,n),i=e._tic.get(c),i&&!e._genTextImage)return void e.textImage(i,o,a);l=e.createGraphics.call(e,1,1),s=l.ctx}else s=e.ctx,d=o,h=a;s.font=`${e._textStyle} ${e._textSize}px ${e._textFont}`;let x=t.split("\n");if(g){d=0,h=e._textLeading*x.length;let o=s.measureText(" ");u=o.fontBoundingBoxAscent,_=o.fontBoundingBoxDescent,n??=h+_,l.resizeCanvas(Math.ceil(s.measureText(t).width),Math.ceil(n)),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>n));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,o,a))},e.textImage=(t,o,a)=>{let r=e._imageMode;e._imageMode="corner","center"==e.ctx.textAlign?o-=.5*t.width:"right"==e.ctx.textAlign&&(o-=t.width),"alphabetic"==e.ctx.textBaseline&&(a-=e._textLeading),"middle"==e.ctx.textBaseline?a-=t._descent+.5*t._ascent+e._textLeadDiff:"bottom"==e.ctx.textBaseline?a-=t._ascent+t._descent+e._textLeadDiff:"top"==e.ctx.textBaseline&&(a-=t._descent+e._textLeadDiff),e.image(t,o,a),e._imageMode=r},e.nf=(e,t,o)=>{let a=e<0,r=(e=Math.abs(e)).toFixed(o).split(".");r[0]=r[0].padStart(t,"0");let n=r.join(".");return a&&(n="-"+n),n}},Q5.modules.ai=e=>{e.askAI=(e="")=>{throw Error("Ask AI ✨ "+e)},e._aiErrorAssistance=async t=>{let o=t.message?.includes("Ask AI ✨");if(o||console.error(t),Q5.disableFriendlyErrors)return;!o&&Q5.errorTolerant||e.noLoop();let a=t.stack?.split("\n");if(!t.stack||a.length<=1)return;let r=1,n="(";for(-1==navigator.userAgent.indexOf("Chrome")&&(r=0,n="@");a[r].indexOf("q5.js:")>=0;)r++;let s=a[r].split(n).at(-1);s=s.split(":");let i=parseInt(s.at(-2));o&&i++;let l=s.slice(0,-2).join(":"),c=l.split("/").at(-1);try{let e=(await(await fetch(l)).text()).split("\n"),a=e[i-1].trim(),r="",n=1;for(;r.length<1600&&(i-n>=0&&(r=e[i-n].trim()+"\n"+r),i+n<e.length);)r+=e[i+n].trim()+"\n",n++;let s="https://chatgpt.com/?q=q5.js+"+(o&&t.message.length>10?t.message.slice(10):"Whats+wrong+with+this+line%3F+short+answer")+(o?"":"%0A%0A"+encodeURIComponent(t.name+": "+t.message))+"%0A%0ALine%3A+"+encodeURIComponent(a)+"%0A%0AExcerpt+for+context%3A%0A%0A"+encodeURIComponent(r);o||console.log("Error in "+c+" on line "+i+":\n\n"+a),console.warn("Ask AI ✨ "+s),o&&window.open(s,"_blank")}catch(e){}}},Q5.modules.color=(e,t)=>{e.RGB=e.RGBA=e._colorMode="rgb",e.OKLCH="oklch",e.colorMode=(o,a)=>{e._colorMode=o;let r="srgb"==e.canvas.colorSpace||"srgb"==o;if(a??=r?"integer":"float",e._colorFormat="float"==a||1==a?1:255,"oklch"==o)t.Color=Q5.ColorOKLCH;else{let o="srgb"==e.canvas.colorSpace;255==e._colorFormat?t.Color=o?Q5.ColorRGBA_8:Q5.ColorRGBA_P3_8:t.Color=o?Q5.ColorRGBA:Q5.ColorRGBA_P3,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=(t,o,a,r)=>{let n=e.Color;if(t._q5Color)return new n(...t.levels);if(null==o){if("string"==typeof t)if("#"==t[0])t.length<=5?(t.length>4&&(r=parseInt(t[4]+t[4],16)),a=parseInt(t[3]+t[3],16),o=parseInt(t[2]+t[2],16),t=parseInt(t[1]+t[1],16)):(t.length>7&&(r=parseInt(t.slice(7,9),16)),a=parseInt(t.slice(5,7),16),o=parseInt(t.slice(3,5),16),t=parseInt(t.slice(1,3),16));else{if(!e._namedColors[t])return console.error("q5 can't parse color: "+t+"\nOnly numeric input, hex, and common named colors are supported."),new n(0,0,0);t=e._namedColors[t]}Array.isArray(t)&&(o=t[1],a=t[2],r=t[3],t=t[0])}return 1==e._colorFormat&&(t/=255,o&&(o/=255),a&&(a/=255),r&&(r/=255)),null==a?new n(t,t,t,o):new n(t,o,a,r)},e.red=e=>e.r,e.green=e=>e.g,e.blue=e=>e.b,e.alpha=e=>e.a,e.lightness=t=>"oklch"==e._colorMode?t.l:100*(.2126*t.r+.7152*t.g+.0722*t.b)/255,e.hue=t=>{if("oklch"==e._colorMode)return t.h;let o=t.r,a=t.g,r=t.b;255==e._colorFormat&&(o/=255,a/=255,r/=255);let n,s=Math.max(o,a,r),i=Math.min(o,a,r);return n=s==i?0:s==o?60*(a-r)/(s-i):s==a?60*(r-o)/(s-i)+120:60*(o-a)/(s-i)+240,n<0&&(n+=360),n},e.lerpColor=(t,o,a)=>{if("rgb"==e._colorMode)return new e.Color(e.constrain(e.lerp(t.r,o.r,a),0,255),e.constrain(e.lerp(t.g,o.g,a),0,255),e.constrain(e.lerp(t.b,o.b,a),0,255),e.constrain(e.lerp(t.a,o.a,a),0,255));{let r=o.h-t.h;r>180&&(r-=360),r<-180&&(r+=360);let n=t.h+a*r;return n<0&&(n+=360),n>360&&(n-=360),new e.Color(e.constrain(e.lerp(t.l,o.l,a),0,100),e.constrain(e.lerp(t.c,o.c,a),0,100),n,e.constrain(e.lerp(t.a,o.a,a),0,255))}}},Q5.Color=class{constructor(){this._q5Color=!0}},Q5.ColorOKLCH=class extends Q5.Color{constructor(e,t,o,a){super(),this.l=e,this.c=t,this.h=o,this.a=a??1}toString(){return`oklch(${this.l} ${this.c} ${this.h} / ${this.a})`}},Q5.ColorRGBA=class extends Q5.Color{constructor(e,t,o,a){super(),this.r=e,this.g=t,this.b=o,this.a=a??1}get levels(){return[this.r,this.g,this.b,this.a]}toString(){return`color(srgb ${this.r} ${this.g} ${this.b} / ${this.a})`}},Q5.ColorRGBA_P3=class extends Q5.ColorRGBA{toString(){return`color(display-p3 ${this.r} ${this.g} ${this.b} / ${this.a})`}},Q5.ColorRGBA_8=class extends Q5.ColorRGBA{constructor(e,t,o,a){super(e,t,o,a??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_8=class extends Q5.ColorRGBA{constructor(e,t,o,a){super(e,t,o,a??255),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),o=(this._b/255).toFixed(3),a=(this._a/255).toFixed(3);this._css=`color(display-p3 ${e} ${t} ${o} / ${a})`,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 o=t.style,a=t.parentElement;o&&a&&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?(a.classList.remove("q5-centered","q5-maxed","q5-fullscreen"),o.width=t.w*t.displayScale+"px",o.height=t.h*t.displayScale+"px"):(a.classList.add("q5-"+t.displayMode),a=a.getBoundingClientRect(),t.w/t.h>a.width/a.height?("centered"==t.displayMode?(o.width=t.w*t.displayScale+"px",o.maxWidth="100%"):o.width="100%",o.height="auto",o.maxHeight=""):(o.width="auto",o.maxWidth="","centered"==t.displayMode?(o.height=t.h*t.displayScale+"px",o.maxHeight="100%"):o.height="100%")))},e.displayMode=(o="normal",a="default",r=1)=>{"string"==typeof r&&(r=parseFloat(r.slice(1))),Object.assign(t,{displayMode:o,renderQuality:a,displayScale:r}),e._adjustDisplay()},e.fullscreen=e=>{if(void 0===e)return document.fullscreenElement;e?document.body.requestFullscreen():document.body.exitFullscreen()}},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 o={},a=[e.LEFT,e.CENTER,e.RIGHT],r=e.canvas;function n(t){const o=e.canvas.getBoundingClientRect(),a=e.canvas.scrollWidth/e.width||1,r=e.canvas.scrollHeight/e.height||1;return{x:(t.clientX-o.left)/a,y:(t.clientY-o.top)/r,id:t.identifier}}if(e._startAudio=()=>{e.getAudioContext&&"suspended"==e.getAudioContext()?.state&&e.userStartAudio()},e._updateMouse=o=>{if(!o.changedTouches)if(r){let a=r.getBoundingClientRect(),n=r.scrollWidth/e.width||1,s=r.scrollHeight/e.height||1;t.mouseX=(o.clientX-a.left)/n,t.mouseY=(o.clientY-a.top)/s,"webgpu"==r.renderer&&(t.mouseX-=r.hw,t.mouseY-=r.hh)}else t.mouseX=o.clientX,t.mouseY=o.clientY},e._onmousedown=o=>{e._startAudio(),e._updateMouse(o),t.mouseIsPressed=!0,t.mouseButton=a[o.button],e.mousePressed(o)},e._onmousemove=t=>{e._updateMouse(t),e.mouseIsPressed?e.mouseDragged(t):e.mouseMoved(t)},e._onmouseup=o=>{e._updateMouse(o),t.mouseIsPressed=!1,e.mouseReleased(o)},e._onclick=o=>{e._updateMouse(o),t.mouseIsPressed=!0,e.mouseClicked(o),t.mouseIsPressed=!1},e.cursor=(t,o,a)=>{let r="";t.includes(".")&&(t=`url("${t}")`,r=", auto"),void 0!==o&&(t+=" "+o+" "+a),e.canvas.style.cursor=t+r},e.noCursor=()=>{e.canvas.style.cursor="none"},e.requestPointerLock=document.body?.requestPointerLock,e.exitPointerLock=document.exitPointerLock,e._onkeydown=a=>{a.repeat||(e._startAudio(),t.keyIsPressed=!0,t.key=a.key,t.keyCode=a.keyCode,o[e.keyCode]=o[e.key.toLowerCase()]=!0,e.keyPressed(a),1==a.key.length&&e.keyTyped(a))},e._onkeyup=a=>{t.keyIsPressed=!1,t.key=a.key,t.keyCode=a.keyCode,o[e.keyCode]=o[e.key.toLowerCase()]=!1,e.keyReleased(a)},e.keyIsDown=e=>!!o["string"==typeof e?e.toLowerCase():e],e._ontouchstart=o=>{e._startAudio(),t.touches=[...o.touches].map(n),e._isTouchAware||(t.mouseX=e.touches[0].x,t.mouseY=e.touches[0].y,t.mouseIsPressed=!0,t.mouseButton=e.LEFT,e.mousePressed(o)||o.preventDefault()),e.touchStarted(o)||o.preventDefault()},e._ontouchmove=o=>{t.touches=[...o.touches].map(n),e._isTouchAware||(t.mouseX=e.touches[0].x,t.mouseY=e.touches[0].y,e.mouseDragged(o)||o.preventDefault()),e.touchMoved(o)||o.preventDefault()},e._ontouchend=o=>{t.touches=[...o.touches].map(n),e._isTouchAware||e.touches.length||(t.mouseIsPressed=!1,e.mouseReleased(o)||o.preventDefault()),e.touchEnded(o)||o.preventDefault()},r&&(r.addEventListener("mousedown",(t=>e._onmousedown(t))),r.addEventListener("mouseup",(t=>e._onmouseup(t))),r.addEventListener("click",(t=>e._onclick(t))),r.addEventListener("touchstart",(t=>e._ontouchstart(t))),r.addEventListener("touchmove",(t=>e._ontouchmove(t))),r.addEventListener("touchcancel",(t=>e._ontouchend(t))),r.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)=>{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=Q5.prototype.map=(e,t,o,a,r,n)=>{let s=a+1*(e-t)/(o-t)*(r-a);return n?a<r?Math.min(Math.max(s,a),r):Math.min(Math.max(s,r),a):s},e.lerp=(e,t,o)=>e*(1-o)+t*o,e.constrain=(e,t,o)=>Math.min(Math.max(e,t),o),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,o,a)=>e.map(t,o,a,0,1),e.sq=e=>e*e,e.fract=e=>e-Math.floor(e);for(let t of["sin","cos","tan"])e[t]=o=>("degrees"==e._angleMode&&(o=e.radians(o)),Math[t](o));for(let t of["asin","acos","atan"])e[t]=o=>{let a=Math[t](o);return"degrees"==e._angleMode&&(a=e.degrees(a)),a};function o(){let e,t,o=4294967295;return{setSeed(a){e=t=(a??Math.random()*o)>>>0},getSeed:()=>t,rand:()=>(e^=e<<17,e^=e>>13,e^=e<<5,(e>>>0)/o)}}e.atan2=(t,o)=>{let a=Math.atan2(t,o);return"degrees"==e._angleMode&&(a=e.degrees(a)),a};let a=o();a.setSeed(),e.randomSeed=e=>a.setSeed(e),e.random=(e,t)=>void 0===e?a.rand():"number"==typeof e?void 0!==t?a.rand()*(t-e)+e:a.rand()*e:e[Math.trunc(e.length*a.rand())],e.randomGenerator=t=>{t==e.LCG?a=function(){const e=4294967296;let t,o;return{setSeed(a){o=t=(a??Math.random()*e)>>>0},getSeed:()=>t,rand:()=>(o=(1664525*o+1013904223)%e,o/e)}}():t==e.SHR3&&(a=o()),a.setSeed()};var r=new function(){var e,t,o,r=new Array(128),n=new Array(256),s=new Array(128),i=new Array(128),l=new Array(256),c=new Array(256),d=()=>4294967296*a.rand()-2147483648,h=()=>.5+2.328306e-10*(d()|0),u=()=>{for(var t,a,n,l,c=3.44262;;){if(t=o*s[e],0==e){do{n=h(),l=h(),t=.2904764*-Math.log(n),a=-Math.log(l)}while(a+a<t*t);return o>0?c+t:-c-t}if(i[e]+h()*(i[e-1]-i[e])<Math.exp(-.5*t*t))return t;if(o=d(),e=127&o,Math.abs(o)<r[e])return o*s[e]}},_=()=>{for(var o;;){if(0==e)return 7.69711-Math.log(h());if(o=t*l[e],c[e]+h()*(c[e-1]-c[e])<Math.exp(-o))return o;if((t=d())<n[e=255&t])return t*l[e]}};this.SHR3=d,this.UNI=h,this.RNOR=()=>(o=d(),e=127&o,Math.abs(o)<r[e]?o*s[e]:u()),this.REXP=()=>(t=d()>>>0)<r[e=255&t]?t*l[e]:_(),this.zigset=()=>{var e,t,o=2147483648,a=4294967296,d=3.442619855899,h=d,u=.00991256303526217,_=7.697117470131487,p=_,g=.003949659822581572;for(e=u/Math.exp(-.5*d*d),r[0]=Math.floor(d/e*o),r[1]=0,s[0]=e/o,s[127]=d/o,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))),r[t+1]=Math.floor(d/h*o),h=d,i[t]=Math.exp(-.5*d*d),s[t]=d/o;for(e=g/Math.exp(-_),n[0]=Math.floor(_/e*a),n[1]=0,l[0]=e/a,l[255]=_/a,c[0]=1,c[255]=Math.exp(-_),t=254;t>=1;t--)_=-Math.log(g/_+Math.exp(-_)),n[t+1]=Math.floor(_/p*a),p=_,c[t]=Math.exp(-_),l[t]=_/a}};let n;r.hasInit=!1,e.randomGaussian=(e,t)=>(r.hasInit||(r.zigset(),r.hasInit=!0),r.RNOR()*t+e),e.randomExponential=()=>(r.hasInit||(r.zigset(),r.hasInit=!0),r.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"],n=null},e.noiseSeed=t=>{n=new e.Noise(t)},e.noise=(t=0,o=0,a=0)=>(n??=new e.Noise,n.noise(t,o,a)),e.noiseDetail=(t,o)=>{n??=new e.Noise,t>0&&(n.octaves=t),o>0&&(n.falloff=o)}},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,o,a=[];for(let e=0;e<256;e++)a[e]=e;for(let r=255;r>0;r--)t=(e=16807*e%2147483647)%(r+1),o=a[r],a[r]=a[t],a[t]=o;return a}dot(e,t,o,a){return e[0]*t+e[1]*o+e[2]*a}mix(e,t,o){return(1-o)*e+o*t}fade(e){return e*e*e*(e*(6*e-15)+10)}noise(e,t,o){let a=this,r=0,n=1,s=1,i=0;for(let l=0;l<a.octaves;l++){const l=255&Math.floor(e*n),c=255&Math.floor(t*n),d=255&Math.floor(o*n),h=e*n-Math.floor(e*n),u=t*n-Math.floor(t*n),_=o*n-Math.floor(o*n),p=a.fade(h),g=a.fade(u),x=a.fade(_),m=a.p[l]+c,f=a.p[m]+d,y=a.p[m+1]+d,v=a.p[l+1]+c,w=a.p[v]+d,C=a.p[v+1]+d,M=a.mix(a.dot(a.grad3[a.p[f]%12],h,u,_),a.dot(a.grad3[a.p[w]%12],h-1,u,_),p),S=a.mix(a.dot(a.grad3[a.p[y]%12],h,u-1,_),a.dot(a.grad3[a.p[C]%12],h-1,u-1,_),p),b=a.mix(a.dot(a.grad3[a.p[f+1]%12],h,u,_-1),a.dot(a.grad3[a.p[w+1]%12],h-1,u,_-1),p),R=a.mix(a.dot(a.grad3[a.p[y+1]%12],h,u-1,_-1),a.dot(a.grad3[a.p[C+1]%12],h-1,u-1,_-1),p),Q=a.mix(M,S,g),E=a.mix(b,R,g);r+=a.mix(Q,E,x)*s,i+=s,s*=a.falloff,n*=2}return(r/i+1)/2}},Q5.modules.sound=(e,t)=>{e.Sound=Q5.Sound,e.loadSound=(e,o)=>{t._preloadCount++,Q5.aud??=new window.AudioContext;let a=new Q5.Sound(e,o);return a.addEventListener("canplaythrough",(()=>{t._preloadCount--,a.loaded=!0,o&&o(a)})),a},e.getAudioContext=()=>Q5.aud,e.userStartAudio=()=>Q5.aud.resume()},Q5.Sound=class extends Audio{constructor(e){super(e);let t=this;t.load(),t.panner=Q5.aud.createStereoPanner(),t.source=Q5.aud.createMediaElementSource(t),t.source.connect(t.panner),t.panner.connect(Q5.aud.destination),Object.defineProperty(t,"pan",{get:()=>t.panner.pan.value,set:e=>t.panner.pan.value=e})}setVolume(e){this.volume=e}setLoop(e){this.loop=e}setPan(e){this.pan=e}isLoaded(){return this.loaded}isPlaying(){return!this.paused}},Q5.modules.util=(e,t)=>{e._loadFile=(e,o,a)=>{t._preloadCount++;let r={};return fetch(e).then((e=>"json"==a?e.json():"text"==a?e.text():void 0)).then((e=>{t._preloadCount--,Object.assign(r,e),o&&o(e)})),r},e.loadStrings=(t,o)=>e._loadFile(t,o,"text"),e.loadJSON=(t,o)=>e._loadFile(t,o,"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,o,a)=>new Q5.Vector(t,o,a,e)},Q5.Vector=class{constructor(e,t,o,a){this.x=e||0,this.y=t||0,this.z=o||0,this._$=a||window,this._cn=null,this._cnsq=null}set(e,t,o){this.x=e||0,this.y=t||0,this.z=o||0}copy(){return new Q5.Vector(this.x,this.y,this.z)}_arg2v(e,t,o){return void 0!==e?.x?e:void 0!==t?{x:e,y:t,z:o||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,o=this.y-e.y,a=this.z-e.z;return Math.sqrt(t*t+o*o+a*a)}cross(){let e=this._arg2v(...arguments),t=this.y*e.z-this.z*e.y,o=this.z*e.x-this.x*e.z,a=this.x*e.y-this.y*e.x;return this.x=t,this.y=o,this.z=a,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 o=e/t;this.x*=o,this.y*=o,this.z*=o,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),o=this._$.sin(e),a=this.x*t-this.y*o,r=this.x*o+this.y*t;return this.x=a,this.y=r,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)),o=e.at(-1);return this.x+=(t.x-this.x)*o,this.y+=(t.y-this.y)*o,this.z+=(t.z-this.z)*o,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,o){void 0===o&&(o=1),this._cn=o,this._cnsq=o*o;const a=this._$.cos(t),r=this._$.sin(t),n=this._$.cos(e),s=this._$.sin(e);return this.x=o*s*r,this.y=-o*n,this.z=o*s*a,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,o)=>e.equals(t,o),Q5.Vector.lerp=(e,t,o)=>e.copy().lerp(t,o),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,o,a)=>(new Q5.Vector)[e](t,o,a);
8
+ function Q5(e,t,o){let a,r=this;if(r._q5=!0,r._parent=t,r._renderer=o||"q2d",r._preloadCount=0,e??="global","auto"==e){if(!window.setup&&!window.draw)return;e="global"}r._scope=e,"global"==e&&(Q5._hasGlobal=r._isGlobal=!0,a=Q5._nodejs?global:window);let n=new Proxy(r,{set:(e,t,o)=>(r[t]=o,r._isGlobal&&(a[t]=o),!0)});r.canvas=r.ctx=r.drawingContext=null,r.pixels=[];let s=null;r.frameCount=0,r.deltaTime=16,r._targetFrameRate=0,r._targetFrameDuration=16.666666666666668,r._frameRate=r._fps=60,r._loop=!0,r._hooks={postCanvas:[],preRender:[]};let i=0;r.millis=()=>performance.now()-i,r.noCanvas=()=>{r.canvas?.remove&&r.canvas.remove(),r.canvas=0,n.ctx=n.drawingContext=0},window&&(r.windowWidth=window.innerWidth,r.windowHeight=window.innerHeight,r.deviceOrientation=window.screen?.orientation?.type),r._incrementPreload=()=>n._preloadCount++,r._decrementPreload=()=>n._preloadCount--,r._draw=e=>{let t=e||performance.now();if(r._lastFrameTime??=t-r._targetFrameDuration,r._shouldResize&&(r.windowResized(),r._shouldResize=!1),r._loop)s=c(r._draw);else if(r.frameCount&&!r._redraw)return;if(s&&r.frameCount){if(t-r._lastFrameTime<r._targetFrameDuration-4)return}n.deltaTime=t-r._lastFrameTime,r._frameRate=1e3/r.deltaTime,n.frameCount++;let o=performance.now();r.ctx&&r.resetMatrix(),r._beginRender&&r._beginRender();for(let e of Q5.methods.pre)e.call(r);r.draw(),r._render&&r._render();for(let e of Q5.methods.post)e.call(r);r._finishRender&&r._finishRender(),n.pmouseX=r.mouseX,n.pmouseY=r.mouseY,r._lastFrameTime=t;let a=performance.now();r._fps=Math.round(1e3/(a-o))},r.noLoop=()=>{r._loop=!1,s=null},r.loop=()=>{r._loop=!0,null==s&&r._draw()},r.isLooping=()=>r._loop,r.redraw=(e=1)=>{r._redraw=!0;for(let t=0;t<e;t++)r._draw();r._redraw=!1},r.remove=()=>{r.noLoop(),r.canvas.remove()},r.frameRate=e=>(e&&(r._targetFrameRate=e,r._targetFrameDuration=1e3/e),r._frameRate),r.getTargetFrameRate=()=>r._targetFrameRate,r.getFPS=()=>r._fps,r.Element=function(e){this.elt=e},r._elements=[],r.TWO_PI=r.TAU=2*Math.PI,r.log=r.print=console.log,r.describe=()=>{};for(let e in Q5.modules)Q5.modules[e](r,n);let l=Q5.renderers[r._renderer];for(let e in l)l[e](r,n);for(let e in Q5)"_"!=e[1]&&e[1]==e[1].toUpperCase()&&(r[e]=Q5[e]);if("graphics"==e)return;"global"==e&&(Object.assign(Q5,r),delete Q5.Q5);for(let e of Q5.methods.init)e.call(r);for(let[e,t]of Object.entries(Q5.prototype))"_"!=e[0]&&"function"==typeof r[e]&&(r[e]=t.bind(r));if("global"==e){let e=Object.getOwnPropertyNames(r);for(let t of e)"_"!=t[0]&&(a[t]=r[t])}"function"==typeof e&&e(r),Q5._instanceCount++;let c=window.requestAnimationFrame||function(e){const t=r._lastFrameTime+r._targetFrameDuration;return setTimeout((()=>{e(t)}),t-performance.now())},d=a||r;r._isTouchAware=d.touchStarted||d.touchMoved||d.mouseReleased;let h=d.preload,u=["setup","draw","preload","mouseMoved","mousePressed","mouseReleased","mouseDragged","mouseClicked","keyPressed","keyReleased","keyTyped","touchStarted","touchMoved","touchEnded","windowResized"];for(let e of u)d[e]?r._isGlobal&&(r[e]=()=>{try{return d[e]()}catch(e){r._aiErrorAssistance?r._aiErrorAssistance(e):console.error(e)}}):r[e]=()=>{};async function _(){if(r._startDone=!0,r._preloadCount>0)return c(_);i=performance.now(),await r.setup(),r.frameCount||(null===r.ctx&&r.createCanvas(100,100),r._setupDone=!0,r.ctx&&r.resetMatrix(),c(r._draw))}(r.setup||r.draw)&&(arguments.length&&"namespace"!=e&&"webgpu"!=o||h?(r.preload(),_()):(d.preload=r.preload=()=>{r._startDone||_()},setTimeout(r.preload,32)))}Q5.renderers={},Q5.modules={},Q5._nodejs="object"==typeof process,Q5._instanceCount=0,Q5._friendlyError=(e,t)=>{throw Error(t+": "+e)},Q5._validateParameters=()=>!0,Q5.methods={init:[],pre:[],post:[],remove:[]},Q5.prototype.registerMethod=(e,t)=>Q5.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.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 o=e.canvas;if(o.width=e.width=100,o.height=e.height=100,"image"!=e._scope&&(o.renderer=e._renderer,o[e._renderer]=!0),e._pixelDensity=1,e._adjustDisplay=()=>{o.style&&(o.style.width=o.w+"px",o.style.height=o.h+"px")},e.createCanvas=function(t,a,r){r??=arguments[3];let n=Object.assign({},Q5.canvasOptions);if("object"==typeof r&&Object.assign(n,r),"image"!=e._scope){let t=e.displayDensity();"graphics"==e._scope?t=this._pixelDensity:window.IntersectionObserver&&new IntersectionObserver((e=>{o.visible=e[0].isIntersecting})).observe(o),e._pixelDensity=Math.ceil(t)}e._setCanvasSize(t,a),Object.assign(o,n);let s=e._createCanvas(o.w,o.h,n);if(e._hooks)for(let t of e._hooks.postCanvas)t();return s},e._save=async(e,t,o)=>{if(t=t||"untitled","jpg"==(o=o||"png")||"png"==o||"webp"==o)if(e instanceof OffscreenCanvas){const t=await e.convertToBlob({type:"image/"+o});e=await new Promise((e=>{const o=new FileReader;o.onloadend=()=>e(o.result),o.readAsDataURL(t)}))}else e=e.toDataURL("image/"+o);else{let t="text/plain";"json"==o&&("string"!=typeof e&&(e=JSON.stringify(e)),t="text/json"),e=new Blob([e],{type:t}),e=URL.createObjectURL(e)}let a=document.createElement("a");a.href=e,a.download=t+"."+o,a.click(),URL.revokeObjectURL(a.href)},e.save=(t,o,a)=>{if((!t||"string"==typeof t&&(!o||!a&&o.length<5))&&(a=o,o=t,t=e.canvas),a)return e._save(t,o,a);o?(o=o.split("."),e._save(t,o[0],o.at(-1))):e._save(t)},e._setCanvasSize=(a,r)=>{a??=window.innerWidth,r??=window.innerHeight,o.w=a=Math.ceil(a),o.h=r=Math.ceil(r),o.hw=a/2,o.hh=r/2,o.width=Math.ceil(a*e._pixelDensity),o.height=Math.ceil(r*e._pixelDensity),e._da?e.flexibleCanvas(e._dau):(t.width=a,t.height=r),e.displayMode&&!o.displayMode?e.displayMode():e._adjustDisplay()},"image"!=e._scope){if(o&&"graphics"!=e._scope){function a(){let t=e._parent;t??=document.getElementsByTagName("main")[0],t||(t=document.createElement("main"),document.body.append(t)),o.parent(t)}o.parent=t=>{function a(){e.frameCount>1&&(e._shouldResize=!0,e._adjustDisplay())}o.parentElement&&o.parentElement.removeChild(o),"string"==typeof t&&(t=document.getElementById(t)),t.append(o),"function"==typeof ResizeObserver?(e._ro&&e._ro.disconnect(),e._ro=new ResizeObserver(a),e._ro.observe(t)):e.frameCount||window.addEventListener("resize",a)},document.body?a():document.addEventListener("DOMContentLoaded",a)}e.resizeCanvas=(t,a)=>{if(!e.ctx)return e.createCanvas(t,a);t==o.w&&a==o.h||e._resizeCanvas(t,a)},e.canvas.resize=e.resizeCanvas,e.canvas.save=e.saveCanvas=e.save,e.displayDensity=()=>window.devicePixelRatio,e.pixelDensity=t=>t&&t!=e._pixelDensity?(e._pixelDensity=t,e._setCanvasSize(o.w,o.h),t):e._pixelDensity,e.flexibleCanvas=(a=400)=>{a?(e._da=o.width/(a*e._pixelDensity),t.width=e._dau=a,t.height=o.h/o.w*a):e._da=0}}},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.renderers.q2d={},Q5.renderers.q2d.canvas=(e,t)=>{let o=e.canvas;e.colorMode&&e.colorMode("rgb","integer"),e._createCanvas=function(a,r,n){return t.ctx=t.drawingContext=o.getContext("2d",n),"image"!=e._scope&&(e.ctx.fillStyle="white",e.ctx.strokeStyle="black",e.ctx.lineCap="round",e.ctx.lineJoin="miter",e.ctx.textAlign="left"),e.ctx.scale(e._pixelDensity,e._pixelDensity),e.ctx.save(),o},"image"!=e._scope&&(e._resizeCanvas=(t,a)=>{let r={};for(let t in e.ctx)"function"!=typeof e.ctx[t]&&(r[t]=e.ctx[t]);delete r.canvas;let n=new e._OffscreenCanvas(o.width,o.height);n.w=o.w,n.h=o.h,n.getContext("2d").drawImage(o,0,0),e._setCanvasSize(t,a);for(let t in r)e.ctx[t]=r[t];e.scale(e._pixelDensity),e.ctx.drawImage(n,0,0,n.w,n.h)},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.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.strokeWeight=t=>{t||(e._doStroke=!1),e._da&&(t*=e._da),e.ctx.lineWidth=t||1e-4},e.noStroke=()=>e._doStroke=!1,e.clear=()=>{e.ctx.save(),e.ctx.resetTransform(),e.ctx.clearRect(0,0,e.canvas.width,e.canvas.height),e.ctx.restore()},e.translate=(t,o)=>{e._da&&(t*=e._da,o*=e._da),e.ctx.translate(t,o)},e.rotate=t=>{"degrees"==e._angleMode&&(t=e.radians(t)),e.ctx.rotate(t)},e.scale=(t,o)=>{o??=t,e.ctx.scale(t,o)},e.opacity=t=>e.ctx.globalAlpha=t,e.applyMatrix=(t,o,a,r,n,s)=>e.ctx.transform(t,o,a,r,n,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.scale(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 o of e._styleNames)t[o]=e[o];e._styles.push(t)},e.pop=e.popMatrix=()=>{e.ctx.restore();let t=e._styles.pop();for(let o of e._styleNames)e[o]=t[o]},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,o,a){let r=new Q5("graphics");return a??={},a.alpha??=!0,a.colorSpace??=e.canvas.colorSpace,r.createCanvas.call(e,t,o,a),r},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.renderers.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,o=[];function a(){e._doFill&&e.ctx.fill(),e._doStroke&&e.ctx.stroke()}function r(t,o,r,n,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(),r==n)d&&(s=e.radians(s),i=e.radians(i)),e.ctx.arc(t,o,r/2,s,i);else{for(let a=0;a<c+1;a++){let l=a/c,d=e.lerp(s,i,l),h=e.cos(d)*r/2,u=e.sin(d)*n/2;e.ctx[a?"lineTo":"moveTo"](t+h,o+u)}l==e.CHORD?e.ctx.closePath():l==e.PIE&&(e.ctx.lineTo(t,o),e.ctx.closePath())}a()}}function n(t,o,r,n){(e._doFill||e._doStroke)&&(e._da&&(t*=e._da,o*=e._da,r*=e._da,n*=e._da),e.ctx.beginPath(),e.ctx.ellipse(t,o,r/2,n/2,0,0,e.TAU),a())}function s(t,o,r,n,i,l,c,d){if(e._doFill||e._doStroke){if(void 0===i)return function(t,o,r,n){e._da&&(t*=e._da,o*=e._da,r*=e._da,n*=e._da),e.ctx.beginPath(),e.ctx.rect(t,o,r,n),a()}(t,o,r,n);if(void 0===l)return s(t,o,r,n,i,i,i,i);e._da&&(t*=e._da,o*=e._da,r*=e._da,n*=e._da,i*=e._da,l*=e._da,d*=e._da,c*=e._da),e.ctx.roundRect(t,o,r,n,[i,l,c,d]),a()}}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.background=function(t){e.ctx.save(),e.ctx.resetTransform(),t.canvas?e.image(t,0,0,e.width,e.height):(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,o,a,r)=>{e._doStroke&&(e._da&&(t*=e._da,o*=e._da,a*=e._da,r*=e._da),e.ctx.beginPath(),e.ctx.moveTo(t,o),e.ctx.lineTo(a,r),e.ctx.stroke())},e.arc=(t,o,a,n,s,i,l,c=25)=>{if(s==i)return e.ellipse(t,o,a,n);l??=e.PIE,e._ellipseMode==e.CENTER?r(t,o,a,n,s,i,l,c):e._ellipseMode==e.RADIUS?r(t,o,2*a,2*n,s,i,l,c):e._ellipseMode==e.CORNER?r(t+a/2,o+n/2,a,n,s,i,l,c):e._ellipseMode==e.CORNERS&&r((t+a)/2,(o+n)/2,a-t,n-o,s,i,l,c)},e.ellipse=(t,o,a,r)=>{r??=a,e._ellipseMode==e.CENTER?n(t,o,a,r):e._ellipseMode==e.RADIUS?n(t,o,2*a,2*r):e._ellipseMode==e.CORNER?n(t+a/2,o+r/2,a,r):e._ellipseMode==e.CORNERS&&n((t+a)/2,(o+r)/2,a-t,r-o)},e.circle=(t,o,r)=>{e._ellipseMode==e.CENTER?(e._da&&(t*=e._da,o*=e._da,r*=e._da),e.ctx.beginPath(),e.ctx.arc(t,o,r/2,0,e.TAU),a()):e.ellipse(t,o,r,r)},e.point=(t,o)=>{t.x&&(o=t.y,t=t.x),e._da&&(t*=e._da,o*=e._da),e.ctx.save(),e.ctx.beginPath(),e.ctx.arc(t,o,e.ctx.lineWidth/2,0,e.TAU),e.ctx.fillStyle=e.ctx.strokeStyle,e.ctx.fill(),e.ctx.restore()},e.rect=(t,o,a,r=a,n,i,l,c)=>{e._rectMode==e.CENTER?s(t-a/2,o-r/2,a,r,n,i,l,c):e._rectMode==e.RADIUS?s(t-a,o-r,2*a,2*r,n,i,l,c):e._rectMode==e.CORNER?s(t,o,a,r,n,i,l,c):e._rectMode==e.CORNERS&&s(t,o,a-t,r-o,n,i,l,c)},e.square=(t,o,a,r,n,s,i)=>e.rect(t,o,a,a,r,n,s,i),e.beginShape=()=>{o=[],e.ctx.beginPath(),t=!0},e.beginContour=()=>{e.ctx.closePath(),o=[],t=!0},e.endContour=()=>{o=[],t=!0},e.vertex=(a,r)=>{e._da&&(a*=e._da,r*=e._da),o=[],t?e.ctx.moveTo(a,r):e.ctx.lineTo(a,r),t=!1},e.bezierVertex=(t,a,r,n,s,i)=>{e._da&&(t*=e._da,a*=e._da,r*=e._da,n*=e._da,s*=e._da,i*=e._da),o=[],e.ctx.bezierCurveTo(t,a,r,n,s,i)},e.quadraticVertex=(t,a,r,n)=>{e._da&&(t*=e._da,a*=e._da,r*=e._da,n*=e._da),o=[],e.ctx.quadraticCurveTo(t,a,r,n)},e.bezier=(t,o,a,r,n,s,i,l)=>{e.beginShape(),e.vertex(t,o),e.bezierVertex(a,r,n,s,i,l),e.endShape()},e.triangle=(t,o,a,r,n,s)=>{e.beginShape(),e.vertex(t,o),e.vertex(a,r),e.vertex(n,s),e.endShape(e.CLOSE)},e.quad=(t,o,a,r,n,s,i,l)=>{e.beginShape(),e.vertex(t,o),e.vertex(a,r),e.vertex(n,s),e.vertex(i,l),e.endShape(e.CLOSE)},e.endShape=t=>{o=[],t&&e.ctx.closePath(),a()},e.curveVertex=(a,r)=>{if(e._da&&(a*=e._da,r*=e._da),o.push([a,r]),o.length<4)return;let n=function(e,t,o,a,r,n,s,i,l,c){function d(e,t,o,a,r,n){let s=Math.pow(a-t,2)+Math.pow(r-o,2);return Math.pow(s,.5*n)+e}let h=[],u=d(0,e,t,o,a,c),_=d(u,o,a,r,n,c),p=d(_,r,n,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]+o*g[1],m=t*g[0]+a*g[1],f=o*g[2]+r*g[3],y=a*g[2]+n*g[3],v=r*g[4]+s*g[5],w=n*g[4]+i*g[5],C=x*g[6]+f*g[7],M=m*g[6]+y*g[7],S=f*g[8]+v*g[9],b=y*g[8]+w*g[9],R=C*g[2]+S*g[3],Q=M*g[2]+b*g[3];h.push([R,Q])}return h}(...o.at(-4),...o.at(-3),...o.at(-2),...o.at(-1),e._curveDetail,e._curveAlpha);for(let o=0;o<n.length;o++)t?e.ctx.moveTo(...n[o]):e.ctx.lineTo(...n[o]),t=!1},e.curve=(t,o,a,r,n,s,i,l)=>{e.beginShape(),e.curveVertex(t,o),e.curveVertex(a,r),e.curveVertex(n,s),e.curveVertex(i,l),e.endShape()},e.curvePoint=(e,t,o,a,r)=>{const n=r*r*r,s=r*r;return e*(-.5*n+s-.5*r)+t*(1.5*n-2.5*s+1)+o*(-1.5*n+2*s+.5*r)+a*(.5*n-.5*s)},e.bezierPoint=(e,t,o,a,r)=>{const n=1-r;return Math.pow(n,3)*e+3*Math.pow(n,2)*r*t+3*n*Math.pow(r,2)*o+Math.pow(r,3)*a},e.curveTangent=(e,t,o,a,r)=>{const n=r*r;return e*(-3*n/2+2*r-.5)+t*(9*n/2-5*r)+o*(-9*n/2+4*r+.5)+a*(3*n/2-r)},e.bezierTangent=(e,t,o,a,r)=>{const n=1-r;return 3*a*Math.pow(r,2)-3*o*Math.pow(r,2)+6*o*n*r-6*t*n*r+3*t*Math.pow(n,2)-3*e*Math.pow(n,2)},e.erase=function(t=255,o=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, ${o/255})`},e.noErase=function(){e.ctx.globalCompositeOperation="source-over",e.ctx.restore()},e.inFill=(t,o)=>{const a=e._pixelDensity;return e.ctx.isPointInPath(t*a,o*a)},e.inStroke=(t,o)=>{const a=e._pixelDensity;return e.ctx.isPointInStroke(t*a,o*a)}},Q5.renderers.q2d.image=(e,t)=>{Q5.Image??=class{constructor(e,t,o){let a=this;a._scope="image",a.canvas=a.ctx=a.drawingContext=null,a.pixels=[],Q5.modules.canvas(a,a);let r=Q5.renderers.q2d;for(let e of["canvas","image","soft_filters"])r[e]&&r[e](a,a);a.createCanvas(e,t,o),delete a.createCanvas,a._loop=!1}get w(){return this.width}get h(){return this.height}},e.createImage=(t,o,a)=>(a??={},a.alpha??=!0,a.colorSpace??=e.canvas.colorSpace||Q5.canvasOptions.colorSpace,new Q5.Image(t,o,a)),e.loadImage=function(o,a,r){if(o.canvas)return o;if("gif"==o.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 n=[...arguments].at(-1);r="object"==typeof n?n:null;let s=e.createImage(1,1,r);function i(e){s.resize(e.naturalWidth||e.width,e.naturalHeight||e.height),s.ctx.drawImage(e,0,0),t._preloadCount--,a&&a(s)}if(Q5._nodejs&&global.CairoCanvas)global.CairoCanvas.loadImage(o).then(i).catch((e=>{throw t._preloadCount--,e}));else{let e=new window.Image;e.src=o,e.crossOrigin="Anonymous",e._pixelDensity=1,e.onload=()=>i(e),e.onerror=e=>{throw t._preloadCount--,e}}return s},e.imageMode=t=>e._imageMode=t,e.image=(t,o,a,r,n,s=0,i=0,l,c)=>{let d=t.canvas||t;Q5._createNodeJSCanvas&&(d=d.context.canvas),r??=t.width||t.videoWidth,n??=t.height||t.videoHeight,"center"==e._imageMode&&(o-=.5*r,a-=.5*n),e._da&&(o*=e._da,a*=e._da,r*=e._da,n*=e._da,s*=e._da,i*=e._da,l*=e._da,c*=e._da);let h=t._pixelDensity||1;l?l*=h:l=d.width||d.videoWidth,c?c*=h:c=d.height||d.videoHeight,e.ctx.drawImage(d,s*h,i*h,l,c,o,a,r,n),e._tint&&(e.ctx.globalCompositeOperation="multiply",e.ctx.fillStyle=e._tint.toString(),e.ctx.fillRect(o,a,r,n),e.ctx.globalCompositeOperation="source-over")},e._tint=null;let o=null;e._softFilter=()=>{throw new Error("Load q5-2d-soft-filters.js to use software filters.")},e.filter=(t,o)=>{if(!e.ctx.filter)return e._softFilter(t,o);if("string"==typeof t)f=t;else if(t==Q5.GRAY)f="saturate(0%)";else if(t==Q5.INVERT)f="invert(100%)";else if(t==Q5.BLUR){let t=Math.ceil(o*e._pixelDensity)||1;f=`blur(${t}px)`}else{if(t!=Q5.THRESHOLD)return e._softFilter(t,o);{o??=.5;let e=Math.floor(.5/Math.max(o,1e-5)*100);f=`saturate(0%) brightness(${e}%) contrast(1000000%)`}}e.ctx.filter=f,e.ctx.drawImage(e.canvas,0,0,e.canvas.w,e.canvas.h),e.ctx.filter="none"},"image"==e._scope&&(e.resize=(t,o)=>{let a=new e._OffscreenCanvas(e.canvas.width,e.canvas.height);a.getContext("2d",{colorSpace:e.canvas.colorSpace}).drawImage(e.canvas,0,0),e._setCanvasSize(t,o),e.ctx.clearRect(0,0,e.canvas.width,e.canvas.height),e.ctx.drawImage(a,0,0,e.canvas.width,e.canvas.height)}),e.trim=()=>{let t=e._pixelDensity||1,o=e.canvas.width,a=e.canvas.height,r=e.ctx.getImageData(0,0,o,a).data,n=o,s=0,i=a,l=0,c=3;for(let e=0;e<a;e++)for(let t=0;t<o;t++)0!==r[c]&&(t<n&&(n=t),t>s&&(s=t),e<i&&(i=e),e>l&&(l=e)),c+=4;return i=Math.floor(i/t),l=Math.floor(l/t),n=Math.floor(n/t),s=Math.floor(s/t),e.get(n,i,s-n+1,l-i+1)},e.mask=t=>{e.ctx.save(),e.ctx.resetTransform();let o=e.ctx.globalCompositeOperation;e.ctx.globalCompositeOperation="destination-in",e.ctx.drawImage(t.canvas,0,0),e.ctx.globalCompositeOperation=o,e.ctx.restore()},e.get=(t,o,a,r)=>{let n=e._pixelDensity||1;if(void 0!==t&&void 0===a){let a=e.ctx.getImageData(t*n,o*n,1,1).data;return new e.Color(a[0],a[1],a[2],a[3]/255)}t=(t||0)*n,o=(o||0)*n;let s=a=a||e.width,i=r=r||e.height;a*=n,r*=n;let l=e.createImage(a,r),c=e.ctx.getImageData(t,o,a,r);return l.ctx.putImageData(c,0,0),l._pixelDensity=n,l.width=s,l.height=i,l},e.set=(t,o,a)=>{if(a.canvas){let r=e._tint;return e._tint=null,e.image(a,t,o),void(e._tint=r)}e.pixels.length||e.loadPixels();let r=e._pixelDensity||1;for(let n=0;n<r;n++)for(let s=0;s<r;s++){let i=4*((o*r+n)*e.canvas.width+t*r+s);e.pixels[i]=a.r??a.l,e.pixels[i+1]=a.g??a.c,e.pixels[i+2]=a.b??a.h,e.pixels[i+3]=a.a}},e.loadPixels=()=>{o=e.ctx.getImageData(0,0,e.canvas.width,e.canvas.height),t.pixels=o.data},e.updatePixels=()=>{null!=o&&e.ctx.putImageData(o,0,0)},e.smooth=()=>e.ctx.imageSmoothingEnabled=!0,e.noSmooth=()=>e.ctx.imageSmoothingEnabled=!1,"image"!=e._scope&&(e.tint=function(t){e._tint=t._q5Color?t:e.color(...arguments)},e.noTint=()=>e._tint=null)},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.renderers.q2d.soft_filters=e=>{let t=null;function o(){let o=e.canvas.width*e.canvas.height*4;t&&t.length==o||(t=new Uint8ClampedArray(o))}e._softFilter=(a,r)=>{e._filters||(e._filters=[],e._filters[Q5.THRESHOLD]=(e,t)=>{void 0===t?t=127.5:t*=255;for(let o=0;o<e.length;o+=4){const a=.2126*e[o]+.7152*e[o+1]+.0722*e[o+2];e[o]=e[o+1]=e[o+2]=a>=t?255:0}},e._filters[Q5.GRAY]=e=>{for(let t=0;t<e.length;t+=4){const o=.2126*e[t]+.7152*e[t+1]+.0722*e[t+2];e[t]=e[t+1]=e[t+2]=o}},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 o=t-1;for(let a=0;a<e.length;a+=4)e[a]=255*(e[a]*t>>8)/o,e[a+1]=255*(e[a+1]*t>>8)/o,e[a+2]=255*(e[a+2]*t>>8)/o},e._filters[Q5.DILATE]=a=>{o(),t.set(a);let[r,n]=[e.canvas.width,e.canvas.height];for(let e=0;e<n;e++)for(let o=0;o<r;o++){let s=4*Math.max(o-1,0),i=4*Math.min(o+1,r-1),l=4*Math.max(e-1,0)*r,c=4*Math.min(e+1,n-1)*r,d=4*e*r,h=4*o;for(let e=0;e<4;e++){let o=e+l,r=e+c,n=e+d;a[d+h+e]=Math.max(t[o+h],t[n+s],t[n+h],t[n+i],t[r+h])}}},e._filters[Q5.ERODE]=a=>{o(),t.set(a);let[r,n]=[e.canvas.width,e.canvas.height];for(let e=0;e<n;e++)for(let o=0;o<r;o++){let s=4*Math.max(o-1,0),i=4*Math.min(o+1,r-1),l=4*Math.max(e-1,0)*r,c=4*Math.min(e+1,n-1)*r,d=4*e*r,h=4*o;for(let e=0;e<4;e++){let o=e+l,r=e+c,n=e+d;a[d+h+e]=Math.min(t[o+h],t[n+s],t[n+h],t[n+i],t[r+h])}}},e._filters[Q5.BLUR]=(a,r)=>{r=r||1,r=Math.floor(r*e._pixelDensity),o(),t.set(a);let n=2*r+1,s=function(e){let t=new Float32Array(e),o=.3*r+.8,a=o*o*2;for(let r=0;r<e;r++){let n=r-e/2,s=Math.exp(-n*n/a)/(2.5066282746*o);t[r]=s}return t}(n),[i,l]=[e.canvas.width,e.canvas.height];for(let e=0;e<l;e++)for(let o=0;o<i;o++){let l=0,c=0,d=0,h=0;for(let a=0;a<n;a++){let n=4*(e*i+Math.min(Math.max(o-r+a,0),i-1));l+=t[n]*s[a],c+=t[n+1]*s[a],d+=t[n+2]*s[a],h+=t[n+3]*s[a]}let u=4*(e*i+o);a[u]=l,a[u+1]=c,a[u+2]=d,a[u+3]=h}t.set(a);for(let e=0;e<l;e++)for(let o=0;o<i;o++){let c=0,d=0,h=0,u=0;for(let a=0;a<n;a++){let n=4*(Math.min(Math.max(e-r+a,0),l-1)*i+o);c+=t[n]*s[a],d+=t[n+1]*s[a],h+=t[n+2]*s[a],u+=t[n+3]*s[a]}let _=4*(e*i+o);a[_]=c,a[_+1]=d,a[_+2]=h,a[_+3]=u}});let n=e.ctx.getImageData(0,0,e.canvas.width,e.canvas.height);e._filters[a](n.data,r),e.ctx.putImageData(n,0,0)}},Q5.renderers.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,o)=>{t._preloadCount++;let a=e.split("/").pop().split(".")[0].replace(" ",""),r=new FontFace(a,`url(${e})`);return document.fonts.add(r),r.load().then((()=>{t._preloadCount--,o&&o(a)})),a},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,o)=>{e.ctx.textAlign=t,o&&(e.ctx.textBaseline=o==e.CENTER?"middle":o)},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,o=0;for(const[a,r]of this.entries())r.lastAccessed<t&&(t=r.lastAccessed,e=o),o++;o=e;for(const t of this.keys()){if(0==o){e=t;break}o--}this.delete(e)}},e._tic=new e._TimedCache,e.textCache=(t,o)=>(o&&(e._tic.maxSize=o),void 0!==t&&(e._textCache=t),e._textCache),e._genTextImageKey=(t,o,a)=>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+"_":"")+(o||"")+(a?"x"+a:""),e.createTextImage=(t,o,a)=>{let r=e._textCache;e._textCache=!0,e._genTextImage=!0,e.text(t,0,0,o,a),e._genTextImage=!1;let n=e._genTextImageKey(t,o,a);return e._textCache=r,e._tic.get(n)},e.text=(t,o,a,r,n)=>{if(void 0===t)return;if(t=t.toString(),e._da&&(o*=e._da,a*=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,r,n),i=e._tic.get(c),i&&!e._genTextImage)return void e.textImage(i,o,a);l=e.createGraphics.call(e,1,1),s=l.ctx}else s=e.ctx,d=o,h=a;s.font=`${e._textStyle} ${e._textSize}px ${e._textFont}`;let x=t.split("\n");if(g){d=0,h=e._textLeading*x.length;let o=s.measureText(" ");u=o.fontBoundingBoxAscent,_=o.fontBoundingBoxDescent,n??=h+_,l.resizeCanvas(Math.ceil(s.measureText(t).width),Math.ceil(n)),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>n));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,o,a))},e.textImage=(t,o,a)=>{let r=e._imageMode;e._imageMode="corner","center"==e.ctx.textAlign?o-=.5*t.width:"right"==e.ctx.textAlign&&(o-=t.width),"alphabetic"==e.ctx.textBaseline&&(a-=e._textLeading),"middle"==e.ctx.textBaseline?a-=t._descent+.5*t._ascent+e._textLeadDiff:"bottom"==e.ctx.textBaseline?a-=t._ascent+t._descent+e._textLeadDiff:"top"==e.ctx.textBaseline&&(a-=t._descent+e._textLeadDiff),e.image(t,o,a),e._imageMode=r},e.nf=(e,t,o)=>{let a=e<0,r=(e=Math.abs(e)).toFixed(o).split(".");r[0]=r[0].padStart(t,"0");let n=r.join(".");return a&&(n="-"+n),n}},Q5.modules.ai=e=>{e.askAI=(e="")=>{throw Error("Ask AI ✨ "+e)},e._aiErrorAssistance=async t=>{let o=t.message?.includes("Ask AI ✨");if(o||console.error(t),Q5.disableFriendlyErrors)return;!o&&Q5.errorTolerant||e.noLoop();let a=t.stack?.split("\n");if(!t.stack||a.length<=1)return;let r=1,n="(";for(-1==navigator.userAgent.indexOf("Chrome")&&(r=0,n="@");a[r].indexOf("q5.js:")>=0;)r++;let s=a[r].split(n).at(-1);s=s.split(":");let i=parseInt(s.at(-2));o&&i++;let l=s.slice(0,-2).join(":"),c=l.split("/").at(-1);try{let e=(await(await fetch(l)).text()).split("\n"),a=e[i-1].trim(),r="",n=1;for(;r.length<1600&&(i-n>=0&&(r=e[i-n].trim()+"\n"+r),i+n<e.length);)r+=e[i+n].trim()+"\n",n++;let s="https://chatgpt.com/?q=q5.js+"+(o&&t.message.length>10?t.message.slice(10):"Whats+wrong+with+this+line%3F+short+answer")+(o?"":"%0A%0A"+encodeURIComponent(t.name+": "+t.message))+"%0A%0ALine%3A+"+encodeURIComponent(a)+"%0A%0AExcerpt+for+context%3A%0A%0A"+encodeURIComponent(r);o||console.log("Error in "+c+" on line "+i+":\n\n"+a),console.warn("Ask AI ✨ "+s),o&&window.open(s,"_blank")}catch(e){}}},Q5.modules.color=(e,t)=>{e.RGB=e.RGBA=e._colorMode="rgb",e.OKLCH="oklch",e.colorMode=(o,a)=>{e._colorMode=o;let r="srgb"==e.canvas.colorSpace||"srgb"==o;if(a??=r?"integer":"float",e._colorFormat="float"==a||1==a?1:255,"oklch"==o)t.Color=Q5.ColorOKLCH;else{let o="srgb"==e.canvas.colorSpace;255==e._colorFormat?t.Color=o?Q5.ColorRGBA_8:Q5.ColorRGBA_P3_8:t.Color=o?Q5.ColorRGBA:Q5.ColorRGBA_P3,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=(t,o,a,r)=>{let n=e.Color;if(t._q5Color)return new n(...t.levels);if(null==o){if("string"==typeof t){if("#"==t[0])t.length<=5?(t.length>4&&(r=parseInt(t[4]+t[4],16)),a=parseInt(t[3]+t[3],16),o=parseInt(t[2]+t[2],16),t=parseInt(t[1]+t[1],16)):(t.length>7&&(r=parseInt(t.slice(7,9),16)),a=parseInt(t.slice(5,7),16),o=parseInt(t.slice(3,5),16),t=parseInt(t.slice(1,3),16));else{if(!e._namedColors[t])return console.error("q5 can't parse color: "+t+"\nOnly numeric input, hex, and common named colors are supported."),new n(0,0,0);[t,o,a,r]=e._namedColors[t]}1==e._colorFormat&&(t/=255,o&&(o/=255),a&&(a/=255),r&&(r/=255))}Array.isArray(t)&&(o=t[1],a=t[2],r=t[3],t=t[0])}return null==a?new n(t,t,t,o):new n(t,o,a,r)},e.red=e=>e.r,e.green=e=>e.g,e.blue=e=>e.b,e.alpha=e=>e.a,e.lightness=t=>"oklch"==e._colorMode?t.l:100*(.2126*t.r+.7152*t.g+.0722*t.b)/255,e.hue=t=>{if("oklch"==e._colorMode)return t.h;let o=t.r,a=t.g,r=t.b;255==e._colorFormat&&(o/=255,a/=255,r/=255);let n,s=Math.max(o,a,r),i=Math.min(o,a,r);return n=s==i?0:s==o?60*(a-r)/(s-i):s==a?60*(r-o)/(s-i)+120:60*(o-a)/(s-i)+240,n<0&&(n+=360),n},e.lerpColor=(t,o,a)=>{if("rgb"==e._colorMode)return new e.Color(e.constrain(e.lerp(t.r,o.r,a),0,255),e.constrain(e.lerp(t.g,o.g,a),0,255),e.constrain(e.lerp(t.b,o.b,a),0,255),e.constrain(e.lerp(t.a,o.a,a),0,255));{let r=o.h-t.h;r>180&&(r-=360),r<-180&&(r+=360);let n=t.h+a*r;return n<0&&(n+=360),n>360&&(n-=360),new e.Color(e.constrain(e.lerp(t.l,o.l,a),0,100),e.constrain(e.lerp(t.c,o.c,a),0,100),n,e.constrain(e.lerp(t.a,o.a,a),0,255))}}},Q5.Color=class{constructor(){this._q5Color=!0}},Q5.ColorOKLCH=class extends Q5.Color{constructor(e,t,o,a){super(),this.l=e,this.c=t,this.h=o,this.a=a??1}toString(){return`oklch(${this.l} ${this.c} ${this.h} / ${this.a})`}},Q5.ColorRGBA=class extends Q5.Color{constructor(e,t,o,a){super(),this.r=e,this.g=t,this.b=o,this.a=a??1}get levels(){return[this.r,this.g,this.b,this.a]}toString(){return`color(srgb ${this.r} ${this.g} ${this.b} / ${this.a})`}},Q5.ColorRGBA_P3=class extends Q5.ColorRGBA{toString(){return`color(display-p3 ${this.r} ${this.g} ${this.b} / ${this.a})`}},Q5.ColorRGBA_8=class extends Q5.ColorRGBA{constructor(e,t,o,a){super(e,t,o,a??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_8=class extends Q5.ColorRGBA{constructor(e,t,o,a){super(e,t,o,a??255),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),o=(this._b/255).toFixed(3),a=(this._a/255).toFixed(3);this._css=`color(display-p3 ${e} ${t} ${o} / ${a})`,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 o=t.style,a=t.parentElement;o&&a&&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?(a.classList.remove("q5-centered","q5-maxed","q5-fullscreen"),o.width=t.w*t.displayScale+"px",o.height=t.h*t.displayScale+"px"):(a.classList.add("q5-"+t.displayMode),a=a.getBoundingClientRect(),t.w/t.h>a.width/a.height?("centered"==t.displayMode?(o.width=t.w*t.displayScale+"px",o.maxWidth="100%"):o.width="100%",o.height="auto",o.maxHeight=""):(o.width="auto",o.maxWidth="","centered"==t.displayMode?(o.height=t.h*t.displayScale+"px",o.maxHeight="100%"):o.height="100%")))},e.displayMode=(o="normal",a="default",r=1)=>{"string"==typeof r&&(r=parseFloat(r.slice(1))),Object.assign(t,{displayMode:o,renderQuality:a,displayScale:r}),e._adjustDisplay()},e.fullscreen=e=>{if(void 0===e)return document.fullscreenElement;e?document.body.requestFullscreen():document.body.exitFullscreen()}},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 o={},a=[e.LEFT,e.CENTER,e.RIGHT],r=e.canvas;function n(t){const o=e.canvas.getBoundingClientRect(),a=e.canvas.scrollWidth/e.width||1,r=e.canvas.scrollHeight/e.height||1;return{x:(t.clientX-o.left)/a,y:(t.clientY-o.top)/r,id:t.identifier}}if(e._startAudio=()=>{e.getAudioContext&&"suspended"==e.getAudioContext()?.state&&e.userStartAudio()},e._updateMouse=o=>{if(!o.changedTouches)if(r){let a=r.getBoundingClientRect(),n=r.scrollWidth/e.width||1,s=r.scrollHeight/e.height||1;t.mouseX=(o.clientX-a.left)/n,t.mouseY=(o.clientY-a.top)/s,"webgpu"==r.renderer&&(t.mouseX-=r.hw,t.mouseY-=r.hh)}else t.mouseX=o.clientX,t.mouseY=o.clientY},e._onmousedown=o=>{e._startAudio(),e._updateMouse(o),t.mouseIsPressed=!0,t.mouseButton=a[o.button],e.mousePressed(o)},e._onmousemove=t=>{e._updateMouse(t),e.mouseIsPressed?e.mouseDragged(t):e.mouseMoved(t)},e._onmouseup=o=>{e._updateMouse(o),t.mouseIsPressed=!1,e.mouseReleased(o)},e._onclick=o=>{e._updateMouse(o),t.mouseIsPressed=!0,e.mouseClicked(o),t.mouseIsPressed=!1},e.cursor=(t,o,a)=>{let r="";t.includes(".")&&(t=`url("${t}")`,r=", auto"),void 0!==o&&(t+=" "+o+" "+a),e.canvas.style.cursor=t+r},e.noCursor=()=>{e.canvas.style.cursor="none"},e.requestPointerLock=document.body?.requestPointerLock,e.exitPointerLock=document.exitPointerLock,e._onkeydown=a=>{a.repeat||(e._startAudio(),t.keyIsPressed=!0,t.key=a.key,t.keyCode=a.keyCode,o[e.keyCode]=o[e.key.toLowerCase()]=!0,e.keyPressed(a),1==a.key.length&&e.keyTyped(a))},e._onkeyup=a=>{t.keyIsPressed=!1,t.key=a.key,t.keyCode=a.keyCode,o[e.keyCode]=o[e.key.toLowerCase()]=!1,e.keyReleased(a)},e.keyIsDown=e=>!!o["string"==typeof e?e.toLowerCase():e],e._ontouchstart=o=>{e._startAudio(),t.touches=[...o.touches].map(n),e._isTouchAware||(t.mouseX=e.touches[0].x,t.mouseY=e.touches[0].y,t.mouseIsPressed=!0,t.mouseButton=e.LEFT,e.mousePressed(o)||o.preventDefault()),e.touchStarted(o)||o.preventDefault()},e._ontouchmove=o=>{t.touches=[...o.touches].map(n),e._isTouchAware||(t.mouseX=e.touches[0].x,t.mouseY=e.touches[0].y,e.mouseDragged(o)||o.preventDefault()),e.touchMoved(o)||o.preventDefault()},e._ontouchend=o=>{t.touches=[...o.touches].map(n),e._isTouchAware||e.touches.length||(t.mouseIsPressed=!1,e.mouseReleased(o)||o.preventDefault()),e.touchEnded(o)||o.preventDefault()},r&&(r.addEventListener("mousedown",(t=>e._onmousedown(t))),r.addEventListener("mouseup",(t=>e._onmouseup(t))),r.addEventListener("click",(t=>e._onclick(t))),r.addEventListener("touchstart",(t=>e._ontouchstart(t))),r.addEventListener("touchmove",(t=>e._ontouchmove(t))),r.addEventListener("touchcancel",(t=>e._ontouchend(t))),r.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)=>{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=Q5.prototype.map=(e,t,o,a,r,n)=>{let s=a+1*(e-t)/(o-t)*(r-a);return n?a<r?Math.min(Math.max(s,a),r):Math.min(Math.max(s,r),a):s},e.lerp=(e,t,o)=>e*(1-o)+t*o,e.constrain=(e,t,o)=>Math.min(Math.max(e,t),o),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,o,a)=>e.map(t,o,a,0,1),e.sq=e=>e*e,e.fract=e=>e-Math.floor(e);for(let t of["sin","cos","tan"])e[t]=o=>("degrees"==e._angleMode&&(o=e.radians(o)),Math[t](o));for(let t of["asin","acos","atan"])e[t]=o=>{let a=Math[t](o);return"degrees"==e._angleMode&&(a=e.degrees(a)),a};function o(){let e,t,o=4294967295;return{setSeed(a){e=t=(a??Math.random()*o)>>>0},getSeed:()=>t,rand:()=>(e^=e<<17,e^=e>>13,e^=e<<5,(e>>>0)/o)}}e.atan2=(t,o)=>{let a=Math.atan2(t,o);return"degrees"==e._angleMode&&(a=e.degrees(a)),a};let a=o();a.setSeed(),e.randomSeed=e=>a.setSeed(e),e.random=(e,t)=>void 0===e?a.rand():"number"==typeof e?void 0!==t?a.rand()*(t-e)+e:a.rand()*e:e[Math.trunc(e.length*a.rand())],e.randomGenerator=t=>{t==e.LCG?a=function(){const e=4294967296;let t,o;return{setSeed(a){o=t=(a??Math.random()*e)>>>0},getSeed:()=>t,rand:()=>(o=(1664525*o+1013904223)%e,o/e)}}():t==e.SHR3&&(a=o()),a.setSeed()};var r=new function(){var e,t,o,r=new Array(128),n=new Array(256),s=new Array(128),i=new Array(128),l=new Array(256),c=new Array(256),d=()=>4294967296*a.rand()-2147483648,h=()=>.5+2.328306e-10*(d()|0),u=()=>{for(var t,a,n,l,c=3.44262;;){if(t=o*s[e],0==e){do{n=h(),l=h(),t=.2904764*-Math.log(n),a=-Math.log(l)}while(a+a<t*t);return o>0?c+t:-c-t}if(i[e]+h()*(i[e-1]-i[e])<Math.exp(-.5*t*t))return t;if(o=d(),e=127&o,Math.abs(o)<r[e])return o*s[e]}},_=()=>{for(var o;;){if(0==e)return 7.69711-Math.log(h());if(o=t*l[e],c[e]+h()*(c[e-1]-c[e])<Math.exp(-o))return o;if((t=d())<n[e=255&t])return t*l[e]}};this.SHR3=d,this.UNI=h,this.RNOR=()=>(o=d(),e=127&o,Math.abs(o)<r[e]?o*s[e]:u()),this.REXP=()=>(t=d()>>>0)<r[e=255&t]?t*l[e]:_(),this.zigset=()=>{var e,t,o=2147483648,a=4294967296,d=3.442619855899,h=d,u=.00991256303526217,_=7.697117470131487,p=_,g=.003949659822581572;for(e=u/Math.exp(-.5*d*d),r[0]=Math.floor(d/e*o),r[1]=0,s[0]=e/o,s[127]=d/o,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))),r[t+1]=Math.floor(d/h*o),h=d,i[t]=Math.exp(-.5*d*d),s[t]=d/o;for(e=g/Math.exp(-_),n[0]=Math.floor(_/e*a),n[1]=0,l[0]=e/a,l[255]=_/a,c[0]=1,c[255]=Math.exp(-_),t=254;t>=1;t--)_=-Math.log(g/_+Math.exp(-_)),n[t+1]=Math.floor(_/p*a),p=_,c[t]=Math.exp(-_),l[t]=_/a}};let n;r.hasInit=!1,e.randomGaussian=(e,t)=>(r.hasInit||(r.zigset(),r.hasInit=!0),r.RNOR()*t+e),e.randomExponential=()=>(r.hasInit||(r.zigset(),r.hasInit=!0),r.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"],n=null},e.noiseSeed=t=>{n=new e.Noise(t)},e.noise=(t=0,o=0,a=0)=>(n??=new e.Noise,n.noise(t,o,a)),e.noiseDetail=(t,o)=>{n??=new e.Noise,t>0&&(n.octaves=t),o>0&&(n.falloff=o)}},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,o,a=[];for(let e=0;e<256;e++)a[e]=e;for(let r=255;r>0;r--)t=(e=16807*e%2147483647)%(r+1),o=a[r],a[r]=a[t],a[t]=o;return a}dot(e,t,o,a){return e[0]*t+e[1]*o+e[2]*a}mix(e,t,o){return(1-o)*e+o*t}fade(e){return e*e*e*(e*(6*e-15)+10)}noise(e,t,o){let a=this,r=0,n=1,s=1,i=0;for(let l=0;l<a.octaves;l++){const l=255&Math.floor(e*n),c=255&Math.floor(t*n),d=255&Math.floor(o*n),h=e*n-Math.floor(e*n),u=t*n-Math.floor(t*n),_=o*n-Math.floor(o*n),p=a.fade(h),g=a.fade(u),x=a.fade(_),m=a.p[l]+c,f=a.p[m]+d,y=a.p[m+1]+d,v=a.p[l+1]+c,w=a.p[v]+d,C=a.p[v+1]+d,M=a.mix(a.dot(a.grad3[a.p[f]%12],h,u,_),a.dot(a.grad3[a.p[w]%12],h-1,u,_),p),S=a.mix(a.dot(a.grad3[a.p[y]%12],h,u-1,_),a.dot(a.grad3[a.p[C]%12],h-1,u-1,_),p),b=a.mix(a.dot(a.grad3[a.p[f+1]%12],h,u,_-1),a.dot(a.grad3[a.p[w+1]%12],h-1,u,_-1),p),R=a.mix(a.dot(a.grad3[a.p[y+1]%12],h,u-1,_-1),a.dot(a.grad3[a.p[C+1]%12],h-1,u-1,_-1),p),Q=a.mix(M,S,g),E=a.mix(b,R,g);r+=a.mix(Q,E,x)*s,i+=s,s*=a.falloff,n*=2}return(r/i+1)/2}},Q5.modules.sound=(e,t)=>{e.Sound=Q5.Sound,e.loadSound=(e,o)=>{t._preloadCount++,Q5.aud??=new window.AudioContext;let a=new Q5.Sound(e,o);return a.addEventListener("canplaythrough",(()=>{t._preloadCount--,a.loaded=!0,o&&o(a)})),a},e.getAudioContext=()=>Q5.aud,e.userStartAudio=()=>Q5.aud.resume()},Q5.Sound=class extends Audio{constructor(e){super(e);let t=this;t.load(),t.panner=Q5.aud.createStereoPanner(),t.source=Q5.aud.createMediaElementSource(t),t.source.connect(t.panner),t.panner.connect(Q5.aud.destination),Object.defineProperty(t,"pan",{get:()=>t.panner.pan.value,set:e=>t.panner.pan.value=e})}setVolume(e){this.volume=e}setLoop(e){this.loop=e}setPan(e){this.pan=e}isLoaded(){return this.loaded}isPlaying(){return!this.paused}},Q5.modules.util=(e,t)=>{e._loadFile=(e,o,a)=>{t._preloadCount++;let r={};return fetch(e).then((e=>"json"==a?e.json():"text"==a?e.text():void 0)).then((e=>{t._preloadCount--,Object.assign(r,e),o&&o(e)})),r},e.loadStrings=(t,o)=>e._loadFile(t,o,"text"),e.loadJSON=(t,o)=>e._loadFile(t,o,"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,o,a)=>new Q5.Vector(t,o,a,e)},Q5.Vector=class{constructor(e,t,o,a){this.x=e||0,this.y=t||0,this.z=o||0,this._$=a||window,this._cn=null,this._cnsq=null}set(e,t,o){this.x=e||0,this.y=t||0,this.z=o||0}copy(){return new Q5.Vector(this.x,this.y,this.z)}_arg2v(e,t,o){return void 0!==e?.x?e:void 0!==t?{x:e,y:t,z:o||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,o=this.y-e.y,a=this.z-e.z;return Math.sqrt(t*t+o*o+a*a)}cross(){let e=this._arg2v(...arguments),t=this.y*e.z-this.z*e.y,o=this.z*e.x-this.x*e.z,a=this.x*e.y-this.y*e.x;return this.x=t,this.y=o,this.z=a,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 o=e/t;this.x*=o,this.y*=o,this.z*=o,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),o=this._$.sin(e),a=this.x*t-this.y*o,r=this.x*o+this.y*t;return this.x=a,this.y=r,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)),o=e.at(-1);return this.x+=(t.x-this.x)*o,this.y+=(t.y-this.y)*o,this.z+=(t.z-this.z)*o,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,o){void 0===o&&(o=1),this._cn=o,this._cnsq=o*o;const a=this._$.cos(t),r=this._$.sin(t),n=this._$.cos(e),s=this._$.sin(e);return this.x=o*s*r,this.y=-o*n,this.z=o*s*a,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,o)=>e.equals(t,o),Q5.Vector.lerp=(e,t,o)=>e.copy().lerp(t,o),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,o,a)=>(new Q5.Vector)[e](t,o,a);
package/q5.js CHANGED
@@ -551,7 +551,12 @@ Q5.renderers.q2d.canvas = ($, q) => {
551
551
  $.ctx.lineWidth = n || 0.0001;
552
552
  };
553
553
  $.noStroke = () => ($._doStroke = false);
554
- $.clear = () => $.ctx.clearRect(0, 0, $.canvas.width, $.canvas.height);
554
+ $.clear = () => {
555
+ $.ctx.save();
556
+ $.ctx.resetTransform();
557
+ $.ctx.clearRect(0, 0, $.canvas.width, $.canvas.height);
558
+ $.ctx.restore();
559
+ };
555
560
 
556
561
  // DRAWING MATRIX
557
562
 
@@ -717,15 +722,17 @@ Q5.renderers.q2d.drawing = ($) => {
717
722
  // DRAWING
718
723
 
719
724
  $.background = function (c) {
720
- if (c.canvas) return $.image(c, 0, 0, $.width, $.height);
721
725
  $.ctx.save();
722
726
  $.ctx.resetTransform();
723
- if (Q5.Color) {
724
- if (!c._q5Color && typeof c != 'string') c = $.color(...arguments);
725
- else if ($._namedColors[c]) c = $.color(...$._namedColors[c]);
727
+ if (c.canvas) $.image(c, 0, 0, $.width, $.height);
728
+ else {
729
+ if (Q5.Color) {
730
+ if (!c._q5Color && typeof c != 'string') c = $.color(...arguments);
731
+ else if ($._namedColors[c]) c = $.color(...$._namedColors[c]);
732
+ }
733
+ $.ctx.fillStyle = c.toString();
734
+ $.ctx.fillRect(0, 0, $.canvas.width, $.canvas.height);
726
735
  }
727
- $.ctx.fillStyle = c.toString();
728
- $.ctx.fillRect(0, 0, $.canvas.width, $.canvas.height);
729
736
  $.ctx.restore();
730
737
  };
731
738
 
@@ -1728,13 +1735,20 @@ Q5.modules.color = ($, q) => {
1728
1735
  c0 = parseInt(c0.slice(1, 3), 16);
1729
1736
  }
1730
1737
  } else if ($._namedColors[c0]) {
1731
- c0 = $._namedColors[c0];
1738
+ [c0, c1, c2, c3] = $._namedColors[c0];
1732
1739
  } else {
1733
1740
  console.error(
1734
1741
  "q5 can't parse color: " + c0 + '\nOnly numeric input, hex, and common named colors are supported.'
1735
1742
  );
1736
1743
  return new C(0, 0, 0);
1737
1744
  }
1745
+
1746
+ if ($._colorFormat == 1) {
1747
+ c0 /= 255;
1748
+ if (c1) c1 /= 255;
1749
+ if (c2) c2 /= 255;
1750
+ if (c3) c3 /= 255;
1751
+ }
1738
1752
  }
1739
1753
  if (Array.isArray(c0)) {
1740
1754
  c1 = c0[1];
@@ -1744,13 +1758,6 @@ Q5.modules.color = ($, q) => {
1744
1758
  }
1745
1759
  }
1746
1760
 
1747
- if ($._colorFormat == 1) {
1748
- c0 /= 255;
1749
- if (c1) c1 /= 255;
1750
- if (c2) c2 /= 255;
1751
- if (c3) c3 /= 255;
1752
- }
1753
-
1754
1761
  if (c2 == undefined) return new C(c0, c0, c0, c1);
1755
1762
  return new C(c0, c1, c2, c3);
1756
1763
  };
@@ -3200,7 +3207,7 @@ Q5.renderers.webgpu.canvas = ($, q) => {
3200
3207
  Q5.webgpu = async function (scope, parent) {
3201
3208
  if (!scope || scope == 'global') Q5._hasGlobal = true;
3202
3209
  if (!navigator.gpu) {
3203
- console.error('q5 WebGPU not supported on this browser!');
3210
+ console.warn('q5 WebGPU not supported on this browser!');
3204
3211
  let q = new Q5(scope, parent);
3205
3212
  q.colorMode('rgb', 1);
3206
3213
  q._beginRender = () => q.translate(q.canvas.hw, q.canvas.hh);
@@ -3563,5 +3570,191 @@ fn fragmentMain(@location(1) colorIndex: f32) -> @location(0) vec4<f32> {
3563
3570
  $.pass.setBindGroup(2, colorsBindGroup);
3564
3571
  });
3565
3572
  };
3566
- Q5.renderers.webgpu.image = ($, q) => {};
3573
+ Q5.renderers.webgpu.image = ($, q) => {
3574
+ $.imageStack = [];
3575
+ $.textures = [];
3576
+
3577
+ $._hooks.postCanvas.push(() => {
3578
+ let imageVertexShader = Q5.device.createShaderModule({
3579
+ code: `
3580
+ struct VertexOutput {
3581
+ @builtin(position) position: vec4<f32>,
3582
+ @location(0) texCoord: vec2<f32>,
3583
+ @location(1) textureIndex: f32
3584
+ };
3585
+
3586
+ struct Uniforms {
3587
+ halfWidth: f32,
3588
+ halfHeight: f32
3589
+ };
3590
+
3591
+ @group(0) @binding(0) var<uniform> uniforms: Uniforms;
3592
+ @group(1) @binding(0) var<storage, read> transforms: array<mat4x4<f32>>;
3593
+
3594
+ @vertex
3595
+ fn vertexMain(@location(0) pos: vec2<f32>, @location(1) texCoord: vec2<f32>, @location(2) transformIndex: f32, @location(3) textureIndex: f32) -> VertexOutput {
3596
+ var vert = vec4<f32>(pos, 0.0, 1.0);
3597
+ vert *= transforms[i32(transformIndex)];
3598
+ vert.x /= uniforms.halfWidth;
3599
+ vert.y /= uniforms.halfHeight;
3600
+
3601
+ var output: VertexOutput;
3602
+ output.position = vert;
3603
+ output.texCoord = texCoord;
3604
+ output.textureIndex = textureIndex;
3605
+ return output;
3606
+ }
3607
+ `
3608
+ });
3609
+
3610
+ let imageFragmentShader = Q5.device.createShaderModule({
3611
+ code: `
3612
+ @group(0) @binding(0) var samp: sampler;
3613
+ @group(0) @binding(1) var textures: array<texture_2d<f32>>;
3614
+
3615
+ @fragment
3616
+ fn fragmentMain(@location(0) texCoord: vec2<f32>, @location(1) textureIndex: f32) -> @location(0) vec4<f32> {
3617
+ return textureSample(textures[i32(textureIndex)], samp, texCoord);
3618
+ }
3619
+ `
3620
+ });
3621
+
3622
+ const bindGroupLayouts = [
3623
+ Q5.device.createBindGroupLayout({
3624
+ entries: [
3625
+ { binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: 'uniform' } },
3626
+ { binding: 1, visibility: GPUShaderStage.FRAGMENT, sampler: {} },
3627
+ { binding: 2, visibility: GPUShaderStage.FRAGMENT, texture: { viewDimension: '2d', sampleType: 'float' } }
3628
+ ]
3629
+ }),
3630
+ Q5.device.createBindGroupLayout({
3631
+ entries: [{ binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: 'read-only-storage' } }]
3632
+ })
3633
+ ];
3634
+
3635
+ const pipelineLayout = Q5.device.createPipelineLayout({
3636
+ bindGroupLayouts: bindGroupLayouts
3637
+ });
3638
+
3639
+ $.pipelines[1] = Q5.device.createRenderPipeline({
3640
+ layout: pipelineLayout,
3641
+ vertex: {
3642
+ module: imageVertexShader,
3643
+ entryPoint: 'vertexMain',
3644
+ buffers: [
3645
+ {
3646
+ arrayStride: 5 * 4, // 4 floats for position and texCoord, 1 float for textureIndex
3647
+ attributes: [
3648
+ { shaderLocation: 0, offset: 0, format: 'float32x2' },
3649
+ { shaderLocation: 1, offset: 2 * 4, format: 'float32x2' },
3650
+ { shaderLocation: 2, offset: 4 * 4, format: 'float32' } // textureIndex
3651
+ ]
3652
+ }
3653
+ ]
3654
+ },
3655
+ fragment: {
3656
+ module: imageFragmentShader,
3657
+ entryPoint: 'fragmentMain',
3658
+ targets: [{ format: 'bgra8unorm' }]
3659
+ },
3660
+ primitive: {
3661
+ topology: 'triangle-list'
3662
+ }
3663
+ });
3664
+
3665
+ $.sampler = Q5.device.createSampler({
3666
+ magFilter: 'linear',
3667
+ minFilter: 'linear'
3668
+ });
3669
+ });
3670
+
3671
+ $.loadImage = async (src) => {
3672
+ const img = new Image();
3673
+ img.onload = async () => {
3674
+ const imageBitmap = await createImageBitmap(img);
3675
+ const texture = Q5.device.createTexture({
3676
+ size: [img.width, img.height, 1],
3677
+ format: 'bgra8unorm',
3678
+ usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT
3679
+ });
3680
+
3681
+ Q5.device.queue.copyExternalImageToTexture({ source: imageBitmap }, { texture }, [img.width, img.height, 1]);
3682
+
3683
+ img.texture = texture;
3684
+ img.index = $.textures.length;
3685
+ $.textures.push(texture);
3686
+ };
3687
+ img.onerror = reject;
3688
+ img.src = src;
3689
+ return img;
3690
+ };
3691
+
3692
+ $._hooks.preRender.push(() => {
3693
+ if (!$.imageStack.length) return;
3694
+
3695
+ // Switch to image pipeline
3696
+ $.pass.setPipeline($.pipelines[1]);
3697
+
3698
+ // Create a vertex buffer for the image quads
3699
+ const vertices = new Float32Array($.vertexStack);
3700
+
3701
+ const vertexBuffer = Q5.device.createBuffer({
3702
+ size: vertices.byteLength,
3703
+ usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST
3704
+ });
3705
+
3706
+ Q5.device.queue.writeBuffer(vertexBuffer, 0, vertices);
3707
+ $.pass.setVertexBuffer(0, vertexBuffer);
3708
+
3709
+ // Set the bind group for the sampler and textures
3710
+ if ($.textures.length !== previousTextureCount) {
3711
+ previousTextureCount = $.textures.length;
3712
+
3713
+ // Create the bind group for all textures
3714
+ const textureViews = $.textures.map((tex) => tex.createView());
3715
+
3716
+ $.textureBindGroup = Q5.device.createBindGroup({
3717
+ layout: $.pipelines[1].getBindGroupLayout(0),
3718
+ entries: [
3719
+ { binding: 0, resource: $.sampler },
3720
+ ...textureViews.map((view, i) => ({ binding: i + 1, resource: view }))
3721
+ ]
3722
+ });
3723
+ }
3724
+
3725
+ // Set the bind group for the sampler and textures
3726
+ $.pass.setBindGroup(0, $.textureBindGroup);
3727
+ });
3728
+
3729
+ $.image = (img, x, y, w, h) => {
3730
+ if ($._matrixDirty) $._saveMatrix();
3731
+ let ti = $._transformIndex;
3732
+
3733
+ $.imageStack.push(img.index);
3734
+
3735
+ // Calculate half-width and half-height
3736
+ let hw = w / 2;
3737
+ let hh = h / 2;
3738
+
3739
+ // Calculate vertices positions
3740
+ let left = x - hw;
3741
+ let right = x + hw;
3742
+ let top = -(y - hh); // y is inverted in WebGPU
3743
+ let bottom = -(y + hh);
3744
+
3745
+ let ii = img.index;
3746
+
3747
+ // prettier-ignore
3748
+ $.vertexStack.push(
3749
+ left, top, 0, 0, ti, ii,
3750
+ right, top, 1, 0, ti, ii,
3751
+ left, bottom, 0, 1, ti, ii,
3752
+ right, top, 1, 0, ti, ii,
3753
+ left, bottom, 0, 1, ti, ii,
3754
+ right, bottom, 1, 1, ti, ii
3755
+ );
3756
+
3757
+ $.drawStack.push(6);
3758
+ };
3759
+ };
3567
3760
  Q5.renderers.webgpu.text = ($, q) => {};
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,r){let o,a=this;if(a._q5=!0,a._parent=t,a._renderer=r||"q2d",a._preloadCount=0,e??="global","auto"==e){if(!window.setup&&!window.draw)return;e="global"}a._scope=e,"global"==e&&(Q5._hasGlobal=a._isGlobal=!0,o=Q5._nodejs?global:window);let n=new Proxy(a,{set:(e,t,r)=>(a[t]=r,a._isGlobal&&(o[t]=r),!0)});a.canvas=a.ctx=a.drawingContext=null,a.pixels=[];let i=null;a.frameCount=0,a.deltaTime=16,a._targetFrameRate=0,a._targetFrameDuration=16.666666666666668,a._frameRate=a._fps=60,a._loop=!0,a._hooks={postCanvas:[],preRender:[]};let s=0;a.millis=()=>performance.now()-s,a.noCanvas=()=>{a.canvas?.remove&&a.canvas.remove(),a.canvas=0,n.ctx=n.drawingContext=0},window&&(a.windowWidth=window.innerWidth,a.windowHeight=window.innerHeight,a.deviceOrientation=window.screen?.orientation?.type),a._incrementPreload=()=>n._preloadCount++,a._decrementPreload=()=>n._preloadCount--,a._draw=e=>{let t=e||performance.now();if(a._lastFrameTime??=t-a._targetFrameDuration,a._shouldResize&&(a.windowResized(),a._shouldResize=!1),a._loop)i=c(a._draw);else if(a.frameCount&&!a._redraw)return;if(i&&a.frameCount){if(t-a._lastFrameTime<a._targetFrameDuration-4)return}n.deltaTime=t-a._lastFrameTime,a._frameRate=1e3/a.deltaTime,n.frameCount++;let r=performance.now();a.ctx&&a.resetMatrix(),a._beginRender&&a._beginRender();for(let e of Q5.methods.pre)e.call(a);a.draw(),a._render&&a._render();for(let e of Q5.methods.post)e.call(a);a._finishRender&&a._finishRender(),n.pmouseX=a.mouseX,n.pmouseY=a.mouseY,a._lastFrameTime=t;let o=performance.now();a._fps=Math.round(1e3/(o-r))},a.noLoop=()=>{a._loop=!1,i=null},a.loop=()=>{a._loop=!0,null==i&&a._draw()},a.isLooping=()=>a._loop,a.redraw=(e=1)=>{a._redraw=!0;for(let t=0;t<e;t++)a._draw();a._redraw=!1},a.remove=()=>{a.noLoop(),a.canvas.remove()},a.frameRate=e=>(e&&(a._targetFrameRate=e,a._targetFrameDuration=1e3/e),a._frameRate),a.getTargetFrameRate=()=>a._targetFrameRate,a.getFPS=()=>a._fps,a.Element=function(e){this.elt=e},a._elements=[],a.TWO_PI=a.TAU=2*Math.PI,a.log=a.print=console.log,a.describe=()=>{};for(let e in Q5.modules)Q5.modules[e](a,n);let l=Q5.renderers[a._renderer];for(let e in l)l[e](a,n);for(let e in Q5)"_"!=e[1]&&e[1]==e[1].toUpperCase()&&(a[e]=Q5[e]);if("graphics"==e)return;"global"==e&&(Object.assign(Q5,a),delete Q5.Q5);for(let e of Q5.methods.init)e.call(a);for(let[e,t]of Object.entries(Q5.prototype))"_"!=e[0]&&"function"==typeof a[e]&&(a[e]=t.bind(a));if("global"==e){let e=Object.getOwnPropertyNames(a);for(let t of e)"_"!=t[0]&&(o[t]=a[t])}"function"==typeof e&&e(a),Q5._instanceCount++;let c=window.requestAnimationFrame||function(e){const t=a._lastFrameTime+a._targetFrameDuration;return setTimeout((()=>{e(t)}),t-performance.now())},d=o||a;a._isTouchAware=d.touchStarted||d.touchMoved||d.mouseReleased;let h=d.preload,u=["setup","draw","preload","mouseMoved","mousePressed","mouseReleased","mouseDragged","mouseClicked","keyPressed","keyReleased","keyTyped","touchStarted","touchMoved","touchEnded","windowResized"];for(let e of u)d[e]?a._isGlobal&&(a[e]=()=>{try{return d[e]()}catch(e){a._aiErrorAssistance?a._aiErrorAssistance(e):console.error(e)}}):a[e]=()=>{};async function _(){if(a._startDone=!0,a._preloadCount>0)return c(_);s=performance.now(),await a.setup(),a.frameCount||(null===a.ctx&&a.createCanvas(100,100),a._setupDone=!0,a.ctx&&a.resetMatrix(),c(a._draw))}(a.setup||a.draw)&&(arguments.length&&"namespace"!=e&&"webgpu"!=r||h?(a.preload(),_()):(d.preload=a.preload=()=>{a._startDone||_()},setTimeout(a.preload,32)))}Q5.renderers={},Q5.modules={},Q5._nodejs="object"==typeof process,Q5._instanceCount=0,Q5._friendlyError=(e,t)=>{throw Error(t+": "+e)},Q5._validateParameters=()=>!0,Q5.methods={init:[],pre:[],post:[],remove:[]},Q5.prototype.registerMethod=(e,t)=>Q5.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.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 r=e.canvas;if(r.width=e.width=100,r.height=e.height=100,"image"!=e._scope&&(r.renderer=e._renderer,r[e._renderer]=!0),e._pixelDensity=1,e._adjustDisplay=()=>{r.style&&(r.style.width=r.w+"px",r.style.height=r.h+"px")},e.createCanvas=function(t,o,a){a??=arguments[3];let n=Object.assign({},Q5.canvasOptions);if("object"==typeof a&&Object.assign(n,a),"image"!=e._scope){let t=e.displayDensity();"graphics"==e._scope?t=this._pixelDensity:window.IntersectionObserver&&new IntersectionObserver((e=>{r.visible=e[0].isIntersecting})).observe(r),e._pixelDensity=Math.ceil(t)}e._setCanvasSize(t,o),Object.assign(r,n);let i=e._createCanvas(r.w,r.h,n);if(e._hooks)for(let t of e._hooks.postCanvas)t();return i},e._save=async(e,t,r)=>{if(t=t||"untitled","jpg"==(r=r||"png")||"png"==r||"webp"==r)if(e instanceof OffscreenCanvas){const t=await e.convertToBlob({type:"image/"+r});e=await new Promise((e=>{const r=new FileReader;r.onloadend=()=>e(r.result),r.readAsDataURL(t)}))}else e=e.toDataURL("image/"+r);else{let t="text/plain";"json"==r&&("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+"."+r,o.click(),URL.revokeObjectURL(o.href)},e.save=(t,r,o)=>{if((!t||"string"==typeof t&&(!r||!o&&r.length<5))&&(o=r,r=t,t=e.canvas),o)return e._save(t,r,o);r?(r=r.split("."),e._save(t,r[0],r.at(-1))):e._save(t)},e._setCanvasSize=(o,a)=>{o??=window.innerWidth,a??=window.innerHeight,r.w=o=Math.ceil(o),r.h=a=Math.ceil(a),r.hw=o/2,r.hh=a/2,r.width=Math.ceil(o*e._pixelDensity),r.height=Math.ceil(a*e._pixelDensity),e._da?e.flexibleCanvas(e._dau):(t.width=o,t.height=a),e.displayMode&&!r.displayMode?e.displayMode():e._adjustDisplay()},"image"!=e._scope){if(r&&"graphics"!=e._scope){function o(){let t=e._parent;t??=document.getElementsByTagName("main")[0],t||(t=document.createElement("main"),document.body.append(t)),r.parent(t)}r.parent=t=>{function o(){e.frameCount>1&&(e._shouldResize=!0,e._adjustDisplay())}r.parentElement&&r.parentElement.removeChild(r),"string"==typeof t&&(t=document.getElementById(t)),t.append(r),"function"==typeof ResizeObserver?(e._ro&&e._ro.disconnect(),e._ro=new ResizeObserver(o),e._ro.observe(t)):e.frameCount||window.addEventListener("resize",o)},document.body?o():document.addEventListener("DOMContentLoaded",o)}e.resizeCanvas=(t,o)=>{if(!e.ctx)return e.createCanvas(t,o);t==r.w&&o==r.h||e._resizeCanvas(t,o)},e.canvas.resize=e.resizeCanvas,e.canvas.save=e.saveCanvas=e.save,e.displayDensity=()=>window.devicePixelRatio,e.pixelDensity=t=>t&&t!=e._pixelDensity?(e._pixelDensity=t,e._setCanvasSize(r.w,r.h),t):e._pixelDensity,e.flexibleCanvas=(o=400)=>{o?(e._da=r.width/(o*e._pixelDensity),t.width=e._dau=o,t.height=r.h/r.w*o):e._da=0}}},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.renderers.q2d={},Q5.renderers.q2d.canvas=(e,t)=>{let r=e.canvas;e.colorMode&&e.colorMode("rgb","integer"),e._createCanvas=function(o,a,n){return t.ctx=t.drawingContext=r.getContext("2d",n),"image"!=e._scope&&(e.ctx.fillStyle="white",e.ctx.strokeStyle="black",e.ctx.lineCap="round",e.ctx.lineJoin="miter",e.ctx.textAlign="left"),e.ctx.scale(e._pixelDensity,e._pixelDensity),e.ctx.save(),r},"image"!=e._scope&&(e._resizeCanvas=(t,o)=>{let a={};for(let t in e.ctx)"function"!=typeof e.ctx[t]&&(a[t]=e.ctx[t]);delete a.canvas;let n=new e._OffscreenCanvas(r.width,r.height);n.w=r.w,n.h=r.h,n.getContext("2d").drawImage(r,0,0),e._setCanvasSize(t,o);for(let t in a)e.ctx[t]=a[t];e.scale(e._pixelDensity),e.ctx.drawImage(n,0,0,n.w,n.h)},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.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.strokeWeight=t=>{t||(e._doStroke=!1),e._da&&(t*=e._da),e.ctx.lineWidth=t||1e-4},e.noStroke=()=>e._doStroke=!1,e.clear=()=>e.ctx.clearRect(0,0,e.canvas.width,e.canvas.height),e.translate=(t,r)=>{e._da&&(t*=e._da,r*=e._da),e.ctx.translate(t,r)},e.rotate=t=>{"degrees"==e._angleMode&&(t=e.radians(t)),e.ctx.rotate(t)},e.scale=(t,r)=>{r??=t,e.ctx.scale(t,r)},e.opacity=t=>e.ctx.globalAlpha=t,e.applyMatrix=(t,r,o,a,n,i)=>e.ctx.transform(t,r,o,a,n,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.scale(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 r of e._styleNames)t[r]=e[r];e._styles.push(t)},e.pop=e.popMatrix=()=>{e.ctx.restore();let t=e._styles.pop();for(let r of e._styleNames)e[r]=t[r]},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,r,o){let a=new Q5("graphics");return o??={},o.alpha??=!0,o.colorSpace??=e.canvas.colorSpace,a.createCanvas.call(e,t,r,o),a},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.renderers.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,r=[];function o(){e._doFill&&e.ctx.fill(),e._doStroke&&e.ctx.stroke()}function a(t,r,a,n,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(),a==n)d&&(i=e.radians(i),s=e.radians(s)),e.ctx.arc(t,r,a/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)*a/2,u=e.sin(d)*n/2;e.ctx[o?"lineTo":"moveTo"](t+h,r+u)}l==e.CHORD?e.ctx.closePath():l==e.PIE&&(e.ctx.lineTo(t,r),e.ctx.closePath())}o()}}function n(t,r,a,n){(e._doFill||e._doStroke)&&(e._da&&(t*=e._da,r*=e._da,a*=e._da,n*=e._da),e.ctx.beginPath(),e.ctx.ellipse(t,r,a/2,n/2,0,0,e.TAU),o())}function i(t,r,a,n,s,l,c,d){if(e._doFill||e._doStroke){if(void 0===s)return function(t,r,a,n){e._da&&(t*=e._da,r*=e._da,a*=e._da,n*=e._da),e.ctx.beginPath(),e.ctx.rect(t,r,a,n),o()}(t,r,a,n);if(void 0===l)return i(t,r,a,n,s,s,s,s);e._da&&(t*=e._da,r*=e._da,a*=e._da,n*=e._da,s*=e._da,l*=e._da,d*=e._da,c*=e._da),e.ctx.roundRect(t,r,a,n,[s,l,c,d]),o()}}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.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,r,o,a)=>{e._doStroke&&(e._da&&(t*=e._da,r*=e._da,o*=e._da,a*=e._da),e.ctx.beginPath(),e.ctx.moveTo(t,r),e.ctx.lineTo(o,a),e.ctx.stroke())},e.arc=(t,r,o,n,i,s,l,c=25)=>{if(i==s)return e.ellipse(t,r,o,n);l??=e.PIE,e._ellipseMode==e.CENTER?a(t,r,o,n,i,s,l,c):e._ellipseMode==e.RADIUS?a(t,r,2*o,2*n,i,s,l,c):e._ellipseMode==e.CORNER?a(t+o/2,r+n/2,o,n,i,s,l,c):e._ellipseMode==e.CORNERS&&a((t+o)/2,(r+n)/2,o-t,n-r,i,s,l,c)},e.ellipse=(t,r,o,a)=>{a??=o,e._ellipseMode==e.CENTER?n(t,r,o,a):e._ellipseMode==e.RADIUS?n(t,r,2*o,2*a):e._ellipseMode==e.CORNER?n(t+o/2,r+a/2,o,a):e._ellipseMode==e.CORNERS&&n((t+o)/2,(r+a)/2,o-t,a-r)},e.circle=(t,r,a)=>{e._ellipseMode==e.CENTER?(e._da&&(t*=e._da,r*=e._da,a*=e._da),e.ctx.beginPath(),e.ctx.arc(t,r,a/2,0,e.TAU),o()):e.ellipse(t,r,a,a)},e.point=(t,r)=>{t.x&&(r=t.y,t=t.x),e._da&&(t*=e._da,r*=e._da),e.ctx.save(),e.ctx.beginPath(),e.ctx.arc(t,r,e.ctx.lineWidth/2,0,e.TAU),e.ctx.fillStyle=e.ctx.strokeStyle,e.ctx.fill(),e.ctx.restore()},e.rect=(t,r,o,a=o,n,s,l,c)=>{e._rectMode==e.CENTER?i(t-o/2,r-a/2,o,a,n,s,l,c):e._rectMode==e.RADIUS?i(t-o,r-a,2*o,2*a,n,s,l,c):e._rectMode==e.CORNER?i(t,r,o,a,n,s,l,c):e._rectMode==e.CORNERS&&i(t,r,o-t,a-r,n,s,l,c)},e.square=(t,r,o,a,n,i,s)=>e.rect(t,r,o,o,a,n,i,s),e.beginShape=()=>{r=[],e.ctx.beginPath(),t=!0},e.beginContour=()=>{e.ctx.closePath(),r=[],t=!0},e.endContour=()=>{r=[],t=!0},e.vertex=(o,a)=>{e._da&&(o*=e._da,a*=e._da),r=[],t?e.ctx.moveTo(o,a):e.ctx.lineTo(o,a),t=!1},e.bezierVertex=(t,o,a,n,i,s)=>{e._da&&(t*=e._da,o*=e._da,a*=e._da,n*=e._da,i*=e._da,s*=e._da),r=[],e.ctx.bezierCurveTo(t,o,a,n,i,s)},e.quadraticVertex=(t,o,a,n)=>{e._da&&(t*=e._da,o*=e._da,a*=e._da,n*=e._da),r=[],e.ctx.quadraticCurveTo(t,o,a,n)},e.bezier=(t,r,o,a,n,i,s,l)=>{e.beginShape(),e.vertex(t,r),e.bezierVertex(o,a,n,i,s,l),e.endShape()},e.triangle=(t,r,o,a,n,i)=>{e.beginShape(),e.vertex(t,r),e.vertex(o,a),e.vertex(n,i),e.endShape(e.CLOSE)},e.quad=(t,r,o,a,n,i,s,l)=>{e.beginShape(),e.vertex(t,r),e.vertex(o,a),e.vertex(n,i),e.vertex(s,l),e.endShape(e.CLOSE)},e.endShape=t=>{r=[],t&&e.ctx.closePath(),o()},e.curveVertex=(o,a)=>{if(e._da&&(o*=e._da,a*=e._da),r.push([o,a]),r.length<4)return;let n=function(e,t,r,o,a,n,i,s,l,c){function d(e,t,r,o,a,n){let i=Math.pow(o-t,2)+Math.pow(a-r,2);return Math.pow(i,.5*n)+e}let h=[],u=d(0,e,t,r,o,c),_=d(u,r,o,a,n,c),p=d(_,a,n,i,s,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]+r*g[1],m=t*g[0]+o*g[1],f=r*g[2]+a*g[3],v=o*g[2]+n*g[3],y=a*g[4]+i*g[5],w=n*g[4]+s*g[5],S=x*g[6]+f*g[7],C=m*g[6]+v*g[7],b=f*g[8]+y*g[9],M=v*g[8]+w*g[9],Q=S*g[2]+b*g[3],R=C*g[2]+M*g[3];h.push([Q,R])}return h}(...r.at(-4),...r.at(-3),...r.at(-2),...r.at(-1),e._curveDetail,e._curveAlpha);for(let r=0;r<n.length;r++)t?e.ctx.moveTo(...n[r]):e.ctx.lineTo(...n[r]),t=!1},e.curve=(t,r,o,a,n,i,s,l)=>{e.beginShape(),e.curveVertex(t,r),e.curveVertex(o,a),e.curveVertex(n,i),e.curveVertex(s,l),e.endShape()},e.curvePoint=(e,t,r,o,a)=>{const n=a*a*a,i=a*a;return e*(-.5*n+i-.5*a)+t*(1.5*n-2.5*i+1)+r*(-1.5*n+2*i+.5*a)+o*(.5*n-.5*i)},e.bezierPoint=(e,t,r,o,a)=>{const n=1-a;return Math.pow(n,3)*e+3*Math.pow(n,2)*a*t+3*n*Math.pow(a,2)*r+Math.pow(a,3)*o},e.curveTangent=(e,t,r,o,a)=>{const n=a*a;return e*(-3*n/2+2*a-.5)+t*(9*n/2-5*a)+r*(-9*n/2+4*a+.5)+o*(3*n/2-a)},e.bezierTangent=(e,t,r,o,a)=>{const n=1-a;return 3*o*Math.pow(a,2)-3*r*Math.pow(a,2)+6*r*n*a-6*t*n*a+3*t*Math.pow(n,2)-3*e*Math.pow(n,2)},e.erase=function(t=255,r=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, ${r/255})`},e.noErase=function(){e.ctx.globalCompositeOperation="source-over",e.ctx.restore()},e.inFill=(t,r)=>{const o=e._pixelDensity;return e.ctx.isPointInPath(t*o,r*o)},e.inStroke=(t,r)=>{const o=e._pixelDensity;return e.ctx.isPointInStroke(t*o,r*o)}},Q5.renderers.q2d.image=(e,t)=>{Q5.Image??=class{constructor(e,t,r){let o=this;o._scope="image",o.canvas=o.ctx=o.drawingContext=null,o.pixels=[],Q5.modules.canvas(o,o);let a=Q5.renderers.q2d;for(let e of["canvas","image","soft_filters"])a[e]&&a[e](o,o);o.createCanvas(e,t,r),delete o.createCanvas,o._loop=!1}get w(){return this.width}get h(){return this.height}},e.createImage=(t,r,o)=>(o??={},o.alpha??=!0,o.colorSpace??=e.canvas.colorSpace||Q5.canvasOptions.colorSpace,new Q5.Image(t,r,o)),e.loadImage=function(r,o,a){if(r.canvas)return r;if("gif"==r.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 n=[...arguments].at(-1);a="object"==typeof n?n:null;let i=e.createImage(1,1,a);function s(e){i.resize(e.naturalWidth||e.width,e.naturalHeight||e.height),i.ctx.drawImage(e,0,0),t._preloadCount--,o&&o(i)}if(Q5._nodejs&&global.CairoCanvas)global.CairoCanvas.loadImage(r).then(s).catch((e=>{throw t._preloadCount--,e}));else{let e=new window.Image;e.src=r,e.crossOrigin="Anonymous",e._pixelDensity=1,e.onload=()=>s(e),e.onerror=e=>{throw t._preloadCount--,e}}return i},e.imageMode=t=>e._imageMode=t,e.image=(t,r,o,a,n,i=0,s=0,l,c)=>{let d=t.canvas||t;Q5._createNodeJSCanvas&&(d=d.context.canvas),a??=t.width||t.videoWidth,n??=t.height||t.videoHeight,"center"==e._imageMode&&(r-=.5*a,o-=.5*n),e._da&&(r*=e._da,o*=e._da,a*=e._da,n*=e._da,i*=e._da,s*=e._da,l*=e._da,c*=e._da);let h=t._pixelDensity||1;l?l*=h:l=d.width||d.videoWidth,c?c*=h:c=d.height||d.videoHeight,e.ctx.drawImage(d,i*h,s*h,l,c,r,o,a,n),e._tint&&(e.ctx.globalCompositeOperation="multiply",e.ctx.fillStyle=e._tint.toString(),e.ctx.fillRect(r,o,a,n),e.ctx.globalCompositeOperation="source-over")},e._tint=null;let r=null;e._softFilter=()=>{throw new Error("Load q5-2d-soft-filters.js to use software filters.")},e.filter=(t,r)=>{if(!e.ctx.filter)return e._softFilter(t,r);if("string"==typeof t)f=t;else if(t==Q5.GRAY)f="saturate(0%)";else if(t==Q5.INVERT)f="invert(100%)";else if(t==Q5.BLUR){let t=Math.ceil(r*e._pixelDensity)||1;f=`blur(${t}px)`}else{if(t!=Q5.THRESHOLD)return e._softFilter(t,r);{r??=.5;let e=Math.floor(.5/Math.max(r,1e-5)*100);f=`saturate(0%) brightness(${e}%) contrast(1000000%)`}}e.ctx.filter=f,e.ctx.drawImage(e.canvas,0,0,e.canvas.w,e.canvas.h),e.ctx.filter="none"},"image"==e._scope&&(e.resize=(t,r)=>{let o=new e._OffscreenCanvas(e.canvas.width,e.canvas.height);o.getContext("2d",{colorSpace:e.canvas.colorSpace}).drawImage(e.canvas,0,0),e._setCanvasSize(t,r),e.ctx.clearRect(0,0,e.canvas.width,e.canvas.height),e.ctx.drawImage(o,0,0,e.canvas.width,e.canvas.height)}),e.trim=()=>{let t=e._pixelDensity||1,r=e.canvas.width,o=e.canvas.height,a=e.ctx.getImageData(0,0,r,o).data,n=r,i=0,s=o,l=0,c=3;for(let e=0;e<o;e++)for(let t=0;t<r;t++)0!==a[c]&&(t<n&&(n=t),t>i&&(i=t),e<s&&(s=e),e>l&&(l=e)),c+=4;return s=Math.floor(s/t),l=Math.floor(l/t),n=Math.floor(n/t),i=Math.floor(i/t),e.get(n,s,i-n+1,l-s+1)},e.mask=t=>{e.ctx.save(),e.ctx.resetTransform();let r=e.ctx.globalCompositeOperation;e.ctx.globalCompositeOperation="destination-in",e.ctx.drawImage(t.canvas,0,0),e.ctx.globalCompositeOperation=r,e.ctx.restore()},e.get=(t,r,o,a)=>{let n=e._pixelDensity||1;if(void 0!==t&&void 0===o){let o=e.ctx.getImageData(t*n,r*n,1,1).data;return new e.Color(o[0],o[1],o[2],o[3]/255)}t=(t||0)*n,r=(r||0)*n;let i=o=o||e.width,s=a=a||e.height;o*=n,a*=n;let l=e.createImage(o,a),c=e.ctx.getImageData(t,r,o,a);return l.ctx.putImageData(c,0,0),l._pixelDensity=n,l.width=i,l.height=s,l},e.set=(t,r,o)=>{if(o.canvas){let a=e._tint;return e._tint=null,e.image(o,t,r),void(e._tint=a)}e.pixels.length||e.loadPixels();let a=e._pixelDensity||1;for(let n=0;n<a;n++)for(let i=0;i<a;i++){let s=4*((r*a+n)*e.canvas.width+t*a+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=()=>{r=e.ctx.getImageData(0,0,e.canvas.width,e.canvas.height),t.pixels=r.data},e.updatePixels=()=>{null!=r&&e.ctx.putImageData(r,0,0)},e.smooth=()=>e.ctx.imageSmoothingEnabled=!0,e.noSmooth=()=>e.ctx.imageSmoothingEnabled=!1,"image"!=e._scope&&(e.tint=function(t){e._tint=t._q5Color?t:e.color(...arguments)},e.noTint=()=>e._tint=null)},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.renderers.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,r)=>{t._preloadCount++;let o=e.split("/").pop().split(".")[0].replace(" ",""),a=new FontFace(o,`url(${e})`);return document.fonts.add(a),a.load().then((()=>{t._preloadCount--,r&&r(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,r)=>{e.ctx.textAlign=t,r&&(e.ctx.textBaseline=r==e.CENTER?"middle":r)},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,r=0;for(const[o,a]of this.entries())a.lastAccessed<t&&(t=a.lastAccessed,e=r),r++;r=e;for(const t of this.keys()){if(0==r){e=t;break}r--}this.delete(e)}},e._tic=new e._TimedCache,e.textCache=(t,r)=>(r&&(e._tic.maxSize=r),void 0!==t&&(e._textCache=t),e._textCache),e._genTextImageKey=(t,r,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+"_":"")+(r||"")+(o?"x"+o:""),e.createTextImage=(t,r,o)=>{let a=e._textCache;e._textCache=!0,e._genTextImage=!0,e.text(t,0,0,r,o),e._genTextImage=!1;let n=e._genTextImageKey(t,r,o);return e._textCache=a,e._tic.get(n)},e.text=(t,r,o,a,n)=>{if(void 0===t)return;if(t=t.toString(),e._da&&(r*=e._da,o*=e._da),!e._doFill&&!e._doStroke)return;let i,s,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,a,n),s=e._tic.get(c),s&&!e._genTextImage)return void e.textImage(s,r,o);l=e.createGraphics.call(e,1,1),i=l.ctx}else i=e.ctx,d=r,h=o;i.font=`${e._textStyle} ${e._textSize}px ${e._textFont}`;let x=t.split("\n");if(g){d=0,h=e._textLeading*x.length;let r=i.measureText(" ");u=r.fontBoundingBoxAscent,_=r.fontBoundingBoxDescent,n??=h+_,l.resizeCanvas(Math.ceil(i.measureText(t).width),Math.ceil(n)),i.fillStyle=e.ctx.fillStyle,i.strokeStyle=e.ctx.strokeStyle,i.lineWidth=e.ctx.lineWidth}let m=i.fillStyle;e._fillSet||(i.fillStyle="black");for(let t=0;t<x.length&&(e._doStroke&&e._strokeSet&&i.strokeText(x[t],d,h),e._doFill&&i.fillText(x[t],d,h),h+=e._textLeading,!(h>n));t++);e._fillSet||(i.fillStyle=m),g&&(s=l.get(),s._ascent=u,s._descent=_,e._tic.set(c,s),e._genTextImage||e.textImage(s,r,o))},e.textImage=(t,r,o)=>{let a=e._imageMode;e._imageMode="corner","center"==e.ctx.textAlign?r-=.5*t.width:"right"==e.ctx.textAlign&&(r-=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,r,o),e._imageMode=a},e.nf=(e,t,r)=>{let o=e<0,a=(e=Math.abs(e)).toFixed(r).split(".");a[0]=a[0].padStart(t,"0");let n=a.join(".");return o&&(n="-"+n),n}},Q5.modules.ai=e=>{e.askAI=(e="")=>{throw Error("Ask AI ✨ "+e)},e._aiErrorAssistance=async t=>{let r=t.message?.includes("Ask AI ✨");if(r||console.error(t),Q5.disableFriendlyErrors)return;!r&&Q5.errorTolerant||e.noLoop();let o=t.stack?.split("\n");if(!t.stack||o.length<=1)return;let a=1,n="(";for(-1==navigator.userAgent.indexOf("Chrome")&&(a=0,n="@");o[a].indexOf("q5.js:")>=0;)a++;let i=o[a].split(n).at(-1);i=i.split(":");let s=parseInt(i.at(-2));r&&s++;let l=i.slice(0,-2).join(":"),c=l.split("/").at(-1);try{let e=(await(await fetch(l)).text()).split("\n"),o=e[s-1].trim(),a="",n=1;for(;a.length<1600&&(s-n>=0&&(a=e[s-n].trim()+"\n"+a),s+n<e.length);)a+=e[s+n].trim()+"\n",n++;let i="https://chatgpt.com/?q=q5.js+"+(r&&t.message.length>10?t.message.slice(10):"Whats+wrong+with+this+line%3F+short+answer")+(r?"":"%0A%0A"+encodeURIComponent(t.name+": "+t.message))+"%0A%0ALine%3A+"+encodeURIComponent(o)+"%0A%0AExcerpt+for+context%3A%0A%0A"+encodeURIComponent(a);r||console.log("Error in "+c+" on line "+s+":\n\n"+o),console.warn("Ask AI ✨ "+i),r&&window.open(i,"_blank")}catch(e){}}},Q5.modules.color=(e,t)=>{e.RGB=e.RGBA=e._colorMode="rgb",e.OKLCH="oklch",e.colorMode=(r,o)=>{e._colorMode=r;let a="srgb"==e.canvas.colorSpace||"srgb"==r;if(o??=a?"integer":"float",e._colorFormat="float"==o||1==o?1:255,"oklch"==r)t.Color=Q5.ColorOKLCH;else{let r="srgb"==e.canvas.colorSpace;255==e._colorFormat?t.Color=r?Q5.ColorRGBA_8:Q5.ColorRGBA_P3_8:t.Color=r?Q5.ColorRGBA:Q5.ColorRGBA_P3,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=(t,r,o,a)=>{let n=e.Color;if(t._q5Color)return new n(...t.levels);if(null==r){if("string"==typeof t)if("#"==t[0])t.length<=5?(t.length>4&&(a=parseInt(t[4]+t[4],16)),o=parseInt(t[3]+t[3],16),r=parseInt(t[2]+t[2],16),t=parseInt(t[1]+t[1],16)):(t.length>7&&(a=parseInt(t.slice(7,9),16)),o=parseInt(t.slice(5,7),16),r=parseInt(t.slice(3,5),16),t=parseInt(t.slice(1,3),16));else{if(!e._namedColors[t])return console.error("q5 can't parse color: "+t+"\nOnly numeric input, hex, and common named colors are supported."),new n(0,0,0);t=e._namedColors[t]}Array.isArray(t)&&(r=t[1],o=t[2],a=t[3],t=t[0])}return 1==e._colorFormat&&(t/=255,r&&(r/=255),o&&(o/=255),a&&(a/=255)),null==o?new n(t,t,t,r):new n(t,r,o,a)},e.red=e=>e.r,e.green=e=>e.g,e.blue=e=>e.b,e.alpha=e=>e.a,e.lightness=t=>"oklch"==e._colorMode?t.l:100*(.2126*t.r+.7152*t.g+.0722*t.b)/255,e.hue=t=>{if("oklch"==e._colorMode)return t.h;let r=t.r,o=t.g,a=t.b;255==e._colorFormat&&(r/=255,o/=255,a/=255);let n,i=Math.max(r,o,a),s=Math.min(r,o,a);return n=i==s?0:i==r?60*(o-a)/(i-s):i==o?60*(a-r)/(i-s)+120:60*(r-o)/(i-s)+240,n<0&&(n+=360),n},e.lerpColor=(t,r,o)=>{if("rgb"==e._colorMode)return new e.Color(e.constrain(e.lerp(t.r,r.r,o),0,255),e.constrain(e.lerp(t.g,r.g,o),0,255),e.constrain(e.lerp(t.b,r.b,o),0,255),e.constrain(e.lerp(t.a,r.a,o),0,255));{let a=r.h-t.h;a>180&&(a-=360),a<-180&&(a+=360);let n=t.h+o*a;return n<0&&(n+=360),n>360&&(n-=360),new e.Color(e.constrain(e.lerp(t.l,r.l,o),0,100),e.constrain(e.lerp(t.c,r.c,o),0,100),n,e.constrain(e.lerp(t.a,r.a,o),0,255))}}},Q5.Color=class{constructor(){this._q5Color=!0}},Q5.ColorOKLCH=class extends Q5.Color{constructor(e,t,r,o){super(),this.l=e,this.c=t,this.h=r,this.a=o??1}toString(){return`oklch(${this.l} ${this.c} ${this.h} / ${this.a})`}},Q5.ColorRGBA=class extends Q5.Color{constructor(e,t,r,o){super(),this.r=e,this.g=t,this.b=r,this.a=o??1}get levels(){return[this.r,this.g,this.b,this.a]}toString(){return`color(srgb ${this.r} ${this.g} ${this.b} / ${this.a})`}},Q5.ColorRGBA_P3=class extends Q5.ColorRGBA{toString(){return`color(display-p3 ${this.r} ${this.g} ${this.b} / ${this.a})`}},Q5.ColorRGBA_8=class extends Q5.ColorRGBA{constructor(e,t,r,o){super(e,t,r,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_8=class extends Q5.ColorRGBA{constructor(e,t,r,o){super(e,t,r,o??255),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),r=(this._b/255).toFixed(3),o=(this._a/255).toFixed(3);this._css=`color(display-p3 ${e} ${t} ${r} / ${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 r=t.style,o=t.parentElement;r&&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"),r.width=t.w*t.displayScale+"px",r.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?(r.width=t.w*t.displayScale+"px",r.maxWidth="100%"):r.width="100%",r.height="auto",r.maxHeight=""):(r.width="auto",r.maxWidth="","centered"==t.displayMode?(r.height=t.h*t.displayScale+"px",r.maxHeight="100%"):r.height="100%")))},e.displayMode=(r="normal",o="default",a=1)=>{"string"==typeof a&&(a=parseFloat(a.slice(1))),Object.assign(t,{displayMode:r,renderQuality:o,displayScale:a}),e._adjustDisplay()},e.fullscreen=e=>{if(void 0===e)return document.fullscreenElement;e?document.body.requestFullscreen():document.body.exitFullscreen()}},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 r={},o=[e.LEFT,e.CENTER,e.RIGHT],a=e.canvas;function n(t){const r=e.canvas.getBoundingClientRect(),o=e.canvas.scrollWidth/e.width||1,a=e.canvas.scrollHeight/e.height||1;return{x:(t.clientX-r.left)/o,y:(t.clientY-r.top)/a,id:t.identifier}}if(e._startAudio=()=>{e.getAudioContext&&"suspended"==e.getAudioContext()?.state&&e.userStartAudio()},e._updateMouse=r=>{if(!r.changedTouches)if(a){let o=a.getBoundingClientRect(),n=a.scrollWidth/e.width||1,i=a.scrollHeight/e.height||1;t.mouseX=(r.clientX-o.left)/n,t.mouseY=(r.clientY-o.top)/i,"webgpu"==a.renderer&&(t.mouseX-=a.hw,t.mouseY-=a.hh)}else t.mouseX=r.clientX,t.mouseY=r.clientY},e._onmousedown=r=>{e._startAudio(),e._updateMouse(r),t.mouseIsPressed=!0,t.mouseButton=o[r.button],e.mousePressed(r)},e._onmousemove=t=>{e._updateMouse(t),e.mouseIsPressed?e.mouseDragged(t):e.mouseMoved(t)},e._onmouseup=r=>{e._updateMouse(r),t.mouseIsPressed=!1,e.mouseReleased(r)},e._onclick=r=>{e._updateMouse(r),t.mouseIsPressed=!0,e.mouseClicked(r),t.mouseIsPressed=!1},e.cursor=(t,r,o)=>{let a="";t.includes(".")&&(t=`url("${t}")`,a=", auto"),void 0!==r&&(t+=" "+r+" "+o),e.canvas.style.cursor=t+a},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,r[e.keyCode]=r[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,r[e.keyCode]=r[e.key.toLowerCase()]=!1,e.keyReleased(o)},e.keyIsDown=e=>!!r["string"==typeof e?e.toLowerCase():e],e._ontouchstart=r=>{e._startAudio(),t.touches=[...r.touches].map(n),e._isTouchAware||(t.mouseX=e.touches[0].x,t.mouseY=e.touches[0].y,t.mouseIsPressed=!0,t.mouseButton=e.LEFT,e.mousePressed(r)||r.preventDefault()),e.touchStarted(r)||r.preventDefault()},e._ontouchmove=r=>{t.touches=[...r.touches].map(n),e._isTouchAware||(t.mouseX=e.touches[0].x,t.mouseY=e.touches[0].y,e.mouseDragged(r)||r.preventDefault()),e.touchMoved(r)||r.preventDefault()},e._ontouchend=r=>{t.touches=[...r.touches].map(n),e._isTouchAware||e.touches.length||(t.mouseIsPressed=!1,e.mouseReleased(r)||r.preventDefault()),e.touchEnded(r)||r.preventDefault()},a&&(a.addEventListener("mousedown",(t=>e._onmousedown(t))),a.addEventListener("mouseup",(t=>e._onmouseup(t))),a.addEventListener("click",(t=>e._onclick(t))),a.addEventListener("touchstart",(t=>e._ontouchstart(t))),a.addEventListener("touchmove",(t=>e._ontouchmove(t))),a.addEventListener("touchcancel",(t=>e._ontouchend(t))),a.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)=>{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=Q5.prototype.map=(e,t,r,o,a,n)=>{let i=o+1*(e-t)/(r-t)*(a-o);return n?o<a?Math.min(Math.max(i,o),a):Math.min(Math.max(i,a),o):i},e.lerp=(e,t,r)=>e*(1-r)+t*r,e.constrain=(e,t,r)=>Math.min(Math.max(e,t),r),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,r,o)=>e.map(t,r,o,0,1),e.sq=e=>e*e,e.fract=e=>e-Math.floor(e);for(let t of["sin","cos","tan"])e[t]=r=>("degrees"==e._angleMode&&(r=e.radians(r)),Math[t](r));for(let t of["asin","acos","atan"])e[t]=r=>{let o=Math[t](r);return"degrees"==e._angleMode&&(o=e.degrees(o)),o};function r(){let e,t,r=4294967295;return{setSeed(o){e=t=(o??Math.random()*r)>>>0},getSeed:()=>t,rand:()=>(e^=e<<17,e^=e>>13,e^=e<<5,(e>>>0)/r)}}e.atan2=(t,r)=>{let o=Math.atan2(t,r);return"degrees"==e._angleMode&&(o=e.degrees(o)),o};let o=r();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,r;return{setSeed(o){r=t=(o??Math.random()*e)>>>0},getSeed:()=>t,rand:()=>(r=(1664525*r+1013904223)%e,r/e)}}():t==e.SHR3&&(o=r()),o.setSeed()};var a=new function(){var e,t,r,a=new Array(128),n=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,n,l,c=3.44262;;){if(t=r*i[e],0==e){do{n=h(),l=h(),t=.2904764*-Math.log(n),o=-Math.log(l)}while(o+o<t*t);return r>0?c+t:-c-t}if(s[e]+h()*(s[e-1]-s[e])<Math.exp(-.5*t*t))return t;if(r=d(),e=127&r,Math.abs(r)<a[e])return r*i[e]}},_=()=>{for(var r;;){if(0==e)return 7.69711-Math.log(h());if(r=t*l[e],c[e]+h()*(c[e-1]-c[e])<Math.exp(-r))return r;if((t=d())<n[e=255&t])return t*l[e]}};this.SHR3=d,this.UNI=h,this.RNOR=()=>(r=d(),e=127&r,Math.abs(r)<a[e]?r*i[e]:u()),this.REXP=()=>(t=d()>>>0)<a[e=255&t]?t*l[e]:_(),this.zigset=()=>{var e,t,r=2147483648,o=4294967296,d=3.442619855899,h=d,u=.00991256303526217,_=7.697117470131487,p=_,g=.003949659822581572;for(e=u/Math.exp(-.5*d*d),a[0]=Math.floor(d/e*r),a[1]=0,i[0]=e/r,i[127]=d/r,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))),a[t+1]=Math.floor(d/h*r),h=d,s[t]=Math.exp(-.5*d*d),i[t]=d/r;for(e=g/Math.exp(-_),n[0]=Math.floor(_/e*o),n[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(-_)),n[t+1]=Math.floor(_/p*o),p=_,c[t]=Math.exp(-_),l[t]=_/o}};let n;a.hasInit=!1,e.randomGaussian=(e,t)=>(a.hasInit||(a.zigset(),a.hasInit=!0),a.RNOR()*t+e),e.randomExponential=()=>(a.hasInit||(a.zigset(),a.hasInit=!0),a.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"],n=null},e.noiseSeed=t=>{n=new e.Noise(t)},e.noise=(t=0,r=0,o=0)=>(n??=new e.Noise,n.noise(t,r,o)),e.noiseDetail=(t,r)=>{n??=new e.Noise,t>0&&(n.octaves=t),r>0&&(n.falloff=r)}},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,r,o=[];for(let e=0;e<256;e++)o[e]=e;for(let a=255;a>0;a--)t=(e=16807*e%2147483647)%(a+1),r=o[a],o[a]=o[t],o[t]=r;return o}dot(e,t,r,o){return e[0]*t+e[1]*r+e[2]*o}mix(e,t,r){return(1-r)*e+r*t}fade(e){return e*e*e*(e*(6*e-15)+10)}noise(e,t,r){let o=this,a=0,n=1,i=1,s=0;for(let l=0;l<o.octaves;l++){const l=255&Math.floor(e*n),c=255&Math.floor(t*n),d=255&Math.floor(r*n),h=e*n-Math.floor(e*n),u=t*n-Math.floor(t*n),_=r*n-Math.floor(r*n),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,S=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),b=o.mix(o.dot(o.grad3[o.p[v]%12],h,u-1,_),o.dot(o.grad3[o.p[S]%12],h-1,u-1,_),p),M=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),Q=o.mix(o.dot(o.grad3[o.p[v+1]%12],h,u-1,_-1),o.dot(o.grad3[o.p[S+1]%12],h-1,u-1,_-1),p),R=o.mix(C,b,g),I=o.mix(M,Q,g);a+=o.mix(R,I,x)*i,s+=i,i*=o.falloff,n*=2}return(a/s+1)/2}},Q5.modules.sound=(e,t)=>{e.Sound=Q5.Sound,e.loadSound=(e,r)=>{t._preloadCount++,Q5.aud??=new window.AudioContext;let o=new Q5.Sound(e,r);return o.addEventListener("canplaythrough",(()=>{t._preloadCount--,o.loaded=!0,r&&r(o)})),o},e.getAudioContext=()=>Q5.aud,e.userStartAudio=()=>Q5.aud.resume()},Q5.Sound=class extends Audio{constructor(e){super(e);let t=this;t.load(),t.panner=Q5.aud.createStereoPanner(),t.source=Q5.aud.createMediaElementSource(t),t.source.connect(t.panner),t.panner.connect(Q5.aud.destination),Object.defineProperty(t,"pan",{get:()=>t.panner.pan.value,set:e=>t.panner.pan.value=e})}setVolume(e){this.volume=e}setLoop(e){this.loop=e}setPan(e){this.pan=e}isLoaded(){return this.loaded}isPlaying(){return!this.paused}},Q5.modules.util=(e,t)=>{e._loadFile=(e,r,o)=>{t._preloadCount++;let a={};return fetch(e).then((e=>"json"==o?e.json():"text"==o?e.text():void 0)).then((e=>{t._preloadCount--,Object.assign(a,e),r&&r(e)})),a},e.loadStrings=(t,r)=>e._loadFile(t,r,"text"),e.loadJSON=(t,r)=>e._loadFile(t,r,"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,r,o)=>new Q5.Vector(t,r,o,e)},Q5.Vector=class{constructor(e,t,r,o){this.x=e||0,this.y=t||0,this.z=r||0,this._$=o||window,this._cn=null,this._cnsq=null}set(e,t,r){this.x=e||0,this.y=t||0,this.z=r||0}copy(){return new Q5.Vector(this.x,this.y,this.z)}_arg2v(e,t,r){return void 0!==e?.x?e:void 0!==t?{x:e,y:t,z:r||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,r=this.y-e.y,o=this.z-e.z;return Math.sqrt(t*t+r*r+o*o)}cross(){let e=this._arg2v(...arguments),t=this.y*e.z-this.z*e.y,r=this.z*e.x-this.x*e.z,o=this.x*e.y-this.y*e.x;return this.x=t,this.y=r,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 r=e/t;this.x*=r,this.y*=r,this.z*=r,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),r=this._$.sin(e),o=this.x*t-this.y*r,a=this.x*r+this.y*t;return this.x=o,this.y=a,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)),r=e.at(-1);return this.x+=(t.x-this.x)*r,this.y+=(t.y-this.y)*r,this.z+=(t.z-this.z)*r,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,r){void 0===r&&(r=1),this._cn=r,this._cnsq=r*r;const o=this._$.cos(t),a=this._$.sin(t),n=this._$.cos(e),i=this._$.sin(e);return this.x=r*i*a,this.y=-r*n,this.z=r*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,r)=>e.equals(t,r),Q5.Vector.lerp=(e,t,r)=>e.copy().lerp(t,r),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,r,o)=>(new Q5.Vector)[e](t,r,o);Q5.renderers.webgpu={},Q5.renderers.webgpu.canvas=(e,t)=>{let r,o,a,n,i=e.canvas;function s(t,r,a,n=1){"string"==typeof t&&(t=Q5.color(t)),null==a&&(n=r,r=a=t),t._q5Color?o.push(...t.levels):o.push(t,r,a,n),e._colorIndex++}i.width=e.width=500,i.height=e.height=500,e.colorMode&&e.colorMode("rgb","float"),e._createCanvas=(r,n,s)=>{t.ctx=t.drawingContext=i.getContext("webgpu"),s.format=navigator.gpu.getPreferredCanvasFormat(),s.device=Q5.device,e.ctx.configure(s),e.pipelines=[],e.pipelinesStack=[],e.verticesStack=[],e.drawStack=[],o=e.colorsStack=[1,1,1,1],e._colorIndex=0;let l=Q5.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"uniform",hasDynamicOffset:!1}}]}),c=Q5.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage",hasDynamicOffset:!1}}]});e.bindGroupLayouts=[l,c];const d=Q5.device.createBuffer({size:8,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});Q5.device.queue.writeBuffer(d,0,new Float32Array([e.canvas.hw,e.canvas.hh])),a=Q5.device.createBindGroup({layout:l,entries:[{binding:0,resource:{buffer:d}}]})},e._resizeCanvas=(t,r)=>{e._setCanvasSize(t,r)},e.resetMatrix=()=>{e._matrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],e._transformIndex=0},e.resetMatrix(),e._matrixDirty=!1,e.transformStates=[e._matrix.slice()],e._transformIndexStack=[],e.push=()=>{e._transformIndexStack.push(e._transformIndex)},e.pop=()=>{if(e._transformIndexStack.length>0){let t=e._transformIndexStack.pop();e._matrix=e.transformStates[t].slice(),e._transformIndex=t}else console.warn("Matrix index stack is empty!")},e.translate=(t,r,o)=>{(t||r||o)&&(e._matrix[3]+=t,e._matrix[7]+=r,e._matrix[11]+=o||0,e._matrixDirty=!0)},e.rotate=t=>{if(!t)return;"degrees"==e._angleMode&&(t=e.radians(t));let r=Math.cos(t),o=Math.sin(t),a=e._matrix[0],n=e._matrix[1],i=e._matrix[4],s=e._matrix[5];a||n||i||s?(e._matrix[0]=a*r+i*o,e._matrix[1]=n*r+s*o,e._matrix[4]=a*-o+i*r,e._matrix[5]=n*-o+s*r):(e._matrix[0]=r,e._matrix[1]=o,e._matrix[4]=-o,e._matrix[5]=r),e._matrixDirty=!0},e.scale=(t=1,r,o=1)=>{r??=t,e._matrix[0]*=t,e._matrix[5]*=r,e._matrix[10]*=o,e._matrixDirty=!0},e._saveMatrix=()=>{e.transformStates.push(e._matrix.slice()),e._transformIndex=e.transformStates.length-1,e._matrixDirty=!1},e._beginRender=()=>{e.encoder=Q5.device.createCommandEncoder(),r=t.pass=e.encoder.beginRenderPass({colorAttachments:[{view:ctx.getCurrentTexture().createView(),loadOp:"clear",storeOp:"store"}]})},e._render=()=>{if(r.setBindGroup(0,a),transformStates.length>1||!n){const t=Q5.device.createBuffer({size:64*transformStates.length,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});Q5.device.queue.writeBuffer(t,0,new Float32Array(transformStates.flat())),n=Q5.device.createBindGroup({layout:e.bindGroupLayouts[1],entries:[{binding:0,resource:{buffer:t}}]})}r.setBindGroup(1,n);for(let t of e._hooks.preRender)t();let t=e.drawStack,o=0,i=-1;for(let a=0;a<t.length;a+=2){i!=t[a]&&(i=t[a],r.setPipeline(e.pipelines[i]));let n=t[a+1];r.draw(n,1,o,0),o+=n}},e._finishRender=()=>{r.end();const o=e.encoder.finish();Q5.device.queue.submit([o]),t.pass=e.encoder=null,e.verticesStack.length=0,e.drawStack.length=0,e.colorsStack.length=4,e.pipelinesStack.length=0,e._colorIndex=0,rotation=0,e.resetMatrix(),e._matrixDirty=!1,e.transformStates.length=1,e._transformIndexStack.length=0},e.fill=function(){s(...arguments),e._doFill=!0,e._fillIndex=e._colorIndex},e.stroke=function(){s(...arguments),e._doStroke=!0,e._fillIndex=e._colorIndex},e.noFill=()=>e._doFill=!1,e.noStroke=()=>e._doStroke=!1,e._strokeWeight=1,e.strokeWeight=t=>e._strokeWeight=t,e.clear=()=>{}},Q5.webgpu=async function(e,t){if(e&&"global"!=e||(Q5._hasGlobal=!0),!navigator.gpu){console.error("q5 WebGPU not supported on this browser!");let r=new Q5(e,t);return r.colorMode("rgb",1),r._beginRender=()=>r.translate(r.canvas.hw,r.canvas.hh),r}let r=await navigator.gpu.requestAdapter();if(!r)throw new Error("No appropriate GPUAdapter found.");return Q5.device=await r.requestDevice(),new Q5(e,t,"webgpu")},Q5.renderers.webgpu.drawing=(e,t)=>{let r,o,a;e.CLOSE=1,e._hooks.postCanvas.push((()=>{let t=Q5.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage",hasDynamicOffset:!1}}]});e.bindGroupLayouts.push(t),r=e.verticesStack,o=e.drawStack,a=e.colorsStack;let n={arrayStride:16,attributes:[{format:"float32x2",offset:0,shaderLocation:0},{format:"float32",offset:8,shaderLocation:1},{format:"float32",offset:12,shaderLocation:2}]},i=Q5.device.createShaderModule({code:"\nstruct VertexOutput {\n\t@builtin(position) position: vec4<f32>,\n\t@location(1) colorIndex: f32\n};\n\nstruct Uniforms {\n\thalfWidth: f32,\n\thalfHeight: f32\n};\n\n@group(0) @binding(0) var<uniform> uniforms: Uniforms;\n@group(1) @binding(0) var<storage, read> transforms: array<mat4x4<f32>>;\n\n@vertex\nfn vertexMain(@location(0) pos: vec2<f32>, @location(1) colorIndex: f32, @location(2) transformIndex: f32) -> VertexOutput {\n\tvar vert = vec4<f32>(pos, 0.0, 1.0);\n\tvert *= transforms[i32(transformIndex)];\n\tvert.x /= uniforms.halfWidth;\n\tvert.y /= uniforms.halfHeight;\n\n\tvar output: VertexOutput;\n\toutput.position = vert;\n\toutput.colorIndex = colorIndex;\n\treturn output;\n}\n"}),s=Q5.device.createShaderModule({code:"\n@group(2) @binding(0) var<storage, read> uColors : array<vec4<f32>>;\n\n@fragment\nfn fragmentMain(@location(1) colorIndex: f32) -> @location(0) vec4<f32> {\n\tlet index = u32(colorIndex);\n\treturn mix(uColors[index], uColors[index + 1u], fract(colorIndex));\n}\n"}),l=Q5.device.createPipelineLayout({bindGroupLayouts:e.bindGroupLayouts});e._createPipeline=e=>Q5.device.createRenderPipeline({layout:l,vertex:{module:i,entryPoint:"vertexMain",buffers:[n]},fragment:{module:s,entryPoint:"fragmentMain",targets:[{format:"bgra8unorm",blend:e}]},primitive:{topology:"triangle-list"}}),e.pipelines[0]=e._createPipeline(blendConfigs.normal)}));let n=["zero","one","src-alpha","one-minus-src-alpha","dst","dst-alpha","one-minus-dst-alpha","one-minus-src"],i=["add","subtract","reverse-subtract","min","max"];let s;e.blendConfigs={},Object.entries({normal:[2,3,0,2,3,0],lighter:[2,1,0,2,1,0],subtract:[2,1,2,2,1,2],multiply:[4,0,0,5,0,0],screen:[1,3,0,1,3,0],darken:[1,3,3,1,3,3],lighten:[1,3,4,1,3,4],overlay:[2,3,0,2,3,0],hard_light:[2,3,0,2,3,0],soft_light:[2,3,0,2,3,0],difference:[2,3,2,2,3,2],exclusion:[2,3,0,2,3,0],color_dodge:[1,7,0,1,7,0],color_burn:[6,1,0,6,1,0],linear_dodge:[2,1,0,2,1,0],linear_burn:[2,7,1,2,7,1],vivid_light:[2,7,0,2,7,0],pin_light:[2,7,0,2,7,0],hard_mix:[2,7,0,2,7,0]}).forEach((([t,r])=>{e.blendConfigs[t]={color:{srcFactor:n[r[0]],dstFactor:n[r[1]],operation:i[r[2]]},alpha:{srcFactor:n[r[3]],dstFactor:n[r[4]],operation:i[r[5]]}}})),e._blendMode="normal",e.blendMode=t=>{t!=e._blendMode&&("source-over"==t&&(t="normal"),t=t.toLowerCase().replace(/[ -]/g,"_"),e._blendMode=t,e.pipelines[0]=e._createPipeline(e.blendConfigs[t]))},e.beginShape=()=>{s=[]},e.vertex=(t,r)=>{e._matrixDirty&&e._saveMatrix(),s.push(t,-r,e._colorIndex,e._transformIndex)},e.endShape=e=>{let t=s;if(t.length<12)throw new Error("A shape must have at least 3 vertices.");e&&t.push(t[0],t[1],t[2],t[3]);let a=[];for(let e=4;e<t.length;e+=4)a.push(t[0],t[1],t[2],t[3],t[e-4],t[e-3],t[e-2],t[e-1],t[e],t[e+1],t[e+2],t[e+3]);r.push(...a),o.push(0,a.length/4),s=[]},e.triangle=(t,r,o,a,n,i)=>{e.beginShape(),e.vertex(t,r),e.vertex(o,a),e.vertex(n,i),e.endShape(1)},e.rect=(t,a,n,i)=>{let s=n/2,l=i/2,c=t-s,d=t+s,h=-(a-l),u=-(a+l),_=e._colorIndex;e._matrixDirty&&e._saveMatrix();let p=e._transformIndex;r.push(c,h,_,p,d,h,_,p,c,u,_,p,d,h,_,p,c,u,_,p,d,u,_,p),o.push(0,6)},e.point=(t,r)=>{let o=e._strokeWeight;1==o?e.rect(t,r,1,1):e.ellipse(t,r,o,o)},e.background=()=>{};e.ellipse=(t,a,n,i)=>{const s=(l=n==i?n:Math.max(n,i))<14?8:l<16?10:l<18?12:l<20?14:l<22?16:l<24?18:l<28?20:l<34?22:l<42?24:l<48?26:l<56?28:l<64?30:l<72?32:l<84?34:l<96?36:l<98?38:l<113?40:l<149?44:l<199?48:l<261?52:l<353?56:l<461?60:l<585?64:l<1200?70:l<1800?80:l<2400?90:100;var l;let c=Math.max(n,1)/2,d=n==i?c:Math.max(i,1)/2,h=0;const u=e.TAU/s,_=e._colorIndex;e._matrixDirty&&e._saveMatrix();const p=e._transformIndex;let g,x,m,f;for(let e=0;e<=s;e++)g=m,x=f,m=t+c*Math.cos(h),f=a+d*Math.sin(h),h+=u,0!=e&&r.push(t,a,_,p,g,x,_,p,m,f,_,p);o.push(0,3*s)},e.circle=(t,r,o)=>e.ellipse(t,r,o,o),e._hooks.preRender.push((()=>{const t=Q5.device.createBuffer({size:6*r.length,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST});Q5.device.queue.writeBuffer(t,0,new Float32Array(r)),e.pass.setVertexBuffer(0,t);const o=Q5.device.createBuffer({size:4*a.length,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});Q5.device.queue.writeBuffer(o,0,new Float32Array(a));const n=Q5.device.createBindGroup({layout:e.bindGroupLayouts[2],entries:[{binding:0,resource:{buffer:o,offset:0,size:4*a.length}}]});e.pass.setBindGroup(2,n)}))},Q5.renderers.webgpu.image=(e,t)=>{},Q5.renderers.webgpu.text=(e,t)=>{};
8
+ function Q5(e,t,r){let o,a=this;if(a._q5=!0,a._parent=t,a._renderer=r||"q2d",a._preloadCount=0,e??="global","auto"==e){if(!window.setup&&!window.draw)return;e="global"}a._scope=e,"global"==e&&(Q5._hasGlobal=a._isGlobal=!0,o=Q5._nodejs?global:window);let n=new Proxy(a,{set:(e,t,r)=>(a[t]=r,a._isGlobal&&(o[t]=r),!0)});a.canvas=a.ctx=a.drawingContext=null,a.pixels=[];let i=null;a.frameCount=0,a.deltaTime=16,a._targetFrameRate=0,a._targetFrameDuration=16.666666666666668,a._frameRate=a._fps=60,a._loop=!0,a._hooks={postCanvas:[],preRender:[]};let s=0;a.millis=()=>performance.now()-s,a.noCanvas=()=>{a.canvas?.remove&&a.canvas.remove(),a.canvas=0,n.ctx=n.drawingContext=0},window&&(a.windowWidth=window.innerWidth,a.windowHeight=window.innerHeight,a.deviceOrientation=window.screen?.orientation?.type),a._incrementPreload=()=>n._preloadCount++,a._decrementPreload=()=>n._preloadCount--,a._draw=e=>{let t=e||performance.now();if(a._lastFrameTime??=t-a._targetFrameDuration,a._shouldResize&&(a.windowResized(),a._shouldResize=!1),a._loop)i=c(a._draw);else if(a.frameCount&&!a._redraw)return;if(i&&a.frameCount){if(t-a._lastFrameTime<a._targetFrameDuration-4)return}n.deltaTime=t-a._lastFrameTime,a._frameRate=1e3/a.deltaTime,n.frameCount++;let r=performance.now();a.ctx&&a.resetMatrix(),a._beginRender&&a._beginRender();for(let e of Q5.methods.pre)e.call(a);a.draw(),a._render&&a._render();for(let e of Q5.methods.post)e.call(a);a._finishRender&&a._finishRender(),n.pmouseX=a.mouseX,n.pmouseY=a.mouseY,a._lastFrameTime=t;let o=performance.now();a._fps=Math.round(1e3/(o-r))},a.noLoop=()=>{a._loop=!1,i=null},a.loop=()=>{a._loop=!0,null==i&&a._draw()},a.isLooping=()=>a._loop,a.redraw=(e=1)=>{a._redraw=!0;for(let t=0;t<e;t++)a._draw();a._redraw=!1},a.remove=()=>{a.noLoop(),a.canvas.remove()},a.frameRate=e=>(e&&(a._targetFrameRate=e,a._targetFrameDuration=1e3/e),a._frameRate),a.getTargetFrameRate=()=>a._targetFrameRate,a.getFPS=()=>a._fps,a.Element=function(e){this.elt=e},a._elements=[],a.TWO_PI=a.TAU=2*Math.PI,a.log=a.print=console.log,a.describe=()=>{};for(let e in Q5.modules)Q5.modules[e](a,n);let l=Q5.renderers[a._renderer];for(let e in l)l[e](a,n);for(let e in Q5)"_"!=e[1]&&e[1]==e[1].toUpperCase()&&(a[e]=Q5[e]);if("graphics"==e)return;"global"==e&&(Object.assign(Q5,a),delete Q5.Q5);for(let e of Q5.methods.init)e.call(a);for(let[e,t]of Object.entries(Q5.prototype))"_"!=e[0]&&"function"==typeof a[e]&&(a[e]=t.bind(a));if("global"==e){let e=Object.getOwnPropertyNames(a);for(let t of e)"_"!=t[0]&&(o[t]=a[t])}"function"==typeof e&&e(a),Q5._instanceCount++;let c=window.requestAnimationFrame||function(e){const t=a._lastFrameTime+a._targetFrameDuration;return setTimeout((()=>{e(t)}),t-performance.now())},d=o||a;a._isTouchAware=d.touchStarted||d.touchMoved||d.mouseReleased;let h=d.preload,u=["setup","draw","preload","mouseMoved","mousePressed","mouseReleased","mouseDragged","mouseClicked","keyPressed","keyReleased","keyTyped","touchStarted","touchMoved","touchEnded","windowResized"];for(let e of u)d[e]?a._isGlobal&&(a[e]=()=>{try{return d[e]()}catch(e){a._aiErrorAssistance?a._aiErrorAssistance(e):console.error(e)}}):a[e]=()=>{};async function p(){if(a._startDone=!0,a._preloadCount>0)return c(p);s=performance.now(),await a.setup(),a.frameCount||(null===a.ctx&&a.createCanvas(100,100),a._setupDone=!0,a.ctx&&a.resetMatrix(),c(a._draw))}(a.setup||a.draw)&&(arguments.length&&"namespace"!=e&&"webgpu"!=r||h?(a.preload(),p()):(d.preload=a.preload=()=>{a._startDone||p()},setTimeout(a.preload,32)))}Q5.renderers={},Q5.modules={},Q5._nodejs="object"==typeof process,Q5._instanceCount=0,Q5._friendlyError=(e,t)=>{throw Error(t+": "+e)},Q5._validateParameters=()=>!0,Q5.methods={init:[],pre:[],post:[],remove:[]},Q5.prototype.registerMethod=(e,t)=>Q5.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.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 r=e.canvas;if(r.width=e.width=100,r.height=e.height=100,"image"!=e._scope&&(r.renderer=e._renderer,r[e._renderer]=!0),e._pixelDensity=1,e._adjustDisplay=()=>{r.style&&(r.style.width=r.w+"px",r.style.height=r.h+"px")},e.createCanvas=function(t,o,a){a??=arguments[3];let n=Object.assign({},Q5.canvasOptions);if("object"==typeof a&&Object.assign(n,a),"image"!=e._scope){let t=e.displayDensity();"graphics"==e._scope?t=this._pixelDensity:window.IntersectionObserver&&new IntersectionObserver((e=>{r.visible=e[0].isIntersecting})).observe(r),e._pixelDensity=Math.ceil(t)}e._setCanvasSize(t,o),Object.assign(r,n);let i=e._createCanvas(r.w,r.h,n);if(e._hooks)for(let t of e._hooks.postCanvas)t();return i},e._save=async(e,t,r)=>{if(t=t||"untitled","jpg"==(r=r||"png")||"png"==r||"webp"==r)if(e instanceof OffscreenCanvas){const t=await e.convertToBlob({type:"image/"+r});e=await new Promise((e=>{const r=new FileReader;r.onloadend=()=>e(r.result),r.readAsDataURL(t)}))}else e=e.toDataURL("image/"+r);else{let t="text/plain";"json"==r&&("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+"."+r,o.click(),URL.revokeObjectURL(o.href)},e.save=(t,r,o)=>{if((!t||"string"==typeof t&&(!r||!o&&r.length<5))&&(o=r,r=t,t=e.canvas),o)return e._save(t,r,o);r?(r=r.split("."),e._save(t,r[0],r.at(-1))):e._save(t)},e._setCanvasSize=(o,a)=>{o??=window.innerWidth,a??=window.innerHeight,r.w=o=Math.ceil(o),r.h=a=Math.ceil(a),r.hw=o/2,r.hh=a/2,r.width=Math.ceil(o*e._pixelDensity),r.height=Math.ceil(a*e._pixelDensity),e._da?e.flexibleCanvas(e._dau):(t.width=o,t.height=a),e.displayMode&&!r.displayMode?e.displayMode():e._adjustDisplay()},"image"!=e._scope){if(r&&"graphics"!=e._scope){function o(){let t=e._parent;t??=document.getElementsByTagName("main")[0],t||(t=document.createElement("main"),document.body.append(t)),r.parent(t)}r.parent=t=>{function o(){e.frameCount>1&&(e._shouldResize=!0,e._adjustDisplay())}r.parentElement&&r.parentElement.removeChild(r),"string"==typeof t&&(t=document.getElementById(t)),t.append(r),"function"==typeof ResizeObserver?(e._ro&&e._ro.disconnect(),e._ro=new ResizeObserver(o),e._ro.observe(t)):e.frameCount||window.addEventListener("resize",o)},document.body?o():document.addEventListener("DOMContentLoaded",o)}e.resizeCanvas=(t,o)=>{if(!e.ctx)return e.createCanvas(t,o);t==r.w&&o==r.h||e._resizeCanvas(t,o)},e.canvas.resize=e.resizeCanvas,e.canvas.save=e.saveCanvas=e.save,e.displayDensity=()=>window.devicePixelRatio,e.pixelDensity=t=>t&&t!=e._pixelDensity?(e._pixelDensity=t,e._setCanvasSize(r.w,r.h),t):e._pixelDensity,e.flexibleCanvas=(o=400)=>{o?(e._da=r.width/(o*e._pixelDensity),t.width=e._dau=o,t.height=r.h/r.w*o):e._da=0}}},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.renderers.q2d={},Q5.renderers.q2d.canvas=(e,t)=>{let r=e.canvas;e.colorMode&&e.colorMode("rgb","integer"),e._createCanvas=function(o,a,n){return t.ctx=t.drawingContext=r.getContext("2d",n),"image"!=e._scope&&(e.ctx.fillStyle="white",e.ctx.strokeStyle="black",e.ctx.lineCap="round",e.ctx.lineJoin="miter",e.ctx.textAlign="left"),e.ctx.scale(e._pixelDensity,e._pixelDensity),e.ctx.save(),r},"image"!=e._scope&&(e._resizeCanvas=(t,o)=>{let a={};for(let t in e.ctx)"function"!=typeof e.ctx[t]&&(a[t]=e.ctx[t]);delete a.canvas;let n=new e._OffscreenCanvas(r.width,r.height);n.w=r.w,n.h=r.h,n.getContext("2d").drawImage(r,0,0),e._setCanvasSize(t,o);for(let t in a)e.ctx[t]=a[t];e.scale(e._pixelDensity),e.ctx.drawImage(n,0,0,n.w,n.h)},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.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.strokeWeight=t=>{t||(e._doStroke=!1),e._da&&(t*=e._da),e.ctx.lineWidth=t||1e-4},e.noStroke=()=>e._doStroke=!1,e.clear=()=>{e.ctx.save(),e.ctx.resetTransform(),e.ctx.clearRect(0,0,e.canvas.width,e.canvas.height),e.ctx.restore()},e.translate=(t,r)=>{e._da&&(t*=e._da,r*=e._da),e.ctx.translate(t,r)},e.rotate=t=>{"degrees"==e._angleMode&&(t=e.radians(t)),e.ctx.rotate(t)},e.scale=(t,r)=>{r??=t,e.ctx.scale(t,r)},e.opacity=t=>e.ctx.globalAlpha=t,e.applyMatrix=(t,r,o,a,n,i)=>e.ctx.transform(t,r,o,a,n,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.scale(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 r of e._styleNames)t[r]=e[r];e._styles.push(t)},e.pop=e.popMatrix=()=>{e.ctx.restore();let t=e._styles.pop();for(let r of e._styleNames)e[r]=t[r]},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,r,o){let a=new Q5("graphics");return o??={},o.alpha??=!0,o.colorSpace??=e.canvas.colorSpace,a.createCanvas.call(e,t,r,o),a},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.renderers.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,r=[];function o(){e._doFill&&e.ctx.fill(),e._doStroke&&e.ctx.stroke()}function a(t,r,a,n,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(),a==n)d&&(i=e.radians(i),s=e.radians(s)),e.ctx.arc(t,r,a/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)*a/2,u=e.sin(d)*n/2;e.ctx[o?"lineTo":"moveTo"](t+h,r+u)}l==e.CHORD?e.ctx.closePath():l==e.PIE&&(e.ctx.lineTo(t,r),e.ctx.closePath())}o()}}function n(t,r,a,n){(e._doFill||e._doStroke)&&(e._da&&(t*=e._da,r*=e._da,a*=e._da,n*=e._da),e.ctx.beginPath(),e.ctx.ellipse(t,r,a/2,n/2,0,0,e.TAU),o())}function i(t,r,a,n,s,l,c,d){if(e._doFill||e._doStroke){if(void 0===s)return function(t,r,a,n){e._da&&(t*=e._da,r*=e._da,a*=e._da,n*=e._da),e.ctx.beginPath(),e.ctx.rect(t,r,a,n),o()}(t,r,a,n);if(void 0===l)return i(t,r,a,n,s,s,s,s);e._da&&(t*=e._da,r*=e._da,a*=e._da,n*=e._da,s*=e._da,l*=e._da,d*=e._da,c*=e._da),e.ctx.roundRect(t,r,a,n,[s,l,c,d]),o()}}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.background=function(t){e.ctx.save(),e.ctx.resetTransform(),t.canvas?e.image(t,0,0,e.width,e.height):(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,r,o,a)=>{e._doStroke&&(e._da&&(t*=e._da,r*=e._da,o*=e._da,a*=e._da),e.ctx.beginPath(),e.ctx.moveTo(t,r),e.ctx.lineTo(o,a),e.ctx.stroke())},e.arc=(t,r,o,n,i,s,l,c=25)=>{if(i==s)return e.ellipse(t,r,o,n);l??=e.PIE,e._ellipseMode==e.CENTER?a(t,r,o,n,i,s,l,c):e._ellipseMode==e.RADIUS?a(t,r,2*o,2*n,i,s,l,c):e._ellipseMode==e.CORNER?a(t+o/2,r+n/2,o,n,i,s,l,c):e._ellipseMode==e.CORNERS&&a((t+o)/2,(r+n)/2,o-t,n-r,i,s,l,c)},e.ellipse=(t,r,o,a)=>{a??=o,e._ellipseMode==e.CENTER?n(t,r,o,a):e._ellipseMode==e.RADIUS?n(t,r,2*o,2*a):e._ellipseMode==e.CORNER?n(t+o/2,r+a/2,o,a):e._ellipseMode==e.CORNERS&&n((t+o)/2,(r+a)/2,o-t,a-r)},e.circle=(t,r,a)=>{e._ellipseMode==e.CENTER?(e._da&&(t*=e._da,r*=e._da,a*=e._da),e.ctx.beginPath(),e.ctx.arc(t,r,a/2,0,e.TAU),o()):e.ellipse(t,r,a,a)},e.point=(t,r)=>{t.x&&(r=t.y,t=t.x),e._da&&(t*=e._da,r*=e._da),e.ctx.save(),e.ctx.beginPath(),e.ctx.arc(t,r,e.ctx.lineWidth/2,0,e.TAU),e.ctx.fillStyle=e.ctx.strokeStyle,e.ctx.fill(),e.ctx.restore()},e.rect=(t,r,o,a=o,n,s,l,c)=>{e._rectMode==e.CENTER?i(t-o/2,r-a/2,o,a,n,s,l,c):e._rectMode==e.RADIUS?i(t-o,r-a,2*o,2*a,n,s,l,c):e._rectMode==e.CORNER?i(t,r,o,a,n,s,l,c):e._rectMode==e.CORNERS&&i(t,r,o-t,a-r,n,s,l,c)},e.square=(t,r,o,a,n,i,s)=>e.rect(t,r,o,o,a,n,i,s),e.beginShape=()=>{r=[],e.ctx.beginPath(),t=!0},e.beginContour=()=>{e.ctx.closePath(),r=[],t=!0},e.endContour=()=>{r=[],t=!0},e.vertex=(o,a)=>{e._da&&(o*=e._da,a*=e._da),r=[],t?e.ctx.moveTo(o,a):e.ctx.lineTo(o,a),t=!1},e.bezierVertex=(t,o,a,n,i,s)=>{e._da&&(t*=e._da,o*=e._da,a*=e._da,n*=e._da,i*=e._da,s*=e._da),r=[],e.ctx.bezierCurveTo(t,o,a,n,i,s)},e.quadraticVertex=(t,o,a,n)=>{e._da&&(t*=e._da,o*=e._da,a*=e._da,n*=e._da),r=[],e.ctx.quadraticCurveTo(t,o,a,n)},e.bezier=(t,r,o,a,n,i,s,l)=>{e.beginShape(),e.vertex(t,r),e.bezierVertex(o,a,n,i,s,l),e.endShape()},e.triangle=(t,r,o,a,n,i)=>{e.beginShape(),e.vertex(t,r),e.vertex(o,a),e.vertex(n,i),e.endShape(e.CLOSE)},e.quad=(t,r,o,a,n,i,s,l)=>{e.beginShape(),e.vertex(t,r),e.vertex(o,a),e.vertex(n,i),e.vertex(s,l),e.endShape(e.CLOSE)},e.endShape=t=>{r=[],t&&e.ctx.closePath(),o()},e.curveVertex=(o,a)=>{if(e._da&&(o*=e._da,a*=e._da),r.push([o,a]),r.length<4)return;let n=function(e,t,r,o,a,n,i,s,l,c){function d(e,t,r,o,a,n){let i=Math.pow(o-t,2)+Math.pow(a-r,2);return Math.pow(i,.5*n)+e}let h=[],u=d(0,e,t,r,o,c),p=d(u,r,o,a,n,c),_=d(p,a,n,i,s,c);for(let c=0;c<l;c++){let d=u+c/(l-1)*(p-u),g=[(u-d)/(u-0),(d-0)/(u-0),(p-d)/(p-u),(d-u)/(p-u),(_-d)/(_-p),(d-p)/(_-p),(p-d)/(p-0),(d-0)/(p-0),(_-d)/(_-u),(d-u)/(_-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]+r*g[1],f=t*g[0]+o*g[1],m=r*g[2]+a*g[3],v=o*g[2]+n*g[3],y=a*g[4]+i*g[5],w=n*g[4]+s*g[5],S=x*g[6]+m*g[7],b=f*g[6]+v*g[7],C=m*g[8]+y*g[9],M=v*g[8]+w*g[9],Q=S*g[2]+C*g[3],R=b*g[2]+M*g[3];h.push([Q,R])}return h}(...r.at(-4),...r.at(-3),...r.at(-2),...r.at(-1),e._curveDetail,e._curveAlpha);for(let r=0;r<n.length;r++)t?e.ctx.moveTo(...n[r]):e.ctx.lineTo(...n[r]),t=!1},e.curve=(t,r,o,a,n,i,s,l)=>{e.beginShape(),e.curveVertex(t,r),e.curveVertex(o,a),e.curveVertex(n,i),e.curveVertex(s,l),e.endShape()},e.curvePoint=(e,t,r,o,a)=>{const n=a*a*a,i=a*a;return e*(-.5*n+i-.5*a)+t*(1.5*n-2.5*i+1)+r*(-1.5*n+2*i+.5*a)+o*(.5*n-.5*i)},e.bezierPoint=(e,t,r,o,a)=>{const n=1-a;return Math.pow(n,3)*e+3*Math.pow(n,2)*a*t+3*n*Math.pow(a,2)*r+Math.pow(a,3)*o},e.curveTangent=(e,t,r,o,a)=>{const n=a*a;return e*(-3*n/2+2*a-.5)+t*(9*n/2-5*a)+r*(-9*n/2+4*a+.5)+o*(3*n/2-a)},e.bezierTangent=(e,t,r,o,a)=>{const n=1-a;return 3*o*Math.pow(a,2)-3*r*Math.pow(a,2)+6*r*n*a-6*t*n*a+3*t*Math.pow(n,2)-3*e*Math.pow(n,2)},e.erase=function(t=255,r=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, ${r/255})`},e.noErase=function(){e.ctx.globalCompositeOperation="source-over",e.ctx.restore()},e.inFill=(t,r)=>{const o=e._pixelDensity;return e.ctx.isPointInPath(t*o,r*o)},e.inStroke=(t,r)=>{const o=e._pixelDensity;return e.ctx.isPointInStroke(t*o,r*o)}},Q5.renderers.q2d.image=(e,t)=>{Q5.Image??=class{constructor(e,t,r){let o=this;o._scope="image",o.canvas=o.ctx=o.drawingContext=null,o.pixels=[],Q5.modules.canvas(o,o);let a=Q5.renderers.q2d;for(let e of["canvas","image","soft_filters"])a[e]&&a[e](o,o);o.createCanvas(e,t,r),delete o.createCanvas,o._loop=!1}get w(){return this.width}get h(){return this.height}},e.createImage=(t,r,o)=>(o??={},o.alpha??=!0,o.colorSpace??=e.canvas.colorSpace||Q5.canvasOptions.colorSpace,new Q5.Image(t,r,o)),e.loadImage=function(r,o,a){if(r.canvas)return r;if("gif"==r.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 n=[...arguments].at(-1);a="object"==typeof n?n:null;let i=e.createImage(1,1,a);function s(e){i.resize(e.naturalWidth||e.width,e.naturalHeight||e.height),i.ctx.drawImage(e,0,0),t._preloadCount--,o&&o(i)}if(Q5._nodejs&&global.CairoCanvas)global.CairoCanvas.loadImage(r).then(s).catch((e=>{throw t._preloadCount--,e}));else{let e=new window.Image;e.src=r,e.crossOrigin="Anonymous",e._pixelDensity=1,e.onload=()=>s(e),e.onerror=e=>{throw t._preloadCount--,e}}return i},e.imageMode=t=>e._imageMode=t,e.image=(t,r,o,a,n,i=0,s=0,l,c)=>{let d=t.canvas||t;Q5._createNodeJSCanvas&&(d=d.context.canvas),a??=t.width||t.videoWidth,n??=t.height||t.videoHeight,"center"==e._imageMode&&(r-=.5*a,o-=.5*n),e._da&&(r*=e._da,o*=e._da,a*=e._da,n*=e._da,i*=e._da,s*=e._da,l*=e._da,c*=e._da);let h=t._pixelDensity||1;l?l*=h:l=d.width||d.videoWidth,c?c*=h:c=d.height||d.videoHeight,e.ctx.drawImage(d,i*h,s*h,l,c,r,o,a,n),e._tint&&(e.ctx.globalCompositeOperation="multiply",e.ctx.fillStyle=e._tint.toString(),e.ctx.fillRect(r,o,a,n),e.ctx.globalCompositeOperation="source-over")},e._tint=null;let r=null;e._softFilter=()=>{throw new Error("Load q5-2d-soft-filters.js to use software filters.")},e.filter=(t,r)=>{if(!e.ctx.filter)return e._softFilter(t,r);if("string"==typeof t)f=t;else if(t==Q5.GRAY)f="saturate(0%)";else if(t==Q5.INVERT)f="invert(100%)";else if(t==Q5.BLUR){let t=Math.ceil(r*e._pixelDensity)||1;f=`blur(${t}px)`}else{if(t!=Q5.THRESHOLD)return e._softFilter(t,r);{r??=.5;let e=Math.floor(.5/Math.max(r,1e-5)*100);f=`saturate(0%) brightness(${e}%) contrast(1000000%)`}}e.ctx.filter=f,e.ctx.drawImage(e.canvas,0,0,e.canvas.w,e.canvas.h),e.ctx.filter="none"},"image"==e._scope&&(e.resize=(t,r)=>{let o=new e._OffscreenCanvas(e.canvas.width,e.canvas.height);o.getContext("2d",{colorSpace:e.canvas.colorSpace}).drawImage(e.canvas,0,0),e._setCanvasSize(t,r),e.ctx.clearRect(0,0,e.canvas.width,e.canvas.height),e.ctx.drawImage(o,0,0,e.canvas.width,e.canvas.height)}),e.trim=()=>{let t=e._pixelDensity||1,r=e.canvas.width,o=e.canvas.height,a=e.ctx.getImageData(0,0,r,o).data,n=r,i=0,s=o,l=0,c=3;for(let e=0;e<o;e++)for(let t=0;t<r;t++)0!==a[c]&&(t<n&&(n=t),t>i&&(i=t),e<s&&(s=e),e>l&&(l=e)),c+=4;return s=Math.floor(s/t),l=Math.floor(l/t),n=Math.floor(n/t),i=Math.floor(i/t),e.get(n,s,i-n+1,l-s+1)},e.mask=t=>{e.ctx.save(),e.ctx.resetTransform();let r=e.ctx.globalCompositeOperation;e.ctx.globalCompositeOperation="destination-in",e.ctx.drawImage(t.canvas,0,0),e.ctx.globalCompositeOperation=r,e.ctx.restore()},e.get=(t,r,o,a)=>{let n=e._pixelDensity||1;if(void 0!==t&&void 0===o){let o=e.ctx.getImageData(t*n,r*n,1,1).data;return new e.Color(o[0],o[1],o[2],o[3]/255)}t=(t||0)*n,r=(r||0)*n;let i=o=o||e.width,s=a=a||e.height;o*=n,a*=n;let l=e.createImage(o,a),c=e.ctx.getImageData(t,r,o,a);return l.ctx.putImageData(c,0,0),l._pixelDensity=n,l.width=i,l.height=s,l},e.set=(t,r,o)=>{if(o.canvas){let a=e._tint;return e._tint=null,e.image(o,t,r),void(e._tint=a)}e.pixels.length||e.loadPixels();let a=e._pixelDensity||1;for(let n=0;n<a;n++)for(let i=0;i<a;i++){let s=4*((r*a+n)*e.canvas.width+t*a+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=()=>{r=e.ctx.getImageData(0,0,e.canvas.width,e.canvas.height),t.pixels=r.data},e.updatePixels=()=>{null!=r&&e.ctx.putImageData(r,0,0)},e.smooth=()=>e.ctx.imageSmoothingEnabled=!0,e.noSmooth=()=>e.ctx.imageSmoothingEnabled=!1,"image"!=e._scope&&(e.tint=function(t){e._tint=t._q5Color?t:e.color(...arguments)},e.noTint=()=>e._tint=null)},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.renderers.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,r)=>{t._preloadCount++;let o=e.split("/").pop().split(".")[0].replace(" ",""),a=new FontFace(o,`url(${e})`);return document.fonts.add(a),a.load().then((()=>{t._preloadCount--,r&&r(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,r)=>{e.ctx.textAlign=t,r&&(e.ctx.textBaseline=r==e.CENTER?"middle":r)},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,r=0;for(const[o,a]of this.entries())a.lastAccessed<t&&(t=a.lastAccessed,e=r),r++;r=e;for(const t of this.keys()){if(0==r){e=t;break}r--}this.delete(e)}},e._tic=new e._TimedCache,e.textCache=(t,r)=>(r&&(e._tic.maxSize=r),void 0!==t&&(e._textCache=t),e._textCache),e._genTextImageKey=(t,r,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+"_":"")+(r||"")+(o?"x"+o:""),e.createTextImage=(t,r,o)=>{let a=e._textCache;e._textCache=!0,e._genTextImage=!0,e.text(t,0,0,r,o),e._genTextImage=!1;let n=e._genTextImageKey(t,r,o);return e._textCache=a,e._tic.get(n)},e.text=(t,r,o,a,n)=>{if(void 0===t)return;if(t=t.toString(),e._da&&(r*=e._da,o*=e._da),!e._doFill&&!e._doStroke)return;let i,s,l,c,d,h,u,p,_=e.ctx.getTransform(),g=e._genTextImage||e._textCache&&(0!=_.b||0!=_.c);if(g){if(c=e._genTextImageKey(t,a,n),s=e._tic.get(c),s&&!e._genTextImage)return void e.textImage(s,r,o);l=e.createGraphics.call(e,1,1),i=l.ctx}else i=e.ctx,d=r,h=o;i.font=`${e._textStyle} ${e._textSize}px ${e._textFont}`;let x=t.split("\n");if(g){d=0,h=e._textLeading*x.length;let r=i.measureText(" ");u=r.fontBoundingBoxAscent,p=r.fontBoundingBoxDescent,n??=h+p,l.resizeCanvas(Math.ceil(i.measureText(t).width),Math.ceil(n)),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<x.length&&(e._doStroke&&e._strokeSet&&i.strokeText(x[t],d,h),e._doFill&&i.fillText(x[t],d,h),h+=e._textLeading,!(h>n));t++);e._fillSet||(i.fillStyle=f),g&&(s=l.get(),s._ascent=u,s._descent=p,e._tic.set(c,s),e._genTextImage||e.textImage(s,r,o))},e.textImage=(t,r,o)=>{let a=e._imageMode;e._imageMode="corner","center"==e.ctx.textAlign?r-=.5*t.width:"right"==e.ctx.textAlign&&(r-=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,r,o),e._imageMode=a},e.nf=(e,t,r)=>{let o=e<0,a=(e=Math.abs(e)).toFixed(r).split(".");a[0]=a[0].padStart(t,"0");let n=a.join(".");return o&&(n="-"+n),n}},Q5.modules.ai=e=>{e.askAI=(e="")=>{throw Error("Ask AI ✨ "+e)},e._aiErrorAssistance=async t=>{let r=t.message?.includes("Ask AI ✨");if(r||console.error(t),Q5.disableFriendlyErrors)return;!r&&Q5.errorTolerant||e.noLoop();let o=t.stack?.split("\n");if(!t.stack||o.length<=1)return;let a=1,n="(";for(-1==navigator.userAgent.indexOf("Chrome")&&(a=0,n="@");o[a].indexOf("q5.js:")>=0;)a++;let i=o[a].split(n).at(-1);i=i.split(":");let s=parseInt(i.at(-2));r&&s++;let l=i.slice(0,-2).join(":"),c=l.split("/").at(-1);try{let e=(await(await fetch(l)).text()).split("\n"),o=e[s-1].trim(),a="",n=1;for(;a.length<1600&&(s-n>=0&&(a=e[s-n].trim()+"\n"+a),s+n<e.length);)a+=e[s+n].trim()+"\n",n++;let i="https://chatgpt.com/?q=q5.js+"+(r&&t.message.length>10?t.message.slice(10):"Whats+wrong+with+this+line%3F+short+answer")+(r?"":"%0A%0A"+encodeURIComponent(t.name+": "+t.message))+"%0A%0ALine%3A+"+encodeURIComponent(o)+"%0A%0AExcerpt+for+context%3A%0A%0A"+encodeURIComponent(a);r||console.log("Error in "+c+" on line "+s+":\n\n"+o),console.warn("Ask AI ✨ "+i),r&&window.open(i,"_blank")}catch(e){}}},Q5.modules.color=(e,t)=>{e.RGB=e.RGBA=e._colorMode="rgb",e.OKLCH="oklch",e.colorMode=(r,o)=>{e._colorMode=r;let a="srgb"==e.canvas.colorSpace||"srgb"==r;if(o??=a?"integer":"float",e._colorFormat="float"==o||1==o?1:255,"oklch"==r)t.Color=Q5.ColorOKLCH;else{let r="srgb"==e.canvas.colorSpace;255==e._colorFormat?t.Color=r?Q5.ColorRGBA_8:Q5.ColorRGBA_P3_8:t.Color=r?Q5.ColorRGBA:Q5.ColorRGBA_P3,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=(t,r,o,a)=>{let n=e.Color;if(t._q5Color)return new n(...t.levels);if(null==r){if("string"==typeof t){if("#"==t[0])t.length<=5?(t.length>4&&(a=parseInt(t[4]+t[4],16)),o=parseInt(t[3]+t[3],16),r=parseInt(t[2]+t[2],16),t=parseInt(t[1]+t[1],16)):(t.length>7&&(a=parseInt(t.slice(7,9),16)),o=parseInt(t.slice(5,7),16),r=parseInt(t.slice(3,5),16),t=parseInt(t.slice(1,3),16));else{if(!e._namedColors[t])return console.error("q5 can't parse color: "+t+"\nOnly numeric input, hex, and common named colors are supported."),new n(0,0,0);[t,r,o,a]=e._namedColors[t]}1==e._colorFormat&&(t/=255,r&&(r/=255),o&&(o/=255),a&&(a/=255))}Array.isArray(t)&&(r=t[1],o=t[2],a=t[3],t=t[0])}return null==o?new n(t,t,t,r):new n(t,r,o,a)},e.red=e=>e.r,e.green=e=>e.g,e.blue=e=>e.b,e.alpha=e=>e.a,e.lightness=t=>"oklch"==e._colorMode?t.l:100*(.2126*t.r+.7152*t.g+.0722*t.b)/255,e.hue=t=>{if("oklch"==e._colorMode)return t.h;let r=t.r,o=t.g,a=t.b;255==e._colorFormat&&(r/=255,o/=255,a/=255);let n,i=Math.max(r,o,a),s=Math.min(r,o,a);return n=i==s?0:i==r?60*(o-a)/(i-s):i==o?60*(a-r)/(i-s)+120:60*(r-o)/(i-s)+240,n<0&&(n+=360),n},e.lerpColor=(t,r,o)=>{if("rgb"==e._colorMode)return new e.Color(e.constrain(e.lerp(t.r,r.r,o),0,255),e.constrain(e.lerp(t.g,r.g,o),0,255),e.constrain(e.lerp(t.b,r.b,o),0,255),e.constrain(e.lerp(t.a,r.a,o),0,255));{let a=r.h-t.h;a>180&&(a-=360),a<-180&&(a+=360);let n=t.h+o*a;return n<0&&(n+=360),n>360&&(n-=360),new e.Color(e.constrain(e.lerp(t.l,r.l,o),0,100),e.constrain(e.lerp(t.c,r.c,o),0,100),n,e.constrain(e.lerp(t.a,r.a,o),0,255))}}},Q5.Color=class{constructor(){this._q5Color=!0}},Q5.ColorOKLCH=class extends Q5.Color{constructor(e,t,r,o){super(),this.l=e,this.c=t,this.h=r,this.a=o??1}toString(){return`oklch(${this.l} ${this.c} ${this.h} / ${this.a})`}},Q5.ColorRGBA=class extends Q5.Color{constructor(e,t,r,o){super(),this.r=e,this.g=t,this.b=r,this.a=o??1}get levels(){return[this.r,this.g,this.b,this.a]}toString(){return`color(srgb ${this.r} ${this.g} ${this.b} / ${this.a})`}},Q5.ColorRGBA_P3=class extends Q5.ColorRGBA{toString(){return`color(display-p3 ${this.r} ${this.g} ${this.b} / ${this.a})`}},Q5.ColorRGBA_8=class extends Q5.ColorRGBA{constructor(e,t,r,o){super(e,t,r,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_8=class extends Q5.ColorRGBA{constructor(e,t,r,o){super(e,t,r,o??255),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),r=(this._b/255).toFixed(3),o=(this._a/255).toFixed(3);this._css=`color(display-p3 ${e} ${t} ${r} / ${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 r=t.style,o=t.parentElement;r&&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"),r.width=t.w*t.displayScale+"px",r.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?(r.width=t.w*t.displayScale+"px",r.maxWidth="100%"):r.width="100%",r.height="auto",r.maxHeight=""):(r.width="auto",r.maxWidth="","centered"==t.displayMode?(r.height=t.h*t.displayScale+"px",r.maxHeight="100%"):r.height="100%")))},e.displayMode=(r="normal",o="default",a=1)=>{"string"==typeof a&&(a=parseFloat(a.slice(1))),Object.assign(t,{displayMode:r,renderQuality:o,displayScale:a}),e._adjustDisplay()},e.fullscreen=e=>{if(void 0===e)return document.fullscreenElement;e?document.body.requestFullscreen():document.body.exitFullscreen()}},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 r={},o=[e.LEFT,e.CENTER,e.RIGHT],a=e.canvas;function n(t){const r=e.canvas.getBoundingClientRect(),o=e.canvas.scrollWidth/e.width||1,a=e.canvas.scrollHeight/e.height||1;return{x:(t.clientX-r.left)/o,y:(t.clientY-r.top)/a,id:t.identifier}}if(e._startAudio=()=>{e.getAudioContext&&"suspended"==e.getAudioContext()?.state&&e.userStartAudio()},e._updateMouse=r=>{if(!r.changedTouches)if(a){let o=a.getBoundingClientRect(),n=a.scrollWidth/e.width||1,i=a.scrollHeight/e.height||1;t.mouseX=(r.clientX-o.left)/n,t.mouseY=(r.clientY-o.top)/i,"webgpu"==a.renderer&&(t.mouseX-=a.hw,t.mouseY-=a.hh)}else t.mouseX=r.clientX,t.mouseY=r.clientY},e._onmousedown=r=>{e._startAudio(),e._updateMouse(r),t.mouseIsPressed=!0,t.mouseButton=o[r.button],e.mousePressed(r)},e._onmousemove=t=>{e._updateMouse(t),e.mouseIsPressed?e.mouseDragged(t):e.mouseMoved(t)},e._onmouseup=r=>{e._updateMouse(r),t.mouseIsPressed=!1,e.mouseReleased(r)},e._onclick=r=>{e._updateMouse(r),t.mouseIsPressed=!0,e.mouseClicked(r),t.mouseIsPressed=!1},e.cursor=(t,r,o)=>{let a="";t.includes(".")&&(t=`url("${t}")`,a=", auto"),void 0!==r&&(t+=" "+r+" "+o),e.canvas.style.cursor=t+a},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,r[e.keyCode]=r[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,r[e.keyCode]=r[e.key.toLowerCase()]=!1,e.keyReleased(o)},e.keyIsDown=e=>!!r["string"==typeof e?e.toLowerCase():e],e._ontouchstart=r=>{e._startAudio(),t.touches=[...r.touches].map(n),e._isTouchAware||(t.mouseX=e.touches[0].x,t.mouseY=e.touches[0].y,t.mouseIsPressed=!0,t.mouseButton=e.LEFT,e.mousePressed(r)||r.preventDefault()),e.touchStarted(r)||r.preventDefault()},e._ontouchmove=r=>{t.touches=[...r.touches].map(n),e._isTouchAware||(t.mouseX=e.touches[0].x,t.mouseY=e.touches[0].y,e.mouseDragged(r)||r.preventDefault()),e.touchMoved(r)||r.preventDefault()},e._ontouchend=r=>{t.touches=[...r.touches].map(n),e._isTouchAware||e.touches.length||(t.mouseIsPressed=!1,e.mouseReleased(r)||r.preventDefault()),e.touchEnded(r)||r.preventDefault()},a&&(a.addEventListener("mousedown",(t=>e._onmousedown(t))),a.addEventListener("mouseup",(t=>e._onmouseup(t))),a.addEventListener("click",(t=>e._onclick(t))),a.addEventListener("touchstart",(t=>e._ontouchstart(t))),a.addEventListener("touchmove",(t=>e._ontouchmove(t))),a.addEventListener("touchcancel",(t=>e._ontouchend(t))),a.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)=>{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=Q5.prototype.map=(e,t,r,o,a,n)=>{let i=o+1*(e-t)/(r-t)*(a-o);return n?o<a?Math.min(Math.max(i,o),a):Math.min(Math.max(i,a),o):i},e.lerp=(e,t,r)=>e*(1-r)+t*r,e.constrain=(e,t,r)=>Math.min(Math.max(e,t),r),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,r,o)=>e.map(t,r,o,0,1),e.sq=e=>e*e,e.fract=e=>e-Math.floor(e);for(let t of["sin","cos","tan"])e[t]=r=>("degrees"==e._angleMode&&(r=e.radians(r)),Math[t](r));for(let t of["asin","acos","atan"])e[t]=r=>{let o=Math[t](r);return"degrees"==e._angleMode&&(o=e.degrees(o)),o};function r(){let e,t,r=4294967295;return{setSeed(o){e=t=(o??Math.random()*r)>>>0},getSeed:()=>t,rand:()=>(e^=e<<17,e^=e>>13,e^=e<<5,(e>>>0)/r)}}e.atan2=(t,r)=>{let o=Math.atan2(t,r);return"degrees"==e._angleMode&&(o=e.degrees(o)),o};let o=r();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,r;return{setSeed(o){r=t=(o??Math.random()*e)>>>0},getSeed:()=>t,rand:()=>(r=(1664525*r+1013904223)%e,r/e)}}():t==e.SHR3&&(o=r()),o.setSeed()};var a=new function(){var e,t,r,a=new Array(128),n=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,n,l,c=3.44262;;){if(t=r*i[e],0==e){do{n=h(),l=h(),t=.2904764*-Math.log(n),o=-Math.log(l)}while(o+o<t*t);return r>0?c+t:-c-t}if(s[e]+h()*(s[e-1]-s[e])<Math.exp(-.5*t*t))return t;if(r=d(),e=127&r,Math.abs(r)<a[e])return r*i[e]}},p=()=>{for(var r;;){if(0==e)return 7.69711-Math.log(h());if(r=t*l[e],c[e]+h()*(c[e-1]-c[e])<Math.exp(-r))return r;if((t=d())<n[e=255&t])return t*l[e]}};this.SHR3=d,this.UNI=h,this.RNOR=()=>(r=d(),e=127&r,Math.abs(r)<a[e]?r*i[e]:u()),this.REXP=()=>(t=d()>>>0)<a[e=255&t]?t*l[e]:p(),this.zigset=()=>{var e,t,r=2147483648,o=4294967296,d=3.442619855899,h=d,u=.00991256303526217,p=7.697117470131487,_=p,g=.003949659822581572;for(e=u/Math.exp(-.5*d*d),a[0]=Math.floor(d/e*r),a[1]=0,i[0]=e/r,i[127]=d/r,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))),a[t+1]=Math.floor(d/h*r),h=d,s[t]=Math.exp(-.5*d*d),i[t]=d/r;for(e=g/Math.exp(-p),n[0]=Math.floor(p/e*o),n[1]=0,l[0]=e/o,l[255]=p/o,c[0]=1,c[255]=Math.exp(-p),t=254;t>=1;t--)p=-Math.log(g/p+Math.exp(-p)),n[t+1]=Math.floor(p/_*o),_=p,c[t]=Math.exp(-p),l[t]=p/o}};let n;a.hasInit=!1,e.randomGaussian=(e,t)=>(a.hasInit||(a.zigset(),a.hasInit=!0),a.RNOR()*t+e),e.randomExponential=()=>(a.hasInit||(a.zigset(),a.hasInit=!0),a.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"],n=null},e.noiseSeed=t=>{n=new e.Noise(t)},e.noise=(t=0,r=0,o=0)=>(n??=new e.Noise,n.noise(t,r,o)),e.noiseDetail=(t,r)=>{n??=new e.Noise,t>0&&(n.octaves=t),r>0&&(n.falloff=r)}},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,r,o=[];for(let e=0;e<256;e++)o[e]=e;for(let a=255;a>0;a--)t=(e=16807*e%2147483647)%(a+1),r=o[a],o[a]=o[t],o[t]=r;return o}dot(e,t,r,o){return e[0]*t+e[1]*r+e[2]*o}mix(e,t,r){return(1-r)*e+r*t}fade(e){return e*e*e*(e*(6*e-15)+10)}noise(e,t,r){let o=this,a=0,n=1,i=1,s=0;for(let l=0;l<o.octaves;l++){const l=255&Math.floor(e*n),c=255&Math.floor(t*n),d=255&Math.floor(r*n),h=e*n-Math.floor(e*n),u=t*n-Math.floor(t*n),p=r*n-Math.floor(r*n),_=o.fade(h),g=o.fade(u),x=o.fade(p),f=o.p[l]+c,m=o.p[f]+d,v=o.p[f+1]+d,y=o.p[l+1]+c,w=o.p[y]+d,S=o.p[y+1]+d,b=o.mix(o.dot(o.grad3[o.p[m]%12],h,u,p),o.dot(o.grad3[o.p[w]%12],h-1,u,p),_),C=o.mix(o.dot(o.grad3[o.p[v]%12],h,u-1,p),o.dot(o.grad3[o.p[S]%12],h-1,u-1,p),_),M=o.mix(o.dot(o.grad3[o.p[m+1]%12],h,u,p-1),o.dot(o.grad3[o.p[w+1]%12],h-1,u,p-1),_),Q=o.mix(o.dot(o.grad3[o.p[v+1]%12],h,u-1,p-1),o.dot(o.grad3[o.p[S+1]%12],h-1,u-1,p-1),_),R=o.mix(b,C,g),I=o.mix(M,Q,g);a+=o.mix(R,I,x)*i,s+=i,i*=o.falloff,n*=2}return(a/s+1)/2}},Q5.modules.sound=(e,t)=>{e.Sound=Q5.Sound,e.loadSound=(e,r)=>{t._preloadCount++,Q5.aud??=new window.AudioContext;let o=new Q5.Sound(e,r);return o.addEventListener("canplaythrough",(()=>{t._preloadCount--,o.loaded=!0,r&&r(o)})),o},e.getAudioContext=()=>Q5.aud,e.userStartAudio=()=>Q5.aud.resume()},Q5.Sound=class extends Audio{constructor(e){super(e);let t=this;t.load(),t.panner=Q5.aud.createStereoPanner(),t.source=Q5.aud.createMediaElementSource(t),t.source.connect(t.panner),t.panner.connect(Q5.aud.destination),Object.defineProperty(t,"pan",{get:()=>t.panner.pan.value,set:e=>t.panner.pan.value=e})}setVolume(e){this.volume=e}setLoop(e){this.loop=e}setPan(e){this.pan=e}isLoaded(){return this.loaded}isPlaying(){return!this.paused}},Q5.modules.util=(e,t)=>{e._loadFile=(e,r,o)=>{t._preloadCount++;let a={};return fetch(e).then((e=>"json"==o?e.json():"text"==o?e.text():void 0)).then((e=>{t._preloadCount--,Object.assign(a,e),r&&r(e)})),a},e.loadStrings=(t,r)=>e._loadFile(t,r,"text"),e.loadJSON=(t,r)=>e._loadFile(t,r,"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,r,o)=>new Q5.Vector(t,r,o,e)},Q5.Vector=class{constructor(e,t,r,o){this.x=e||0,this.y=t||0,this.z=r||0,this._$=o||window,this._cn=null,this._cnsq=null}set(e,t,r){this.x=e||0,this.y=t||0,this.z=r||0}copy(){return new Q5.Vector(this.x,this.y,this.z)}_arg2v(e,t,r){return void 0!==e?.x?e:void 0!==t?{x:e,y:t,z:r||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,r=this.y-e.y,o=this.z-e.z;return Math.sqrt(t*t+r*r+o*o)}cross(){let e=this._arg2v(...arguments),t=this.y*e.z-this.z*e.y,r=this.z*e.x-this.x*e.z,o=this.x*e.y-this.y*e.x;return this.x=t,this.y=r,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 r=e/t;this.x*=r,this.y*=r,this.z*=r,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),r=this._$.sin(e),o=this.x*t-this.y*r,a=this.x*r+this.y*t;return this.x=o,this.y=a,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)),r=e.at(-1);return this.x+=(t.x-this.x)*r,this.y+=(t.y-this.y)*r,this.z+=(t.z-this.z)*r,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,r){void 0===r&&(r=1),this._cn=r,this._cnsq=r*r;const o=this._$.cos(t),a=this._$.sin(t),n=this._$.cos(e),i=this._$.sin(e);return this.x=r*i*a,this.y=-r*n,this.z=r*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,r)=>e.equals(t,r),Q5.Vector.lerp=(e,t,r)=>e.copy().lerp(t,r),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,r,o)=>(new Q5.Vector)[e](t,r,o);Q5.renderers.webgpu={},Q5.renderers.webgpu.canvas=(e,t)=>{let r,o,a,n,i=e.canvas;function s(t,r,a,n=1){"string"==typeof t&&(t=Q5.color(t)),null==a&&(n=r,r=a=t),t._q5Color?o.push(...t.levels):o.push(t,r,a,n),e._colorIndex++}i.width=e.width=500,i.height=e.height=500,e.colorMode&&e.colorMode("rgb","float"),e._createCanvas=(r,n,s)=>{t.ctx=t.drawingContext=i.getContext("webgpu"),s.format=navigator.gpu.getPreferredCanvasFormat(),s.device=Q5.device,e.ctx.configure(s),e.pipelines=[],e.pipelinesStack=[],e.verticesStack=[],e.drawStack=[],o=e.colorsStack=[1,1,1,1],e._colorIndex=0;let l=Q5.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"uniform",hasDynamicOffset:!1}}]}),c=Q5.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage",hasDynamicOffset:!1}}]});e.bindGroupLayouts=[l,c];const d=Q5.device.createBuffer({size:8,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});Q5.device.queue.writeBuffer(d,0,new Float32Array([e.canvas.hw,e.canvas.hh])),a=Q5.device.createBindGroup({layout:l,entries:[{binding:0,resource:{buffer:d}}]})},e._resizeCanvas=(t,r)=>{e._setCanvasSize(t,r)},e.resetMatrix=()=>{e._matrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],e._transformIndex=0},e.resetMatrix(),e._matrixDirty=!1,e.transformStates=[e._matrix.slice()],e._transformIndexStack=[],e.push=()=>{e._transformIndexStack.push(e._transformIndex)},e.pop=()=>{if(e._transformIndexStack.length>0){let t=e._transformIndexStack.pop();e._matrix=e.transformStates[t].slice(),e._transformIndex=t}else console.warn("Matrix index stack is empty!")},e.translate=(t,r,o)=>{(t||r||o)&&(e._matrix[3]+=t,e._matrix[7]+=r,e._matrix[11]+=o||0,e._matrixDirty=!0)},e.rotate=t=>{if(!t)return;"degrees"==e._angleMode&&(t=e.radians(t));let r=Math.cos(t),o=Math.sin(t),a=e._matrix[0],n=e._matrix[1],i=e._matrix[4],s=e._matrix[5];a||n||i||s?(e._matrix[0]=a*r+i*o,e._matrix[1]=n*r+s*o,e._matrix[4]=a*-o+i*r,e._matrix[5]=n*-o+s*r):(e._matrix[0]=r,e._matrix[1]=o,e._matrix[4]=-o,e._matrix[5]=r),e._matrixDirty=!0},e.scale=(t=1,r,o=1)=>{r??=t,e._matrix[0]*=t,e._matrix[5]*=r,e._matrix[10]*=o,e._matrixDirty=!0},e._saveMatrix=()=>{e.transformStates.push(e._matrix.slice()),e._transformIndex=e.transformStates.length-1,e._matrixDirty=!1},e._beginRender=()=>{e.encoder=Q5.device.createCommandEncoder(),r=t.pass=e.encoder.beginRenderPass({colorAttachments:[{view:ctx.getCurrentTexture().createView(),loadOp:"clear",storeOp:"store"}]})},e._render=()=>{if(r.setBindGroup(0,a),transformStates.length>1||!n){const t=Q5.device.createBuffer({size:64*transformStates.length,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});Q5.device.queue.writeBuffer(t,0,new Float32Array(transformStates.flat())),n=Q5.device.createBindGroup({layout:e.bindGroupLayouts[1],entries:[{binding:0,resource:{buffer:t}}]})}r.setBindGroup(1,n);for(let t of e._hooks.preRender)t();let t=e.drawStack,o=0,i=-1;for(let a=0;a<t.length;a+=2){i!=t[a]&&(i=t[a],r.setPipeline(e.pipelines[i]));let n=t[a+1];r.draw(n,1,o,0),o+=n}},e._finishRender=()=>{r.end();const o=e.encoder.finish();Q5.device.queue.submit([o]),t.pass=e.encoder=null,e.verticesStack.length=0,e.drawStack.length=0,e.colorsStack.length=4,e.pipelinesStack.length=0,e._colorIndex=0,rotation=0,e.resetMatrix(),e._matrixDirty=!1,e.transformStates.length=1,e._transformIndexStack.length=0},e.fill=function(){s(...arguments),e._doFill=!0,e._fillIndex=e._colorIndex},e.stroke=function(){s(...arguments),e._doStroke=!0,e._fillIndex=e._colorIndex},e.noFill=()=>e._doFill=!1,e.noStroke=()=>e._doStroke=!1,e._strokeWeight=1,e.strokeWeight=t=>e._strokeWeight=t,e.clear=()=>{}},Q5.webgpu=async function(e,t){if(e&&"global"!=e||(Q5._hasGlobal=!0),!navigator.gpu){console.warn("q5 WebGPU not supported on this browser!");let r=new Q5(e,t);return r.colorMode("rgb",1),r._beginRender=()=>r.translate(r.canvas.hw,r.canvas.hh),r}let r=await navigator.gpu.requestAdapter();if(!r)throw new Error("No appropriate GPUAdapter found.");return Q5.device=await r.requestDevice(),new Q5(e,t,"webgpu")},Q5.renderers.webgpu.drawing=(e,t)=>{let r,o,a;e.CLOSE=1,e._hooks.postCanvas.push((()=>{let t=Q5.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage",hasDynamicOffset:!1}}]});e.bindGroupLayouts.push(t),r=e.verticesStack,o=e.drawStack,a=e.colorsStack;let n={arrayStride:16,attributes:[{format:"float32x2",offset:0,shaderLocation:0},{format:"float32",offset:8,shaderLocation:1},{format:"float32",offset:12,shaderLocation:2}]},i=Q5.device.createShaderModule({code:"\nstruct VertexOutput {\n\t@builtin(position) position: vec4<f32>,\n\t@location(1) colorIndex: f32\n};\n\nstruct Uniforms {\n\thalfWidth: f32,\n\thalfHeight: f32\n};\n\n@group(0) @binding(0) var<uniform> uniforms: Uniforms;\n@group(1) @binding(0) var<storage, read> transforms: array<mat4x4<f32>>;\n\n@vertex\nfn vertexMain(@location(0) pos: vec2<f32>, @location(1) colorIndex: f32, @location(2) transformIndex: f32) -> VertexOutput {\n\tvar vert = vec4<f32>(pos, 0.0, 1.0);\n\tvert *= transforms[i32(transformIndex)];\n\tvert.x /= uniforms.halfWidth;\n\tvert.y /= uniforms.halfHeight;\n\n\tvar output: VertexOutput;\n\toutput.position = vert;\n\toutput.colorIndex = colorIndex;\n\treturn output;\n}\n"}),s=Q5.device.createShaderModule({code:"\n@group(2) @binding(0) var<storage, read> uColors : array<vec4<f32>>;\n\n@fragment\nfn fragmentMain(@location(1) colorIndex: f32) -> @location(0) vec4<f32> {\n\tlet index = u32(colorIndex);\n\treturn mix(uColors[index], uColors[index + 1u], fract(colorIndex));\n}\n"}),l=Q5.device.createPipelineLayout({bindGroupLayouts:e.bindGroupLayouts});e._createPipeline=e=>Q5.device.createRenderPipeline({layout:l,vertex:{module:i,entryPoint:"vertexMain",buffers:[n]},fragment:{module:s,entryPoint:"fragmentMain",targets:[{format:"bgra8unorm",blend:e}]},primitive:{topology:"triangle-list"}}),e.pipelines[0]=e._createPipeline(blendConfigs.normal)}));let n=["zero","one","src-alpha","one-minus-src-alpha","dst","dst-alpha","one-minus-dst-alpha","one-minus-src"],i=["add","subtract","reverse-subtract","min","max"];let s;e.blendConfigs={},Object.entries({normal:[2,3,0,2,3,0],lighter:[2,1,0,2,1,0],subtract:[2,1,2,2,1,2],multiply:[4,0,0,5,0,0],screen:[1,3,0,1,3,0],darken:[1,3,3,1,3,3],lighten:[1,3,4,1,3,4],overlay:[2,3,0,2,3,0],hard_light:[2,3,0,2,3,0],soft_light:[2,3,0,2,3,0],difference:[2,3,2,2,3,2],exclusion:[2,3,0,2,3,0],color_dodge:[1,7,0,1,7,0],color_burn:[6,1,0,6,1,0],linear_dodge:[2,1,0,2,1,0],linear_burn:[2,7,1,2,7,1],vivid_light:[2,7,0,2,7,0],pin_light:[2,7,0,2,7,0],hard_mix:[2,7,0,2,7,0]}).forEach((([t,r])=>{e.blendConfigs[t]={color:{srcFactor:n[r[0]],dstFactor:n[r[1]],operation:i[r[2]]},alpha:{srcFactor:n[r[3]],dstFactor:n[r[4]],operation:i[r[5]]}}})),e._blendMode="normal",e.blendMode=t=>{t!=e._blendMode&&("source-over"==t&&(t="normal"),t=t.toLowerCase().replace(/[ -]/g,"_"),e._blendMode=t,e.pipelines[0]=e._createPipeline(e.blendConfigs[t]))},e.beginShape=()=>{s=[]},e.vertex=(t,r)=>{e._matrixDirty&&e._saveMatrix(),s.push(t,-r,e._colorIndex,e._transformIndex)},e.endShape=e=>{let t=s;if(t.length<12)throw new Error("A shape must have at least 3 vertices.");e&&t.push(t[0],t[1],t[2],t[3]);let a=[];for(let e=4;e<t.length;e+=4)a.push(t[0],t[1],t[2],t[3],t[e-4],t[e-3],t[e-2],t[e-1],t[e],t[e+1],t[e+2],t[e+3]);r.push(...a),o.push(0,a.length/4),s=[]},e.triangle=(t,r,o,a,n,i)=>{e.beginShape(),e.vertex(t,r),e.vertex(o,a),e.vertex(n,i),e.endShape(1)},e.rect=(t,a,n,i)=>{let s=n/2,l=i/2,c=t-s,d=t+s,h=-(a-l),u=-(a+l),p=e._colorIndex;e._matrixDirty&&e._saveMatrix();let _=e._transformIndex;r.push(c,h,p,_,d,h,p,_,c,u,p,_,d,h,p,_,c,u,p,_,d,u,p,_),o.push(0,6)},e.point=(t,r)=>{let o=e._strokeWeight;1==o?e.rect(t,r,1,1):e.ellipse(t,r,o,o)},e.background=()=>{};e.ellipse=(t,a,n,i)=>{const s=(l=n==i?n:Math.max(n,i))<14?8:l<16?10:l<18?12:l<20?14:l<22?16:l<24?18:l<28?20:l<34?22:l<42?24:l<48?26:l<56?28:l<64?30:l<72?32:l<84?34:l<96?36:l<98?38:l<113?40:l<149?44:l<199?48:l<261?52:l<353?56:l<461?60:l<585?64:l<1200?70:l<1800?80:l<2400?90:100;var l;let c=Math.max(n,1)/2,d=n==i?c:Math.max(i,1)/2,h=0;const u=e.TAU/s,p=e._colorIndex;e._matrixDirty&&e._saveMatrix();const _=e._transformIndex;let g,x,f,m;for(let e=0;e<=s;e++)g=f,x=m,f=t+c*Math.cos(h),m=a+d*Math.sin(h),h+=u,0!=e&&r.push(t,a,p,_,g,x,p,_,f,m,p,_);o.push(0,3*s)},e.circle=(t,r,o)=>e.ellipse(t,r,o,o),e._hooks.preRender.push((()=>{const t=Q5.device.createBuffer({size:6*r.length,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST});Q5.device.queue.writeBuffer(t,0,new Float32Array(r)),e.pass.setVertexBuffer(0,t);const o=Q5.device.createBuffer({size:4*a.length,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});Q5.device.queue.writeBuffer(o,0,new Float32Array(a));const n=Q5.device.createBindGroup({layout:e.bindGroupLayouts[2],entries:[{binding:0,resource:{buffer:o,offset:0,size:4*a.length}}]});e.pass.setBindGroup(2,n)}))},Q5.renderers.webgpu.image=(e,t)=>{e.imageStack=[],e.textures=[],e._hooks.postCanvas.push((()=>{let t=Q5.device.createShaderModule({code:"\nstruct VertexOutput {\n @builtin(position) position: vec4<f32>,\n @location(0) texCoord: vec2<f32>,\n @location(1) textureIndex: f32\n};\n\nstruct Uniforms {\n halfWidth: f32,\n halfHeight: f32\n};\n\n@group(0) @binding(0) var<uniform> uniforms: Uniforms;\n@group(1) @binding(0) var<storage, read> transforms: array<mat4x4<f32>>;\n\n@vertex\nfn vertexMain(@location(0) pos: vec2<f32>, @location(1) texCoord: vec2<f32>, @location(2) transformIndex: f32, @location(3) textureIndex: f32) -> VertexOutput {\n var vert = vec4<f32>(pos, 0.0, 1.0);\n vert *= transforms[i32(transformIndex)];\n vert.x /= uniforms.halfWidth;\n vert.y /= uniforms.halfHeight;\n\n var output: VertexOutput;\n output.position = vert;\n output.texCoord = texCoord;\n output.textureIndex = textureIndex;\n return output;\n}\n"}),r=Q5.device.createShaderModule({code:"\n@group(0) @binding(0) var samp: sampler;\n@group(0) @binding(1) var textures: array<texture_2d<f32>>;\n\n@fragment\nfn fragmentMain(@location(0) texCoord: vec2<f32>, @location(1) textureIndex: f32) -> @location(0) vec4<f32> {\n return textureSample(textures[i32(textureIndex)], samp, texCoord);\n}\n"});const o=[Q5.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,sampler:{}},{binding:2,visibility:GPUShaderStage.FRAGMENT,texture:{viewDimension:"2d",sampleType:"float"}}]}),Q5.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}}]})],a=Q5.device.createPipelineLayout({bindGroupLayouts:o});e.pipelines[1]=Q5.device.createRenderPipeline({layout:a,vertex:{module:t,entryPoint:"vertexMain",buffers:[{arrayStride:20,attributes:[{shaderLocation:0,offset:0,format:"float32x2"},{shaderLocation:1,offset:8,format:"float32x2"},{shaderLocation:2,offset:16,format:"float32"}]}]},fragment:{module:r,entryPoint:"fragmentMain",targets:[{format:"bgra8unorm"}]},primitive:{topology:"triangle-list"}}),e.sampler=Q5.device.createSampler({magFilter:"linear",minFilter:"linear"})})),e.loadImage=async t=>{const r=new Image;return r.onload=async()=>{const t=await createImageBitmap(r),o=Q5.device.createTexture({size:[r.width,r.height,1],format:"bgra8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT});Q5.device.queue.copyExternalImageToTexture({source:t},{texture:o},[r.width,r.height,1]),r.texture=o,r.index=e.textures.length,e.textures.push(o)},r.onerror=reject,r.src=t,r},e._hooks.preRender.push((()=>{if(!e.imageStack.length)return;e.pass.setPipeline(e.pipelines[1]);const t=new Float32Array(e.vertexStack),r=Q5.device.createBuffer({size:t.byteLength,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST});if(Q5.device.queue.writeBuffer(r,0,t),e.pass.setVertexBuffer(0,r),e.textures.length!==previousTextureCount){previousTextureCount=e.textures.length;const t=e.textures.map((e=>e.createView()));e.textureBindGroup=Q5.device.createBindGroup({layout:e.pipelines[1].getBindGroupLayout(0),entries:[{binding:0,resource:e.sampler},...t.map(((e,t)=>({binding:t+1,resource:e})))]})}e.pass.setBindGroup(0,e.textureBindGroup)})),e.image=(t,r,o,a,n)=>{e._matrixDirty&&e._saveMatrix();let i=e._transformIndex;e.imageStack.push(t.index);let s=a/2,l=n/2,c=r-s,d=r+s,h=-(o-l),u=-(o+l),p=t.index;e.vertexStack.push(c,h,0,0,i,p,d,h,1,0,i,p,c,u,0,1,i,p,d,h,1,0,i,p,c,u,0,1,i,p,d,u,1,1,i,p),e.drawStack.push(6)}},Q5.renderers.webgpu.text=(e,t)=>{};
@@ -70,7 +70,12 @@ Q5.renderers.q2d.canvas = ($, q) => {
70
70
  $.ctx.lineWidth = n || 0.0001;
71
71
  };
72
72
  $.noStroke = () => ($._doStroke = false);
73
- $.clear = () => $.ctx.clearRect(0, 0, $.canvas.width, $.canvas.height);
73
+ $.clear = () => {
74
+ $.ctx.save();
75
+ $.ctx.resetTransform();
76
+ $.ctx.clearRect(0, 0, $.canvas.width, $.canvas.height);
77
+ $.ctx.restore();
78
+ };
74
79
 
75
80
  // DRAWING MATRIX
76
81
 
@@ -72,15 +72,17 @@ Q5.renderers.q2d.drawing = ($) => {
72
72
  // DRAWING
73
73
 
74
74
  $.background = function (c) {
75
- if (c.canvas) return $.image(c, 0, 0, $.width, $.height);
76
75
  $.ctx.save();
77
76
  $.ctx.resetTransform();
78
- if (Q5.Color) {
79
- if (!c._q5Color && typeof c != 'string') c = $.color(...arguments);
80
- else if ($._namedColors[c]) c = $.color(...$._namedColors[c]);
77
+ if (c.canvas) $.image(c, 0, 0, $.width, $.height);
78
+ else {
79
+ if (Q5.Color) {
80
+ if (!c._q5Color && typeof c != 'string') c = $.color(...arguments);
81
+ else if ($._namedColors[c]) c = $.color(...$._namedColors[c]);
82
+ }
83
+ $.ctx.fillStyle = c.toString();
84
+ $.ctx.fillRect(0, 0, $.canvas.width, $.canvas.height);
81
85
  }
82
- $.ctx.fillStyle = c.toString();
83
- $.ctx.fillRect(0, 0, $.canvas.width, $.canvas.height);
84
86
  $.ctx.restore();
85
87
  };
86
88
 
package/src/q5-color.js CHANGED
@@ -72,27 +72,22 @@ Q5.modules.color = ($, q) => {
72
72
  c0 = parseInt(c0.slice(1, 3), 16);
73
73
  }
74
74
  } else if ($._namedColors[c0]) {
75
- c0 = $._namedColors[c0];
75
+ [c0, c1, c2, c3] = $._namedColors[c0];
76
76
  } else {
77
77
  console.error(
78
78
  "q5 can't parse color: " + c0 + '\nOnly numeric input, hex, and common named colors are supported.'
79
79
  );
80
80
  return new C(0, 0, 0);
81
81
  }
82
- }
83
- if (Array.isArray(c0)) {
84
- c1 = c0[1];
85
- c2 = c0[2];
86
- c3 = c0[3];
87
- c0 = c0[0];
88
- }
89
- }
90
82
 
91
- if ($._colorFormat == 1) {
92
- c0 /= 255;
93
- if (c1) c1 /= 255;
94
- if (c2) c2 /= 255;
95
- if (c3) c3 /= 255;
83
+ if ($._colorFormat == 1) {
84
+ c0 /= 255;
85
+ if (c1) c1 /= 255;
86
+ if (c2) c2 /= 255;
87
+ if (c3) c3 /= 255;
88
+ }
89
+ }
90
+ if (Array.isArray(c0)) [c0, c1, c2, c3] = c0;
96
91
  }
97
92
 
98
93
  if (c2 == undefined) return new C(c0, c0, c0, c1);
@@ -104,11 +99,11 @@ Q5.modules.color = ($, q) => {
104
99
  $.blue = (c) => c.b;
105
100
  $.alpha = (c) => c.a;
106
101
  $.lightness = (c) => {
107
- if ($._colorMode == 'oklch') return c.l;
102
+ if (c.l) return c.l;
108
103
  return ((0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b) * 100) / 255;
109
104
  };
110
105
  $.hue = (c) => {
111
- if ($._colorMode == 'oklch') return c.h;
106
+ if (c.h) return c.h;
112
107
  let r = c.r;
113
108
  let g = c.g;
114
109
  let b = c.b;
@@ -298,7 +298,7 @@ Q5.renderers.webgpu.canvas = ($, q) => {
298
298
  Q5.webgpu = async function (scope, parent) {
299
299
  if (!scope || scope == 'global') Q5._hasGlobal = true;
300
300
  if (!navigator.gpu) {
301
- console.error('q5 WebGPU not supported on this browser!');
301
+ console.warn('q5 WebGPU not supported on this browser!');
302
302
  let q = new Q5(scope, parent);
303
303
  q.colorMode('rgb', 1);
304
304
  q._beginRender = () => q.translate(q.canvas.hw, q.canvas.hh);
@@ -1 +1,187 @@
1
- Q5.renderers.webgpu.image = ($, q) => {};
1
+ Q5.renderers.webgpu.image = ($, q) => {
2
+ $.imageStack = [];
3
+ $.textures = [];
4
+
5
+ $._hooks.postCanvas.push(() => {
6
+ let imageVertexShader = Q5.device.createShaderModule({
7
+ code: `
8
+ struct VertexOutput {
9
+ @builtin(position) position: vec4<f32>,
10
+ @location(0) texCoord: vec2<f32>,
11
+ @location(1) textureIndex: f32
12
+ };
13
+
14
+ struct Uniforms {
15
+ halfWidth: f32,
16
+ halfHeight: f32
17
+ };
18
+
19
+ @group(0) @binding(0) var<uniform> uniforms: Uniforms;
20
+ @group(1) @binding(0) var<storage, read> transforms: array<mat4x4<f32>>;
21
+
22
+ @vertex
23
+ fn vertexMain(@location(0) pos: vec2<f32>, @location(1) texCoord: vec2<f32>, @location(2) transformIndex: f32, @location(3) textureIndex: f32) -> VertexOutput {
24
+ var vert = vec4<f32>(pos, 0.0, 1.0);
25
+ vert *= transforms[i32(transformIndex)];
26
+ vert.x /= uniforms.halfWidth;
27
+ vert.y /= uniforms.halfHeight;
28
+
29
+ var output: VertexOutput;
30
+ output.position = vert;
31
+ output.texCoord = texCoord;
32
+ output.textureIndex = textureIndex;
33
+ return output;
34
+ }
35
+ `
36
+ });
37
+
38
+ let imageFragmentShader = Q5.device.createShaderModule({
39
+ code: `
40
+ @group(0) @binding(0) var samp: sampler;
41
+ @group(0) @binding(1) var textures: array<texture_2d<f32>>;
42
+
43
+ @fragment
44
+ fn fragmentMain(@location(0) texCoord: vec2<f32>, @location(1) textureIndex: f32) -> @location(0) vec4<f32> {
45
+ return textureSample(textures[i32(textureIndex)], samp, texCoord);
46
+ }
47
+ `
48
+ });
49
+
50
+ const bindGroupLayouts = [
51
+ Q5.device.createBindGroupLayout({
52
+ entries: [
53
+ { binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: 'uniform' } },
54
+ { binding: 1, visibility: GPUShaderStage.FRAGMENT, sampler: {} },
55
+ { binding: 2, visibility: GPUShaderStage.FRAGMENT, texture: { viewDimension: '2d', sampleType: 'float' } }
56
+ ]
57
+ }),
58
+ Q5.device.createBindGroupLayout({
59
+ entries: [{ binding: 0, visibility: GPUShaderStage.VERTEX, buffer: { type: 'read-only-storage' } }]
60
+ })
61
+ ];
62
+
63
+ const pipelineLayout = Q5.device.createPipelineLayout({
64
+ bindGroupLayouts: bindGroupLayouts
65
+ });
66
+
67
+ $.pipelines[1] = Q5.device.createRenderPipeline({
68
+ layout: pipelineLayout,
69
+ vertex: {
70
+ module: imageVertexShader,
71
+ entryPoint: 'vertexMain',
72
+ buffers: [
73
+ {
74
+ arrayStride: 5 * 4, // 4 floats for position and texCoord, 1 float for textureIndex
75
+ attributes: [
76
+ { shaderLocation: 0, offset: 0, format: 'float32x2' },
77
+ { shaderLocation: 1, offset: 2 * 4, format: 'float32x2' },
78
+ { shaderLocation: 2, offset: 4 * 4, format: 'float32' } // textureIndex
79
+ ]
80
+ }
81
+ ]
82
+ },
83
+ fragment: {
84
+ module: imageFragmentShader,
85
+ entryPoint: 'fragmentMain',
86
+ targets: [{ format: 'bgra8unorm' }]
87
+ },
88
+ primitive: {
89
+ topology: 'triangle-list'
90
+ }
91
+ });
92
+
93
+ $.sampler = Q5.device.createSampler({
94
+ magFilter: 'linear',
95
+ minFilter: 'linear'
96
+ });
97
+ });
98
+
99
+ $.loadImage = async (src) => {
100
+ const img = new Image();
101
+ img.onload = async () => {
102
+ const imageBitmap = await createImageBitmap(img);
103
+ const texture = Q5.device.createTexture({
104
+ size: [img.width, img.height, 1],
105
+ format: 'bgra8unorm',
106
+ usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT
107
+ });
108
+
109
+ Q5.device.queue.copyExternalImageToTexture({ source: imageBitmap }, { texture }, [img.width, img.height, 1]);
110
+
111
+ img.texture = texture;
112
+ img.index = $.textures.length;
113
+ $.textures.push(texture);
114
+ };
115
+ img.onerror = reject;
116
+ img.src = src;
117
+ return img;
118
+ };
119
+
120
+ $._hooks.preRender.push(() => {
121
+ if (!$.imageStack.length) return;
122
+
123
+ // Switch to image pipeline
124
+ $.pass.setPipeline($.pipelines[1]);
125
+
126
+ // Create a vertex buffer for the image quads
127
+ const vertices = new Float32Array($.vertexStack);
128
+
129
+ const vertexBuffer = Q5.device.createBuffer({
130
+ size: vertices.byteLength,
131
+ usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST
132
+ });
133
+
134
+ Q5.device.queue.writeBuffer(vertexBuffer, 0, vertices);
135
+ $.pass.setVertexBuffer(0, vertexBuffer);
136
+
137
+ // Set the bind group for the sampler and textures
138
+ if ($.textures.length !== previousTextureCount) {
139
+ previousTextureCount = $.textures.length;
140
+
141
+ // Create the bind group for all textures
142
+ const textureViews = $.textures.map((tex) => tex.createView());
143
+
144
+ $.textureBindGroup = Q5.device.createBindGroup({
145
+ layout: $.pipelines[1].getBindGroupLayout(0),
146
+ entries: [
147
+ { binding: 0, resource: $.sampler },
148
+ ...textureViews.map((view, i) => ({ binding: i + 1, resource: view }))
149
+ ]
150
+ });
151
+ }
152
+
153
+ // Set the bind group for the sampler and textures
154
+ $.pass.setBindGroup(0, $.textureBindGroup);
155
+ });
156
+
157
+ $.image = (img, x, y, w, h) => {
158
+ if ($._matrixDirty) $._saveMatrix();
159
+ let ti = $._transformIndex;
160
+
161
+ $.imageStack.push(img.index);
162
+
163
+ // Calculate half-width and half-height
164
+ let hw = w / 2;
165
+ let hh = h / 2;
166
+
167
+ // Calculate vertices positions
168
+ let left = x - hw;
169
+ let right = x + hw;
170
+ let top = -(y - hh); // y is inverted in WebGPU
171
+ let bottom = -(y + hh);
172
+
173
+ let ii = img.index;
174
+
175
+ // prettier-ignore
176
+ $.vertexStack.push(
177
+ left, top, 0, 0, ti, ii,
178
+ right, top, 1, 0, ti, ii,
179
+ left, bottom, 0, 1, ti, ii,
180
+ right, top, 1, 0, ti, ii,
181
+ left, bottom, 0, 1, ti, ii,
182
+ right, bottom, 1, 1, ti, ii
183
+ );
184
+
185
+ $.drawStack.push(6);
186
+ };
187
+ };
package/src/readme.md CHANGED
@@ -109,11 +109,9 @@ Image based features in this module require the q5-2d-image module.
109
109
 
110
110
  > ⚠️ Experimental features! ⚠️
111
111
 
112
- To use q5's WebGPU renderer, run `Q5.webgpu()` at the top of your sketch. Explicit use of `createCanvas` is required.
112
+ To use q5's WebGPU renderer, run `Q5.webgpu()` at the bottom of your sketch. Explicit use of `createCanvas` is required.
113
113
 
114
114
  ```js
115
- Q5.webgpu();
116
-
117
115
  function setup() {
118
116
  createCanvas(200, 200);
119
117
  noStroke();
@@ -123,6 +121,8 @@ function draw() {
123
121
  clear();
124
122
  rect(50, 50, 100, 100);
125
123
  }
124
+
125
+ Q5.webgpu();
126
126
  ```
127
127
 
128
128
  For now, be sure to set `noStroke` in your setup code and `clear` the canvas at the start of your `draw` function to match current q5 webgpu limitations.