q5 2.4.3 → 2.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/package.json +1 -1
- package/q5.js +50 -39
- package/q5.min.js +1 -1
- package/src/q5-2d-canvas.js +2 -25
- package/src/q5-canvas.js +30 -0
- package/src/q5-core.js +2 -2
- package/src/q5-webgpu-canvas.js +11 -11
- package/src/q5-webgpu-drawing.js +5 -1
package/README.md
CHANGED
|
@@ -339,13 +339,13 @@ Unminified:
|
|
|
339
339
|
|
|
340
340
|
- p5.js **5112kb** ⚠️
|
|
341
341
|
- p5.sound.js 488kb
|
|
342
|
-
- q5.js
|
|
342
|
+
- q5.js 93kb
|
|
343
343
|
|
|
344
344
|
Minified:
|
|
345
345
|
|
|
346
346
|
- p5.min.js 1034kb ⚠️
|
|
347
347
|
- p5.sound.min.js 200kb
|
|
348
|
-
- q5.min.js **
|
|
348
|
+
- q5.min.js **61kb** 🎉
|
|
349
349
|
|
|
350
350
|
## Benchmarks
|
|
351
351
|
|
package/package.json
CHANGED
package/q5.js
CHANGED
|
@@ -86,12 +86,12 @@ function Q5(scope, parent, renderer) {
|
|
|
86
86
|
$._frameRate = 1000 / $.deltaTime;
|
|
87
87
|
q.frameCount++;
|
|
88
88
|
let pre = performance.now();
|
|
89
|
-
|
|
89
|
+
$.resetMatrix();
|
|
90
90
|
if ($._beginRender) $._beginRender();
|
|
91
91
|
for (let m of Q5.methods.pre) m.call($);
|
|
92
92
|
$.draw();
|
|
93
|
-
if ($._render) $._render();
|
|
94
93
|
for (let m of Q5.methods.post) m.call($);
|
|
94
|
+
if ($._render) $._render();
|
|
95
95
|
if ($._finishRender) $._finishRender();
|
|
96
96
|
q.pmouseX = $.mouseX;
|
|
97
97
|
q.pmouseY = $.mouseY;
|
|
@@ -533,6 +533,36 @@ Q5.modules.canvas = ($, q) => {
|
|
|
533
533
|
q.height = (c.h / c.w) * unit;
|
|
534
534
|
} else $._da = 0;
|
|
535
535
|
};
|
|
536
|
+
|
|
537
|
+
$._styleNames = [
|
|
538
|
+
'_doStroke',
|
|
539
|
+
'_doFill',
|
|
540
|
+
'_strokeSet',
|
|
541
|
+
'_fillSet',
|
|
542
|
+
'_tint',
|
|
543
|
+
'_imageMode',
|
|
544
|
+
'_rectMode',
|
|
545
|
+
'_ellipseMode',
|
|
546
|
+
'_textFont',
|
|
547
|
+
'_textLeading',
|
|
548
|
+
'_leadingSet',
|
|
549
|
+
'_textSize',
|
|
550
|
+
'_textAlign',
|
|
551
|
+
'_textBaseline',
|
|
552
|
+
'_textStyle',
|
|
553
|
+
'_textWrap'
|
|
554
|
+
];
|
|
555
|
+
$._styles = [];
|
|
556
|
+
|
|
557
|
+
$._pushStyles = () => {
|
|
558
|
+
let styles = {};
|
|
559
|
+
for (let s of $._styleNames) styles[s] = $[s];
|
|
560
|
+
$._styles.push(styles);
|
|
561
|
+
};
|
|
562
|
+
$._popStyles = () => {
|
|
563
|
+
let styles = $._styles.pop();
|
|
564
|
+
for (let s of $._styleNames) $[s] = styles[s];
|
|
565
|
+
};
|
|
536
566
|
};
|
|
537
567
|
|
|
538
568
|
Q5.canvasOptions = {
|
|
@@ -652,36 +682,13 @@ Q5.renderers.q2d.canvas = ($, q) => {
|
|
|
652
682
|
$.scale($._pixelDensity);
|
|
653
683
|
};
|
|
654
684
|
|
|
655
|
-
$._styleNames = [
|
|
656
|
-
'_doStroke',
|
|
657
|
-
'_doFill',
|
|
658
|
-
'_strokeSet',
|
|
659
|
-
'_fillSet',
|
|
660
|
-
'_tint',
|
|
661
|
-
'_imageMode',
|
|
662
|
-
'_rectMode',
|
|
663
|
-
'_ellipseMode',
|
|
664
|
-
'_textFont',
|
|
665
|
-
'_textLeading',
|
|
666
|
-
'_leadingSet',
|
|
667
|
-
'_textSize',
|
|
668
|
-
'_textAlign',
|
|
669
|
-
'_textBaseline',
|
|
670
|
-
'_textStyle',
|
|
671
|
-
'_textWrap'
|
|
672
|
-
];
|
|
673
|
-
$._styles = [];
|
|
674
|
-
|
|
675
685
|
$.push = $.pushMatrix = () => {
|
|
676
686
|
$.ctx.save();
|
|
677
|
-
|
|
678
|
-
for (let s of $._styleNames) styles[s] = $[s];
|
|
679
|
-
$._styles.push(styles);
|
|
687
|
+
$._pushStyles();
|
|
680
688
|
};
|
|
681
689
|
$.pop = $.popMatrix = () => {
|
|
682
690
|
$.ctx.restore();
|
|
683
|
-
|
|
684
|
-
for (let s of $._styleNames) $[s] = styles[s];
|
|
691
|
+
$._popStyles();
|
|
685
692
|
};
|
|
686
693
|
|
|
687
694
|
$.createCapture = (x) => {
|
|
@@ -3086,20 +3093,22 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
3086
3093
|
// Stack to keep track of transformation matrix indexes
|
|
3087
3094
|
$._transformIndexStack = [];
|
|
3088
3095
|
|
|
3089
|
-
$.push = () => {
|
|
3096
|
+
$.push = $.pushMatrix = () => {
|
|
3090
3097
|
// Push the current matrix index onto the stack
|
|
3091
3098
|
$._transformIndexStack.push($._transformIndex);
|
|
3099
|
+
$._pushStyles();
|
|
3092
3100
|
};
|
|
3093
3101
|
|
|
3094
|
-
$.pop = () => {
|
|
3095
|
-
if (
|
|
3096
|
-
|
|
3097
|
-
let idx = $._transformIndexStack.pop();
|
|
3098
|
-
$._matrix = $.transformStates[idx].slice();
|
|
3099
|
-
$._transformIndex = idx;
|
|
3100
|
-
} else {
|
|
3101
|
-
console.warn('Matrix index stack is empty!');
|
|
3102
|
+
$.pop = $.popMatrix = () => {
|
|
3103
|
+
if (!$._transformIndexStack.length) {
|
|
3104
|
+
return console.warn('Matrix index stack is empty!');
|
|
3102
3105
|
}
|
|
3106
|
+
// Pop the last matrix index from the stack and set it as the current matrix index
|
|
3107
|
+
let idx = $._transformIndexStack.pop();
|
|
3108
|
+
$._matrix = $.transformStates[idx].slice();
|
|
3109
|
+
$._transformIndex = idx;
|
|
3110
|
+
$._matrixDirty = false;
|
|
3111
|
+
$._popStyles();
|
|
3103
3112
|
};
|
|
3104
3113
|
|
|
3105
3114
|
$.translate = (x, y, z) => {
|
|
@@ -3298,8 +3307,6 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
3298
3307
|
$.colorsStack.length = 4;
|
|
3299
3308
|
colorIndex = 0;
|
|
3300
3309
|
rotation = 0;
|
|
3301
|
-
$.resetMatrix();
|
|
3302
|
-
$._matrixDirty = false;
|
|
3303
3310
|
$.transformStates.length = 1;
|
|
3304
3311
|
$._transformIndexStack.length = 0;
|
|
3305
3312
|
};
|
|
@@ -3502,6 +3509,10 @@ fn fragmentMain(@location(1) colorIndex: f32) -> @location(0) vec4<f32> {
|
|
|
3502
3509
|
};
|
|
3503
3510
|
|
|
3504
3511
|
$.endShape = (close) => {
|
|
3512
|
+
if (!$._doFill) {
|
|
3513
|
+
shapeVertices = [];
|
|
3514
|
+
return;
|
|
3515
|
+
}
|
|
3505
3516
|
let v = shapeVertices;
|
|
3506
3517
|
if (v.length < 12) {
|
|
3507
3518
|
throw new Error('A shape must have at least 3 vertices.');
|
|
@@ -3528,10 +3539,10 @@ fn fragmentMain(@location(1) colorIndex: f32) -> @location(0) vec4<f32> {
|
|
|
3528
3539
|
v[i + 3]
|
|
3529
3540
|
);
|
|
3530
3541
|
}
|
|
3542
|
+
shapeVertices = [];
|
|
3531
3543
|
|
|
3532
3544
|
verticesStack.push(...triangles);
|
|
3533
3545
|
drawStack.push(0, triangles.length / 4);
|
|
3534
|
-
shapeVertices = [];
|
|
3535
3546
|
};
|
|
3536
3547
|
|
|
3537
3548
|
$.triangle = (x1, y1, x2, y2, x3, y3) => {
|
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 a,o=this;if(o._q5=!0,o._parent=t,o._renderer=r||"q2d",o._preloadCount=0,e??="global","auto"==e){if(!window.setup&&!window.draw)return;e="global"}o._scope=e,"global"==e&&(Q5._hasGlobal=o._isGlobal=!0,a=Q5._nodejs?global:window);let n=new Proxy(o,{set:(e,t,r)=>(o[t]=r,o._isGlobal&&(a[t]=r),!0)});o.canvas=o.ctx=o.drawingContext=null,o.pixels=[];let i=null;o.frameCount=0,o.deltaTime=16,o._targetFrameRate=0,o._targetFrameDuration=16.666666666666668,o._frameRate=o._fps=60,o._loop=!0,o._hooks={postCanvas:[],preRender:[],postRender:[]};let s=0;o.millis=()=>performance.now()-s,o.noCanvas=()=>{o.canvas?.remove&&o.canvas.remove(),o.canvas=0,n.ctx=n.drawingContext=0},window&&(o.windowWidth=window.innerWidth,o.windowHeight=window.innerHeight,o.deviceOrientation=window.screen?.orientation?.type),o._incrementPreload=()=>n._preloadCount++,o._decrementPreload=()=>n._preloadCount--,o._draw=e=>{let t=e||performance.now();if(o._lastFrameTime??=t-o._targetFrameDuration,o._shouldResize&&(o.windowResized(),o._shouldResize=!1),o._loop)i=d(o._draw);else if(o.frameCount&&!o._redraw)return;if(i&&o.frameCount){if(t-o._lastFrameTime<o._targetFrameDuration-4)return}n.deltaTime=t-o._lastFrameTime,o._frameRate=1e3/o.deltaTime,n.frameCount++;let r=performance.now();o.ctx&&o.resetMatrix(),o._beginRender&&o._beginRender();for(let e of Q5.methods.pre)e.call(o);o.draw(),o._render&&o._render();for(let e of Q5.methods.post)e.call(o);o._finishRender&&o._finishRender(),n.pmouseX=o.mouseX,n.pmouseY=o.mouseY,o._lastFrameTime=t;let a=performance.now();o._fps=Math.round(1e3/(a-r))},o.noLoop=()=>{o._loop=!1,i=null},o.loop=()=>{o._loop=!0,null==i&&o._draw()},o.isLooping=()=>o._loop,o.redraw=(e=1)=>{o._redraw=!0;for(let t=0;t<e;t++)o._draw();o._redraw=!1},o.remove=()=>{o.noLoop(),o.canvas.remove()},o.frameRate=e=>(e&&(o._targetFrameRate=e,o._targetFrameDuration=1e3/e),o._frameRate),o.getTargetFrameRate=()=>o._targetFrameRate,o.getFPS=()=>o._fps,o.Element=function(e){this.elt=e},o._elements=[],o.TWO_PI=o.TAU=2*Math.PI,o.log=o.print=console.log,o.describe=()=>{};for(let e in Q5.modules)Q5.modules[e](o,n);let l=Q5.renderers[o._renderer];for(let e in l)l[e](o,n);for(let e in Q5)"_"!=e[1]&&e[1]==e[1].toUpperCase()&&(o[e]=Q5[e]);if("graphics"==e)return;"global"==e&&(Object.assign(Q5,o),delete Q5.Q5);for(let e of Q5.methods.init)e.call(o);for(let[e,t]of Object.entries(Q5.prototype))"_"!=e[0]&&"function"==typeof o[e]&&(o[e]=t.bind(o));if("global"==e){let e=Object.getOwnPropertyNames(o);for(let t of e)"_"!=t[0]&&(a[t]=o[t])}"function"==typeof e&&e(o),Q5._instanceCount++;let d=window.requestAnimationFrame||function(e){const t=o._lastFrameTime+o._targetFrameDuration;return setTimeout((()=>{e(t)}),t-performance.now())},c=a||o;o._isTouchAware=c.touchStarted||c.touchMoved||c.mouseReleased;let h=c.preload,u=["setup","draw","preload","mouseMoved","mousePressed","mouseReleased","mouseDragged","mouseClicked","keyPressed","keyReleased","keyTyped","touchStarted","touchMoved","touchEnded","windowResized"];for(let e of u)c[e]?o._isGlobal&&(o[e]=()=>{try{return c[e]()}catch(e){throw o._aiErrorAssistance&&o._aiErrorAssistance(e),e}}):o[e]=()=>{};async function p(){if(o._startDone=!0,o._preloadCount>0)return d(p);s=performance.now(),await o.setup(),o.frameCount||(null===o.ctx&&o.createCanvas(100,100),o._setupDone=!0,o.ctx&&o.resetMatrix(),d(o._draw))}(o.setup||o.draw)&&(arguments.length&&"namespace"!=e&&"webgpu"!=r||h?(o.preload(),p()):(c.preload=o.preload=()=>{o._startDone||p()},setTimeout(o.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.CENTER="center",e.LEFT="left",e.RIGHT="right",e.TOP="top",e.BOTTOM="bottom",e.BASELINE="alphabetic",e.NORMAL="normal",e.ITALIC="italic",e.BOLD="bold",e.BOLDITALIC="italic bold",e.ROUND="round",e.SQUARE="butt",e.PROJECT="square",e.MITER="miter",e.BEVEL="bevel",e.CHORD=0,e.PIE=1,e.OPEN=2,e.RADIUS="radius",e.CORNER="corner",e.CORNERS="corners",e.CLOSE=1,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.P2D="2d",e.WEBGL="webgl",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,e._pixelDensity=1,e.displayDensity=()=>window.devicePixelRatio||1,"image"!=e._scope&&(r.renderer=e._renderer,r[e._renderer]=!0,e._pixelDensity=Math.ceil(e.displayDensity())),e._adjustDisplay=()=>{r.style&&(r.style.width=r.w+"px",r.style.height=r.h+"px")},e.createCanvas=function(t,a,o){o??=arguments[3];let n=Object.assign({},Q5.canvasOptions);"object"==typeof o&&Object.assign(n,o),"image"!=e._scope&&("graphics"==e._scope?e._pixelDensity=this._pixelDensity:window.IntersectionObserver&&new IntersectionObserver((e=>{r.visible=e[0].isIntersecting})).observe(r)),e._setCanvasSize(t,a),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.createGraphics=function(t,r,a){let o=new Q5("graphics");return a??={},a.alpha??=!0,a.colorSpace??=e.canvas.colorSpace,o.createCanvas.call(e,t,r,a),o},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 a=document.createElement("a");a.href=e,a.download=t+"."+r,a.click(),URL.revokeObjectURL(a.href)},e.save=(t,r,a)=>{if((!t||"string"==typeof t&&(!r||!a&&r.length<5))&&(a=r,r=t,t=e.canvas),a)return e._save(t,r,a);r?(r=r.split("."),e._save(t,r[0],r.at(-1))):e._save(t)},e._setCanvasSize=(a,o)=>{a??=window.innerWidth,o??=window.innerHeight,r.w=a=Math.ceil(a),r.h=o=Math.ceil(o),r.hw=a/2,r.hh=o/2,r.width=Math.ceil(a*e._pixelDensity),r.height=Math.ceil(o*e._pixelDensity),e._da?e.flexibleCanvas(e._dau):(t.width=a,t.height=o),e.displayMode&&!r.displayMode?e.displayMode():e._adjustDisplay()},"image"!=e._scope){if(r&&"graphics"!=e._scope){function a(){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 a(){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(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==r.w&&a==r.h||e._resizeCanvas(t,a)},e.canvas.resize=e.resizeCanvas,e.canvas.save=e.saveCanvas=e.save,e.pixelDensity=t=>t&&t!=e._pixelDensity?(e._pixelDensity=t,e._setCanvasSize(r.w,r.h),t):e._pixelDensity,e.flexibleCanvas=(a=400)=>{a?(e._da=r.width/(a*e._pixelDensity),t.width=e._dau=a,t.height=r.h/r.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 r=e.canvas;e.colorMode&&e.colorMode("rgb","integer"),e._createCanvas=function(a,o,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,a)=>{let o={};for(let t in e.ctx)"function"!=typeof e.ctx[t]&&(o[t]=e.ctx[t]);delete o.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,a);for(let t in o)e.ctx[t]=o[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?t=e.color(...arguments):e._namedColors[t]&&(t=e.color(...e._namedColors[t]))),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?t=e.color(...arguments):e._namedColors[t]&&(t=e.color(...e._namedColors[t]))),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=>{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,a,o,n,i)=>e.ctx.transform(t,r,a,o,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},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._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 a(){e._doFill&&e.ctx.fill(),e._doStroke&&e.ctx.stroke()}function o(t,r,o,n,i,s,l,d){if(!e._doFill&&!e._doStroke)return;let c=e._angleMode,h=c?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(),o==n)c&&(i=e.radians(i),s=e.radians(s)),e.ctx.arc(t,r,o/2,i,s);else{for(let a=0;a<d+1;a++){let l=a/d,c=e.lerp(i,s,l),h=e.cos(c)*o/2,u=e.sin(c)*n/2;e.ctx[a?"lineTo":"moveTo"](t+h,r+u)}l==e.CHORD?e.ctx.closePath():l==e.PIE&&(e.ctx.lineTo(t,r),e.ctx.closePath())}a()}}function n(t,r,o,n){(e._doFill||e._doStroke)&&(e._da&&(t*=e._da,r*=e._da,o*=e._da,n*=e._da),e.ctx.beginPath(),e.ctx.ellipse(t,r,o/2,n/2,0,0,e.TAU),a())}function i(t,r,o,n,s,l,d,c){if(e._doFill||e._doStroke){if(void 0===s)return function(t,r,o,n){e._da&&(t*=e._da,r*=e._da,o*=e._da,n*=e._da),e.ctx.beginPath(),e.ctx.rect(t,r,o,n),a()}(t,r,o,n);if(void 0===l)return i(t,r,o,n,s,s,s,s);e._da&&(t*=e._da,r*=e._da,o*=e._da,n*=e._da,s*=e._da,l*=e._da,c*=e._da,d*=e._da),e.ctx.roundRect(t,r,o,n,[s,l,d,c]),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?t=e.color(...arguments):e._namedColors[t]&&(t=e.color(...e._namedColors[t]))),e.ctx.fillStyle=t.toString(),e.ctx.fillRect(0,0,e.canvas.width,e.canvas.height)),e.ctx.restore()},e.line=(t,r,a,o)=>{e._doStroke&&(e._da&&(t*=e._da,r*=e._da,a*=e._da,o*=e._da),e.ctx.beginPath(),e.ctx.moveTo(t,r),e.ctx.lineTo(a,o),e.ctx.stroke())},e.arc=(t,r,a,n,i,s,l,d=25)=>{if(i==s)return e.ellipse(t,r,a,n);l??=e.PIE,e._ellipseMode==e.CENTER?o(t,r,a,n,i,s,l,d):e._ellipseMode==e.RADIUS?o(t,r,2*a,2*n,i,s,l,d):e._ellipseMode==e.CORNER?o(t+a/2,r+n/2,a,n,i,s,l,d):e._ellipseMode==e.CORNERS&&o((t+a)/2,(r+n)/2,a-t,n-r,i,s,l,d)},e.ellipse=(t,r,a,o)=>{o??=a,e._ellipseMode==e.CENTER?n(t,r,a,o):e._ellipseMode==e.RADIUS?n(t,r,2*a,2*o):e._ellipseMode==e.CORNER?n(t+a/2,r+o/2,a,o):e._ellipseMode==e.CORNERS&&n((t+a)/2,(r+o)/2,a-t,o-r)},e.circle=(t,r,o)=>{e._ellipseMode==e.CENTER?(e._da&&(t*=e._da,r*=e._da,o*=e._da),e.ctx.beginPath(),e.ctx.arc(t,r,o/2,0,e.TAU),a()):e.ellipse(t,r,o,o)},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,a,o=a,n,s,l,d)=>{e._rectMode==e.CENTER?i(t-a/2,r-o/2,a,o,n,s,l,d):e._rectMode==e.RADIUS?i(t-a,r-o,2*a,2*o,n,s,l,d):e._rectMode==e.CORNER?i(t,r,a,o,n,s,l,d):e._rectMode==e.CORNERS&&i(t,r,a-t,o-r,n,s,l,d)},e.square=(t,r,a,o,n,i,s)=>e.rect(t,r,a,a,o,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=(a,o)=>{e._da&&(a*=e._da,o*=e._da),r=[],t?e.ctx.moveTo(a,o):e.ctx.lineTo(a,o),t=!1},e.bezierVertex=(t,a,o,n,i,s)=>{e._da&&(t*=e._da,a*=e._da,o*=e._da,n*=e._da,i*=e._da,s*=e._da),r=[],e.ctx.bezierCurveTo(t,a,o,n,i,s)},e.quadraticVertex=(t,a,o,n)=>{e._da&&(t*=e._da,a*=e._da,o*=e._da,n*=e._da),r=[],e.ctx.quadraticCurveTo(t,a,o,n)},e.bezier=(t,r,a,o,n,i,s,l)=>{e.beginShape(),e.vertex(t,r),e.bezierVertex(a,o,n,i,s,l),e.endShape()},e.triangle=(t,r,a,o,n,i)=>{e.beginShape(),e.vertex(t,r),e.vertex(a,o),e.vertex(n,i),e.endShape(e.CLOSE)},e.quad=(t,r,a,o,n,i,s,l)=>{e.beginShape(),e.vertex(t,r),e.vertex(a,o),e.vertex(n,i),e.vertex(s,l),e.endShape(e.CLOSE)},e.endShape=t=>{r=[],t&&e.ctx.closePath(),a()},e.curveVertex=(a,o)=>{if(e._da&&(a*=e._da,o*=e._da),r.push([a,o]),r.length<4)return;let n=function(e,t,r,a,o,n,i,s,l,d){function c(e,t,r,a,o,n){let i=Math.pow(a-t,2)+Math.pow(o-r,2);return Math.pow(i,.5*n)+e}let h=[],u=c(0,e,t,r,a,d),p=c(u,r,a,o,n,d),_=c(p,o,n,i,s,d);for(let d=0;d<l;d++){let c=u+d/(l-1)*(p-u),x=[(u-c)/(u-0),(c-0)/(u-0),(p-c)/(p-u),(c-u)/(p-u),(_-c)/(_-p),(c-p)/(_-p),(p-c)/(p-0),(c-0)/(p-0),(_-c)/(_-u),(c-u)/(_-u)];for(let e=0;e<x.length;e+=2)isNaN(x[e])&&(x[e]=1,x[e+1]=0),isFinite(x[e])||(x[e]>0?(x[e]=1,x[e+1]=0):(x[e]=0,x[e+1]=1));let g=e*x[0]+r*x[1],m=t*x[0]+a*x[1],f=r*x[2]+o*x[3],v=a*x[2]+n*x[3],y=o*x[4]+i*x[5],w=n*x[4]+s*x[5],b=g*x[6]+f*x[7],S=m*x[6]+v*x[7],M=f*x[8]+y*x[9],C=v*x[8]+w*x[9],Q=b*x[2]+M*x[3],R=S*x[2]+C*x[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,a,o,n,i,s,l)=>{e.beginShape(),e.curveVertex(t,r),e.curveVertex(a,o),e.curveVertex(n,i),e.curveVertex(s,l),e.endShape()},e.curvePoint=(e,t,r,a,o)=>{const n=o*o*o,i=o*o;return e*(-.5*n+i-.5*o)+t*(1.5*n-2.5*i+1)+r*(-1.5*n+2*i+.5*o)+a*(.5*n-.5*i)},e.bezierPoint=(e,t,r,a,o)=>{const n=1-o;return Math.pow(n,3)*e+3*Math.pow(n,2)*o*t+3*n*Math.pow(o,2)*r+Math.pow(o,3)*a},e.curveTangent=(e,t,r,a,o)=>{const n=o*o;return e*(-3*n/2+2*o-.5)+t*(9*n/2-5*o)+r*(-9*n/2+4*o+.5)+a*(3*n/2-o)},e.bezierTangent=(e,t,r,a,o)=>{const n=1-o;return 3*a*Math.pow(o,2)-3*r*Math.pow(o,2)+6*r*n*o-6*t*n*o+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 a=e._pixelDensity;return e.ctx.isPointInPath(t*a,r*a)},e.inStroke=(t,r)=>{const a=e._pixelDensity;return e.ctx.isPointInStroke(t*a,r*a)}},Q5.renderers.q2d.image=(e,t)=>{Q5.Image??=class{constructor(e,t,r){let a=this;a._scope="image",a.canvas=a.ctx=a.drawingContext=null,a.pixels=[],Q5.modules.canvas(a,a);let o=Q5.renderers.q2d;for(let e of["canvas","image","soft_filters"])o[e]&&o[e](a,a);a.createCanvas(e,t,r),delete a.createCanvas,a._loop=!1}get w(){return this.width}get h(){return this.height}},e.createImage=(t,r,a)=>(a??={},a.alpha??=!0,a.colorSpace??=e.canvas.colorSpace||Q5.canvasOptions.colorSpace,new Q5.Image(t,r,a)),e.loadImage=function(r,a,o){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);o="object"==typeof n?n:null;let i=e.createImage(1,1,o);function s(e){i.resize(e.naturalWidth||e.width,e.naturalHeight||e.height),i.ctx.drawImage(e,0,0),t._preloadCount--,a&&a(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,a,o,n,i=0,s=0,l,d)=>{let c=t.canvas||t;Q5._createNodeJSCanvas&&(c=c.context.canvas),o??=t.width||t.videoWidth,n??=t.height||t.videoHeight,"center"==e._imageMode&&(r-=.5*o,a-=.5*n),e._da&&(r*=e._da,a*=e._da,o*=e._da,n*=e._da,i*=e._da,s*=e._da,l*=e._da,d*=e._da);let h=t._pixelDensity||1;l?l*=h:l=c.width||c.videoWidth,d?d*=h:d=c.height||c.videoHeight,e.ctx.drawImage(c,i*h,s*h,l,d,r,a,o,n),e._tint&&(e.ctx.globalCompositeOperation="multiply",e.ctx.fillStyle=e._tint.toString(),e.ctx.fillRect(r,a,o,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 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,r),e.ctx.clearRect(0,0,e.canvas.width,e.canvas.height),e.ctx.drawImage(a,0,0,e.canvas.width,e.canvas.height)}),e._getImageData=(t,r,a,o)=>e.ctx.getImageData(t,r,a,o,{colorSpace:e.canvas.colorSpace}),e.trim=()=>{let t=e._pixelDensity||1,r=e.canvas.width,a=e.canvas.height,o=e._getImageData(0,0,r,a).data,n=r,i=0,s=a,l=0,d=3;for(let e=0;e<a;e++)for(let t=0;t<r;t++)0!==o[d]&&(t<n&&(n=t),t>i&&(i=t),e<s&&(s=e),e>l&&(l=e)),d+=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,a,o)=>{let n=e._pixelDensity||1;if(void 0!==t&&void 0===a){let a=e._getImageData(t*n,r*n,1,1).data;return new e.Color(a[0],a[1],a[2],a[3]/255)}t=(t||0)*n,r=(r||0)*n;let i=a=a||e.width,s=o=o||e.height;a*=n,o*=n;let l=e.createImage(a,o),d=e._getImageData(t,r,a,o);return l.ctx.putImageData(d,0,0),l._pixelDensity=n,l.width=i,l.height=s,l},e.set=(t,r,a)=>{if(a.canvas){let o=e._tint;return e._tint=null,e.image(a,t,r),void(e._tint=o)}e.pixels.length||e.loadPixels();let o=e._pixelDensity||1;for(let n=0;n<o;n++)for(let i=0;i<o;i++){let s=4*((r*o+n)*e.canvas.width+t*o+i);e.pixels[s]=a.r??a.l,e.pixels[s+1]=a.g??a.c,e.pixels[s+2]=a.b??a.h,e.pixels[s+3]=a.a}},e.loadPixels=()=>{r=e._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._textFont="sans-serif",e._textSize=12,e._textLeading=15,e._textLeadDiff=3,e._textStyle="normal",e.loadFont=(e,r)=>{t._preloadCount++;let a=e.split("/").pop().split(".")[0].replace(" ",""),o=new FontFace(a,`url(${e})`);return document.fonts.add(o),o.load().then((()=>{t._preloadCount--,r&&r(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,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.textFill=e.fill,e.textStroke=e.stroke,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[a,o]of this.entries())o.lastAccessed<t&&(t=o.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,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+"_":"")+(r||"")+(a?"x"+a:""),e.createTextImage=(t,r,a)=>{let o=e._genTextImageKey(t,r,a);if(e._tic.get(o))return e._tic.get(o);let n=e._textCache;return e._textCache=!0,e._genTextImage=!0,e.text(t,0,0,r,a),e._genTextImage=!1,e._textCache=n,e._tic.get(o)},e.text=(t,r,a,o,n)=>{if(void 0===t)return;if(t=t.toString(),e._da&&(r*=e._da,a*=e._da),!e._doFill&&!e._doStroke)return;let i,s,l,d,c,h,u,p,_=e.ctx.getTransform(),x=e._genTextImage||e._textCache&&(0!=_.b||0!=_.c);if(x){if(d=e._genTextImageKey(t,o,n),s=e._tic.get(d),s&&!e._genTextImage)return void e.textImage(s,r,a);l=e.createGraphics.call(e,1,1),i=l.ctx}else i=e.ctx,c=r,h=a;i.font=`${e._textStyle} ${e._textSize}px ${e._textFont}`;let g=t.split("\n");if(x){c=0,h=e._textLeading*g.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 m=i.fillStyle;e._fillSet||(i.fillStyle="black");for(let t=0;t<g.length&&(e._doStroke&&e._strokeSet&&i.strokeText(g[t],c,h),e._doFill&&i.fillText(g[t],c,h),h+=e._textLeading,!(h>n));t++);e._fillSet||(i.fillStyle=m),x&&(s=l,s._ascent=u,s._descent=p,e._tic.set(d,s),e._genTextImage||e.textImage(s,r,a))},e.textImage=(t,r,a)=>{let o=e._imageMode;e._imageMode="corner","center"==e.ctx.textAlign?r-=.5*t.width:"right"==e.ctx.textAlign&&(r-=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,r,a),e._imageMode=o},e.nf=(e,t,r)=>{let a=e<0,o=(e=Math.abs(e)).toFixed(r).split(".");o[0]=o[0].padStart(t,"0");let n=o.join(".");return a&&(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(Q5.disableFriendlyErrors&&!r)return;!r&&Q5.errorTolerant||e.noLoop();let a=t.stack?.split("\n");if(!t.stack||a.length<=1)return;let o=1,n="(";for(-1==navigator.userAgent.indexOf("Chrome")&&(o=0,n="@");a[o].indexOf("q5")>=0;)o++;let i=a[o].split(n).at(-1);i=i.split(":");let s=parseInt(i.at(-2));r&&s++;let l=i.slice(0,-2).join(":"),d=l.split("/").at(-1);try{let e=(await(await fetch(l)).text()).split("\n"),a=e[s-1].trim(),o="",n=1;for(;o.length<1600&&(s-n>=0&&(o=e[s-n].trim()+"\n"+o),s+n<e.length);)o+=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(a)+"%0A%0AExcerpt+for+context%3A%0A%0A"+encodeURIComponent(o);if(console.warn("Error in "+d+" on line "+s+":\n\n"+a),console.warn("Ask AI ✨ "+i),r)return window.open(i,"_blank")}catch(e){}}},Q5.modules.color=(e,t)=>{e.RGB=e.RGBA=e._colorMode="rgb",e.OKLCH="oklch",e.colorMode=(r,a)=>{e._colorMode=r;let o="srgb"==e.canvas.colorSpace||"srgb"==r;if(a??=o?"integer":"float",e._colorFormat="float"==a||1==a?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,a,o)=>{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&&(o=parseInt(t[4]+t[4],16)),a=parseInt(t[3]+t[3],16),r=parseInt(t[2]+t[2],16),t=parseInt(t[1]+t[1],16)):(t.length>7&&(o=parseInt(t.slice(7,9),16)),a=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,a,o]=e._namedColors[t]}1==e._colorFormat&&(t/=255,r&&(r/=255),a&&(a/=255),o&&(o/=255))}Array.isArray(t)&&([t,r,a,o]=t)}return null==a?new n(t,t,t,r):new n(t,r,a,o)},e.red=e=>e.r,e.green=e=>e.g,e.blue=e=>e.b,e.alpha=e=>e.a,e.lightness=e=>e.l?e.l:100*(.2126*e.r+.7152*e.g+.0722*e.b)/255,e.hue=t=>{if(t.h)return t.h;let r=t.r,a=t.g,o=t.b;255==e._colorFormat&&(r/=255,a/=255,o/=255);let n,i=Math.max(r,a,o),s=Math.min(r,a,o);return n=i==s?0:i==r?60*(a-o)/(i-s):i==a?60*(o-r)/(i-s)+120:60*(r-a)/(i-s)+240,n<0&&(n+=360),n},e.lerpColor=(t,r,a)=>{if("rgb"==e._colorMode)return new e.Color(e.constrain(e.lerp(t.r,r.r,a),0,255),e.constrain(e.lerp(t.g,r.g,a),0,255),e.constrain(e.lerp(t.b,r.b,a),0,255),e.constrain(e.lerp(t.a,r.a,a),0,255));{let o=r.h-t.h;o>180&&(o-=360),o<-180&&(o+=360);let n=t.h+a*o;return n<0&&(n+=360),n>360&&(n-=360),new e.Color(e.constrain(e.lerp(t.l,r.l,a),0,100),e.constrain(e.lerp(t.c,r.c,a),0,100),n,e.constrain(e.lerp(t.a,r.a,a),0,255))}}},Q5.Color=class{constructor(){this._q5Color=!0}},Q5.ColorOKLCH=class extends Q5.Color{constructor(e,t,r,a){super(),this.l=e,this.c=t,this.h=r,this.a=a??1}toString(){return`oklch(${this.l} ${this.c} ${this.h} / ${this.a})`}},Q5.ColorRGBA=class extends Q5.Color{constructor(e,t,r,a){super(),this.r=e,this.g=t,this.b=r,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,r,a){super(e,t,r,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,r,a){super(e,t,r,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),r=(this._b/255).toFixed(3),a=(this._a/255).toFixed(3);this._css=`color(display-p3 ${e} ${t} ${r} / ${a})`,this._edited=!1}return this._css}},Q5.modules.display=e=>{if(!e.canvas||"graphics"==e._scope)return;let t=e.canvas;e.CENTERED="centered",e.FULLSCREEN="fullscreen",e.MAXED="maxed",e.PIXELATED="pixelated",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,a=t.parentElement;r&&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"),r.width=t.w*t.displayScale+"px",r.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?(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",a="default",o=1)=>{"string"==typeof o&&(o=parseFloat(o.slice(1))),Object.assign(t,{displayMode:r,renderQuality:a,displayScale:o}),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={},a=[e.LEFT,e.CENTER,e.RIGHT],o=e.canvas;function n(t){const r=e.canvas.getBoundingClientRect(),a=e.canvas.scrollWidth/e.width||1,o=e.canvas.scrollHeight/e.height||1;return{x:(t.clientX-r.left)/a,y:(t.clientY-r.top)/o,id:t.identifier}}if(e._startAudio=()=>{e.getAudioContext&&"suspended"==e.getAudioContext()?.state&&e.userStartAudio()},e._updateMouse=r=>{if(!r.changedTouches)if(o){let a=o.getBoundingClientRect(),n=o.scrollWidth/e.width||1,i=o.scrollHeight/e.height||1;t.mouseX=(r.clientX-a.left)/n,t.mouseY=(r.clientY-a.top)/i,"webgpu"==o.renderer&&(t.mouseX-=o.hw,t.mouseY-=o.hh)}else t.mouseX=r.clientX,t.mouseY=r.clientY},e._onmousedown=r=>{e._startAudio(),e._updateMouse(r),t.mouseIsPressed=!0,t.mouseButton=a[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,a)=>{let o="";t.includes(".")&&(t=`url("${t}")`,o=", auto"),void 0!==r&&(t+=" "+r+" "+a),e.canvas.style.cursor=t+o},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,r[e.keyCode]=r[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,r[e.keyCode]=r[e.key.toLowerCase()]=!1,e.keyReleased(a)},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()},o&&(o.addEventListener("mousedown",(t=>e._onmousedown(t))),o.addEventListener("mouseup",(t=>e._onmouseup(t))),o.addEventListener("click",(t=>e._onclick(t))),o.addEventListener("touchstart",(t=>e._ontouchstart(t))),o.addEventListener("touchmove",(t=>e._ontouchmove(t))),o.addEventListener("touchcancel",(t=>e._ontouchend(t))),o.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.RADIANS=0,e.DEGREES=1,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;let r=0;e.angleMode=t=>{"radians"==t&&(t=0),r=e._angleMode=t};let a=e._DEGTORAD=Math.PI/180,o=e._RADTODEG=180/Math.PI;function n(){let e,t,r=4294967295;return{setSeed(a){e=t=(a??Math.random()*r)>>>0},getSeed:()=>t,rand:()=>(e^=e<<17,e^=e>>13,e^=e<<5,(e>>>0)/r)}}e.degrees=t=>t*e._RADTODEG,e.radians=t=>t*e._DEGTORAD,e.map=Q5.prototype.map=(e,t,r,a,o,n)=>{let i=a+1*(e-t)/(r-t)*(o-a);return n?a<o?Math.min(Math.max(i,a),o):Math.min(Math.max(i,o),a):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,a)=>e.map(t,r,a,0,1),e.sq=e=>e*e,e.fract=e=>e-Math.floor(e),e.sin=e=>Math.sin(r?e*a:e),e.cos=e=>Math.cos(r?e*a:e),e.tan=e=>Math.tan(r?e*a:e),e.asin=e=>{let t=Math.asin(e);return r?t*o:t},e.acos=e=>{let t=Math.acos(e);return r?t*o:t},e.atan=e=>{let t=Math.atan(e);return r?t*o:t},e.atan2=(e,t)=>{let a=Math.atan2(e,t);return r?a*o:a};let i=n();i.setSeed(),e.randomSeed=e=>i.setSeed(e),e.random=(e,t)=>void 0===e?i.rand():"number"==typeof e?void 0!==t?i.rand()*(t-e)+e:i.rand()*e:e[Math.trunc(e.length*i.rand())],e.randomGenerator=t=>{t==e.LCG?i=function(){const e=4294967296;let t,r;return{setSeed(a){r=t=(a??Math.random()*e)>>>0},getSeed:()=>t,rand:()=>(r=(1664525*r+1013904223)%e,r/e)}}():t==e.SHR3&&(i=n()),i.setSeed()};var s=new function(){var e,t,r,a=new Array(128),o=new Array(256),n=new Array(128),s=new Array(128),l=new Array(256),d=new Array(256),c=()=>4294967296*i.rand()-2147483648,h=()=>.5+2.328306e-10*(c()|0),u=()=>{for(var t,o,i,l,d=3.44262;;){if(t=r*n[e],0==e){do{i=h(),l=h(),t=.2904764*-Math.log(i),o=-Math.log(l)}while(o+o<t*t);return r>0?d+t:-d-t}if(s[e]+h()*(s[e-1]-s[e])<Math.exp(-.5*t*t))return t;if(r=c(),e=127&r,Math.abs(r)<a[e])return r*n[e]}},p=()=>{for(var r;;){if(0==e)return 7.69711-Math.log(h());if(r=t*l[e],d[e]+h()*(d[e-1]-d[e])<Math.exp(-r))return r;if((t=c())<o[e=255&t])return t*l[e]}};this.SHR3=c,this.UNI=h,this.RNOR=()=>(r=c(),e=127&r,Math.abs(r)<a[e]?r*n[e]:u()),this.REXP=()=>(t=c()>>>0)<a[e=255&t]?t*l[e]:p(),this.zigset=()=>{var e,t,r=2147483648,i=4294967296,c=3.442619855899,h=c,u=.00991256303526217,p=7.697117470131487,_=p,x=.003949659822581572;for(e=u/Math.exp(-.5*c*c),a[0]=Math.floor(c/e*r),a[1]=0,n[0]=e/r,n[127]=c/r,s[0]=1,s[127]=Math.exp(-.5*c*c),t=126;t>=1;t--)c=Math.sqrt(-2*Math.log(u/c+Math.exp(-.5*c*c))),a[t+1]=Math.floor(c/h*r),h=c,s[t]=Math.exp(-.5*c*c),n[t]=c/r;for(e=x/Math.exp(-p),o[0]=Math.floor(p/e*i),o[1]=0,l[0]=e/i,l[255]=p/i,d[0]=1,d[255]=Math.exp(-p),t=254;t>=1;t--)p=-Math.log(x/p+Math.exp(-p)),o[t+1]=Math.floor(p/_*i),_=p,d[t]=Math.exp(-p),l[t]=p/i}};let l;s.hasInit=!1,e.randomGaussian=(e,t)=>(s.hasInit||(s.zigset(),s.hasInit=!0),s.RNOR()*t+e),e.randomExponential=()=>(s.hasInit||(s.zigset(),s.hasInit=!0),s.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"],l=null},e.noiseSeed=t=>{l=new e.Noise(t)},e.noise=(t=0,r=0,a=0)=>(l??=new e.Noise,l.noise(t,r,a)),e.noiseDetail=(t,r)=>{l??=new e.Noise,t>0&&(l.octaves=t),r>0&&(l.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,a=[];for(let e=0;e<256;e++)a[e]=e;for(let o=255;o>0;o--)t=(e=16807*e%2147483647)%(o+1),r=a[o],a[o]=a[t],a[t]=r;return a}dot(e,t,r,a){return e[0]*t+e[1]*r+e[2]*a}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 a=this,o=0,n=1,i=1,s=0;for(let l=0;l<a.octaves;l++){const l=255&Math.floor(e*n),d=255&Math.floor(t*n),c=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),_=a.fade(h),x=a.fade(u),g=a.fade(p),m=a.p[l]+d,f=a.p[m]+c,v=a.p[m+1]+c,y=a.p[l+1]+d,w=a.p[y]+c,b=a.p[y+1]+c,S=a.mix(a.dot(a.grad3[a.p[f]%12],h,u,p),a.dot(a.grad3[a.p[w]%12],h-1,u,p),_),M=a.mix(a.dot(a.grad3[a.p[v]%12],h,u-1,p),a.dot(a.grad3[a.p[b]%12],h-1,u-1,p),_),C=a.mix(a.dot(a.grad3[a.p[f+1]%12],h,u,p-1),a.dot(a.grad3[a.p[w+1]%12],h-1,u,p-1),_),Q=a.mix(a.dot(a.grad3[a.p[v+1]%12],h,u-1,p-1),a.dot(a.grad3[a.p[b+1]%12],h-1,u-1,p-1),_),R=a.mix(S,M,x),I=a.mix(C,Q,x);o+=a.mix(R,I,g)*i,s+=i,i*=a.falloff,n*=2}return(o/s+1)/2}},Q5.modules.sound=(e,t)=>{e.Sound=Q5.Sound,e.loadSound=(e,r)=>{t._preloadCount++,Q5.aud??=new window.AudioContext;let a=new Q5.Sound(e,r);return a.addEventListener("canplaythrough",(()=>{t._preloadCount--,a.loaded=!0,r&&r(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,r,a)=>{t._preloadCount++;let o={};return fetch(e).then((e=>"json"==a?e.json():"text"==a?e.text():void 0)).then((e=>{t._preloadCount--,Object.assign(o,e),r&&r(e)})),o},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,a)=>new Q5.Vector(t,r,a,e)},Q5.Vector=class{constructor(e,t,r,a){this.x=e||0,this.y=t||0,this.z=r||0,this._$=a||window,this._cn=null,this._cnsq=null}set(e,t,r){return this.x=e?.x||e||0,this.y=e?.y||t||0,this.z=e?.z||r||0,this}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,a=this.z-e.z;return Math.sqrt(t*t+r*r+a*a)}cross(){let e=this._arg2v(...arguments),t=this.y*e.z-this.z*e.y,r=this.z*e.x-this.x*e.z,a=this.x*e.y-this.y*e.x;return this.x=t,this.y=r,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 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)}setHeading(e){let t=this.mag();return this.x=t*this._$.cos(e),this.y=t*this._$.sin(e),this}rotate(e){let t=this._$.cos(e),r=this._$.sin(e),a=this.x*t-this.y*r,o=this.x*r+this.y*t;return this.x=a,this.y=o,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=e.at(-1);if(0==t)return this;let r=this._arg2v(...e.slice(0,-1));return this.x+=(r.x-this.x)*t,this.y+=(r.y-this.y)*t,this.z+=(r.z-this.z)*t,this}slerp(){let e=[...arguments],t=e.at(-1);if(0==t)return this;let r=this._arg2v(...e.slice(0,-1));if(1==t)return this.set(r);let a=this.mag(),o=r.mag();if(0==a||0==o)return this.mult(1-t).add(r.mult(t));let n=Q5.Vector.cross(this,r),i=n.mag(),s=Math.atan2(i,this.dot(r));if(i>0)n.div(i);else{if(s<this._$.HALF_PI)return this.mult(1-t).add(r.mult(t));0==this.z&&0==r.z?n.set(0,0,1):0!=this.x?n.set(this.y,-this.x,0).normalize():n.set(1,0,0)}let l=n.cross(this),d=1-t+t*o/a,c=d*Math.cos(t*s),h=d*Math.sin(t*s);return this.x=this.x*c+l.x*h,this.y=this.y*c+l.y*h,this.z=this.z*c+l.z*h,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 a=this._$.cos(t),o=this._$.sin(t),n=this._$.cos(e),i=this._$.sin(e);return this.x=r*i*o,this.y=-r*n,this.z=r*i*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,r)=>e.equals(t,r),Q5.Vector.lerp=(e,t,r)=>e.copy().lerp(t,r),Q5.Vector.slerp=(e,t,r)=>e.copy().slerp(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,a)=>(new Q5.Vector)[e](t,r,a);Q5.renderers.webgpu={},Q5.renderers.webgpu.canvas=(e,t)=>{let r,a=e.canvas;a.width=e.width=500,a.height=e.height=500,e.colorMode&&e.colorMode("rgb","float"),e.pipelines=[];let o=e.drawStack=[],n=e.colorsStack=[1,1,1,1];e._envLayout=Q5.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"uniform",hasDynamicOffset:!1}}]}),e._transformLayout=Q5.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage",hasDynamicOffset:!1}}]}),e.bindGroupLayouts=[e._envLayout,e._transformLayout];const i=Q5.device.createBuffer({size:8,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});e._createCanvas=(r,o,n)=>(t.ctx=t.drawingContext=a.getContext("webgpu"),n.format=navigator.gpu.getPreferredCanvasFormat(),n.device=Q5.device,e.ctx.configure(n),Q5.device.queue.writeBuffer(i,0,new Float32Array([e.canvas.hw,e.canvas.hh])),e._envBindGroup=Q5.device.createBindGroup({layout:e._envLayout,entries:[{binding:0,resource:{buffer:i}}]}),a),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,a)=>{(t||r||a)&&(e._matrix[3]+=t,e._matrix[7]-=r,e._matrix[11]+=a||0,e._matrixDirty=!0)},e.rotate=t=>{if(!t)return;e._angleMode&&(t*=e._DEGTORAD);let r=Math.cos(t),a=Math.sin(t),o=e._matrix[0],n=e._matrix[1],i=e._matrix[4],s=e._matrix[5];o||n||i||s?(e._matrix[0]=o*r+i*a,e._matrix[1]=n*r+s*a,e._matrix[4]=o*-a+i*r,e._matrix[5]=n*-a+s*r):(e._matrix[0]=r,e._matrix[1]=a,e._matrix[4]=-a,e._matrix[5]=r),e._matrixDirty=!0},e.scale=(t=1,r,a=1)=>{r??=t,e._matrix[0]*=t,e._matrix[5]*=r,e._matrix[10]*=a,e._matrixDirty=!0},e._saveMatrix=()=>{e.transformStates.push(e._matrix.slice()),e._transformIndex=e.transformStates.length-1,e._matrixDirty=!1};let s=0;const l=(t,r,a,o=1)=>{"string"==typeof t?t=e.color(t):null==a&&(o=r??1,r=a=t),t._q5Color?n.push(t.r,t.g,t.b,t.a):n.push(t,r,a,o),s++};e.fill=(t,r,a,o)=>{l(t,r,a,o),e._doFill=!0,e._fillIndex=s},e.stroke=(t,r,a,o)=>{l(t,r,a,o),e._doStroke=!0,e._strokeIndex=s},e.noFill=()=>e._doFill=!1,e.noStroke=()=>e._doStroke=!1,e._strokeWeight=1,e.strokeWeight=t=>e._strokeWeight=Math.abs(t),e._calcBox=(e,t,r,a,o)=>{let n,i,s,l,d=r/2,c=a/2;return o&&"corner"!=o?"center"==o?(n=e-d,i=e+d,s=-(t-c),l=-(t+c)):(n=e,i=r,s=-t,l=-a):(n=e,i=e+r,s=-t,l=-(t+a)),[n,i,s,l]},e.clear=()=>{},e._beginRender=()=>{e.encoder=Q5.device.createCommandEncoder(),r=t.pass=e.encoder.beginRenderPass({label:"q5-webgpu",colorAttachments:[{view:ctx.getCurrentTexture().createView(),loadOp:"clear",storeOp:"store"}]})},e._render=()=>{if(transformStates.length>1||!e._transformBindGroup){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())),e._transformBindGroup=Q5.device.createBindGroup({layout:e._transformLayout,entries:[{binding:0,resource:{buffer:t}}]})}r.setBindGroup(0,e._envBindGroup),r.setBindGroup(1,e._transformBindGroup);for(let t of e._hooks.preRender)t();let t=0,a=0,n=-1;r.setPipeline(e.pipelines[0]);for(let i=0;i<o.length;i+=2){let s=o[i+1];n!=o[i]&&(n=o[i],r.setPipeline(e.pipelines[n])),0==n?(r.draw(s,1,t,0),t+=s):1==n&&(-1!=s&&r.setBindGroup(3,e._textureBindGroups[s]),r.draw(6,1,a,0),a+=6)}for(let t of e._hooks.postRender)t()},e._finishRender=()=>{r.end();const a=e.encoder.finish();Q5.device.queue.submit([a]),t.pass=e.encoder=null,e.drawStack.length=0,e.colorsStack.length=4,s=0,rotation=0,e.resetMatrix(),e._matrixDirty=!1,e.transformStates.length=1,e._transformIndexStack.length=0}},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,a,o=e.canvas,n=e.drawStack,i=e.colorsStack,s=[],l=Q5.device.createShaderModule({label:"drawingVertexShader",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"}),d=Q5.device.createShaderModule({label:"drawingFragmentShader",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"});a=Q5.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage",hasDynamicOffset:!1}}]}),e.bindGroupLayouts.push(a);let c={arrayStride:16,attributes:[{format:"float32x2",offset:0,shaderLocation:0},{format:"float32",offset:8,shaderLocation:1},{format:"float32",offset:12,shaderLocation:2}]},h=["zero","one","src-alpha","one-minus-src-alpha","dst","dst-alpha","one-minus-dst-alpha","one-minus-src"],u=["add","subtract","reverse-subtract","min","max"];const p={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]};e.blendConfigs={};for(const[t,r]of Object.entries(p))e.blendConfigs[t]={color:{srcFactor:h[r[0]],dstFactor:h[r[1]],operation:u[r[2]]},alpha:{srcFactor:h[r[3]],dstFactor:h[r[4]],operation:u[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]))};let _,x=Q5.device.createPipelineLayout({label:"drawingPipelineLayout",bindGroupLayouts:e.bindGroupLayouts});e._createPipeline=e=>Q5.device.createRenderPipeline({label:"drawingPipeline",layout:x,vertex:{module:l,entryPoint:"vertexMain",buffers:[c]},fragment:{module:d,entryPoint:"fragmentMain",targets:[{format:"bgra8unorm",blend:e}]},primitive:{topology:"triangle-list"}}),e.pipelines[0]=e._createPipeline(e.blendConfigs.normal),e.beginShape=()=>{_=[]},e.vertex=(t,r)=>{e._matrixDirty&&e._saveMatrix(),_.push(t,-r,e._fillIndex,e._transformIndex)},e.endShape=e=>{let t=_;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 r=[];for(let e=4;e<t.length;e+=4)r.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]);s.push(...r),n.push(0,r.length/4),_=[]},e.triangle=(t,r,a,o,n,i)=>{e.beginShape(),e.vertex(t,r),e.vertex(a,o),e.vertex(n,i),e.endShape(1)},e.rectMode=t=>e._rectMode=t,e.rect=(t,a,o,i)=>{let[l,d,c,h]=e._calcBox(t,a,o,i,e._rectMode),u=r??e._fillIndex;e._matrixDirty&&e._saveMatrix();let p=e._transformIndex;s.push(l,c,u,p,d,c,u,p,l,h,u,p,d,c,u,p,l,h,u,p,d,h,u,p),n.push(0,6)},e.point=(t,a)=>{r=e._strokeIndex;let o=e._strokeWeight;o<2?(o=Math.round(o),e.rect(t,a,o,o)):e.ellipse(t,a,o,o),r=null},e.line=(t,a,o,n)=>{r=e._strokeIndex,e.push(),e.translate(t,a),e.rotate(e.atan2(n-a,o-t));let i=Math.sqrt((o-t)**2+(n-a)**2),s=e._strokeWeight;e.rect(0,-s/2,i,s),e.pop(),r=null},e.background=(t,r,a,n)=>{e.push(),e.resetMatrix(),t.src?e.image(t,-o.hw,-o.hh,o.w,o.h):(e.fill(t,r,a,n),e.rect(-o.hw,-o.hh,o.w,o.h)),e.pop()};e.ellipseMode=t=>e._ellipseMode=t,e.ellipse=(t,a,o,i)=>{const l=(d=o==i?o:Math.max(o,i))<4?6:d<6?8:d<10?10:d<16?12:d<20?14:d<22?16:d<24?18:d<28?20:d<34?22:d<42?24:d<48?26:d<56?28:d<64?30:d<72?32:d<84?34:d<96?36:d<98?38:d<113?40:d<149?44:d<199?48:d<261?52:d<353?56:d<461?60:d<585?64:d<1200?70:d<1800?80:d<2400?90:100;var d;let c=Math.max(o,1)/2,h=o==i?c:Math.max(i,1)/2,u=0;const p=e.TAU/l,_=r??e._fillIndex;e._matrixDirty&&e._saveMatrix();const x=e._transformIndex;let g,m,f,v;for(let e=0;e<=l;e++)g=f,m=v,f=t+c*Math.cos(u),v=a+h*Math.sin(u),u+=p,0!=e&&s.push(t,a,_,x,g,m,_,x,f,v,_,x);n.push(0,3*l)},e.circle=(t,r,a)=>e.ellipse(t,r,a,a),e._hooks.preRender.push((()=>{e.pass.setPipeline(e.pipelines[0]);const t=new Float32Array(s),r=Q5.device.createBuffer({size:t.byteLength,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST});Q5.device.queue.writeBuffer(r,0,t),e.pass.setVertexBuffer(0,r);const o=Q5.device.createBuffer({size:4*i.length,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});Q5.device.queue.writeBuffer(o,0,new Float32Array(i)),e._colorsBindGroup=Q5.device.createBindGroup({layout:a,entries:[{binding:0,resource:{buffer:o,offset:0,size:4*i.length}}]}),e.pass.setBindGroup(2,e._colorsBindGroup)})),e._hooks.postRender.push((()=>{s.length=0}))},Q5.renderers.webgpu.image=(e,t)=>{e._textureBindGroups=[];let r=[],a=Q5.device.createShaderModule({label:"imageVertexShader",code:"\nstruct VertexOutput {\n\t@builtin(position) position: vec4<f32>,\n\t@location(0) texCoord: vec2<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) texCoord: vec2<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.texCoord = texCoord;\n\treturn output;\n}\n\t"}),o=Q5.device.createShaderModule({label:"imageFragmentShader",code:"\n@group(3) @binding(0) var samp: sampler;\n@group(3) @binding(1) var texture: texture_2d<f32>;\n\n@fragment\nfn fragmentMain(@location(0) texCoord: vec2<f32>) -> @location(0) vec4<f32> {\n\t// Sample the texture using the interpolated texture coordinate\n\treturn textureSample(texture, samp, texCoord);\n}\n\t"}),n=Q5.device.createBindGroupLayout({label:"textureLayout",entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,texture:{viewDimension:"2d",sampleType:"float"}}]});e.bindGroupLayouts.push(n);const i=Q5.device.createPipelineLayout({label:"imagePipelineLayout",bindGroupLayouts:e.bindGroupLayouts});e.pipelines[1]=Q5.device.createRenderPipeline({label:"imagePipeline",layout:i,vertex:{module:a,entryPoint:"vertexMain",buffers:[{arrayStride:0,attributes:[]},{arrayStride:20,attributes:[{shaderLocation:0,offset:0,format:"float32x2"},{shaderLocation:1,offset:8,format:"float32x2"},{shaderLocation:2,offset:16,format:"float32"}]}]},fragment:{module:o,entryPoint:"fragmentMain",targets:[{format:"bgra8unorm",blend:e.blendConfigs?.normal||{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha",operation:"add"},alpha:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha",operation:"add"}}}]},primitive:{topology:"triangle-list"}});let s=Q5.device.createSampler({magFilter:"linear",minFilter:"linear"});e._createTexture=t=>{t.canvas&&(t=t.canvas);let r=[t.width,t.height,1];const a=Q5.device.createTexture({size:r,format:"bgra8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT});Q5.device.queue.copyExternalImageToTexture({source:t},{texture:a},r),t.textureIndex=e._textureBindGroups.length;const o=Q5.device.createBindGroup({layout:n,entries:[{binding:0,resource:s},{binding:1,resource:a.createView()}]});e._textureBindGroups.push(o)},e.loadImage=e.loadTexture=r=>{t._preloadCount++;const a=new Image;return a.crossOrigin="Anonymous",a.onload=()=>{e._createTexture(a),t._preloadCount--},a.src=r,a},e.imageMode=t=>e._imageMode=t,e.image=(t,a,o,n,i)=>{if(t.canvas&&(t=t.canvas),null==t.textureIndex)return;e._matrixDirty&&e._saveMatrix();let s=e._transformIndex;n??=t.width/e._pixelDensity,i??=t.height/e._pixelDensity;let[l,d,c,h]=e._calcBox(a,o,n,i,e._imageMode);r.push(l,c,0,0,s,d,c,1,0,s,l,h,0,1,s,d,c,1,0,s,l,h,0,1,s,d,h,1,1,s),e.drawStack.push(1,t.textureIndex)},e._hooks.preRender.push((()=>{if(!e._textureBindGroups.length)return;e.pass.setPipeline(e.pipelines[1]);const t=new Float32Array(r),a=Q5.device.createBuffer({size:t.byteLength,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST});Q5.device.queue.writeBuffer(a,0,t),e.pass.setVertexBuffer(1,a)})),e._hooks.postRender.push((()=>{r.length=0}))},Q5.renderers.webgpu.text=(e,t)=>{let r=e.createGraphics(1,1);r.pixelDensity(e._pixelDensity),r._imageMode="corner",e.loadFont=e=>(t._preloadCount++,r.loadFont(e,(()=>{t._preloadCount--}))),e.textFont=r.textFont,e.textSize=r.textSize,e.textLeading=r.textLeading,e.textStyle=r.textStyle,e.textAlign=r.textAlign,e.textWidth=r.textWidth,e.textAscent=r.textAscent,e.textDescent=r.textDescent,e.textFill=(t,a,o,n)=>r.fill(e.color(t,a,o,n)),e.textStroke=(t,a,o,n)=>r.stroke(e.color(t,a,o,n)),e.text=(t,a,o,n,i)=>{let s=r.createTextImage(t,n,i);null==s.canvas.textureIndex&&e._createTexture(s),e.textImage(s,a,o)},e.createTextImage=r.createTextImage,e.textImage=(t,a,o)=>{"center"==r.ctx.textAlign?a-=.5*t.width:"right"==r.ctx.textAlign&&(a-=t.width),"alphabetic"==r.ctx.textBaseline&&(o-=r._textLeading),"middle"==r.ctx.textBaseline?o-=t._descent+.5*t._ascent+r._textLeadDiff:"bottom"==r.ctx.textBaseline?o-=t._ascent+t._descent+r._textLeadDiff:"top"==r.ctx.textBaseline&&(o-=t._descent+r._textLeadDiff),e.image(t,a,o)}};
|
|
8
|
+
function Q5(e,t,r){let a,o=this;if(o._q5=!0,o._parent=t,o._renderer=r||"q2d",o._preloadCount=0,e??="global","auto"==e){if(!window.setup&&!window.draw)return;e="global"}o._scope=e,"global"==e&&(Q5._hasGlobal=o._isGlobal=!0,a=Q5._nodejs?global:window);let n=new Proxy(o,{set:(e,t,r)=>(o[t]=r,o._isGlobal&&(a[t]=r),!0)});o.canvas=o.ctx=o.drawingContext=null,o.pixels=[];let i=null;o.frameCount=0,o.deltaTime=16,o._targetFrameRate=0,o._targetFrameDuration=16.666666666666668,o._frameRate=o._fps=60,o._loop=!0,o._hooks={postCanvas:[],preRender:[],postRender:[]};let s=0;o.millis=()=>performance.now()-s,o.noCanvas=()=>{o.canvas?.remove&&o.canvas.remove(),o.canvas=0,n.ctx=n.drawingContext=0},window&&(o.windowWidth=window.innerWidth,o.windowHeight=window.innerHeight,o.deviceOrientation=window.screen?.orientation?.type),o._incrementPreload=()=>n._preloadCount++,o._decrementPreload=()=>n._preloadCount--,o._draw=e=>{let t=e||performance.now();if(o._lastFrameTime??=t-o._targetFrameDuration,o._shouldResize&&(o.windowResized(),o._shouldResize=!1),o._loop)i=d(o._draw);else if(o.frameCount&&!o._redraw)return;if(i&&o.frameCount){if(t-o._lastFrameTime<o._targetFrameDuration-4)return}n.deltaTime=t-o._lastFrameTime,o._frameRate=1e3/o.deltaTime,n.frameCount++;let r=performance.now();o.resetMatrix(),o._beginRender&&o._beginRender();for(let e of Q5.methods.pre)e.call(o);o.draw();for(let e of Q5.methods.post)e.call(o);o._render&&o._render(),o._finishRender&&o._finishRender(),n.pmouseX=o.mouseX,n.pmouseY=o.mouseY,o._lastFrameTime=t;let a=performance.now();o._fps=Math.round(1e3/(a-r))},o.noLoop=()=>{o._loop=!1,i=null},o.loop=()=>{o._loop=!0,null==i&&o._draw()},o.isLooping=()=>o._loop,o.redraw=(e=1)=>{o._redraw=!0;for(let t=0;t<e;t++)o._draw();o._redraw=!1},o.remove=()=>{o.noLoop(),o.canvas.remove()},o.frameRate=e=>(e&&(o._targetFrameRate=e,o._targetFrameDuration=1e3/e),o._frameRate),o.getTargetFrameRate=()=>o._targetFrameRate,o.getFPS=()=>o._fps,o.Element=function(e){this.elt=e},o._elements=[],o.TWO_PI=o.TAU=2*Math.PI,o.log=o.print=console.log,o.describe=()=>{};for(let e in Q5.modules)Q5.modules[e](o,n);let l=Q5.renderers[o._renderer];for(let e in l)l[e](o,n);for(let e in Q5)"_"!=e[1]&&e[1]==e[1].toUpperCase()&&(o[e]=Q5[e]);if("graphics"==e)return;"global"==e&&(Object.assign(Q5,o),delete Q5.Q5);for(let e of Q5.methods.init)e.call(o);for(let[e,t]of Object.entries(Q5.prototype))"_"!=e[0]&&"function"==typeof o[e]&&(o[e]=t.bind(o));if("global"==e){let e=Object.getOwnPropertyNames(o);for(let t of e)"_"!=t[0]&&(a[t]=o[t])}"function"==typeof e&&e(o),Q5._instanceCount++;let d=window.requestAnimationFrame||function(e){const t=o._lastFrameTime+o._targetFrameDuration;return setTimeout((()=>{e(t)}),t-performance.now())},c=a||o;o._isTouchAware=c.touchStarted||c.touchMoved||c.mouseReleased;let h=c.preload,u=["setup","draw","preload","mouseMoved","mousePressed","mouseReleased","mouseDragged","mouseClicked","keyPressed","keyReleased","keyTyped","touchStarted","touchMoved","touchEnded","windowResized"];for(let e of u)c[e]?o._isGlobal&&(o[e]=()=>{try{return c[e]()}catch(e){throw o._aiErrorAssistance&&o._aiErrorAssistance(e),e}}):o[e]=()=>{};async function p(){if(o._startDone=!0,o._preloadCount>0)return d(p);s=performance.now(),await o.setup(),o.frameCount||(null===o.ctx&&o.createCanvas(100,100),o._setupDone=!0,o.ctx&&o.resetMatrix(),d(o._draw))}(o.setup||o.draw)&&(arguments.length&&"namespace"!=e&&"webgpu"!=r||h?(o.preload(),p()):(c.preload=o.preload=()=>{o._startDone||p()},setTimeout(o.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.CENTER="center",e.LEFT="left",e.RIGHT="right",e.TOP="top",e.BOTTOM="bottom",e.BASELINE="alphabetic",e.NORMAL="normal",e.ITALIC="italic",e.BOLD="bold",e.BOLDITALIC="italic bold",e.ROUND="round",e.SQUARE="butt",e.PROJECT="square",e.MITER="miter",e.BEVEL="bevel",e.CHORD=0,e.PIE=1,e.OPEN=2,e.RADIUS="radius",e.CORNER="corner",e.CORNERS="corners",e.CLOSE=1,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.P2D="2d",e.WEBGL="webgl",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,e._pixelDensity=1,e.displayDensity=()=>window.devicePixelRatio||1,"image"!=e._scope&&(r.renderer=e._renderer,r[e._renderer]=!0,e._pixelDensity=Math.ceil(e.displayDensity())),e._adjustDisplay=()=>{r.style&&(r.style.width=r.w+"px",r.style.height=r.h+"px")},e.createCanvas=function(t,a,o){o??=arguments[3];let n=Object.assign({},Q5.canvasOptions);"object"==typeof o&&Object.assign(n,o),"image"!=e._scope&&("graphics"==e._scope?e._pixelDensity=this._pixelDensity:window.IntersectionObserver&&new IntersectionObserver((e=>{r.visible=e[0].isIntersecting})).observe(r)),e._setCanvasSize(t,a),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.createGraphics=function(t,r,a){let o=new Q5("graphics");return a??={},a.alpha??=!0,a.colorSpace??=e.canvas.colorSpace,o.createCanvas.call(e,t,r,a),o},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 a=document.createElement("a");a.href=e,a.download=t+"."+r,a.click(),URL.revokeObjectURL(a.href)},e.save=(t,r,a)=>{if((!t||"string"==typeof t&&(!r||!a&&r.length<5))&&(a=r,r=t,t=e.canvas),a)return e._save(t,r,a);r?(r=r.split("."),e._save(t,r[0],r.at(-1))):e._save(t)},e._setCanvasSize=(a,o)=>{a??=window.innerWidth,o??=window.innerHeight,r.w=a=Math.ceil(a),r.h=o=Math.ceil(o),r.hw=a/2,r.hh=o/2,r.width=Math.ceil(a*e._pixelDensity),r.height=Math.ceil(o*e._pixelDensity),e._da?e.flexibleCanvas(e._dau):(t.width=a,t.height=o),e.displayMode&&!r.displayMode?e.displayMode():e._adjustDisplay()},"image"!=e._scope){if(r&&"graphics"!=e._scope){function a(){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 a(){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(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==r.w&&a==r.h||e._resizeCanvas(t,a)},e.canvas.resize=e.resizeCanvas,e.canvas.save=e.saveCanvas=e.save,e.pixelDensity=t=>t&&t!=e._pixelDensity?(e._pixelDensity=t,e._setCanvasSize(r.w,r.h),t):e._pixelDensity,e.flexibleCanvas=(a=400)=>{a?(e._da=r.width/(a*e._pixelDensity),t.width=e._dau=a,t.height=r.h/r.w*a):e._da=0},e._styleNames=["_doStroke","_doFill","_strokeSet","_fillSet","_tint","_imageMode","_rectMode","_ellipseMode","_textFont","_textLeading","_leadingSet","_textSize","_textAlign","_textBaseline","_textStyle","_textWrap"],e._styles=[],e._pushStyles=()=>{let t={};for(let r of e._styleNames)t[r]=e[r];e._styles.push(t)},e._popStyles=()=>{let t=e._styles.pop();for(let r of e._styleNames)e[r]=t[r]}}},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(a,o,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,a)=>{let o={};for(let t in e.ctx)"function"!=typeof e.ctx[t]&&(o[t]=e.ctx[t]);delete o.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,a);for(let t in o)e.ctx[t]=o[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?t=e.color(...arguments):e._namedColors[t]&&(t=e.color(...e._namedColors[t]))),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?t=e.color(...arguments):e._namedColors[t]&&(t=e.color(...e._namedColors[t]))),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=>{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,a,o,n,i)=>e.ctx.transform(t,r,a,o,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.push=e.pushMatrix=()=>{e.ctx.save(),e._pushStyles()},e.pop=e.popMatrix=()=>{e.ctx.restore(),e._popStyles()},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},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._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 a(){e._doFill&&e.ctx.fill(),e._doStroke&&e.ctx.stroke()}function o(t,r,o,n,i,s,l,d){if(!e._doFill&&!e._doStroke)return;let c=e._angleMode,h=c?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(),o==n)c&&(i=e.radians(i),s=e.radians(s)),e.ctx.arc(t,r,o/2,i,s);else{for(let a=0;a<d+1;a++){let l=a/d,c=e.lerp(i,s,l),h=e.cos(c)*o/2,u=e.sin(c)*n/2;e.ctx[a?"lineTo":"moveTo"](t+h,r+u)}l==e.CHORD?e.ctx.closePath():l==e.PIE&&(e.ctx.lineTo(t,r),e.ctx.closePath())}a()}}function n(t,r,o,n){(e._doFill||e._doStroke)&&(e._da&&(t*=e._da,r*=e._da,o*=e._da,n*=e._da),e.ctx.beginPath(),e.ctx.ellipse(t,r,o/2,n/2,0,0,e.TAU),a())}function i(t,r,o,n,s,l,d,c){if(e._doFill||e._doStroke){if(void 0===s)return function(t,r,o,n){e._da&&(t*=e._da,r*=e._da,o*=e._da,n*=e._da),e.ctx.beginPath(),e.ctx.rect(t,r,o,n),a()}(t,r,o,n);if(void 0===l)return i(t,r,o,n,s,s,s,s);e._da&&(t*=e._da,r*=e._da,o*=e._da,n*=e._da,s*=e._da,l*=e._da,c*=e._da,d*=e._da),e.ctx.roundRect(t,r,o,n,[s,l,d,c]),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?t=e.color(...arguments):e._namedColors[t]&&(t=e.color(...e._namedColors[t]))),e.ctx.fillStyle=t.toString(),e.ctx.fillRect(0,0,e.canvas.width,e.canvas.height)),e.ctx.restore()},e.line=(t,r,a,o)=>{e._doStroke&&(e._da&&(t*=e._da,r*=e._da,a*=e._da,o*=e._da),e.ctx.beginPath(),e.ctx.moveTo(t,r),e.ctx.lineTo(a,o),e.ctx.stroke())},e.arc=(t,r,a,n,i,s,l,d=25)=>{if(i==s)return e.ellipse(t,r,a,n);l??=e.PIE,e._ellipseMode==e.CENTER?o(t,r,a,n,i,s,l,d):e._ellipseMode==e.RADIUS?o(t,r,2*a,2*n,i,s,l,d):e._ellipseMode==e.CORNER?o(t+a/2,r+n/2,a,n,i,s,l,d):e._ellipseMode==e.CORNERS&&o((t+a)/2,(r+n)/2,a-t,n-r,i,s,l,d)},e.ellipse=(t,r,a,o)=>{o??=a,e._ellipseMode==e.CENTER?n(t,r,a,o):e._ellipseMode==e.RADIUS?n(t,r,2*a,2*o):e._ellipseMode==e.CORNER?n(t+a/2,r+o/2,a,o):e._ellipseMode==e.CORNERS&&n((t+a)/2,(r+o)/2,a-t,o-r)},e.circle=(t,r,o)=>{e._ellipseMode==e.CENTER?(e._da&&(t*=e._da,r*=e._da,o*=e._da),e.ctx.beginPath(),e.ctx.arc(t,r,o/2,0,e.TAU),a()):e.ellipse(t,r,o,o)},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,a,o=a,n,s,l,d)=>{e._rectMode==e.CENTER?i(t-a/2,r-o/2,a,o,n,s,l,d):e._rectMode==e.RADIUS?i(t-a,r-o,2*a,2*o,n,s,l,d):e._rectMode==e.CORNER?i(t,r,a,o,n,s,l,d):e._rectMode==e.CORNERS&&i(t,r,a-t,o-r,n,s,l,d)},e.square=(t,r,a,o,n,i,s)=>e.rect(t,r,a,a,o,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=(a,o)=>{e._da&&(a*=e._da,o*=e._da),r=[],t?e.ctx.moveTo(a,o):e.ctx.lineTo(a,o),t=!1},e.bezierVertex=(t,a,o,n,i,s)=>{e._da&&(t*=e._da,a*=e._da,o*=e._da,n*=e._da,i*=e._da,s*=e._da),r=[],e.ctx.bezierCurveTo(t,a,o,n,i,s)},e.quadraticVertex=(t,a,o,n)=>{e._da&&(t*=e._da,a*=e._da,o*=e._da,n*=e._da),r=[],e.ctx.quadraticCurveTo(t,a,o,n)},e.bezier=(t,r,a,o,n,i,s,l)=>{e.beginShape(),e.vertex(t,r),e.bezierVertex(a,o,n,i,s,l),e.endShape()},e.triangle=(t,r,a,o,n,i)=>{e.beginShape(),e.vertex(t,r),e.vertex(a,o),e.vertex(n,i),e.endShape(e.CLOSE)},e.quad=(t,r,a,o,n,i,s,l)=>{e.beginShape(),e.vertex(t,r),e.vertex(a,o),e.vertex(n,i),e.vertex(s,l),e.endShape(e.CLOSE)},e.endShape=t=>{r=[],t&&e.ctx.closePath(),a()},e.curveVertex=(a,o)=>{if(e._da&&(a*=e._da,o*=e._da),r.push([a,o]),r.length<4)return;let n=function(e,t,r,a,o,n,i,s,l,d){function c(e,t,r,a,o,n){let i=Math.pow(a-t,2)+Math.pow(o-r,2);return Math.pow(i,.5*n)+e}let h=[],u=c(0,e,t,r,a,d),p=c(u,r,a,o,n,d),_=c(p,o,n,i,s,d);for(let d=0;d<l;d++){let c=u+d/(l-1)*(p-u),x=[(u-c)/(u-0),(c-0)/(u-0),(p-c)/(p-u),(c-u)/(p-u),(_-c)/(_-p),(c-p)/(_-p),(p-c)/(p-0),(c-0)/(p-0),(_-c)/(_-u),(c-u)/(_-u)];for(let e=0;e<x.length;e+=2)isNaN(x[e])&&(x[e]=1,x[e+1]=0),isFinite(x[e])||(x[e]>0?(x[e]=1,x[e+1]=0):(x[e]=0,x[e+1]=1));let g=e*x[0]+r*x[1],m=t*x[0]+a*x[1],f=r*x[2]+o*x[3],v=a*x[2]+n*x[3],y=o*x[4]+i*x[5],w=n*x[4]+s*x[5],b=g*x[6]+f*x[7],S=m*x[6]+v*x[7],M=f*x[8]+y*x[9],C=v*x[8]+w*x[9],Q=b*x[2]+M*x[3],R=S*x[2]+C*x[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,a,o,n,i,s,l)=>{e.beginShape(),e.curveVertex(t,r),e.curveVertex(a,o),e.curveVertex(n,i),e.curveVertex(s,l),e.endShape()},e.curvePoint=(e,t,r,a,o)=>{const n=o*o*o,i=o*o;return e*(-.5*n+i-.5*o)+t*(1.5*n-2.5*i+1)+r*(-1.5*n+2*i+.5*o)+a*(.5*n-.5*i)},e.bezierPoint=(e,t,r,a,o)=>{const n=1-o;return Math.pow(n,3)*e+3*Math.pow(n,2)*o*t+3*n*Math.pow(o,2)*r+Math.pow(o,3)*a},e.curveTangent=(e,t,r,a,o)=>{const n=o*o;return e*(-3*n/2+2*o-.5)+t*(9*n/2-5*o)+r*(-9*n/2+4*o+.5)+a*(3*n/2-o)},e.bezierTangent=(e,t,r,a,o)=>{const n=1-o;return 3*a*Math.pow(o,2)-3*r*Math.pow(o,2)+6*r*n*o-6*t*n*o+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 a=e._pixelDensity;return e.ctx.isPointInPath(t*a,r*a)},e.inStroke=(t,r)=>{const a=e._pixelDensity;return e.ctx.isPointInStroke(t*a,r*a)}},Q5.renderers.q2d.image=(e,t)=>{Q5.Image??=class{constructor(e,t,r){let a=this;a._scope="image",a.canvas=a.ctx=a.drawingContext=null,a.pixels=[],Q5.modules.canvas(a,a);let o=Q5.renderers.q2d;for(let e of["canvas","image","soft_filters"])o[e]&&o[e](a,a);a.createCanvas(e,t,r),delete a.createCanvas,a._loop=!1}get w(){return this.width}get h(){return this.height}},e.createImage=(t,r,a)=>(a??={},a.alpha??=!0,a.colorSpace??=e.canvas.colorSpace||Q5.canvasOptions.colorSpace,new Q5.Image(t,r,a)),e.loadImage=function(r,a,o){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);o="object"==typeof n?n:null;let i=e.createImage(1,1,o);function s(e){i.resize(e.naturalWidth||e.width,e.naturalHeight||e.height),i.ctx.drawImage(e,0,0),t._preloadCount--,a&&a(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,a,o,n,i=0,s=0,l,d)=>{let c=t.canvas||t;Q5._createNodeJSCanvas&&(c=c.context.canvas),o??=t.width||t.videoWidth,n??=t.height||t.videoHeight,"center"==e._imageMode&&(r-=.5*o,a-=.5*n),e._da&&(r*=e._da,a*=e._da,o*=e._da,n*=e._da,i*=e._da,s*=e._da,l*=e._da,d*=e._da);let h=t._pixelDensity||1;l?l*=h:l=c.width||c.videoWidth,d?d*=h:d=c.height||c.videoHeight,e.ctx.drawImage(c,i*h,s*h,l,d,r,a,o,n),e._tint&&(e.ctx.globalCompositeOperation="multiply",e.ctx.fillStyle=e._tint.toString(),e.ctx.fillRect(r,a,o,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 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,r),e.ctx.clearRect(0,0,e.canvas.width,e.canvas.height),e.ctx.drawImage(a,0,0,e.canvas.width,e.canvas.height)}),e._getImageData=(t,r,a,o)=>e.ctx.getImageData(t,r,a,o,{colorSpace:e.canvas.colorSpace}),e.trim=()=>{let t=e._pixelDensity||1,r=e.canvas.width,a=e.canvas.height,o=e._getImageData(0,0,r,a).data,n=r,i=0,s=a,l=0,d=3;for(let e=0;e<a;e++)for(let t=0;t<r;t++)0!==o[d]&&(t<n&&(n=t),t>i&&(i=t),e<s&&(s=e),e>l&&(l=e)),d+=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,a,o)=>{let n=e._pixelDensity||1;if(void 0!==t&&void 0===a){let a=e._getImageData(t*n,r*n,1,1).data;return new e.Color(a[0],a[1],a[2],a[3]/255)}t=(t||0)*n,r=(r||0)*n;let i=a=a||e.width,s=o=o||e.height;a*=n,o*=n;let l=e.createImage(a,o),d=e._getImageData(t,r,a,o);return l.ctx.putImageData(d,0,0),l._pixelDensity=n,l.width=i,l.height=s,l},e.set=(t,r,a)=>{if(a.canvas){let o=e._tint;return e._tint=null,e.image(a,t,r),void(e._tint=o)}e.pixels.length||e.loadPixels();let o=e._pixelDensity||1;for(let n=0;n<o;n++)for(let i=0;i<o;i++){let s=4*((r*o+n)*e.canvas.width+t*o+i);e.pixels[s]=a.r??a.l,e.pixels[s+1]=a.g??a.c,e.pixels[s+2]=a.b??a.h,e.pixels[s+3]=a.a}},e.loadPixels=()=>{r=e._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._textFont="sans-serif",e._textSize=12,e._textLeading=15,e._textLeadDiff=3,e._textStyle="normal",e.loadFont=(e,r)=>{t._preloadCount++;let a=e.split("/").pop().split(".")[0].replace(" ",""),o=new FontFace(a,`url(${e})`);return document.fonts.add(o),o.load().then((()=>{t._preloadCount--,r&&r(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,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.textFill=e.fill,e.textStroke=e.stroke,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[a,o]of this.entries())o.lastAccessed<t&&(t=o.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,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+"_":"")+(r||"")+(a?"x"+a:""),e.createTextImage=(t,r,a)=>{let o=e._genTextImageKey(t,r,a);if(e._tic.get(o))return e._tic.get(o);let n=e._textCache;return e._textCache=!0,e._genTextImage=!0,e.text(t,0,0,r,a),e._genTextImage=!1,e._textCache=n,e._tic.get(o)},e.text=(t,r,a,o,n)=>{if(void 0===t)return;if(t=t.toString(),e._da&&(r*=e._da,a*=e._da),!e._doFill&&!e._doStroke)return;let i,s,l,d,c,h,u,p,_=e.ctx.getTransform(),x=e._genTextImage||e._textCache&&(0!=_.b||0!=_.c);if(x){if(d=e._genTextImageKey(t,o,n),s=e._tic.get(d),s&&!e._genTextImage)return void e.textImage(s,r,a);l=e.createGraphics.call(e,1,1),i=l.ctx}else i=e.ctx,c=r,h=a;i.font=`${e._textStyle} ${e._textSize}px ${e._textFont}`;let g=t.split("\n");if(x){c=0,h=e._textLeading*g.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 m=i.fillStyle;e._fillSet||(i.fillStyle="black");for(let t=0;t<g.length&&(e._doStroke&&e._strokeSet&&i.strokeText(g[t],c,h),e._doFill&&i.fillText(g[t],c,h),h+=e._textLeading,!(h>n));t++);e._fillSet||(i.fillStyle=m),x&&(s=l,s._ascent=u,s._descent=p,e._tic.set(d,s),e._genTextImage||e.textImage(s,r,a))},e.textImage=(t,r,a)=>{let o=e._imageMode;e._imageMode="corner","center"==e.ctx.textAlign?r-=.5*t.width:"right"==e.ctx.textAlign&&(r-=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,r,a),e._imageMode=o},e.nf=(e,t,r)=>{let a=e<0,o=(e=Math.abs(e)).toFixed(r).split(".");o[0]=o[0].padStart(t,"0");let n=o.join(".");return a&&(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(Q5.disableFriendlyErrors&&!r)return;!r&&Q5.errorTolerant||e.noLoop();let a=t.stack?.split("\n");if(!t.stack||a.length<=1)return;let o=1,n="(";for(-1==navigator.userAgent.indexOf("Chrome")&&(o=0,n="@");a[o].indexOf("q5")>=0;)o++;let i=a[o].split(n).at(-1);i=i.split(":");let s=parseInt(i.at(-2));r&&s++;let l=i.slice(0,-2).join(":"),d=l.split("/").at(-1);try{let e=(await(await fetch(l)).text()).split("\n"),a=e[s-1].trim(),o="",n=1;for(;o.length<1600&&(s-n>=0&&(o=e[s-n].trim()+"\n"+o),s+n<e.length);)o+=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(a)+"%0A%0AExcerpt+for+context%3A%0A%0A"+encodeURIComponent(o);if(console.warn("Error in "+d+" on line "+s+":\n\n"+a),console.warn("Ask AI ✨ "+i),r)return window.open(i,"_blank")}catch(e){}}},Q5.modules.color=(e,t)=>{e.RGB=e.RGBA=e._colorMode="rgb",e.OKLCH="oklch",e.colorMode=(r,a)=>{e._colorMode=r;let o="srgb"==e.canvas.colorSpace||"srgb"==r;if(a??=o?"integer":"float",e._colorFormat="float"==a||1==a?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,a,o)=>{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&&(o=parseInt(t[4]+t[4],16)),a=parseInt(t[3]+t[3],16),r=parseInt(t[2]+t[2],16),t=parseInt(t[1]+t[1],16)):(t.length>7&&(o=parseInt(t.slice(7,9),16)),a=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,a,o]=e._namedColors[t]}1==e._colorFormat&&(t/=255,r&&(r/=255),a&&(a/=255),o&&(o/=255))}Array.isArray(t)&&([t,r,a,o]=t)}return null==a?new n(t,t,t,r):new n(t,r,a,o)},e.red=e=>e.r,e.green=e=>e.g,e.blue=e=>e.b,e.alpha=e=>e.a,e.lightness=e=>e.l?e.l:100*(.2126*e.r+.7152*e.g+.0722*e.b)/255,e.hue=t=>{if(t.h)return t.h;let r=t.r,a=t.g,o=t.b;255==e._colorFormat&&(r/=255,a/=255,o/=255);let n,i=Math.max(r,a,o),s=Math.min(r,a,o);return n=i==s?0:i==r?60*(a-o)/(i-s):i==a?60*(o-r)/(i-s)+120:60*(r-a)/(i-s)+240,n<0&&(n+=360),n},e.lerpColor=(t,r,a)=>{if("rgb"==e._colorMode)return new e.Color(e.constrain(e.lerp(t.r,r.r,a),0,255),e.constrain(e.lerp(t.g,r.g,a),0,255),e.constrain(e.lerp(t.b,r.b,a),0,255),e.constrain(e.lerp(t.a,r.a,a),0,255));{let o=r.h-t.h;o>180&&(o-=360),o<-180&&(o+=360);let n=t.h+a*o;return n<0&&(n+=360),n>360&&(n-=360),new e.Color(e.constrain(e.lerp(t.l,r.l,a),0,100),e.constrain(e.lerp(t.c,r.c,a),0,100),n,e.constrain(e.lerp(t.a,r.a,a),0,255))}}},Q5.Color=class{constructor(){this._q5Color=!0}},Q5.ColorOKLCH=class extends Q5.Color{constructor(e,t,r,a){super(),this.l=e,this.c=t,this.h=r,this.a=a??1}toString(){return`oklch(${this.l} ${this.c} ${this.h} / ${this.a})`}},Q5.ColorRGBA=class extends Q5.Color{constructor(e,t,r,a){super(),this.r=e,this.g=t,this.b=r,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,r,a){super(e,t,r,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,r,a){super(e,t,r,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),r=(this._b/255).toFixed(3),a=(this._a/255).toFixed(3);this._css=`color(display-p3 ${e} ${t} ${r} / ${a})`,this._edited=!1}return this._css}},Q5.modules.display=e=>{if(!e.canvas||"graphics"==e._scope)return;let t=e.canvas;e.CENTERED="centered",e.FULLSCREEN="fullscreen",e.MAXED="maxed",e.PIXELATED="pixelated",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,a=t.parentElement;r&&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"),r.width=t.w*t.displayScale+"px",r.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?(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",a="default",o=1)=>{"string"==typeof o&&(o=parseFloat(o.slice(1))),Object.assign(t,{displayMode:r,renderQuality:a,displayScale:o}),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={},a=[e.LEFT,e.CENTER,e.RIGHT],o=e.canvas;function n(t){const r=e.canvas.getBoundingClientRect(),a=e.canvas.scrollWidth/e.width||1,o=e.canvas.scrollHeight/e.height||1;return{x:(t.clientX-r.left)/a,y:(t.clientY-r.top)/o,id:t.identifier}}if(e._startAudio=()=>{e.getAudioContext&&"suspended"==e.getAudioContext()?.state&&e.userStartAudio()},e._updateMouse=r=>{if(!r.changedTouches)if(o){let a=o.getBoundingClientRect(),n=o.scrollWidth/e.width||1,i=o.scrollHeight/e.height||1;t.mouseX=(r.clientX-a.left)/n,t.mouseY=(r.clientY-a.top)/i,"webgpu"==o.renderer&&(t.mouseX-=o.hw,t.mouseY-=o.hh)}else t.mouseX=r.clientX,t.mouseY=r.clientY},e._onmousedown=r=>{e._startAudio(),e._updateMouse(r),t.mouseIsPressed=!0,t.mouseButton=a[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,a)=>{let o="";t.includes(".")&&(t=`url("${t}")`,o=", auto"),void 0!==r&&(t+=" "+r+" "+a),e.canvas.style.cursor=t+o},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,r[e.keyCode]=r[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,r[e.keyCode]=r[e.key.toLowerCase()]=!1,e.keyReleased(a)},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()},o&&(o.addEventListener("mousedown",(t=>e._onmousedown(t))),o.addEventListener("mouseup",(t=>e._onmouseup(t))),o.addEventListener("click",(t=>e._onclick(t))),o.addEventListener("touchstart",(t=>e._ontouchstart(t))),o.addEventListener("touchmove",(t=>e._ontouchmove(t))),o.addEventListener("touchcancel",(t=>e._ontouchend(t))),o.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.RADIANS=0,e.DEGREES=1,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;let r=0;e.angleMode=t=>{"radians"==t&&(t=0),r=e._angleMode=t};let a=e._DEGTORAD=Math.PI/180,o=e._RADTODEG=180/Math.PI;function n(){let e,t,r=4294967295;return{setSeed(a){e=t=(a??Math.random()*r)>>>0},getSeed:()=>t,rand:()=>(e^=e<<17,e^=e>>13,e^=e<<5,(e>>>0)/r)}}e.degrees=t=>t*e._RADTODEG,e.radians=t=>t*e._DEGTORAD,e.map=Q5.prototype.map=(e,t,r,a,o,n)=>{let i=a+1*(e-t)/(r-t)*(o-a);return n?a<o?Math.min(Math.max(i,a),o):Math.min(Math.max(i,o),a):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,a)=>e.map(t,r,a,0,1),e.sq=e=>e*e,e.fract=e=>e-Math.floor(e),e.sin=e=>Math.sin(r?e*a:e),e.cos=e=>Math.cos(r?e*a:e),e.tan=e=>Math.tan(r?e*a:e),e.asin=e=>{let t=Math.asin(e);return r?t*o:t},e.acos=e=>{let t=Math.acos(e);return r?t*o:t},e.atan=e=>{let t=Math.atan(e);return r?t*o:t},e.atan2=(e,t)=>{let a=Math.atan2(e,t);return r?a*o:a};let i=n();i.setSeed(),e.randomSeed=e=>i.setSeed(e),e.random=(e,t)=>void 0===e?i.rand():"number"==typeof e?void 0!==t?i.rand()*(t-e)+e:i.rand()*e:e[Math.trunc(e.length*i.rand())],e.randomGenerator=t=>{t==e.LCG?i=function(){const e=4294967296;let t,r;return{setSeed(a){r=t=(a??Math.random()*e)>>>0},getSeed:()=>t,rand:()=>(r=(1664525*r+1013904223)%e,r/e)}}():t==e.SHR3&&(i=n()),i.setSeed()};var s=new function(){var e,t,r,a=new Array(128),o=new Array(256),n=new Array(128),s=new Array(128),l=new Array(256),d=new Array(256),c=()=>4294967296*i.rand()-2147483648,h=()=>.5+2.328306e-10*(c()|0),u=()=>{for(var t,o,i,l,d=3.44262;;){if(t=r*n[e],0==e){do{i=h(),l=h(),t=.2904764*-Math.log(i),o=-Math.log(l)}while(o+o<t*t);return r>0?d+t:-d-t}if(s[e]+h()*(s[e-1]-s[e])<Math.exp(-.5*t*t))return t;if(r=c(),e=127&r,Math.abs(r)<a[e])return r*n[e]}},p=()=>{for(var r;;){if(0==e)return 7.69711-Math.log(h());if(r=t*l[e],d[e]+h()*(d[e-1]-d[e])<Math.exp(-r))return r;if((t=c())<o[e=255&t])return t*l[e]}};this.SHR3=c,this.UNI=h,this.RNOR=()=>(r=c(),e=127&r,Math.abs(r)<a[e]?r*n[e]:u()),this.REXP=()=>(t=c()>>>0)<a[e=255&t]?t*l[e]:p(),this.zigset=()=>{var e,t,r=2147483648,i=4294967296,c=3.442619855899,h=c,u=.00991256303526217,p=7.697117470131487,_=p,x=.003949659822581572;for(e=u/Math.exp(-.5*c*c),a[0]=Math.floor(c/e*r),a[1]=0,n[0]=e/r,n[127]=c/r,s[0]=1,s[127]=Math.exp(-.5*c*c),t=126;t>=1;t--)c=Math.sqrt(-2*Math.log(u/c+Math.exp(-.5*c*c))),a[t+1]=Math.floor(c/h*r),h=c,s[t]=Math.exp(-.5*c*c),n[t]=c/r;for(e=x/Math.exp(-p),o[0]=Math.floor(p/e*i),o[1]=0,l[0]=e/i,l[255]=p/i,d[0]=1,d[255]=Math.exp(-p),t=254;t>=1;t--)p=-Math.log(x/p+Math.exp(-p)),o[t+1]=Math.floor(p/_*i),_=p,d[t]=Math.exp(-p),l[t]=p/i}};let l;s.hasInit=!1,e.randomGaussian=(e,t)=>(s.hasInit||(s.zigset(),s.hasInit=!0),s.RNOR()*t+e),e.randomExponential=()=>(s.hasInit||(s.zigset(),s.hasInit=!0),s.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"],l=null},e.noiseSeed=t=>{l=new e.Noise(t)},e.noise=(t=0,r=0,a=0)=>(l??=new e.Noise,l.noise(t,r,a)),e.noiseDetail=(t,r)=>{l??=new e.Noise,t>0&&(l.octaves=t),r>0&&(l.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,a=[];for(let e=0;e<256;e++)a[e]=e;for(let o=255;o>0;o--)t=(e=16807*e%2147483647)%(o+1),r=a[o],a[o]=a[t],a[t]=r;return a}dot(e,t,r,a){return e[0]*t+e[1]*r+e[2]*a}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 a=this,o=0,n=1,i=1,s=0;for(let l=0;l<a.octaves;l++){const l=255&Math.floor(e*n),d=255&Math.floor(t*n),c=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),_=a.fade(h),x=a.fade(u),g=a.fade(p),m=a.p[l]+d,f=a.p[m]+c,v=a.p[m+1]+c,y=a.p[l+1]+d,w=a.p[y]+c,b=a.p[y+1]+c,S=a.mix(a.dot(a.grad3[a.p[f]%12],h,u,p),a.dot(a.grad3[a.p[w]%12],h-1,u,p),_),M=a.mix(a.dot(a.grad3[a.p[v]%12],h,u-1,p),a.dot(a.grad3[a.p[b]%12],h-1,u-1,p),_),C=a.mix(a.dot(a.grad3[a.p[f+1]%12],h,u,p-1),a.dot(a.grad3[a.p[w+1]%12],h-1,u,p-1),_),Q=a.mix(a.dot(a.grad3[a.p[v+1]%12],h,u-1,p-1),a.dot(a.grad3[a.p[b+1]%12],h-1,u-1,p-1),_),R=a.mix(S,M,x),I=a.mix(C,Q,x);o+=a.mix(R,I,g)*i,s+=i,i*=a.falloff,n*=2}return(o/s+1)/2}},Q5.modules.sound=(e,t)=>{e.Sound=Q5.Sound,e.loadSound=(e,r)=>{t._preloadCount++,Q5.aud??=new window.AudioContext;let a=new Q5.Sound(e,r);return a.addEventListener("canplaythrough",(()=>{t._preloadCount--,a.loaded=!0,r&&r(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,r,a)=>{t._preloadCount++;let o={};return fetch(e).then((e=>"json"==a?e.json():"text"==a?e.text():void 0)).then((e=>{t._preloadCount--,Object.assign(o,e),r&&r(e)})),o},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,a)=>new Q5.Vector(t,r,a,e)},Q5.Vector=class{constructor(e,t,r,a){this.x=e||0,this.y=t||0,this.z=r||0,this._$=a||window,this._cn=null,this._cnsq=null}set(e,t,r){return this.x=e?.x||e||0,this.y=e?.y||t||0,this.z=e?.z||r||0,this}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,a=this.z-e.z;return Math.sqrt(t*t+r*r+a*a)}cross(){let e=this._arg2v(...arguments),t=this.y*e.z-this.z*e.y,r=this.z*e.x-this.x*e.z,a=this.x*e.y-this.y*e.x;return this.x=t,this.y=r,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 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)}setHeading(e){let t=this.mag();return this.x=t*this._$.cos(e),this.y=t*this._$.sin(e),this}rotate(e){let t=this._$.cos(e),r=this._$.sin(e),a=this.x*t-this.y*r,o=this.x*r+this.y*t;return this.x=a,this.y=o,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=e.at(-1);if(0==t)return this;let r=this._arg2v(...e.slice(0,-1));return this.x+=(r.x-this.x)*t,this.y+=(r.y-this.y)*t,this.z+=(r.z-this.z)*t,this}slerp(){let e=[...arguments],t=e.at(-1);if(0==t)return this;let r=this._arg2v(...e.slice(0,-1));if(1==t)return this.set(r);let a=this.mag(),o=r.mag();if(0==a||0==o)return this.mult(1-t).add(r.mult(t));let n=Q5.Vector.cross(this,r),i=n.mag(),s=Math.atan2(i,this.dot(r));if(i>0)n.div(i);else{if(s<this._$.HALF_PI)return this.mult(1-t).add(r.mult(t));0==this.z&&0==r.z?n.set(0,0,1):0!=this.x?n.set(this.y,-this.x,0).normalize():n.set(1,0,0)}let l=n.cross(this),d=1-t+t*o/a,c=d*Math.cos(t*s),h=d*Math.sin(t*s);return this.x=this.x*c+l.x*h,this.y=this.y*c+l.y*h,this.z=this.z*c+l.z*h,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 a=this._$.cos(t),o=this._$.sin(t),n=this._$.cos(e),i=this._$.sin(e);return this.x=r*i*o,this.y=-r*n,this.z=r*i*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,r)=>e.equals(t,r),Q5.Vector.lerp=(e,t,r)=>e.copy().lerp(t,r),Q5.Vector.slerp=(e,t,r)=>e.copy().slerp(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,a)=>(new Q5.Vector)[e](t,r,a);Q5.renderers.webgpu={},Q5.renderers.webgpu.canvas=(e,t)=>{let r,a=e.canvas;a.width=e.width=500,a.height=e.height=500,e.colorMode&&e.colorMode("rgb","float"),e.pipelines=[];let o=e.drawStack=[],n=e.colorsStack=[1,1,1,1];e._envLayout=Q5.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"uniform",hasDynamicOffset:!1}}]}),e._transformLayout=Q5.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage",hasDynamicOffset:!1}}]}),e.bindGroupLayouts=[e._envLayout,e._transformLayout];const i=Q5.device.createBuffer({size:8,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});e._createCanvas=(r,o,n)=>(t.ctx=t.drawingContext=a.getContext("webgpu"),n.format=navigator.gpu.getPreferredCanvasFormat(),n.device=Q5.device,e.ctx.configure(n),Q5.device.queue.writeBuffer(i,0,new Float32Array([e.canvas.hw,e.canvas.hh])),e._envBindGroup=Q5.device.createBindGroup({layout:e._envLayout,entries:[{binding:0,resource:{buffer:i}}]}),a),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.pushMatrix=()=>{e._transformIndexStack.push(e._transformIndex),e._pushStyles()},e.pop=e.popMatrix=()=>{if(!e._transformIndexStack.length)return console.warn("Matrix index stack is empty!");let t=e._transformIndexStack.pop();e._matrix=e.transformStates[t].slice(),e._transformIndex=t,e._matrixDirty=!1,e._popStyles()},e.translate=(t,r,a)=>{(t||r||a)&&(e._matrix[3]+=t,e._matrix[7]-=r,e._matrix[11]+=a||0,e._matrixDirty=!0)},e.rotate=t=>{if(!t)return;e._angleMode&&(t*=e._DEGTORAD);let r=Math.cos(t),a=Math.sin(t),o=e._matrix[0],n=e._matrix[1],i=e._matrix[4],s=e._matrix[5];o||n||i||s?(e._matrix[0]=o*r+i*a,e._matrix[1]=n*r+s*a,e._matrix[4]=o*-a+i*r,e._matrix[5]=n*-a+s*r):(e._matrix[0]=r,e._matrix[1]=a,e._matrix[4]=-a,e._matrix[5]=r),e._matrixDirty=!0},e.scale=(t=1,r,a=1)=>{r??=t,e._matrix[0]*=t,e._matrix[5]*=r,e._matrix[10]*=a,e._matrixDirty=!0},e._saveMatrix=()=>{e.transformStates.push(e._matrix.slice()),e._transformIndex=e.transformStates.length-1,e._matrixDirty=!1};let s=0;const l=(t,r,a,o=1)=>{"string"==typeof t?t=e.color(t):null==a&&(o=r??1,r=a=t),t._q5Color?n.push(t.r,t.g,t.b,t.a):n.push(t,r,a,o),s++};e.fill=(t,r,a,o)=>{l(t,r,a,o),e._doFill=!0,e._fillIndex=s},e.stroke=(t,r,a,o)=>{l(t,r,a,o),e._doStroke=!0,e._strokeIndex=s},e.noFill=()=>e._doFill=!1,e.noStroke=()=>e._doStroke=!1,e._strokeWeight=1,e.strokeWeight=t=>e._strokeWeight=Math.abs(t),e._calcBox=(e,t,r,a,o)=>{let n,i,s,l,d=r/2,c=a/2;return o&&"corner"!=o?"center"==o?(n=e-d,i=e+d,s=-(t-c),l=-(t+c)):(n=e,i=r,s=-t,l=-a):(n=e,i=e+r,s=-t,l=-(t+a)),[n,i,s,l]},e.clear=()=>{},e._beginRender=()=>{e.encoder=Q5.device.createCommandEncoder(),r=t.pass=e.encoder.beginRenderPass({label:"q5-webgpu",colorAttachments:[{view:ctx.getCurrentTexture().createView(),loadOp:"clear",storeOp:"store"}]})},e._render=()=>{if(transformStates.length>1||!e._transformBindGroup){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())),e._transformBindGroup=Q5.device.createBindGroup({layout:e._transformLayout,entries:[{binding:0,resource:{buffer:t}}]})}r.setBindGroup(0,e._envBindGroup),r.setBindGroup(1,e._transformBindGroup);for(let t of e._hooks.preRender)t();let t=0,a=0,n=-1;r.setPipeline(e.pipelines[0]);for(let i=0;i<o.length;i+=2){let s=o[i+1];n!=o[i]&&(n=o[i],r.setPipeline(e.pipelines[n])),0==n?(r.draw(s,1,t,0),t+=s):1==n&&(-1!=s&&r.setBindGroup(3,e._textureBindGroups[s]),r.draw(6,1,a,0),a+=6)}for(let t of e._hooks.postRender)t()},e._finishRender=()=>{r.end();const a=e.encoder.finish();Q5.device.queue.submit([a]),t.pass=e.encoder=null,e.drawStack.length=0,e.colorsStack.length=4,s=0,rotation=0,e.transformStates.length=1,e._transformIndexStack.length=0}},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,a,o=e.canvas,n=e.drawStack,i=e.colorsStack,s=[],l=Q5.device.createShaderModule({label:"drawingVertexShader",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"}),d=Q5.device.createShaderModule({label:"drawingFragmentShader",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"});a=Q5.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage",hasDynamicOffset:!1}}]}),e.bindGroupLayouts.push(a);let c={arrayStride:16,attributes:[{format:"float32x2",offset:0,shaderLocation:0},{format:"float32",offset:8,shaderLocation:1},{format:"float32",offset:12,shaderLocation:2}]},h=["zero","one","src-alpha","one-minus-src-alpha","dst","dst-alpha","one-minus-dst-alpha","one-minus-src"],u=["add","subtract","reverse-subtract","min","max"];const p={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]};e.blendConfigs={};for(const[t,r]of Object.entries(p))e.blendConfigs[t]={color:{srcFactor:h[r[0]],dstFactor:h[r[1]],operation:u[r[2]]},alpha:{srcFactor:h[r[3]],dstFactor:h[r[4]],operation:u[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]))};let _,x=Q5.device.createPipelineLayout({label:"drawingPipelineLayout",bindGroupLayouts:e.bindGroupLayouts});e._createPipeline=e=>Q5.device.createRenderPipeline({label:"drawingPipeline",layout:x,vertex:{module:l,entryPoint:"vertexMain",buffers:[c]},fragment:{module:d,entryPoint:"fragmentMain",targets:[{format:"bgra8unorm",blend:e}]},primitive:{topology:"triangle-list"}}),e.pipelines[0]=e._createPipeline(e.blendConfigs.normal),e.beginShape=()=>{_=[]},e.vertex=(t,r)=>{e._matrixDirty&&e._saveMatrix(),_.push(t,-r,e._fillIndex,e._transformIndex)},e.endShape=t=>{if(!e._doFill)return void(_=[]);let r=_;if(r.length<12)throw new Error("A shape must have at least 3 vertices.");t&&r.push(r[0],r[1],r[2],r[3]);let a=[];for(let e=4;e<r.length;e+=4)a.push(r[0],r[1],r[2],r[3],r[e-4],r[e-3],r[e-2],r[e-1],r[e],r[e+1],r[e+2],r[e+3]);_=[],s.push(...a),n.push(0,a.length/4)},e.triangle=(t,r,a,o,n,i)=>{e.beginShape(),e.vertex(t,r),e.vertex(a,o),e.vertex(n,i),e.endShape(1)},e.rectMode=t=>e._rectMode=t,e.rect=(t,a,o,i)=>{let[l,d,c,h]=e._calcBox(t,a,o,i,e._rectMode),u=r??e._fillIndex;e._matrixDirty&&e._saveMatrix();let p=e._transformIndex;s.push(l,c,u,p,d,c,u,p,l,h,u,p,d,c,u,p,l,h,u,p,d,h,u,p),n.push(0,6)},e.point=(t,a)=>{r=e._strokeIndex;let o=e._strokeWeight;o<2?(o=Math.round(o),e.rect(t,a,o,o)):e.ellipse(t,a,o,o),r=null},e.line=(t,a,o,n)=>{r=e._strokeIndex,e.push(),e.translate(t,a),e.rotate(e.atan2(n-a,o-t));let i=Math.sqrt((o-t)**2+(n-a)**2),s=e._strokeWeight;e.rect(0,-s/2,i,s),e.pop(),r=null},e.background=(t,r,a,n)=>{e.push(),e.resetMatrix(),t.src?e.image(t,-o.hw,-o.hh,o.w,o.h):(e.fill(t,r,a,n),e.rect(-o.hw,-o.hh,o.w,o.h)),e.pop()};e.ellipseMode=t=>e._ellipseMode=t,e.ellipse=(t,a,o,i)=>{const l=(d=o==i?o:Math.max(o,i))<4?6:d<6?8:d<10?10:d<16?12:d<20?14:d<22?16:d<24?18:d<28?20:d<34?22:d<42?24:d<48?26:d<56?28:d<64?30:d<72?32:d<84?34:d<96?36:d<98?38:d<113?40:d<149?44:d<199?48:d<261?52:d<353?56:d<461?60:d<585?64:d<1200?70:d<1800?80:d<2400?90:100;var d;let c=Math.max(o,1)/2,h=o==i?c:Math.max(i,1)/2,u=0;const p=e.TAU/l,_=r??e._fillIndex;e._matrixDirty&&e._saveMatrix();const x=e._transformIndex;let g,m,f,v;for(let e=0;e<=l;e++)g=f,m=v,f=t+c*Math.cos(u),v=a+h*Math.sin(u),u+=p,0!=e&&s.push(t,a,_,x,g,m,_,x,f,v,_,x);n.push(0,3*l)},e.circle=(t,r,a)=>e.ellipse(t,r,a,a),e._hooks.preRender.push((()=>{e.pass.setPipeline(e.pipelines[0]);const t=new Float32Array(s),r=Q5.device.createBuffer({size:t.byteLength,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST});Q5.device.queue.writeBuffer(r,0,t),e.pass.setVertexBuffer(0,r);const o=Q5.device.createBuffer({size:4*i.length,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});Q5.device.queue.writeBuffer(o,0,new Float32Array(i)),e._colorsBindGroup=Q5.device.createBindGroup({layout:a,entries:[{binding:0,resource:{buffer:o,offset:0,size:4*i.length}}]}),e.pass.setBindGroup(2,e._colorsBindGroup)})),e._hooks.postRender.push((()=>{s.length=0}))},Q5.renderers.webgpu.image=(e,t)=>{e._textureBindGroups=[];let r=[],a=Q5.device.createShaderModule({label:"imageVertexShader",code:"\nstruct VertexOutput {\n\t@builtin(position) position: vec4<f32>,\n\t@location(0) texCoord: vec2<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) texCoord: vec2<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.texCoord = texCoord;\n\treturn output;\n}\n\t"}),o=Q5.device.createShaderModule({label:"imageFragmentShader",code:"\n@group(3) @binding(0) var samp: sampler;\n@group(3) @binding(1) var texture: texture_2d<f32>;\n\n@fragment\nfn fragmentMain(@location(0) texCoord: vec2<f32>) -> @location(0) vec4<f32> {\n\t// Sample the texture using the interpolated texture coordinate\n\treturn textureSample(texture, samp, texCoord);\n}\n\t"}),n=Q5.device.createBindGroupLayout({label:"textureLayout",entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,texture:{viewDimension:"2d",sampleType:"float"}}]});e.bindGroupLayouts.push(n);const i=Q5.device.createPipelineLayout({label:"imagePipelineLayout",bindGroupLayouts:e.bindGroupLayouts});e.pipelines[1]=Q5.device.createRenderPipeline({label:"imagePipeline",layout:i,vertex:{module:a,entryPoint:"vertexMain",buffers:[{arrayStride:0,attributes:[]},{arrayStride:20,attributes:[{shaderLocation:0,offset:0,format:"float32x2"},{shaderLocation:1,offset:8,format:"float32x2"},{shaderLocation:2,offset:16,format:"float32"}]}]},fragment:{module:o,entryPoint:"fragmentMain",targets:[{format:"bgra8unorm",blend:e.blendConfigs?.normal||{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha",operation:"add"},alpha:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha",operation:"add"}}}]},primitive:{topology:"triangle-list"}});let s=Q5.device.createSampler({magFilter:"linear",minFilter:"linear"});e._createTexture=t=>{t.canvas&&(t=t.canvas);let r=[t.width,t.height,1];const a=Q5.device.createTexture({size:r,format:"bgra8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT});Q5.device.queue.copyExternalImageToTexture({source:t},{texture:a},r),t.textureIndex=e._textureBindGroups.length;const o=Q5.device.createBindGroup({layout:n,entries:[{binding:0,resource:s},{binding:1,resource:a.createView()}]});e._textureBindGroups.push(o)},e.loadImage=e.loadTexture=r=>{t._preloadCount++;const a=new Image;return a.crossOrigin="Anonymous",a.onload=()=>{e._createTexture(a),t._preloadCount--},a.src=r,a},e.imageMode=t=>e._imageMode=t,e.image=(t,a,o,n,i)=>{if(t.canvas&&(t=t.canvas),null==t.textureIndex)return;e._matrixDirty&&e._saveMatrix();let s=e._transformIndex;n??=t.width/e._pixelDensity,i??=t.height/e._pixelDensity;let[l,d,c,h]=e._calcBox(a,o,n,i,e._imageMode);r.push(l,c,0,0,s,d,c,1,0,s,l,h,0,1,s,d,c,1,0,s,l,h,0,1,s,d,h,1,1,s),e.drawStack.push(1,t.textureIndex)},e._hooks.preRender.push((()=>{if(!e._textureBindGroups.length)return;e.pass.setPipeline(e.pipelines[1]);const t=new Float32Array(r),a=Q5.device.createBuffer({size:t.byteLength,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST});Q5.device.queue.writeBuffer(a,0,t),e.pass.setVertexBuffer(1,a)})),e._hooks.postRender.push((()=>{r.length=0}))},Q5.renderers.webgpu.text=(e,t)=>{let r=e.createGraphics(1,1);r.pixelDensity(e._pixelDensity),r._imageMode="corner",e.loadFont=e=>(t._preloadCount++,r.loadFont(e,(()=>{t._preloadCount--}))),e.textFont=r.textFont,e.textSize=r.textSize,e.textLeading=r.textLeading,e.textStyle=r.textStyle,e.textAlign=r.textAlign,e.textWidth=r.textWidth,e.textAscent=r.textAscent,e.textDescent=r.textDescent,e.textFill=(t,a,o,n)=>r.fill(e.color(t,a,o,n)),e.textStroke=(t,a,o,n)=>r.stroke(e.color(t,a,o,n)),e.text=(t,a,o,n,i)=>{let s=r.createTextImage(t,n,i);null==s.canvas.textureIndex&&e._createTexture(s),e.textImage(s,a,o)},e.createTextImage=r.createTextImage,e.textImage=(t,a,o)=>{"center"==r.ctx.textAlign?a-=.5*t.width:"right"==r.ctx.textAlign&&(a-=t.width),"alphabetic"==r.ctx.textBaseline&&(o-=r._textLeading),"middle"==r.ctx.textBaseline?o-=t._descent+.5*t._ascent+r._textLeadDiff:"bottom"==r.ctx.textBaseline?o-=t._ascent+t._descent+r._textLeadDiff:"top"==r.ctx.textBaseline&&(o-=t._descent+r._textLeadDiff),e.image(t,a,o)}};
|
package/src/q5-2d-canvas.js
CHANGED
|
@@ -107,36 +107,13 @@ Q5.renderers.q2d.canvas = ($, q) => {
|
|
|
107
107
|
$.scale($._pixelDensity);
|
|
108
108
|
};
|
|
109
109
|
|
|
110
|
-
$._styleNames = [
|
|
111
|
-
'_doStroke',
|
|
112
|
-
'_doFill',
|
|
113
|
-
'_strokeSet',
|
|
114
|
-
'_fillSet',
|
|
115
|
-
'_tint',
|
|
116
|
-
'_imageMode',
|
|
117
|
-
'_rectMode',
|
|
118
|
-
'_ellipseMode',
|
|
119
|
-
'_textFont',
|
|
120
|
-
'_textLeading',
|
|
121
|
-
'_leadingSet',
|
|
122
|
-
'_textSize',
|
|
123
|
-
'_textAlign',
|
|
124
|
-
'_textBaseline',
|
|
125
|
-
'_textStyle',
|
|
126
|
-
'_textWrap'
|
|
127
|
-
];
|
|
128
|
-
$._styles = [];
|
|
129
|
-
|
|
130
110
|
$.push = $.pushMatrix = () => {
|
|
131
111
|
$.ctx.save();
|
|
132
|
-
|
|
133
|
-
for (let s of $._styleNames) styles[s] = $[s];
|
|
134
|
-
$._styles.push(styles);
|
|
112
|
+
$._pushStyles();
|
|
135
113
|
};
|
|
136
114
|
$.pop = $.popMatrix = () => {
|
|
137
115
|
$.ctx.restore();
|
|
138
|
-
|
|
139
|
-
for (let s of $._styleNames) $[s] = styles[s];
|
|
116
|
+
$._popStyles();
|
|
140
117
|
};
|
|
141
118
|
|
|
142
119
|
$.createCapture = (x) => {
|
package/src/q5-canvas.js
CHANGED
|
@@ -251,6 +251,36 @@ Q5.modules.canvas = ($, q) => {
|
|
|
251
251
|
q.height = (c.h / c.w) * unit;
|
|
252
252
|
} else $._da = 0;
|
|
253
253
|
};
|
|
254
|
+
|
|
255
|
+
$._styleNames = [
|
|
256
|
+
'_doStroke',
|
|
257
|
+
'_doFill',
|
|
258
|
+
'_strokeSet',
|
|
259
|
+
'_fillSet',
|
|
260
|
+
'_tint',
|
|
261
|
+
'_imageMode',
|
|
262
|
+
'_rectMode',
|
|
263
|
+
'_ellipseMode',
|
|
264
|
+
'_textFont',
|
|
265
|
+
'_textLeading',
|
|
266
|
+
'_leadingSet',
|
|
267
|
+
'_textSize',
|
|
268
|
+
'_textAlign',
|
|
269
|
+
'_textBaseline',
|
|
270
|
+
'_textStyle',
|
|
271
|
+
'_textWrap'
|
|
272
|
+
];
|
|
273
|
+
$._styles = [];
|
|
274
|
+
|
|
275
|
+
$._pushStyles = () => {
|
|
276
|
+
let styles = {};
|
|
277
|
+
for (let s of $._styleNames) styles[s] = $[s];
|
|
278
|
+
$._styles.push(styles);
|
|
279
|
+
};
|
|
280
|
+
$._popStyles = () => {
|
|
281
|
+
let styles = $._styles.pop();
|
|
282
|
+
for (let s of $._styleNames) $[s] = styles[s];
|
|
283
|
+
};
|
|
254
284
|
};
|
|
255
285
|
|
|
256
286
|
Q5.canvasOptions = {
|
package/src/q5-core.js
CHANGED
|
@@ -86,12 +86,12 @@ function Q5(scope, parent, renderer) {
|
|
|
86
86
|
$._frameRate = 1000 / $.deltaTime;
|
|
87
87
|
q.frameCount++;
|
|
88
88
|
let pre = performance.now();
|
|
89
|
-
|
|
89
|
+
$.resetMatrix();
|
|
90
90
|
if ($._beginRender) $._beginRender();
|
|
91
91
|
for (let m of Q5.methods.pre) m.call($);
|
|
92
92
|
$.draw();
|
|
93
|
-
if ($._render) $._render();
|
|
94
93
|
for (let m of Q5.methods.post) m.call($);
|
|
94
|
+
if ($._render) $._render();
|
|
95
95
|
if ($._finishRender) $._finishRender();
|
|
96
96
|
q.pmouseX = $.mouseX;
|
|
97
97
|
q.pmouseY = $.mouseY;
|
package/src/q5-webgpu-canvas.js
CHANGED
|
@@ -109,20 +109,22 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
109
109
|
// Stack to keep track of transformation matrix indexes
|
|
110
110
|
$._transformIndexStack = [];
|
|
111
111
|
|
|
112
|
-
$.push = () => {
|
|
112
|
+
$.push = $.pushMatrix = () => {
|
|
113
113
|
// Push the current matrix index onto the stack
|
|
114
114
|
$._transformIndexStack.push($._transformIndex);
|
|
115
|
+
$._pushStyles();
|
|
115
116
|
};
|
|
116
117
|
|
|
117
|
-
$.pop = () => {
|
|
118
|
-
if (
|
|
119
|
-
|
|
120
|
-
let idx = $._transformIndexStack.pop();
|
|
121
|
-
$._matrix = $.transformStates[idx].slice();
|
|
122
|
-
$._transformIndex = idx;
|
|
123
|
-
} else {
|
|
124
|
-
console.warn('Matrix index stack is empty!');
|
|
118
|
+
$.pop = $.popMatrix = () => {
|
|
119
|
+
if (!$._transformIndexStack.length) {
|
|
120
|
+
return console.warn('Matrix index stack is empty!');
|
|
125
121
|
}
|
|
122
|
+
// Pop the last matrix index from the stack and set it as the current matrix index
|
|
123
|
+
let idx = $._transformIndexStack.pop();
|
|
124
|
+
$._matrix = $.transformStates[idx].slice();
|
|
125
|
+
$._transformIndex = idx;
|
|
126
|
+
$._matrixDirty = false;
|
|
127
|
+
$._popStyles();
|
|
126
128
|
};
|
|
127
129
|
|
|
128
130
|
$.translate = (x, y, z) => {
|
|
@@ -321,8 +323,6 @@ Q5.renderers.webgpu.canvas = ($, q) => {
|
|
|
321
323
|
$.colorsStack.length = 4;
|
|
322
324
|
colorIndex = 0;
|
|
323
325
|
rotation = 0;
|
|
324
|
-
$.resetMatrix();
|
|
325
|
-
$._matrixDirty = false;
|
|
326
326
|
$.transformStates.length = 1;
|
|
327
327
|
$._transformIndexStack.length = 0;
|
|
328
328
|
};
|
package/src/q5-webgpu-drawing.js
CHANGED
|
@@ -180,6 +180,10 @@ fn fragmentMain(@location(1) colorIndex: f32) -> @location(0) vec4<f32> {
|
|
|
180
180
|
};
|
|
181
181
|
|
|
182
182
|
$.endShape = (close) => {
|
|
183
|
+
if (!$._doFill) {
|
|
184
|
+
shapeVertices = [];
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
183
187
|
let v = shapeVertices;
|
|
184
188
|
if (v.length < 12) {
|
|
185
189
|
throw new Error('A shape must have at least 3 vertices.');
|
|
@@ -206,10 +210,10 @@ fn fragmentMain(@location(1) colorIndex: f32) -> @location(0) vec4<f32> {
|
|
|
206
210
|
v[i + 3]
|
|
207
211
|
);
|
|
208
212
|
}
|
|
213
|
+
shapeVertices = [];
|
|
209
214
|
|
|
210
215
|
verticesStack.push(...triangles);
|
|
211
216
|
drawStack.push(0, triangles.length / 4);
|
|
212
|
-
shapeVertices = [];
|
|
213
217
|
};
|
|
214
218
|
|
|
215
219
|
$.triangle = (x1, y1, x2, y2, x3, y3) => {
|