q5 2.22.3 → 2.23.2

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/deno.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@q5/q5",
3
- "version": "2.22.0",
3
+ "version": "2.23.0",
4
4
  "license": "LGPL-3.0",
5
5
  "description": "Beginner friendly graphics powered by WebGPU and optimized for interactive art!",
6
6
  "author": "quinton-ashley",
7
7
  "exports": "./q5-deno-server.js",
8
- "types": "./q5-deno-server.d.ts",
8
+ "types": "./q5.d.ts",
9
9
  "tasks": {
10
10
  "tests": "deno test --unstable-node-globals -A"
11
11
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "q5",
3
- "version": "2.22.3",
3
+ "version": "2.23.2",
4
4
  "description": "Beginner friendly graphics powered by WebGPU and optimized for interactive art!",
5
5
  "author": "quinton-ashley",
6
6
  "contributors": [
@@ -10,9 +10,10 @@
10
10
  "license": "LGPL-3.0",
11
11
  "homepage": "https://q5js.org/home",
12
12
  "main": "q5-server.js",
13
+ "types": "q5.d.ts",
13
14
  "scripts": {
14
15
  "bundle": "cat src/q5-core.js src/q5-canvas.js src/q5-c2d-canvas.js src/q5-c2d-shapes.js src/q5-c2d-image.js src/q5-c2d-soft-filters.js src/q5-c2d-text.js src/q5-ai.js src/q5-color.js src/q5-display.js src/q5-dom.js src/q5-input.js src/q5-math.js src/q5-record.js src/q5-sound.js src/q5-util.js src/q5-vector.js src/q5-webgpu-canvas.js src/q5-webgpu-shapes.js src/q5-webgpu-image.js src/q5-webgpu-text.js src/q5-webgpu-shaders.js > q5.js",
15
- "min": "terser q5.js --compress ecma=2024 --mangle > q5.min.js",
16
+ "min": "terser q5.js --compress ecma=2025 --mangle > q5.min.js",
16
17
  "dist": "bun bundle && bun min",
17
18
  "dist-p5play": "bun dist && cp q5.js ../../web/p5play-web/v3/q5.js && cp q5.min.js ../../web/p5play-web/v3/q5.min.js",
18
19
  "tests": "jest test",
@@ -29,13 +30,13 @@
29
30
  "url": "https://github.com/q5js/q5.js/issues"
30
31
  },
31
32
  "keywords": [
33
+ "q5.js",
34
+ "q5js",
35
+ "q5xjs",
32
36
  "p5",
33
37
  "p5js",
34
38
  "p5.js",
35
- "p5xjs",
36
- "q5xjs",
37
- "q5.js",
38
- "q5js"
39
+ "p5xjs"
39
40
  ],
40
41
  "devDependencies": {
41
42
  "jest-cli": "^29.7.0",
package/q5.d.ts CHANGED
@@ -343,6 +343,11 @@ q.circle(100, 50, 20);
343
343
  static Image: {
344
344
  new(w: number, h: number, opt?: any): Q5.Image;
345
345
  }
346
+
347
+ /** ⭐️
348
+ * Creates a new Q5 instance with the q5.js WebGPU renderer.
349
+ */
350
+ static WebGPU(): Q5;
346
351
  }
347
352
 
348
353
  namespace Q5 {
@@ -2483,6 +2488,18 @@ function draw() {
2483
2488
  */
2484
2489
  const TAU: number;
2485
2490
 
2491
+ /** 🧮
2492
+ * Half of PI.
2493
+ * Approximately 1.5708.
2494
+ */
2495
+ const HALF_PI: number;
2496
+
2497
+ /** 🧮
2498
+ * A quarter of PI.
2499
+ * Approximately 0.7854.
2500
+ */
2501
+ const QUARTER_PI: number;
2502
+
2486
2503
  // 🔊 sound
2487
2504
 
2488
2505
  /** 🔊
package/q5.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * q5.js
3
- * @version 2.22
3
+ * @version 2.23
4
4
  * @author quinton-ashley, Tezumie, and LingDong-
5
5
  * @license LGPL-3.0
6
6
  * @class Q5
@@ -330,7 +330,7 @@ function createCanvas(w, h, opt) {
330
330
  }
331
331
  }
332
332
 
333
- Q5.version = Q5.VERSION = '2.22';
333
+ Q5.version = Q5.VERSION = '2.23';
334
334
 
335
335
  if (typeof document == 'object') {
336
336
  document.addEventListener('DOMContentLoaded', () => {
@@ -391,7 +391,7 @@ Q5.modules.canvas = ($, q) => {
391
391
  w = null;
392
392
  }
393
393
  options ??= arguments[3];
394
-
394
+ if (typeof options == 'string') options = { renderer: options };
395
395
  let opt = Object.assign({}, Q5.canvasOptions);
396
396
  if (typeof options == 'object') Object.assign(opt, options);
397
397
 
@@ -430,6 +430,7 @@ Q5.modules.canvas = ($, q) => {
430
430
  };
431
431
 
432
432
  $.createGraphics = function (w, h, opt = {}) {
433
+ if (typeof opt == 'string') opt = { renderer: opt };
433
434
  let g = new Q5('graphics', undefined, opt.renderer || ($._webgpuFallback ? 'webgpu-fallback' : $._renderer));
434
435
  opt.alpha ??= true;
435
436
  opt.colorSpace ??= $.canvas.colorSpace;
@@ -655,6 +656,7 @@ Q5.HUE_ROTATE = 13;
655
656
 
656
657
  Q5.C2D = Q5.P2D = Q5.P2DHDR = 'c2d';
657
658
  Q5.WEBGL = 'webgl';
659
+ Q5.WEBGPU = 'webgpu';
658
660
 
659
661
  Q5.canvasOptions = {
660
662
  alpha: false,
@@ -5493,13 +5495,15 @@ Q5.initWebGPU = async () => {
5493
5495
  return true;
5494
5496
  };
5495
5497
 
5496
- Q5.webgpu = async function (scope, parent) {
5498
+ Q5.WebGPU = async function (scope, parent) {
5497
5499
  if (!scope || scope == 'global') Q5._hasGlobal = true;
5498
5500
  if (!(await Q5.initWebGPU())) {
5499
5501
  return new Q5(scope, parent, 'webgpu-fallback');
5500
5502
  }
5501
5503
  return new Q5(scope, parent, 'webgpu');
5502
5504
  };
5505
+
5506
+ Q5.webgpu = Q5.WebGPU;
5503
5507
  Q5.renderers.webgpu.shapes = ($) => {
5504
5508
  $._shapesPL = 1;
5505
5509
 
@@ -6938,6 +6942,7 @@ fn fragMain(f : FragParams) -> @location(0) vec4f {
6938
6942
  };
6939
6943
 
6940
6944
  $.textSize = (size) => {
6945
+ if (size == undefined) return $._textSize;
6941
6946
  $._textSize = size;
6942
6947
  if (!leadingSet) {
6943
6948
  leading = size * leadPercent;
package/q5.min.js CHANGED
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * q5.js
3
- * @version 2.22
3
+ * @version 2.23
4
4
  * @author quinton-ashley, Tezumie, and LingDong-
5
5
  * @license LGPL-3.0
6
6
  * @class Q5
7
7
  */
8
- function Q5(scope,parent,renderer){let $=this;$._q5=true;$._parent=parent;if(renderer=="webgpu-fallback"){$._webgpuFallback=true;$._renderer="c2d"}else{$._renderer=renderer||Q5.render}$._preloadCount=0;let autoLoaded=scope=="auto";scope??="global";if(scope=="auto"){if(!(window.setup||window.update||window.draw))return;scope="global"}$._scope=scope;let globalScope;if(scope=="global"){Q5._hasGlobal=$._isGlobal=true;globalScope=Q5._esm?globalThis:!Q5._server?window:global}if(scope=="graphics")$._graphics=true;let q=new Proxy($,{set:(t,p,v)=>{$[p]=v;if($._isGlobal)globalScope[p]=v;return true}});$.canvas=$.ctx=$.drawingContext=null;$.pixels=[];let looper=null,useRAF=true;$.frameCount=0;$.deltaTime=16;$._targetFrameRate=0;$._targetFrameDuration=16.666666666666668;$._frameRate=$._fps=60;$._loop=true;$._hooks={postCanvas:[],preRender:[],postRender:[]};let millisStart=0;$.millis=()=>performance.now()-millisStart;$.noCanvas=()=>{if($.canvas?.remove)$.canvas.remove();$.canvas=0;q.ctx=q.drawingContext=0};if(window){$.windowWidth=window.innerWidth;$.windowHeight=window.innerHeight;$.deviceOrientation=window.screen?.orientation?.type}$._incrementPreload=()=>q._preloadCount++;$._decrementPreload=()=>q._preloadCount--;$.disablePreloadSystem=()=>$._disablePreload=true;$._draw=timestamp=>{let ts=timestamp||performance.now();$._lastFrameTime??=ts-$._targetFrameDuration;if($._didResize){$.windowResized();$._didResize=false}if($._loop){if(useRAF)looper=raf($._draw);else{let nextTS=ts+$._targetFrameDuration;let frameDelay=nextTS-performance.now();while(frameDelay<0)frameDelay+=$._targetFrameDuration;log(frameDelay);looper=setTimeout((()=>$._draw(nextTS)),frameDelay)}}else if($.frameCount&&!$._redraw)return;if($.frameCount&&useRAF){let timeSinceLast=ts-$._lastFrameTime;if(timeSinceLast<$._targetFrameDuration-4)return}q.deltaTime=ts-$._lastFrameTime;$._frameRate=1e3/$.deltaTime;q.frameCount++;let pre=performance.now();$.resetMatrix();if($._beginRender)$._beginRender();for(let m of Q5.methods.pre)m.call($);try{$.draw()}catch(e){if(!Q5.errorTolerant)$.noLoop();throw e}for(let m of Q5.methods.post)m.call($);$.postProcess();if($._render)$._render();if($._finishRender)$._finishRender();q.pmouseX=$.mouseX;q.pmouseY=$.mouseY;q.moveX=q.moveY=0;$._lastFrameTime=ts;let post=performance.now();$._fps=Math.round(1e3/(post-pre))};$.noLoop=()=>{$._loop=false;if(looper){if(useRAF)cancelAnimationFrame(looper);else clearTimeout(looper)}looper=null};$.loop=()=>{$._loop=true;if($._setupDone&&looper==null)$._draw()};$.isLooping=()=>$._loop;$.redraw=(n=1)=>{$._redraw=true;for(let i=0;i<n;i++){$._draw()}$._redraw=false};$.remove=()=>{$.noLoop();$.canvas.remove()};$.frameRate=hz=>{if(hz){$._targetFrameRate=hz;$._targetFrameDuration=1e3/hz;if($._loop&&$._setupDone&&looper!=null){if(useRAF)cancelAnimationFrame(looper);else clearTimeout(looper);looper=null}useRAF=hz<=60;setTimeout((()=>$._draw()),$._targetFrameDuration)}return $._frameRate};$.getTargetFrameRate=()=>$._targetFrameRate||60;$.getFPS=()=>$._fps;$.Element=function(a){this.elt=a};$._elements=[];$.describe=()=>{};$.log=$.print=console.log;for(let m in Q5.modules){Q5.modules[m]($,q)}let r=Q5.renderers[$._renderer];for(let m in r){r[m]($,q)}for(let k in Q5){if(k[1]!="_"&&k[1]==k[1].toUpperCase()){$[k]=Q5[k]}}if($._webgpuFallback)$.colorMode("rgb",1);if($._graphics)return;if(scope=="global"){let tmp=Object.assign({},$);delete tmp.Color;Object.assign(Q5,tmp);delete Q5.Q5}for(let m of Q5.methods.init){m.call($)}for(let[n,fn]of Object.entries(Q5.prototype)){if(n[0]!="_"&&typeof $[n]=="function")$[n]=fn.bind($)}if(scope=="global"){let props=Object.getOwnPropertyNames($);for(let p of props){if(p[0]!="_")globalScope[p]=$[p]}}if(typeof scope=="function")scope($);Q5._instanceCount++;let raf=window.requestAnimationFrame||function(cb){const idealFrameTime=$._lastFrameTime+$._targetFrameDuration;return setTimeout((()=>{cb(idealFrameTime)}),idealFrameTime-performance.now())};let t=globalScope||$;$._isTouchAware=t.touchStarted||t.touchMoved||t.mouseReleased;if($._isGlobal){$.preload=t.preload;$.setup=t.setup;$.draw=t.draw;$.postProcess=t.postProcess}$.preload??=()=>{};$.setup??=()=>{};$.draw??=()=>{};$.postProcess??=()=>{};let userFns=["setup","postProcess","mouseMoved","mousePressed","mouseReleased","mouseDragged","mouseClicked","mouseWheel","keyPressed","keyReleased","keyTyped","touchStarted","touchMoved","touchEnded","windowResized"];for(let k of userFns){if(!t[k])$[k]=()=>{};else if($._isGlobal){$[k]=event=>t[k](event)}}async function _setup(){$._startDone=true;if($._preloadCount>0||$._g?._preloadCount>0)return raf(_setup);millisStart=performance.now();await $.setup();$._setupDone=true;if($.frameCount)return;if($.ctx===null)$.createCanvas(200,200);raf($._draw)}function _start(){try{$.preload();if(!$._startDone)_setup()}catch(e){if($._askAI)$._askAI(e);throw e}}if(autoLoaded)_start();else setTimeout(_start,32)}Q5.render="c2d";Q5.renderers={};Q5.modules={};Q5._server=typeof process=="object";Q5._esm=this===undefined;Q5._instanceCount=0;Q5._friendlyError=(msg,func)=>{if(!Q5.disableFriendlyErrors)console.error(func+": "+msg)};Q5._validateParameters=()=>true;Q5.methods={init:[],pre:[],post:[],remove:[]};Q5.prototype.registerMethod=(m,fn)=>Q5.methods[m].push(fn);Q5.prototype.registerPreloadMethod=(n,fn)=>Q5.prototype[n]=fn[n];if(Q5._server)global.p5??=global.Q5=Q5;if(typeof window=="object")window.p5??=window.Q5=Q5;else global.window=0;function createCanvas(w,h,opt){if(!Q5._hasGlobal){let q=new Q5;q.createCanvas(w,h,opt)}}Q5.version=Q5.VERSION="2.22";if(typeof document=="object"){document.addEventListener("DOMContentLoaded",(()=>{if(!Q5._hasGlobal)new Q5("auto")}))}Q5.modules.canvas=($,q)=>{$._Canvas=window.OffscreenCanvas||function(){return document.createElement("canvas")};if(Q5._server){if(Q5._createServerCanvas){q.canvas=Q5._createServerCanvas(100,100)}}else if($._scope=="image"||$._scope=="graphics"){q.canvas=new $._Canvas(100,100)}if(!$.canvas){if(typeof document=="object"){q.canvas=document.createElement("canvas");$.canvas.id="q5Canvas"+Q5._instanceCount;$.canvas.classList.add("q5Canvas")}else $.noCanvas()}let c=$.canvas;$.width=200;$.height=200;$._pixelDensity=1;$.displayDensity=()=>window.devicePixelRatio||1;if(c){c.width=200;c.height=200;if($._scope!="image"){c.renderer=$._renderer;c[$._renderer]=true;$._pixelDensity=Math.ceil($.displayDensity())}}$._adjustDisplay=()=>{if(c.style){c.style.width=c.w+"px";c.style.height=c.h+"px"}};$.createCanvas=function(w,h,options){if(typeof w=="object"){options=w;w=null}options??=arguments[3];let opt=Object.assign({},Q5.canvasOptions);if(typeof options=="object")Object.assign(opt,options);if($._scope!="image"){if($._scope=="graphics")$._pixelDensity=this._pixelDensity;else if(window.IntersectionObserver){let wasObserved=false;new IntersectionObserver((e=>{c.visible=e[0].isIntersecting;if(!wasObserved){$._wasLooping=$._loop;wasObserved=true}if(c.visible){if($._wasLooping&&!$._loop)$.loop()}else{$._wasLooping=$._loop;$.noLoop()}})).observe(c)}}$._setCanvasSize(w,h);Object.assign(c,opt);let rend=$._createCanvas(c.w,c.h,opt);if($._hooks){for(let m of $._hooks.postCanvas)m()}if($._addEventMethods)$._addEventMethods(c);return rend};$.createGraphics=function(w,h,opt={}){let g=new Q5("graphics",undefined,opt.renderer||($._webgpuFallback?"webgpu-fallback":$._renderer));opt.alpha??=true;opt.colorSpace??=$.canvas.colorSpace;g.createCanvas.call($,w,h,opt);let scale=g._pixelDensity*$._defaultImageScale;g.defaultWidth=w*scale;g.defaultHeight=h*scale;return g};$._setCanvasSize=(w,h)=>{if(w==undefined)h??=window.innerHeight;else h??=w;w??=window.innerWidth;c.w=w=Math.ceil(w);c.h=h=Math.ceil(h);q.halfWidth=c.hw=w/2;q.halfHeight=c.hh=h/2;c.width=Math.ceil(w*$._pixelDensity);c.height=Math.ceil(h*$._pixelDensity);if(!$._da){q.width=w;q.height=h}else $.flexibleCanvas($._dau);if($.displayMode&&!c.displayMode)$.displayMode();else $._adjustDisplay()};$._setImageSize=(w,h)=>{q.width=c.w=w;q.height=c.h=h;q.halfWidth=c.hw=w/2;q.halfHeight=c.hh=h/2;c.width=Math.ceil(w*$._pixelDensity);c.height=Math.ceil(h*$._pixelDensity)};$.defaultImageScale=scale=>{if(!scale)return $._defaultImageScale;return $._defaultImageScale=scale};$.defaultImageScale(.5);if($._scope=="image")return;if(c&&$._scope!="graphics"){c.parent=el=>{if(c.parentElement)c.parentElement.removeChild(c);if(typeof el=="string")el=document.getElementById(el);el.append(c);function parentResized(){if($.frameCount>1){$._didResize=true;$._adjustDisplay()}}if(typeof ResizeObserver=="function"){if($._ro)$._ro.disconnect();$._ro=new ResizeObserver(parentResized);$._ro.observe(el)}else if(!$.frameCount){window.addEventListener("resize",parentResized)}};function addCanvas(){let el=$._parent;el??=document.getElementsByTagName("main")[0];if(!el){el=document.createElement("main");document.body.append(el)}c.parent(el)}if(document.body)addCanvas();else document.addEventListener("DOMContentLoaded",addCanvas)}$.resizeCanvas=(w,h)=>{if(!$.ctx)return $.createCanvas(w,h);if(w==c.w&&h==c.h)return;$._resizeCanvas(w,h)};if(c&&!Q5._createServerCanvas)c.resize=$.resizeCanvas;$.pixelDensity=v=>{if(!v||v==$._pixelDensity)return $._pixelDensity;$._pixelDensity=v;$._resizeCanvas(c.w,c.h);return v};$.flexibleCanvas=(unit=400)=>{if(unit){$._da=c.width/(unit*$._pixelDensity);q.width=$._dau=unit;q.height=c.h/c.w*unit}else $._da=0};$._styleNames=["_fill","_stroke","_strokeWeight","_doStroke","_doFill","_strokeSet","_fillSet","_shadow","_doShadow","_shadowOffsetX","_shadowOffsetY","_shadowBlur","_tint","_imageMode","_rectMode","_ellipseMode","_textSize","_textAlign","_textBaseline"];$._styles=[];$.pushStyles=()=>{let styles={};for(let s of $._styleNames)styles[s]=$[s];$._styles.push(styles)};$.popStyles=()=>{let styles=$._styles.pop();for(let s of $._styleNames)$[s]=styles[s]};if(window&&$._scope!="graphics"){window.addEventListener("resize",(()=>{$._didResize=true;q.windowWidth=window.innerWidth;q.windowHeight=window.innerHeight;q.deviceOrientation=window.screen?.orientation?.type}))}};Q5.CENTER="center";Q5.LEFT="left";Q5.RIGHT="right";Q5.TOP="top";Q5.BOTTOM="bottom";Q5.BASELINE="alphabetic";Q5.MIDDLE="middle";Q5.NORMAL="normal";Q5.ITALIC="italic";Q5.BOLD="bold";Q5.BOLDITALIC="italic bold";Q5.ROUND="round";Q5.SQUARE="butt";Q5.PROJECT="square";Q5.MITER="miter";Q5.BEVEL="bevel";Q5.CHORD_OPEN=0;Q5.PIE_OPEN=1;Q5.PIE=2;Q5.CHORD=3;Q5.RADIUS="radius";Q5.CORNER="corner";Q5.CORNERS="corners";Q5.OPEN=0;Q5.CLOSE=1;Q5.VIDEO="video";Q5.AUDIO="audio";Q5.LANDSCAPE="landscape";Q5.PORTRAIT="portrait";Q5.BLEND="source-over";Q5.REMOVE="destination-out";Q5.ADD="lighter";Q5.DARKEST="darken";Q5.LIGHTEST="lighten";Q5.DIFFERENCE="difference";Q5.SUBTRACT="subtract";Q5.EXCLUSION="exclusion";Q5.MULTIPLY="multiply";Q5.SCREEN="screen";Q5.REPLACE="copy";Q5.OVERLAY="overlay";Q5.HARD_LIGHT="hard-light";Q5.SOFT_LIGHT="soft-light";Q5.DODGE="color-dodge";Q5.BURN="color-burn";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.SEPIA=9;Q5.BRIGHTNESS=10;Q5.SATURATION=11;Q5.CONTRAST=12;Q5.HUE_ROTATE=13;Q5.C2D=Q5.P2D=Q5.P2DHDR="c2d";Q5.WEBGL="webgl";Q5.canvasOptions={alpha:false,colorSpace:"display-p3"};if(!window.matchMedia||!matchMedia("(dynamic-range: high) and (color-gamut: p3)").matches){Q5.canvasOptions.colorSpace="srgb"}else Q5.supportsHDR=true;Q5.renderers.c2d={};Q5.renderers.c2d.canvas=($,q)=>{let c=$.canvas;if($.colorMode){$.colorMode(Q5.canvasOptions.colorSpace!="srgb"?"rgb":"srgb",255)}$._createCanvas=function(w,h,options){if(!c){console.error("q5 canvas could not be created. skia-canvas and jsdom packages not found.");return}q.ctx=q.drawingContext=c.getContext("2d",options);if($._scope!="image"){$.ctx.fillStyle=$._fill="white";$.ctx.strokeStyle=$._stroke="black";$.ctx.lineCap="round";$.ctx.lineJoin="miter";$.ctx.textAlign="left";$._strokeWeight=1}$.ctx.scale($._pixelDensity,$._pixelDensity);$.ctx.save();return c};$.clear=()=>{$.ctx.save();$.ctx.resetTransform();$.ctx.clearRect(0,0,$.canvas.width,$.canvas.height);$.ctx.restore()};if($._scope=="image")return;$.background=function(c){$.ctx.save();$.ctx.resetTransform();$.ctx.globalAlpha=1;if(c.canvas)$.image(c,0,0,$.canvas.width,$.canvas.height);else{if(Q5.Color&&!c._q5Color){if(typeof c!="string")c=$.color(...arguments);else if($._namedColors[c])c=$.color(...$._namedColors[c])}$.ctx.fillStyle=c.toString();$.ctx.fillRect(0,0,$.canvas.width,$.canvas.height)}$.ctx.restore()};$._resizeCanvas=(w,h)=>{let t={};for(let prop in $.ctx){if(typeof $.ctx[prop]!="function")t[prop]=$.ctx[prop]}delete t.canvas;let o;if($.frameCount>1){o=new $._Canvas(c.width,c.height);o.w=c.w;o.h=c.h;let oCtx=o.getContext("2d");oCtx.drawImage(c,0,0)}$._setCanvasSize(w,h);for(let prop in t)$.ctx[prop]=t[prop];$.scale($._pixelDensity);if(o)$.ctx.drawImage(o,0,0,o.w,o.h)};$.fill=function(c){$._doFill=$._fillSet=true;if(Q5.Color){if(!c._q5Color){if(typeof c!="string")c=$.color(...arguments);else if($._namedColors[c])c=$.color(...$._namedColors[c])}if(c.a<=0)return $._doFill=false}$.ctx.fillStyle=$._fill=c.toString()};$.stroke=function(c){$._doStroke=$._strokeSet=true;if(Q5.Color){if(!c._q5Color){if(typeof c!="string")c=$.color(...arguments);else if($._namedColors[c])c=$.color(...$._namedColors[c])}if(c.a<=0)return $._doStroke=false}$.ctx.strokeStyle=$._stroke=c.toString()};$.strokeWeight=n=>{if(!n)$._doStroke=false;if($._da)n*=$._da;$.ctx.lineWidth=$._strokeWeight=n||1e-4};$.noFill=()=>$._doFill=false;$.noStroke=()=>$._doStroke=false;$.opacity=a=>$.ctx.globalAlpha=a;$._doShadow=false;$._shadowOffsetX=$._shadowOffsetY=$._shadowBlur=10;$.shadow=function(c){if(Q5.Color){if(!c._q5Color){if(typeof c!="string")c=$.color(...arguments);else if($._namedColors[c])c=$.color(...$._namedColors[c])}}$.ctx.shadowColor=$._shadow=c.toString();$._doShadow=true;$.ctx.shadowOffsetX||=$._shadowOffsetX;$.ctx.shadowOffsetY||=$._shadowOffsetY;$.ctx.shadowBlur||=$._shadowBlur};$.shadowBox=(offsetX,offsetY,blur)=>{$.ctx.shadowOffsetX=$._shadowOffsetX=offsetX;$.ctx.shadowOffsetY=$._shadowOffsetY=offsetY||offsetX;$.ctx.shadowBlur=$._shadowBlur=blur||0};$.noShadow=()=>{$._doShadow=false;$.ctx.shadowOffsetX=$.ctx.shadowOffsetY=$.ctx.shadowBlur=0};$.translate=(x,y)=>{if($._da){x*=$._da;y*=$._da}$.ctx.translate(x,y)};$.rotate=r=>{if($._angleMode)r=$.radians(r);$.ctx.rotate(r)};$.scale=(x,y)=>{if(x.x){y=x.y;x=x.x}y??=x;$.ctx.scale(x,y)};$.applyMatrix=(a,b,c,d,e,f)=>$.ctx.transform(a,b,c,d,e,f);$.shearX=ang=>$.ctx.transform(1,0,$.tan(ang),1,0,0);$.shearY=ang=>$.ctx.transform(1,$.tan(ang),0,1,0,0);$.resetMatrix=()=>{if($.ctx){$.ctx.resetTransform();$.scale($._pixelDensity);if($._webgpuFallback)$.translate($.canvas.hw,$.canvas.hh)}};$.pushMatrix=()=>$.ctx.save();$.popMatrix=()=>$.ctx.restore();let _popStyles=$.popStyles;$.popStyles=()=>{_popStyles();$.ctx.fillStyle=$._fill;$.ctx.strokeStyle=$._stroke;$.ctx.lineWidth=$._strokeWeight;$.ctx.shadowColor=$._shadow;$.ctx.shadowOffsetX=$._doShadow?$._shadowOffsetX:0;$.ctx.shadowOffsetY=$._doShadow?$._shadowOffsetY:0;$.ctx.shadowBlur=$._doShadow?$._shadowBlur:0};$.push=()=>{$.ctx.save();$.pushStyles()};$.pop=()=>{$.ctx.restore();_popStyles()}};Q5.renderers.c2d.shapes=$=>{$._doStroke=true;$._doFill=true;$._strokeSet=false;$._fillSet=false;$._ellipseMode=Q5.CENTER;$._rectMode=Q5.CORNER;$._curveDetail=20;$._curveAlpha=0;let firstVertex=true;let curveBuff=[];function ink(){if($._doFill)$.ctx.fill();if($._doStroke)$.ctx.stroke()}$.blendMode=x=>$.ctx.globalCompositeOperation=x;$.strokeCap=x=>$.ctx.lineCap=x;$.strokeJoin=x=>$.ctx.lineJoin=x;$.ellipseMode=x=>$._ellipseMode=x;$.rectMode=x=>$._rectMode=x;$.curveDetail=x=>$._curveDetail=x;$.curveAlpha=x=>$._curveAlpha=x;$.curveTightness=x=>$._curveAlpha=x;$.line=(x0,y0,x1,y1)=>{if($._doStroke){$._da&&(x0*=$._da,y0*=$._da,x1*=$._da,y1*=$._da);$.ctx.beginPath();$.ctx.moveTo(x0,y0);$.ctx.lineTo(x1,y1);$.ctx.stroke()}};const TAU=Math.PI*2;function arc(x,y,w,h,lo,hi,mode){if($._angleMode){lo=$.radians(lo);hi=$.radians(hi)}lo%=TAU;hi%=TAU;if(lo<0)lo+=TAU;if(hi<0)hi+=TAU;if(lo>hi)hi+=TAU;if(lo==hi)return $.ellipse(x,y,w,h);w/=2;h/=2;if(!$._doFill&&mode==$.PIE_OPEN)mode=$.CHORD_OPEN;$.ctx.beginPath();$.ctx.ellipse(x,y,w,h,0,lo,hi);if(mode==$.PIE||mode==$.PIE_OPEN)$.ctx.lineTo(x,y);if($._doFill)$.ctx.fill();if($._doStroke){if(mode==$.PIE||mode==$.CHORD)$.ctx.closePath();if(mode!=$.PIE_OPEN)return $.ctx.stroke();$.ctx.beginPath();$.ctx.ellipse(x,y,w,h,0,lo,hi);$.ctx.stroke()}}$.arc=(x,y,w,h,start,stop,mode)=>{if(start==stop)return $.ellipse(x,y,w,h);if($._da){x*=$._da;y*=$._da;w*=$._da;h*=$._da}mode??=$.PIE_OPEN;if($._ellipseMode==$.CENTER){arc(x,y,w,h,start,stop,mode)}else if($._ellipseMode==$.RADIUS){arc(x,y,w*2,h*2,start,stop,mode)}else if($._ellipseMode==$.CORNER){arc(x+w/2,y+h/2,w,h,start,stop,mode)}else if($._ellipseMode==$.CORNERS){arc((x+w)/2,(y+h)/2,w-x,h-y,start,stop,mode)}};function ellipse(x,y,w,h){$.ctx.beginPath();$.ctx.ellipse(x,y,w/2,h/2,0,0,TAU);ink()}$.ellipse=(x,y,w,h)=>{h??=w;if($._da){x*=$._da;y*=$._da;w*=$._da;h*=$._da}if($._ellipseMode==$.CENTER){ellipse(x,y,w,h)}else if($._ellipseMode==$.RADIUS){ellipse(x,y,w*2,h*2)}else if($._ellipseMode==$.CORNER){ellipse(x+w/2,y+h/2,w,h)}else if($._ellipseMode==$.CORNERS){ellipse((x+w)/2,(y+h)/2,w-x,h-y)}};$.circle=(x,y,d)=>{if($._ellipseMode==$.CENTER){if($._da){x*=$._da;y*=$._da;d*=$._da}$.ctx.beginPath();$.ctx.arc(x,y,d/2,0,TAU);ink()}else $.ellipse(x,y,d,d)};$.point=(x,y)=>{if($._doStroke){if(x.x){y=x.y;x=x.x}if($._da){x*=$._da;y*=$._da}$.ctx.beginPath();$.ctx.moveTo(x,y);$.ctx.lineTo(x,y);$.ctx.stroke()}};function rect(x,y,w,h){if($._da){x*=$._da;y*=$._da;w*=$._da;h*=$._da}$.ctx.beginPath();$.ctx.rect(x,y,w,h);ink()}function roundedRect(x,y,w,h,tl,tr,br,bl){if(tl===undefined){return rect(x,y,w,h)}if(tr===undefined){return roundedRect(x,y,w,h,tl,tl,tl,tl)}if($._da){x*=$._da;y*=$._da;w*=$._da;h*=$._da;tl*=$._da;tr*=$._da;bl*=$._da;br*=$._da}$.ctx.roundRect(x,y,w,h,[tl,tr,br,bl]);ink()}$.rect=(x,y,w,h=w,tl,tr,br,bl)=>{if($._rectMode==$.CENTER){roundedRect(x-w/2,y-h/2,w,h,tl,tr,br,bl)}else if($._rectMode==$.RADIUS){roundedRect(x-w,y-h,w*2,h*2,tl,tr,br,bl)}else if($._rectMode==$.CORNER){roundedRect(x,y,w,h,tl,tr,br,bl)}else if($._rectMode==$.CORNERS){roundedRect(x,y,w-x,h-y,tl,tr,br,bl)}};$.square=(x,y,s,tl,tr,br,bl)=>$.rect(x,y,s,s,tl,tr,br,bl);$.beginShape=()=>{curveBuff=[];$.ctx.beginPath();firstVertex=true};$.beginContour=()=>{$.ctx.closePath();curveBuff=[];firstVertex=true};$.endContour=()=>{curveBuff=[];firstVertex=true};$.vertex=(x,y)=>{if($._da){x*=$._da;y*=$._da}curveBuff=[];if(firstVertex){$.ctx.moveTo(x,y)}else{$.ctx.lineTo(x,y)}firstVertex=false};$.bezierVertex=(cp1x,cp1y,cp2x,cp2y,x,y)=>{if($._da){cp1x*=$._da;cp1y*=$._da;cp2x*=$._da;cp2y*=$._da;x*=$._da;y*=$._da}curveBuff=[];$.ctx.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y)};$.quadraticVertex=(cp1x,cp1y,x,y)=>{if($._da){cp1x*=$._da;cp1y*=$._da;x*=$._da;y*=$._da}curveBuff=[];$.ctx.quadraticCurveTo(cp1x,cp1y,x,y)};$.bezier=(x1,y1,x2,y2,x3,y3,x4,y4)=>{$.beginShape();$.vertex(x1,y1);$.bezierVertex(x2,y2,x3,y3,x4,y4);$.endShape()};$.triangle=(x1,y1,x2,y2,x3,y3)=>{$.beginShape();$.vertex(x1,y1);$.vertex(x2,y2);$.vertex(x3,y3);$.endShape($.CLOSE)};$.quad=(x1,y1,x2,y2,x3,y3,x4,y4)=>{$.beginShape();$.vertex(x1,y1);$.vertex(x2,y2);$.vertex(x3,y3);$.vertex(x4,y4);$.endShape($.CLOSE)};$.endShape=close=>{curveBuff=[];if(close)$.ctx.closePath();ink()};$.curveVertex=(x,y)=>{if($._da){x*=$._da;y*=$._da}curveBuff.push([x,y]);if(curveBuff.length<4)return;let p0=curveBuff.at(-4),p1=curveBuff.at(-3),p2=curveBuff.at(-2),p3=curveBuff.at(-1);let cp1x=p1[0]+(p2[0]-p0[0])/6,cp1y=p1[1]+(p2[1]-p0[1])/6,cp2x=p2[0]-(p3[0]-p1[0])/6,cp2y=p2[1]-(p3[1]-p1[1])/6;if(firstVertex){$.ctx.moveTo(p1[0],p1[1]);firstVertex=false}$.ctx.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,p2[0],p2[1])};$.curve=(x1,y1,x2,y2,x3,y3,x4,y4)=>{$.beginShape();$.curveVertex(x1,y1);$.curveVertex(x2,y2);$.curveVertex(x3,y3);$.curveVertex(x4,y4);$.endShape()};$.curvePoint=(a,b,c,d,t)=>{const t3=t*t*t,t2=t*t,f1=-.5*t3+t2-.5*t,f2=1.5*t3-2.5*t2+1,f3=-1.5*t3+2*t2+.5*t,f4=.5*t3-.5*t2;return a*f1+b*f2+c*f3+d*f4};$.bezierPoint=(a,b,c,d,t)=>{const adjustedT=1-t;return Math.pow(adjustedT,3)*a+3*Math.pow(adjustedT,2)*t*b+3*adjustedT*Math.pow(t,2)*c+Math.pow(t,3)*d};$.curveTangent=(a,b,c,d,t)=>{const t2=t*t,f1=-3*t2/2+2*t-.5,f2=9*t2/2-5*t,f3=-9*t2/2+4*t+.5,f4=3*t2/2-t;return a*f1+b*f2+c*f3+d*f4};$.bezierTangent=(a,b,c,d,t)=>{const adjustedT=1-t;return 3*d*Math.pow(t,2)-3*c*Math.pow(t,2)+6*c*adjustedT*t-6*b*adjustedT*t+3*b*Math.pow(adjustedT,2)-3*a*Math.pow(adjustedT,2)};$.erase=function(fillAlpha=255,strokeAlpha=255){$.ctx.save();$.ctx.globalCompositeOperation="destination-out";$.ctx.fillStyle=`rgb(0 0 0 / ${fillAlpha/255})`;$.ctx.strokeStyle=`rgb(0 0 0 / ${strokeAlpha/255})`};$.noErase=function(){$.ctx.globalCompositeOperation="source-over";$.ctx.restore()};$.inFill=(x,y)=>{const pd=$._pixelDensity;return $.ctx.isPointInPath(x*pd,y*pd)};$.inStroke=(x,y)=>{const pd=$._pixelDensity;return $.ctx.isPointInStroke(x*pd,y*pd)}};Q5.renderers.c2d.image=($,q)=>{class Q5Image{constructor(w,h,opt={}){let $=this;$._scope="image";$.canvas=$.ctx=$.drawingContext=null;$.pixels=[];Q5.modules.canvas($,$);let r=Q5.renderers.c2d;for(let m of["canvas","image","soft_filters"]){if(r[m])r[m]($,$)}$._pixelDensity=opt.pixelDensity||1;$.createCanvas(w,h,opt);let scale=$._pixelDensity*q._defaultImageScale;$.defaultWidth=w*scale;$.defaultHeight=h*scale;delete $.createCanvas;$._loop=false}get w(){return this.width}get h(){return this.height}}Q5.Image??=Q5Image;$._tint=null;let imgData=null;$.createImage=(w,h,opt)=>{opt??={};opt.alpha??=true;opt.colorSpace??=$.canvas.colorSpace||Q5.canvasOptions.colorSpace;return new Q5.Image(w,h,opt)};$.loadImage=function(url,cb,opt){if(url.canvas)return url;if(url.slice(-3).toLowerCase()=="gif"){throw new Error(`q5 doesn't support GIFs. Use a video or p5play animation instead. https://github.com/q5js/q5.js/issues/84`)}q._preloadCount++;let last=[...arguments].at(-1);if(typeof last=="object"){opt=last;cb=null}else opt=null;let g=$.createImage(1,1,opt);let pd=g._pixelDensity;let img=new window.Image;img.crossOrigin="Anonymous";g._loader=new Promise(((resolve,reject)=>{img.onload=()=>{img._pixelDensity=pd;g.defaultWidth=img.width*$._defaultImageScale;g.defaultHeight=img.height*$._defaultImageScale;g.naturalWidth=img.naturalWidth||img.width;g.naturalHeight=img.naturalHeight||img.height;g._setImageSize(Math.ceil(g.naturalWidth/pd),Math.ceil(g.naturalHeight/pd));g.ctx.drawImage(img,0,0);q._preloadCount--;if(cb)cb(g);delete g._loader;resolve(g)};img.onerror=e=>{q._preloadCount--;reject(e)}}));g.src=img.src=url;if($._disablePreload)return g._loader;return g};$.imageMode=mode=>$._imageMode=mode;$.image=(img,dx,dy,dw,dh,sx=0,sy=0,sw,sh)=>{if(!img)return;let drawable=img.canvas||img;dw??=img.defaultWidth||drawable.width||img.videoWidth;dh??=img.defaultHeight||drawable.height||img.videoHeight;if($._imageMode=="center"){dx-=dw*.5;dy-=dh*.5}if($._da){dx*=$._da;dy*=$._da;dw*=$._da;dh*=$._da;sx*=$._da;sy*=$._da;sw*=$._da;sh*=$._da}let pd=img._pixelDensity||1;if(!sw){sw=drawable.width||drawable.videoWidth}else sw*=pd;if(!sh){sh=drawable.height||drawable.videoHeight}else sh*=pd;if($._tint){if(img._retint||img._tint!=$._tint){img._tintImg??=$.createImage(img.w,img.h,{pixelDensity:pd});if(img._tintImg.width!=img.width||img._tintImg.height!=img.height){img._tintImg.resize(img.w,img.h)}let tnt=img._tintImg.ctx;tnt.globalCompositeOperation="copy";tnt.fillStyle=$._tint;tnt.fillRect(0,0,img.width,img.height);if(img.canvas.alpha){tnt.globalCompositeOperation="destination-in";tnt.drawImage(drawable,0,0,img.width,img.height)}tnt.globalCompositeOperation="multiply";tnt.drawImage(drawable,0,0,img.width,img.height);img._tint=$._tint;img._retint=false}drawable=img._tintImg.canvas}if(img.flipped){$.ctx.save();$.ctx.translate(dx+dw,0);$.ctx.scale(-1,1);dx=0}$.ctx.drawImage(drawable,sx*pd,sy*pd,sw,sh,dx,dy,dw,dh);if(img.flipped)$.ctx.restore()};$.filter=(type,value)=>{$.ctx.save();let f="";if($.ctx.filter){if(typeof type=="string"){f=type}else if(type==Q5.GRAY){f=`saturate(0%)`}else if(type==Q5.INVERT){f=`invert(100%)`}else if(type==Q5.BLUR){let r=Math.ceil(value*$._pixelDensity)||1;f=`blur(${r}px)`}else if(type==Q5.THRESHOLD){value??=.5;let b=Math.floor(.5/Math.max(value,1e-5)*100);f=`saturate(0%) brightness(${b}%) contrast(1000000%)`}else if(type==Q5.SEPIA){f=`sepia(${value??1})`}else if(type==Q5.BRIGHTNESS){f=`brightness(${value??1})`}else if(type==Q5.SATURATION){f=`saturate(${value??1})`}else if(type==Q5.CONTRAST){f=`contrast(${value??1})`}else if(type==Q5.HUE_ROTATE){let unit=$._angleMode==0?"rad":"deg";f=`hue-rotate(${value}${unit})`}if(f){$.ctx.filter=f;if($.ctx.filter=="none"){throw new Error(`Invalid filter format: ${type}`)}}}if(!f)$._softFilter(type,value);$.ctx.globalCompositeOperation="source-over";$.ctx.drawImage($.canvas,0,0,$.canvas.w,$.canvas.h);$.ctx.restore();$.modified=$._retint=true};if($._scope=="image"){$.resize=(w,h)=>{let c=$.canvas;let o=new $._Canvas(c.width,c.height);let tmpCtx=o.getContext("2d",{colorSpace:c.colorSpace});tmpCtx.drawImage(c,0,0);$._setImageSize(w,h);$.defaultWidth=c.width*$._defaultImageScale;$.defaultHeight=c.height*$._defaultImageScale;$.ctx.clearRect(0,0,c.width,c.height);$.ctx.drawImage(o,0,0,c.width,c.height);$.modified=$._retint=true}}$._getImageData=(x,y,w,h)=>$.ctx.getImageData(x,y,w,h,{colorSpace:$.canvas.colorSpace});$.trim=()=>{let pd=$._pixelDensity||1;let w=$.canvas.width;let h=$.canvas.height;let data=$._getImageData(0,0,w,h).data;let left=w,right=0,top=h,bottom=0;let i=3;for(let y=0;y<h;y++){for(let x=0;x<w;x++){if(data[i]!==0){if(x<left)left=x;if(x>right)right=x;if(y<top)top=y;if(y>bottom)bottom=y}i+=4}}top=Math.floor(top/pd);bottom=Math.floor(bottom/pd);left=Math.floor(left/pd);right=Math.floor(right/pd);return $.get(left,top,right-left+1,bottom-top+1)};$.mask=img=>{$.ctx.save();$.ctx.resetTransform();let old=$.ctx.globalCompositeOperation;$.ctx.globalCompositeOperation="destination-in";$.ctx.drawImage(img.canvas,0,0);$.ctx.globalCompositeOperation=old;$.ctx.restore();$.modified=$._retint=true};$.inset=(x,y,w,h,dx,dy,dw,dh)=>{let pd=$._pixelDensity||1;$.ctx.drawImage($.canvas,x*pd,y*pd,w*pd,h*pd,dx,dy,dw,dh);$.modified=$._retint=true};$.copy=()=>{let img=$.get();for(let prop in $){if(typeof $[prop]!="function"&&!/(canvas|ctx|texture|textureIndex)/.test(prop)){img[prop]=$[prop]}}return img};$.get=(x,y,w,h)=>{let pd=$._pixelDensity||1;if(x!==undefined&&w===undefined){let c=$._getImageData(x*pd,y*pd,1,1).data;return[c[0],c[1],c[2],c[3]/255]}x=Math.floor(x||0)*pd;y=Math.floor(y||0)*pd;w??=$.width;h??=$.height;let img=$.createImage(w,h,{pixelDensity:pd});img.ctx.drawImage($.canvas,x,y,w*pd,h*pd,0,0,w,h);img.width=w;img.height=h;return img};$.set=(x,y,c)=>{x=Math.floor(x);y=Math.floor(y);$.modified=$._retint=true;if(c.canvas){let old=$._tint;$._tint=null;$.image(c,x,y);$._tint=old;return}if(!$.pixels.length)$.loadPixels();let mod=$._pixelDensity||1;for(let i=0;i<mod;i++){for(let j=0;j<mod;j++){let idx=4*((y*mod+i)*$.canvas.width+x*mod+j);$.pixels[idx]=c.r;$.pixels[idx+1]=c.g;$.pixels[idx+2]=c.b;$.pixels[idx+3]=c.a}}};$.loadPixels=()=>{imgData=$._getImageData(0,0,$.canvas.width,$.canvas.height);q.pixels=imgData.data};$.updatePixels=()=>{if(imgData!=null){$.ctx.putImageData(imgData,0,0);$.modified=$._retint=true}};$.smooth=()=>$.ctx.imageSmoothingEnabled=true;$.noSmooth=()=>$.ctx.imageSmoothingEnabled=false;if($._scope=="image")return;$._saveCanvas=async(data,ext)=>{data=data.canvas||data;if(data instanceof OffscreenCanvas){const blob=await data.convertToBlob({type:"image/"+ext});return await new Promise((resolve=>{const reader=new FileReader;reader.onloadend=()=>resolve(reader.result);reader.readAsDataURL(blob)}))}return data.toDataURL("image/"+ext)};$.tint=function(c){$._tint=(c._q5Color?c:$.color(...arguments)).toString()};$.noTint=()=>$._tint=null};Q5.renderers.c2d.soft_filters=$=>{let u=null;function ensureBuf(){let l=$.canvas.width*$.canvas.height*4;if(!u||u.length!=l)u=new Uint8ClampedArray(l)}function initSoftFilters(){$._filters=[];$._filters[Q5.THRESHOLD]=(d,thresh)=>{if(thresh===undefined)thresh=127.5;else thresh*=255;for(let i=0;i<d.length;i+=4){const gray=.2126*d[i]+.7152*d[i+1]+.0722*d[i+2];d[i]=d[i+1]=d[i+2]=gray>=thresh?255:0}};$._filters[Q5.GRAY]=d=>{for(let i=0;i<d.length;i+=4){const gray=.2126*d[i]+.7152*d[i+1]+.0722*d[i+2];d[i]=d[i+1]=d[i+2]=gray}};$._filters[Q5.OPAQUE]=d=>{for(let i=0;i<d.length;i+=4){d[i+3]=255}};$._filters[Q5.INVERT]=d=>{for(let i=0;i<d.length;i+=4){d[i]=255-d[i];d[i+1]=255-d[i+1];d[i+2]=255-d[i+2]}};$._filters[Q5.POSTERIZE]=(d,lvl=4)=>{let lvl1=lvl-1;for(let i=0;i<d.length;i+=4){d[i]=(d[i]*lvl>>8)*255/lvl1;d[i+1]=(d[i+1]*lvl>>8)*255/lvl1;d[i+2]=(d[i+2]*lvl>>8)*255/lvl1}};$._filters[Q5.DILATE]=(d,func)=>{func??=Math.max;ensureBuf();u.set(d);let[w,h]=[$.canvas.width,$.canvas.height];for(let i=0;i<h;i++){for(let j=0;j<w;j++){let l=4*Math.max(j-1,0);let r=4*Math.min(j+1,w-1);let t=4*Math.max(i-1,0)*w;let b=4*Math.min(i+1,h-1)*w;let oi=4*i*w;let oj=4*j;for(let k=0;k<4;k++){let kt=k+t;let kb=k+b;let ko=k+oi;d[oi+oj+k]=func(u[kt+oj],u[ko+l],u[ko+oj],u[ko+r],u[kb+oj])}}}};$._filters[Q5.ERODE]=d=>{$._filters[Q5.DILATE](d,Math.min)};$._filters[Q5.BLUR]=(d,r)=>{r=r||1;r=Math.floor(r*$._pixelDensity);ensureBuf();u.set(d);let ksize=r*2+1;function gauss(ksize){let im=new Float32Array(ksize);let sigma=.3*r+.8;let ss2=sigma*sigma*2;for(let i=0;i<ksize;i++){let x=i-ksize/2;let z=Math.exp(-(x*x)/ss2)/(2.5066282746*sigma);im[i]=z}return im}let kern=gauss(ksize);let[w,h]=[$.canvas.width,$.canvas.height];for(let i=0;i<h;i++){for(let j=0;j<w;j++){let s0=0,s1=0,s2=0,s3=0;for(let k=0;k<ksize;k++){let jk=Math.min(Math.max(j-r+k,0),w-1);let idx=4*(i*w+jk);s0+=u[idx]*kern[k];s1+=u[idx+1]*kern[k];s2+=u[idx+2]*kern[k];s3+=u[idx+3]*kern[k]}let idx=4*(i*w+j);d[idx]=s0;d[idx+1]=s1;d[idx+2]=s2;d[idx+3]=s3}}u.set(d);for(let i=0;i<h;i++){for(let j=0;j<w;j++){let s0=0,s1=0,s2=0,s3=0;for(let k=0;k<ksize;k++){let ik=Math.min(Math.max(i-r+k,0),h-1);let idx=4*(ik*w+j);s0+=u[idx]*kern[k];s1+=u[idx+1]*kern[k];s2+=u[idx+2]*kern[k];s3+=u[idx+3]*kern[k]}let idx=4*(i*w+j);d[idx]=s0;d[idx+1]=s1;d[idx+2]=s2;d[idx+3]=s3}}}}$._softFilter=(typ,x)=>{if(!$._filters)initSoftFilters();let imgData=$._getImageData(0,0,$.canvas.width,$.canvas.height);$._filters[typ](imgData.data,x);$.ctx.putImageData(imgData,0,0)}};Q5.renderers.c2d.text=($,q)=>{$._textAlign="left";$._textBaseline="alphabetic";$._textSize=12;let font="sans-serif",leadingSet=false,leading=15,leadDiff=3,emphasis="normal",fontMod=false,styleHash=0,styleHashes=[],useCache=false,genTextImage=false,cacheSize=0,cacheMax=12e3;let cache=$._textCache={};$.loadFont=(url,cb)=>{q._preloadCount++;let name=url.split("/").pop().split(".")[0].replace(" ","");let f=new FontFace(name,`url(${url})`);document.fonts.add(f);f._loader=(async()=>{let err;try{await f.load()}catch(e){err=e}q._preloadCount--;delete f._loader;if(err)throw err;if(cb)cb(f);return f})();$.textFont(name);if($._disablePreload)return f._loader;return f};$.textFont=x=>{if(x&&typeof x!="string")x=x.family;if(!x||x==font)return font;font=x;fontMod=true;styleHash=-1};$.textSize=x=>{if(x==undefined||x==$._textSize)return $._textSize;if($._da)x*=$._da;$._textSize=x;fontMod=true;styleHash=-1;if(!leadingSet){leading=x*1.25;leadDiff=leading-x}};$.textStyle=x=>{if(!x||x==emphasis)return emphasis;emphasis=x;fontMod=true;styleHash=-1};$.textLeading=x=>{if(x==undefined)return leading||$._textSize*1.25;leadingSet=true;if(x==leading)return leading;if($._da)x*=$._da;leading=x;leadDiff=x-$._textSize;styleHash=-1};$.textAlign=(horiz,vert)=>{$.ctx.textAlign=$._textAlign=horiz;if(vert){$.ctx.textBaseline=$._textBaseline=vert==$.CENTER?"middle":vert}};const updateFont=()=>{$.ctx.font=`${emphasis} ${$._textSize}px ${font}`;fontMod=false};$.textWidth=str=>{if(fontMod)updateFont();return $.ctx.measureText(str).width};$.textAscent=str=>{if(fontMod)updateFont();return $.ctx.measureText(str).actualBoundingBoxAscent};$.textDescent=str=>{if(fontMod)updateFont();return $.ctx.measureText(str).actualBoundingBoxDescent};$.textFill=$.fill;$.textStroke=$.stroke;let updateStyleHash=()=>{let styleString=font+$._textSize+emphasis+leading;let hash=5381;for(let i=0;i<styleString.length;i++){hash=hash*33^styleString.charCodeAt(i)}styleHash=hash>>>0};$.textCache=(enable,maxSize)=>{if(maxSize)cacheMax=maxSize;if(enable!==undefined)useCache=enable;return useCache};$.createTextImage=(str,w,h)=>{genTextImage=true;let img=$.text(str,0,0,w,h);genTextImage=false;return img};let lines=[];$.text=(str,x,y,w,h)=>{if(str===undefined||!$._doFill&&!$._doStroke)return;str=str.toString();if($._da){x*=$._da;y*=$._da}let ctx=$.ctx;let img,tX,tY;if(fontMod){ctx.font=`${emphasis} ${$._textSize}px ${font}`;fontMod=false}if(useCache||genTextImage){if(styleHash==-1)updateStyleHash();img=cache[str];if(img)img=img[styleHash];if(img){if(img._fill==$._fill&&img._stroke==$._stroke&&img._strokeWeight==$._strokeWeight){if(genTextImage)return img;return $.textImage(img,x,y)}else img.clear()}}if(str.indexOf("\n")==-1)lines[0]=str;else lines=str.split("\n");if(str.length>w){let wrapped=[];for(let line of lines){let i=0;while(i<line.length){let max=i+w;if(max>=line.length){wrapped.push(line.slice(i));break}let end=line.lastIndexOf(" ",max);if(end===-1||end<i)end=max;wrapped.push(line.slice(i,end));i=end+1}}lines=wrapped}if(!useCache&&!genTextImage){tX=x;tY=y}else{tX=0;tY=leading*lines.length;if(!img){let ogBaseline=$.ctx.textBaseline;$.ctx.textBaseline="alphabetic";let measure=ctx.measureText(" ");let ascent=measure.fontBoundingBoxAscent;let descent=measure.fontBoundingBoxDescent;$.ctx.textBaseline=ogBaseline;img=$.createImage.call($,Math.ceil(ctx.measureText(str).width),Math.ceil(tY+descent),{pixelDensity:$._pixelDensity});img._ascent=ascent;img._descent=descent;img._top=descent+leadDiff;img._middle=img._top+ascent*.5;img._bottom=img._top+ascent;img._leading=leading}else{img.modified=true}img._fill=$._fill;img._stroke=$._stroke;img._strokeWeight=$._strokeWeight;ctx=img.ctx;ctx.font=$.ctx.font;ctx.fillStyle=$._fill;ctx.strokeStyle=$._stroke;ctx.lineWidth=$.ctx.lineWidth}let ogFill;if(!$._fillSet){ogFill=ctx.fillStyle;ctx.fillStyle="black"}let lineAmount=0;for(let line of lines){if($._doStroke&&$._strokeSet)ctx.strokeText(line,tX,tY);if($._doFill)ctx.fillText(line,tX,tY);tY+=leading;lineAmount++;if(lineAmount>=h)break}lines=[];if(!$._fillSet)ctx.fillStyle=ogFill;if(useCache||genTextImage){styleHashes.push(styleHash);(cache[str]??={})[styleHash]=img;cacheSize++;if(cacheSize>cacheMax){let half=Math.ceil(cacheSize/2);let hashes=styleHashes.splice(0,half);for(let s in cache){s=cache[s];for(let h of hashes)delete s[h]}cacheSize-=half}if(genTextImage)return img;$.textImage(img,x,y)}};$.textImage=(img,x,y)=>{if(typeof img=="string")img=$.createTextImage(img);let og=$._imageMode;$._imageMode="corner";let ta=$._textAlign;if(ta=="center")x-=img.canvas.hw;else if(ta=="right")x-=img.width;let bl=$._textBaseline;if(bl=="alphabetic")y-=img._leading;else if(bl=="middle")y-=img._middle;else if(bl=="bottom")y-=img._bottom;else if(bl=="top")y-=img._top;$.image(img,x,y);$._imageMode=og}};Q5.modules.ai=$=>{$.askAI=(question="")=>{Q5.disableFriendlyErrors=false;throw Error("Ask AI ✨ "+question)};$._askAI=async e=>{let askAI=e.message?.includes("Ask AI ✨");let stackLines=e.stack?.split("\n");if(!e.stack||stackLines.length<=1)return;let idx=1;let sep="(";if(navigator.userAgent.indexOf("Chrome")==-1){idx=0;sep="@"}while(stackLines[idx].indexOf("q5")>=0)idx++;let errFile=stackLines[idx].split(sep).at(-1);if(errFile.startsWith("blob:"))errFile=errFile.slice(5);let parts=errFile.split(":");let lineNum=parseInt(parts.at(-2));if(askAI)lineNum++;parts[parts.length-1]=parts.at(-1).split(")")[0];let fileUrl=parts.slice(0,-2).join(":");let fileBase=fileUrl.split("/").at(-1);try{let res=await(await fetch(fileUrl)).text();let lines=res.split("\n");let errLine=lines[lineNum-1].trim();let context="";let i=1;while(context.length<1600){if(lineNum-i>=0){context=lines[lineNum-i].trim()+"\n"+context}if(lineNum+i<lines.length){context+=lines[lineNum+i].trim()+"\n"}else break;i++}let question=askAI&&e.message.length>10?e.message.slice(10):"Whats+wrong+with+this+line%3F+short+answer";let url="https://chatgpt.com/?q=using+q5.js+not+p5.js+"+question+(askAI?"":"%0A%0A"+encodeURIComponent(e.name+": "+e.message))+"%0A%0ALine%3A+"+encodeURIComponent(errLine)+"%0A%0AExcerpt+for+context%3A%0A%0A"+encodeURIComponent(context);console.warn("Error in "+fileBase+" on line "+lineNum+":\n\n"+errLine);console.warn("Ask AI ✨ "+url);if(askAI)return window.open(url,"_blank")}catch(err){}}};Q5.modules.color=($,q)=>{$.RGB=$.RGBA=$._colorMode="rgb";$.HSL="hsl";$.HSB="hsb";$.OKLCH="oklch";$.SRGB="srgb";$.DISPLAY_P3="display-p3";$.colorMode=(mode,format,gamut)=>{$._colorMode=mode;let srgb=$.canvas.colorSpace=="srgb"||gamut=="srgb";format??=srgb?"integer":"float";$._colorFormat=format=="float"||format==1?1:255;if(mode=="oklch"){q.Color=Q5.ColorOKLCH}else if(mode=="hsl"){q.Color=srgb?Q5.ColorHSL:Q5.ColorHSL_P3}else if(mode=="hsb"){q.Color=srgb?Q5.ColorHSB:Q5.ColorHSB_P3}else{if($._colorFormat==255){q.Color=srgb?Q5.ColorRGB_8:Q5.ColorRGB_P3_8}else{q.Color=srgb?Q5.ColorRGB:Q5.ColorRGB_P3}$._colorMode="rgb"}};$._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]};$.color=(c0,c1,c2,c3)=>{let C=$.Color;if(c0._q5Color)return new C(...c0.levels);if(c1==undefined){if(typeof c0=="string"){if(c0[0]=="#"){if(c0.length<=5){if(c0.length>4)c3=parseInt(c0[4]+c0[4],16);c2=parseInt(c0[3]+c0[3],16);c1=parseInt(c0[2]+c0[2],16);c0=parseInt(c0[1]+c0[1],16)}else{if(c0.length>7)c3=parseInt(c0.slice(7,9),16);c2=parseInt(c0.slice(5,7),16);c1=parseInt(c0.slice(3,5),16);c0=parseInt(c0.slice(1,3),16)}}else if($._namedColors[c0]){[c0,c1,c2,c3]=$._namedColors[c0]}else{let c=new C(0,0,0);c._css=c0;c.toString=function(){return this._css};return c}if($._colorFormat==1){c0/=255;if(c1)c1/=255;if(c2)c2/=255;if(c3)c3/=255}}if(Array.isArray(c0))[c0,c1,c2,c3]=c0}if(c2==undefined){if($._colorMode==Q5.OKLCH)return new C(c0,0,0,c1);return new C(c0,c0,c0,c1)}return new C(c0,c1,c2,c3)};$.red=c=>c.r;$.green=c=>c.g;$.blue=c=>c.b;$.alpha=c=>c.a;$.lightness=c=>{if(c.l)return c.l;let l=(.2126*c.r+.7152*c.g+.0722*c.b)*100;return $._colorFormat==255?l/255:l};$.hue=c=>{if(c.h)return c.h;let r=c.r;let g=c.g;let b=c.b;if($._colorFormat==255){r/=255;g/=255;b/=255}let max=Math.max(r,g,b);let min=Math.min(r,g,b);let h;if(max==min)h=0;else if(max==r)h=60*(g-b)/(max-min);else if(max==g)h=60*(b-r)/(max-min)+120;else h=60*(r-g)/(max-min)+240;if(h<0)h+=360;return h};$.lerpColor=(a,b,t)=>{t=Math.max(0,Math.min(1,t));if($._colorMode=="rgb"){return new $.Color($.lerp(a.r,b.r,t),$.lerp(a.g,b.g,t),$.lerp(a.b,b.b,t),$.lerp(a.a,b.a,t))}else{let deltaH=b.h-a.h;if(deltaH>180)deltaH-=360;if(deltaH<-180)deltaH+=360;let h=a.h+t*deltaH;if(h<0)h+=360;if(h>360)h-=360;return new $.Color($.lerp(a.l,b.l,t),$.lerp(a.c,b.c,t),h,$.lerp(a.a,b.a,t))}}};Q5.Color=class{constructor(){this._q5Color=true}get alpha(){return this.a}set alpha(v){this.a=v}};Q5.ColorOKLCH=class extends Q5.Color{constructor(l,c,h,a){super();this.l=l;this.c=c;this.h=h;this.a=a??1}get levels(){return[this.l,this.c,this.h,this.a]}equals(c){return c&&this.l==c.l&&this.c==c.c&&this.h==c.h&&this.a==c.a}isSameColor(c){return c&&this.l==c.l&&this.c==c.c&&this.h==c.h}toString(){return`oklch(${this.l} ${this.c} ${this.h} / ${this.a})`}get lightness(){return this.l}set lightness(v){this.l=v}get chroma(){return this.c}set chroma(v){this.c=v}get hue(){return this.h}set hue(v){this.h=v}};Q5.ColorRGB=class extends Q5.Color{constructor(r,g,b,a){super();this.r=r;this.g=g;this.b=b;this.a=a??1}get levels(){return[this.r,this.g,this.b,this.a]}equals(c){return c&&this.r==c.r&&this.g==c.g&&this.b==c.b&&this.a==c.a}isSameColor(c){return c&&this.r==c.r&&this.g==c.g&&this.b==c.b}toString(){return`color(srgb ${this.r} ${this.g} ${this.b} / ${this.a})`}get red(){return this.r}set red(v){this.r=v}get green(){return this.g}set green(v){this.g=v}get blue(){return this.b}set blue(v){this.b=v}};Q5.ColorRGB_P3=class extends Q5.ColorRGB{toString(){return`color(display-p3 ${this.r} ${this.g} ${this.b} / ${this.a})`}};Q5.ColorRGB_8=class extends Q5.ColorRGB{constructor(r,g,b,a){super(r,g,b,a??255)}setRed(v){this.r=v}setGreen(v){this.g=v}setBlue(v){this.b=v}setAlpha(v){this.a=v}toString(){return`rgb(${this.r} ${this.g} ${this.b} / ${this.a/255})`}};Q5.ColorRGB_P3_8=class extends Q5.ColorRGB_8{constructor(r,g,b,a){super(r,g,b,a??255);this._edited=true}get r(){return this._r}set r(v){this._r=v;this._edited=true}get g(){return this._g}set g(v){this._g=v;this._edited=true}get b(){return this._b}set b(v){this._b=v;this._edited=true}get a(){return this._a}set a(v){this._a=v;this._edited=true}toString(){if(this._edited){let r=(this._r/255).toFixed(3);let g=(this._g/255).toFixed(3);let b=(this._b/255).toFixed(3);let a=(this._a/255).toFixed(3);this._css=`color(display-p3 ${r} ${g} ${b} / ${a})`;this._edited=false}return this._css}};Q5.ColorHSL=class extends Q5.Color{constructor(h,s,l,a){super();this.h=h;this.s=s;this.l=l;this.a=a??1}get levels(){return[this.h,this.s,this.l,this.a]}equals(c){return c&&this.h==c.h&&this.s==c.s&&this.l==c.l&&this.a==c.a}isSameColor(c){return c&&this.h==c.h&&this.s==c.s&&this.l==c.l}toString(){return`hsl(${this.h} ${this.s} ${this.l} / ${this.a})`}get hue(){return this.h}set hue(v){this.h=v}get saturation(){return this.s}set saturation(v){this.s=v}get lightness(){return this.l}set lightness(v){this.l=v}};Q5.ColorHSL_P3=class extends Q5.ColorHSL{toString(){let o=Q5.HSLtoRGB(this.h,this.s,this.l);return`color(display-p3 ${o.join(" ")} / ${this.a})`}};Q5.ColorHSB=class extends Q5.ColorHSL{constructor(h,s,b,a){super(h,s,b,a);delete this.l;this.b=b}get levels(){return[this.h,this.s,this.b,this.a]}equals(c){return c&&this.h==c.h&&this.s==c.s&&this.b==c.b&&this.a==c.a}isSameColor(c){return c&&this.h==c.h&&this.s==c.s&&this.b==c.b}toString(){let o=Q5.HSBtoHSL(this.h,this.s,this.b);return`hsl(${o.join(" ")} / ${this.a})`}get v(){return this.b}set v(v){this.b=v}get brightness(){return this.b}set brightness(v){this.b=v}get value(){return this.b}set value(v){this.b=v}};Q5.ColorHSB_P3=class extends Q5.ColorHSB{toString(){let o=Q5.HSLtoRGB(...Q5.HSBtoHSL(this.h,this.s,this.b));return`color(display-p3 ${o.join(" ")} / ${this.a})`}};Q5.HSLtoRGB=(h,s,l)=>{l/=100;let m=s/100*Math.min(l,1-l);let f=(n,k=(n+h/30)%12)=>l-m*Math.max(Math.min(k-3,9-k,1),-1);return[f(0),f(8),f(4)]};Q5.HSBtoHSL=(h,s,v,l=v*(1-s/200))=>[h,!l||l==100?0:(v-l)/Math.min(l,100-l)*100,l];{const multiplyMatrices=(A,B)=>[A[0]*B[0]+A[1]*B[1]+A[2]*B[2],A[3]*B[0]+A[4]*B[1]+A[5]*B[2],A[6]*B[0]+A[7]*B[1]+A[8]*B[2]];const oklch2oklab=(l,c,h)=>[l,isNaN(h)?0:c*Math.cos(h*Math.PI/180),isNaN(h)?0:c*Math.sin(h*Math.PI/180)];const srgbLinear2rgb=rgb=>rgb.map((c=>Math.max(0,Math.min(1,Math.abs(c)>.0031308?(c<0?-1:1)*(1.055*Math.abs(c)**(1/2.4)-.055):12.92*c))));const oklab2xyz=lab=>{const LMSg=multiplyMatrices([1,.3963377773761749,.2158037573099136,1,-.1055613458156586,-.0638541728258133,1,-.0894841775298119,-1.2914855480194092],lab);return multiplyMatrices([1.2268798758459243,-.5578149944602171,.2813910456659647,-.0405757452148008,1.112286803280317,-.0717110580655164,-.0763729366746601,-.4214933324022432,1.5869240198367816],LMSg.map((val=>val**3)))};const xyz2rgbLinear=xyz=>multiplyMatrices([3.2409699419045226,-1.537383177570094,-.4986107602930034,-.9692436362808796,1.8759675015077202,.04155505740717559,.05563007969699366,-.20397695888897652,1.0569715142428786],xyz);Q5.OKLCHtoRGB=(l,c,h)=>srgbLinear2rgb(xyz2rgbLinear(oklab2xyz(oklch2oklab(l,c,h))))}Q5.modules.display=$=>{if(!$.canvas||$._scope=="graphics")return;let c=$.canvas;$.CENTERED="centered";$.FULLSCREEN="fullscreen";$.MAXED="maxed";$.PIXELATED="pixelated";if(Q5._instanceCount==0&&!Q5._server){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>`)}$._adjustDisplay=()=>{let s=c.style;let p=c.parentElement;if(!s||!p||!c.displayMode)return;if(c.renderQuality=="pixelated"){c.classList.add("q5-pixelated");$.pixelDensity(1);$.defaultImageScale(1);if($.noSmooth)$.noSmooth();if($.textFont)$.textFont("monospace")}if(c.displayMode=="default"||c.displayMode=="normal"){p.classList.remove("q5-centered","q5-maxed","q5-fullscreen");s.width=c.w*c.displayScale+"px";s.height=c.h*c.displayScale+"px"}else{p.classList.add("q5-"+c.displayMode);p=p.getBoundingClientRect();if(c.w/c.h>p.width/p.height){if(c.displayMode=="centered"){s.width=c.w*c.displayScale+"px";s.maxWidth="100%"}else s.width="100%";s.height="auto";s.maxHeight=""}else{s.width="auto";s.maxWidth="";if(c.displayMode=="centered"){s.height=c.h*c.displayScale+"px";s.maxHeight="100%"}else s.height="100%"}}};$.displayMode=(displayMode="normal",renderQuality="smooth",displayScale=1)=>{if(typeof displayScale=="string"){displayScale=parseFloat(displayScale.slice(1))}if(displayMode=="center")displayMode="centered";Object.assign(c,{displayMode:displayMode,renderQuality:renderQuality,displayScale:displayScale});if($.ctx)$.pushStyles();$._adjustDisplay();if($.ctx)$.popStyles()};$.fullscreen=v=>{if(v===undefined)return document.fullscreenElement;if(v)document.body.requestFullscreen();else document.body.exitFullscreen()}};Q5.modules.dom=($,q)=>{$.elementMode=mode=>$._elementMode=mode;$.createElement=(tag,content)=>{let el=document.createElement(tag);if($._elementMode=="center"){el.style.transform="translate(-50%, -50%)"}if(content)el.innerHTML=content;Object.defineProperty(el,"x",{get:()=>el._x,set:v=>{let pos=el.style.position;if(!pos||pos=="relative"){el.style.position="absolute"}let x=$.canvas.offsetLeft+v;el.style.left=x+"px";el._x=x}});Object.defineProperty(el,"y",{get:()=>el._y,set:v=>{let pos=el.style.position;if(!pos||pos=="relative"){el.style.position="absolute"}let y=$.canvas.offsetTop+v;el.style.top=y+"px";el._y=y}});Object.defineProperty(el,"width",{get:()=>parseFloat(el.style.width||0),set:v=>el.style.width=v+"px"});Object.defineProperty(el,"height",{get:()=>parseFloat(el.style.height||0),set:v=>el.style.height=v+"px"});el.position=(x,y,scheme)=>{if(scheme)el.style.position=scheme;el.x=x;el.y=y;return el};Object.defineProperty(el,"size",{writable:true});el.size=(w,h)=>{el.width=w;el.height=h;return el};el.center=()=>{el.style.position="absolute";el.x=$.canvas.hw;el.y=$.canvas.hh;return el};el.show=()=>{el.style.display="";return el};el.hide=()=>{el.style.display="none";return el};el.parent=parent=>{parent.append(el);return el};$._addEventMethods(el);$._elements.push(el);if($.canvas)$.canvas.parentElement.append(el);else document.body.append(el);return el};$.createEl=$.createElement;$._addEventMethods=el=>{let l=el.addEventListener;el.mousePressed=cb=>l("mousedown",cb);el.mouseReleased=cb=>l("mouseup",cb);el.mouseClicked=cb=>l("click",cb);el.mouseMoved=cb=>l("mousemove",cb);el.mouseWheel=cb=>l("wheel",cb)};$.createA=(href,content,newTab)=>{let el=$.createEl("a",content);el.href=href;el.target=newTab?"_blank":"_self";return el};$.createButton=content=>$.createEl("button",content);$.createCheckbox=(label="",checked=false)=>{let el=$.createEl("input");el.type="checkbox";el.checked=checked;let lbl=$.createEl("label",label);lbl.addEventListener("click",(()=>{el.checked=!el.checked;el.dispatchEvent(new Event("input",{bubbles:true}));el.dispatchEvent(new Event("change",{bubbles:true}))}));el.insertAdjacentElement("afterend",lbl);el.label=lbl;return el};$.createColorPicker=(value="#ffffff")=>{let el=$.createEl("input");el.type="color";el.value=value.toString();return el};$.createDiv=content=>$.createEl("div",content);$.createImg=src=>{let el=$.createEl("img");el.crossOrigin="anonymous";el.src=src;return el};$.createInput=(value="",type="text")=>{let el=$.createEl("input");el.value=value;el.type=type;el.style.boxSizing="border-box";return el};$.createP=content=>$.createEl("p",content);let radioCount=0;$.createRadio=name=>{let el=$.createEl("div");el.name=name||"radio"+radioCount++;el.buttons=[];Object.defineProperty(el,"value",{get:()=>el.selected?.value,set:v=>{let btn=el.buttons.find((b=>b.value==v));if(btn){btn.checked=true;el.selected=btn}}});el.option=(label,value)=>{let btn=$.createEl("input");btn.type="radio";btn.name=el.name;btn.value=value||label;btn.addEventListener("input",(()=>el.selected=btn));let lbl=$.createEl("label",label);lbl.addEventListener("click",(()=>{btn.checked=true;el.selected=btn;btn.dispatchEvent(new Event("input",{bubbles:true}));btn.dispatchEvent(new Event("change",{bubbles:true}))}));btn.label=lbl;el.append(btn);el.append(lbl);el.buttons.push(btn);return el};return el};$.createSelect=placeholder=>{let el=$.createEl("select");if(placeholder){let opt=$.createEl("option",placeholder);opt.disabled=true;opt.selected=true;el.append(opt)}Object.defineProperty(el,"selected",{get:()=>{if(el.multiple){return Array.from(el.selectedOptions).map((opt=>opt.textContent))}return el.selectedOptions[0]?.textContent},set:v=>{if(el.multiple){Array.from(el.options).forEach((opt=>{opt.selected=v.includes(opt.textContent)}))}else{const option=Array.from(el.options).find((opt=>opt.textContent===v));if(option)option.selected=true}}});Object.defineProperty(el,"value",{get:()=>{if(el.multiple){return Array.from(el.selectedOptions).map((o=>o.value))}return el.selectedOptions[0]?.value},set:v=>{if(el.multiple){el.options.forEach((o=>o.selected=v.includes(o.value)))}else{let opt;for(let i=0;i<el.options.length;i++){if(el.options[i].value==v){opt=el.options[i];break}}if(opt)opt.selected=true}}});el.option=(label,value)=>{let opt=$.createEl("option",label);opt.value=value||label;el.append(opt);return el};return el};$.createSlider=(min,max,value,step)=>{let el=$.createEl("input");el.type="range";el.min=min;el.max=max;el.value=value;el.step=step;el.val=()=>parseFloat(el.value);return el};$.createSpan=content=>$.createEl("span",content);$.createVideo=src=>{let el=$.createEl("video");el.crossOrigin="anonymous";el._load=()=>{el.width||=el.videoWidth;el.height||=el.videoHeight;el.defaultWidth=el.width*$._defaultImageScale;el.defaultHeight=el.height*$._defaultImageScale;el.ready=true};if(src){q._preloadCount++;el._loader=new Promise((resolve=>{el.addEventListener("loadeddata",(()=>{el._load();q._preloadCount--;resolve(el)}));el.src=src}));if($._disablePreload)return el._loader}return el};$.createCapture=function(type,flipped=true,cb){q._preloadCount++;let constraints=typeof type=="string"?{[type]:true}:type||{video:true,audio:true};if(constraints.video===true){constraints.video={width:3840,height:2160}}constraints.video.facingMode??="user";let vid=$.createVideo();vid.playsinline=vid.autoplay=true;if(flipped){vid.flipped=true;vid.style.transform="scale(-1, 1)"}vid.loadPixels=()=>{let g=$.createGraphics(vid.videoWidth,vid.videoHeight,{renderer:"c2d"});g.image(vid,0,0);g.loadPixels();vid.pixels=g.pixels;g.remove()};vid._loader=(async()=>{let stream;try{stream=await navigator.mediaDevices.getUserMedia(constraints)}catch(e){q._preloadCount--;throw e}vid.srcObject=stream;await new Promise((resolve=>vid.addEventListener("loadeddata",resolve)));vid._load();if(cb)cb(vid);q._preloadCount--;return vid})();if($._disablePreload)return vid._loader;return vid};$.findElement=selector=>document.querySelector(selector);$.findElements=selector=>document.querySelectorAll(selector)};Q5.modules.input=($,q)=>{if($._scope=="graphics")return;$.mouseX=0;$.mouseY=0;$.pmouseX=0;$.pmouseY=0;$.touches=[];$.mouseButton="";$.keyIsPressed=false;$.mouseIsPressed=false;$.key="";$.keyCode=0;$.UP_ARROW=38;$.DOWN_ARROW=40;$.LEFT_ARROW=37;$.RIGHT_ARROW=39;$.SHIFT=16;$.TAB=9;$.BACKSPACE=8;$.ENTER=$.RETURN=13;$.ALT=$.OPTION=18;$.CONTROL=17;$.DELETE=46;$.ESCAPE=27;$.ARROW="default";$.CROSS="crosshair";$.HAND="pointer";$.MOVE="move";$.TEXT="text";let keysHeld={};let mouseBtns=[Q5.LEFT,Q5.CENTER,Q5.RIGHT];let c=$.canvas;$._startAudio=()=>{if(!Q5.aud||Q5.aud?.state!="running")$.userStartAudio()};$._updateMouse=e=>{if(e.changedTouches)return;if(c){let rect=c.getBoundingClientRect();let sx=c.scrollWidth/$.width||1;let sy=c.scrollHeight/$.height||1;q.mouseX=(e.clientX-rect.left)/sx;q.mouseY=(e.clientY-rect.top)/sy;if(c.renderer=="webgpu"){q.mouseX-=c.hw;q.mouseY-=c.hh}}else{q.mouseX=e.clientX;q.mouseY=e.clientY}q.moveX=e.movementX;q.moveY=e.movementY};let pressedInCanvas=0;$._onmousedown=e=>{pressedInCanvas++;$._startAudio();$._updateMouse(e);q.mouseIsPressed=true;q.mouseButton=mouseBtns[e.button];$.mousePressed(e)};$._onmousemove=e=>{$._updateMouse(e);if($.mouseIsPressed)$.mouseDragged(e);else $.mouseMoved(e)};$._onmouseup=e=>{$._updateMouse(e);q.mouseIsPressed=false;$.mouseReleased(e)};$._onclick=e=>{$._updateMouse(e);q.mouseIsPressed=true;$.mouseClicked(e);q.mouseIsPressed=false};$._onwheel=e=>{$._updateMouse(e);e.delta=e.deltaY;if($.mouseWheel(e)==false||$._noScroll)e.preventDefault()};$.cursor=(name,x,y)=>{let pfx="";if(name.includes(".")){name=`url("${name}")`;pfx=", auto"}if(x!==undefined){name+=" "+x+" "+y}$.canvas.style.cursor=name+pfx};$.noCursor=()=>$.canvas.style.cursor="none";$.noScroll=()=>$._noScroll=true;if(window){$.lockMouse=document.body?.requestPointerLock;$.unlockMouse=document.exitPointerLock}$._onkeydown=e=>{if(e.repeat)return;$._startAudio();q.keyIsPressed=true;q.key=e.key;q.keyCode=e.keyCode;keysHeld[$.keyCode]=keysHeld[$.key.toLowerCase()]=true;$.keyPressed(e);if(e.key.length==1)$.keyTyped(e)};$._onkeyup=e=>{q.keyIsPressed=false;q.key=e.key;q.keyCode=e.keyCode;keysHeld[$.keyCode]=keysHeld[$.key.toLowerCase()]=false;$.keyReleased(e)};$.keyIsDown=v=>!!keysHeld[typeof v=="string"?v.toLowerCase():v];function getTouchInfo(touch){const rect=$.canvas.getBoundingClientRect();const sx=$.canvas.scrollWidth/$.width||1;const sy=$.canvas.scrollHeight/$.height||1;return{x:(touch.clientX-rect.left)/sx,y:(touch.clientY-rect.top)/sy,id:touch.identifier}}$._ontouchstart=e=>{$._startAudio();q.touches=[...e.touches].map(getTouchInfo);if(!$._isTouchAware){q.mouseX=$.touches[0].x;q.mouseY=$.touches[0].y;q.mouseIsPressed=true;q.mouseButton=$.LEFT;$.mousePressed(e)}$.touchStarted(e)};$._ontouchmove=e=>{q.touches=[...e.touches].map(getTouchInfo);if(!$._isTouchAware){q.mouseX=$.touches[0].x;q.mouseY=$.touches[0].y;if(!$.mouseDragged(e))e.preventDefault()}if(!$.touchMoved(e))e.preventDefault()};$._ontouchend=e=>{q.touches=[...e.touches].map(getTouchInfo);if(!$._isTouchAware&&!$.touches.length){q.mouseIsPressed=false;if(!$.mouseReleased(e))e.preventDefault()}if(!$.touchEnded(e))e.preventDefault()};if(c){let l=c.addEventListener.bind(c);l("mousedown",(e=>$._onmousedown(e)));l("wheel",(e=>$._onwheel(e)));l("click",(e=>$._onclick(e)));l("touchstart",(e=>$._ontouchstart(e)));l("touchmove",(e=>$._ontouchmove(e)));l("touchend",(e=>$._ontouchend(e)));l("touchcancel",(e=>$._ontouchend(e)))}if(window){let l=window.addEventListener;l("keydown",(e=>$._onkeydown(e)),false);l("keyup",(e=>$._onkeyup(e)),false);if(!c){l("mousedown",(e=>$._onmousedown(e)));l("wheel",(e=>$._onwheel(e)));l("click",(e=>$._onclick(e)))}l("mousemove",(e=>$._onmousemove(e)),false);l("mouseup",(e=>{if(pressedInCanvas>0){pressedInCanvas--;$._onmouseup(e)}}))}};Q5.modules.math=($,q)=>{$.RADIANS=0;$.DEGREES=1;$.PI=Math.PI;$.HALF_PI=Math.PI/2;$.QUARTER_PI=Math.PI/4;$.TWO_PI=$.TAU=Math.PI*2;$.abs=Math.abs;$.ceil=Math.ceil;$.exp=Math.exp;$.floor=$.int=Math.floor;$.loge=Math.log;$.mag=Math.hypot;$.max=Math.max;$.min=Math.min;$.pow=Math.pow;$.sqrt=Math.sqrt;$.SHR3=1;$.LCG=2;$.round=(x,d=0)=>{let p=10**d;return Math.round(x*p)/p};let angleMode=$._angleMode=0;$.angleMode=mode=>{angleMode=$._angleMode=mode==0||mode=="radians"?0:1;return!angleMode?"radians":"degrees"};let DEGTORAD=$._DEGTORAD=Math.PI/180;let RADTODEG=$._RADTODEG=180/Math.PI;$.degrees=x=>x*$._RADTODEG;$.radians=x=>x*$._DEGTORAD;$.map=Q5.prototype.map=(value,istart,istop,ostart,ostop,clamp)=>{let val=ostart+(ostop-ostart)*((value-istart)*1/(istop-istart));if(!clamp){return val}if(ostart<ostop){return Math.min(Math.max(val,ostart),ostop)}else{return Math.min(Math.max(val,ostop),ostart)}};$.dist=function(){let a=arguments;if(a.length==2)return Math.hypot(a[0].x-a[1].x,a[0].y-a[1].y);if(a.length==4)return Math.hypot(a[0]-a[2],a[1]-a[3]);return Math.hypot(a[0]-a[3],a[1]-a[4],a[2]-a[5])};$.lerp=(a,b,t)=>a*(1-t)+b*t;$.constrain=(x,lo,hi)=>Math.min(Math.max(x,lo),hi);$.norm=(value,start,stop)=>$.map(value,start,stop,0,1);$.sq=x=>x*x;$.fract=x=>x-Math.floor(x);$.sin=a=>Math.sin(!angleMode?a:a*DEGTORAD);$.cos=a=>Math.cos(!angleMode?a:a*DEGTORAD);$.tan=a=>Math.tan(!angleMode?a:a*DEGTORAD);$.asin=x=>{let a=Math.asin(x);return!angleMode?a:a*RADTODEG};$.acos=x=>{let a=Math.acos(x);return!angleMode?a:a*RADTODEG};$.atan=x=>{let a=Math.atan(x);return!angleMode?a:a*RADTODEG};$.atan2=(y,x)=>{let a=Math.atan2(y,x);return!angleMode?a:a*RADTODEG};function lcg(){const m=4294967296;const a=1664525;const c=1013904223;let seed,z;return{setSeed(val){z=seed=(val==null?Math.random()*m:val)>>>0},getSeed(){return seed},rand(){z=(a*z+c)%m;return z/m}}}function shr3(){let jsr,seed;let m=4294967295;return{setSeed(val){jsr=seed=(val==null?Math.random()*m:val)>>>0},getSeed(){return seed},rand(){jsr^=jsr<<17;jsr^=jsr>>13;jsr^=jsr<<5;return(jsr>>>0)/m}}}let rng1=shr3();rng1.setSeed();$.randomSeed=seed=>rng1.setSeed(seed);$.random=(a,b)=>{if(a===undefined)return rng1.rand();if(typeof a=="number"){if(b!==undefined){return rng1.rand()*(b-a)+a}else{return rng1.rand()*a}}else{return a[Math.trunc(a.length*rng1.rand())]}};if($._renderer=="c2d"&&!$._webgpuFallback){$.randomX=(v=0)=>$.random(-v,$.canvas.w+v);$.randomY=(v=0)=>$.random(-v,$.canvas.h+v)}else{$.randomX=(v=0)=>$.random(-$.canvas.hw-v,$.canvas.hw+v);$.randomY=(v=0)=>$.random(-$.canvas.hh-v,$.canvas.hh+v)}$.randomGenerator=method=>{if(method==$.LCG)rng1=lcg();else if(method==$.SHR3)rng1=shr3();rng1.setSeed()};var ziggurat=new function(){var iz;var jz;var kn=new Array(128);var ke=new Array(256);var hz;var wn=new Array(128);var fn=new Array(128);var we=new Array(256);var fe=new Array(256);var SHR3=()=>rng1.rand()*4294967296-2147483648;var UNI=()=>.5+(SHR3()<<0)*2.328306e-10;var RNOR=()=>{hz=SHR3();iz=hz&127;return Math.abs(hz)<kn[iz]?hz*wn[iz]:nfix()};var REXP=()=>{jz=SHR3()>>>0;iz=jz&255;return jz<kn[iz]?jz*we[iz]:efix()};var nfix=()=>{var r=3.44262;var x,y;var u1,u2;for(;;){x=hz*wn[iz];if(iz==0){do{u1=UNI();u2=UNI();x=-Math.log(u1)*.2904764;y=-Math.log(u2)}while(y+y<x*x);return hz>0?r+x:-r-x}if(fn[iz]+UNI()*(fn[iz-1]-fn[iz])<Math.exp(-.5*x*x)){return x}hz=SHR3();iz=hz&127;if(Math.abs(hz)<kn[iz]){return hz*wn[iz]}}};var efix=()=>{var x;for(;;){if(iz==0){return 7.69711-Math.log(UNI())}x=jz*we[iz];if(fe[iz]+UNI()*(fe[iz-1]-fe[iz])<Math.exp(-x)){return x}jz=SHR3();iz=jz&255;if(jz<ke[iz]){return jz*we[iz]}}};var zigset=()=>{var m1=2147483648;var m2=4294967296;var dn=3.442619855899;var tn=dn;var vn=.00991256303526217;var q;var de=7.697117470131487;var te=de;var ve=.003949659822581572;var i;q=vn/Math.exp(-.5*dn*dn);kn[0]=Math.floor(dn/q*m1);kn[1]=0;wn[0]=q/m1;wn[127]=dn/m1;fn[0]=1;fn[127]=Math.exp(-.5*dn*dn);for(i=126;i>=1;i--){dn=Math.sqrt(-2*Math.log(vn/dn+Math.exp(-.5*dn*dn)));kn[i+1]=Math.floor(dn/tn*m1);tn=dn;fn[i]=Math.exp(-.5*dn*dn);wn[i]=dn/m1}q=ve/Math.exp(-de);ke[0]=Math.floor(de/q*m2);ke[1]=0;we[0]=q/m2;we[255]=de/m2;fe[0]=1;fe[255]=Math.exp(-de);for(i=254;i>=1;i--){de=-Math.log(ve/de+Math.exp(-de));ke[i+1]=Math.floor(de/te*m2);te=de;fe[i]=Math.exp(-de);we[i]=de/m2}};this.SHR3=SHR3;this.UNI=UNI;this.RNOR=RNOR;this.REXP=REXP;this.zigset=zigset};ziggurat.hasInit=false;$.randomGaussian=(mean,std)=>{if(!ziggurat.hasInit){ziggurat.zigset();ziggurat.hasInit=true}return ziggurat.RNOR()*std+mean};$.randomExponential=()=>{if(!ziggurat.hasInit){ziggurat.zigset();ziggurat.hasInit=true}return ziggurat.REXP()};$.PERLIN="perlin";$.SIMPLEX="simplex";$.BLOCKY="blocky";$.NoiseGenerator=Q5.PerlinNoise;let _noise;$.noiseMode=mode=>{q.NoiseGenerator=Q5[mode[0].toUpperCase()+mode.slice(1)+"Noise"];_noise=null};$.noiseSeed=seed=>{_noise=new $.NoiseGenerator(seed)};$.noise=(x=0,y=0,z=0)=>{_noise??=new $.NoiseGenerator;return _noise.noise(x,y,z)};$.noiseDetail=(lod,falloff)=>{_noise??=new $.NoiseGenerator;if(lod>0)_noise.octaves=lod;if(falloff>0)_noise.falloff=falloff}};Q5.NoiseGenerator=class{};Q5.PerlinNoise=class extends Q5.NoiseGenerator{constructor(seed){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;if(seed==undefined){this.p=Array.from({length:256},(()=>Math.floor(Math.random()*256)))}else{this.p=this.seedPermutation(seed)}this.p=this.p.concat(this.p)}seedPermutation(seed){let p=[];for(let i=0;i<256;i++){p[i]=i}let n,q;for(let i=255;i>0;i--){seed=seed*16807%2147483647;n=seed%(i+1);q=p[i];p[i]=p[n];p[n]=q}return p}dot(g,x,y,z){return g[0]*x+g[1]*y+g[2]*z}mix(a,b,t){return(1-t)*a+t*b}fade(t){return t*t*t*(t*(t*6-15)+10)}noise(x,y,z){let t=this;let total=0;let freq=1;let amp=1;let maxAmp=0;for(let i=0;i<t.octaves;i++){const X=Math.floor(x*freq)&255;const Y=Math.floor(y*freq)&255;const Z=Math.floor(z*freq)&255;const xf=x*freq-Math.floor(x*freq);const yf=y*freq-Math.floor(y*freq);const zf=z*freq-Math.floor(z*freq);const u=t.fade(xf);const v=t.fade(yf);const w=t.fade(zf);const A=t.p[X]+Y;const AA=t.p[A]+Z;const AB=t.p[A+1]+Z;const B=t.p[X+1]+Y;const BA=t.p[B]+Z;const BB=t.p[B+1]+Z;const lerp1=t.mix(t.dot(t.grad3[t.p[AA]%12],xf,yf,zf),t.dot(t.grad3[t.p[BA]%12],xf-1,yf,zf),u);const lerp2=t.mix(t.dot(t.grad3[t.p[AB]%12],xf,yf-1,zf),t.dot(t.grad3[t.p[BB]%12],xf-1,yf-1,zf),u);const lerp3=t.mix(t.dot(t.grad3[t.p[AA+1]%12],xf,yf,zf-1),t.dot(t.grad3[t.p[BA+1]%12],xf-1,yf,zf-1),u);const lerp4=t.mix(t.dot(t.grad3[t.p[AB+1]%12],xf,yf-1,zf-1),t.dot(t.grad3[t.p[BB+1]%12],xf-1,yf-1,zf-1),u);const mix1=t.mix(lerp1,lerp2,v);const mix2=t.mix(lerp3,lerp4,v);total+=t.mix(mix1,mix2,w)*amp;maxAmp+=amp;amp*=t.falloff;freq*=2}return(total/maxAmp+1)/2}};Q5.modules.record=($,q)=>{let rec,btn0,btn1,timer,formatSelect,bitrateInput,audioToggle;$.recording=false;function initRecorder(opt={}){document.head.insertAdjacentHTML("beforeend",`<style>\n.rec {\n\tdisplay: flex;\n\tz-index: 1000;\n\tgap: 6px;\n\tbackground: #1a1b1d;\n\tpadding: 6px 8px;\n\tborder-radius: 21px;\n\tbox-shadow: #0000001a 0px 4px 12px;\n\tborder: 2px solid transparent; \n\topacity: 0.6;\n\ttransition: all 0.3s;\n\twidth: 134px;\n\toverflow: hidden;\n}\n\n.rec:hover {\n\twidth: unset;\n\topacity: 0.96;\n}\n\n.rec.recording { border-color: #cc3e44; }\n\n.rec button,\n.rec select { cursor: pointer; }\n\n.rec button,\n.rec select,\n.rec input,\n.rec span {\n\tfont-family: sans-serif;\n\tfont-size: 14px;\n\tpadding: 2px 10px;\n\tborder-radius: 18px;\n\toutline: none;\n\tbackground: #232529;\n\tcolor: #d4dae6;\n\tbox-shadow: #0000001a 0px 4px 12px;\n\tborder: 1px solid #46494e;\n\tvertical-align: middle;\n\tline-height: 18px;\n\ttransition: all 0.3s;\n}\n\n.rec .audio-toggle {\n\tfont-size: 16px;\n\tpadding: 2px 10px;\n}\n\n.rec .bitrate input {\n\tborder-radius: 18px 0 0 18px;\n\tborder-right: 0;\n\twidth: 40px;\n\tpadding: 2px 5px 2px 10px;\n\ttext-align: right;\n}\n\n.rec .bitrate span {\n\tborder-radius: 0 18px 18px 0;\n\tborder-left: 0;\n\tpadding: 2px 10px 2px 5px;\n\tbackground: #333;\n}\n\n.rec .record-button { \n\tcolor: #cc3e44;\n\tfont-size: 18px;\n}\n\n.rec select:hover,\n.rec button:hover { background: #32343b; }\n\n.rec button:disabled {\n\topacity: 0.5;\n\tcolor: #969ba5;\n\tcursor: not-allowed;\n}\n</style>`);rec=$.createEl("div");rec.className="rec";rec.innerHTML=`\n<button class="record-button"></button>\n<span class="record-timer"></span>\n<button></button>\n`;[btn0,timer,btn1]=rec.children;rec.x=rec.y=8;rec.resetTimer=()=>rec.time={hours:0,minutes:0,seconds:0,frames:0};rec.resetTimer();let f="video/mp4; codecs=";rec.formats={"H.264":f+'"avc1.42E01E"',VP9:f+"vp9"};let highProfile=f+'"avc1.640034"';let pixelCount=$.canvas.width*$.canvas.height;if(pixelCount>32e5&&MediaRecorder.isTypeSupported(highProfile)){rec.formats["H.264"]=highProfile}Object.assign(rec.formats,opt.formats);formatSelect=$.createSelect("format");for(const name in rec.formats){formatSelect.option(name,rec.formats[name])}formatSelect.title="Video Format";rec.append(formatSelect);let div=$.createEl("div");div.className="bitrate";div.style.display="flex";rec.append(div);bitrateInput=$.createInput();let span=document.createElement("span");span.textContent="mbps";bitrateInput.title=span.title="Video Bitrate";div.append(bitrateInput);div.append(span);audioToggle=$.createEl("button");audioToggle.className="audio-toggle active";audioToggle.textContent="🔊";audioToggle.title="Toggle Audio Recording";rec.append(audioToggle);rec.captureAudio=true;audioToggle.addEventListener("click",(()=>{rec.captureAudio=!rec.captureAudio;audioToggle.textContent=rec.captureAudio?"🔊":"🔇";audioToggle.classList.toggle("active",rec.captureAudio)}));rec.encoderSettings={};function changeFormat(){rec.encoderSettings.mimeType=formatSelect.value}function changeBitrate(){rec.encoderSettings.videoBitsPerSecond=1e6*bitrateInput.value}formatSelect.addEventListener("change",changeFormat);bitrateInput.addEventListener("change",changeBitrate);Object.defineProperty(rec,"bitrate",{get:()=>bitrateInput.value,set:v=>{bitrateInput.value=v;changeBitrate()}});Object.defineProperty(rec,"format",{get:()=>formatSelect.selected,set:v=>{v=v.toUpperCase();if(rec.formats[v]){formatSelect.selected=v;changeFormat()}}});rec.format="H.264";let h=$.canvas.height;rec.bitrate=h>=4320?96:h>=2160?64:h>=1440?48:h>=1080?32:h>=720?26:16;btn0.addEventListener("click",(()=>{if(!$.recording)start();else if(!rec.paused)$.pauseRecording();else resumeRecording()}));btn1.addEventListener("click",(()=>{if(rec.paused)$.saveRecording();else $.deleteRecording()}));resetUI();$.registerMethod("post",updateTimer)}function start(){if($.recording)return;$.userStartAudio();if(!rec.stream){rec.frameRate??=$.getTargetFrameRate();let canvasStream=$.canvas.captureStream(rec.frameRate);rec.videoTrack=canvasStream.getVideoTracks()[0];if(rec.captureAudio&&$.getAudioContext){let aud=$.getAudioContext();let dest=aud.createMediaStreamDestination();if(aud.destination.input)aud.destination.input.connect(dest);else Q5.soundOut.connect(dest);rec.audioTrack=dest.stream.getAudioTracks()[0];rec.stream=new MediaStream([rec.videoTrack,rec.audioTrack])}else rec.stream=canvasStream}rec.mediaRecorder=new MediaRecorder(rec.stream,rec.encoderSettings);rec.chunks=[];rec.mediaRecorder.addEventListener("dataavailable",(e=>{if(e.data.size>0)rec.chunks.push(e.data)}));rec.mediaRecorder.start();q.recording=true;rec.paused=false;rec.classList.add("recording");rec.resetTimer();resetUI(true)}function resumeRecording(){if(!$.recording||!rec.paused)return;rec.mediaRecorder.resume();rec.paused=false;resetUI(true)}function stop(){if(!$.recording)return;rec.resetTimer();rec.mediaRecorder.stop();q.recording=false;rec.paused=false;rec.classList.remove("recording")}function resetUI(r){btn0.textContent=r?"⏸":"⏺";btn0.title=(r?"Pause":"Start")+" Recording";btn1.textContent=r?"🗑️":"💾";btn1.title=(r?"Delete":"Save")+" Recording";btn1.disabled=!r}function updateTimer(){if($.recording&&!rec.paused){rec.time.frames++;let fr=$.getTargetFrameRate();if(rec.time.frames>=fr){rec.time.seconds+=Math.floor(rec.time.frames/fr);rec.time.frames%=fr;if(rec.time.seconds>=60){rec.time.minutes+=Math.floor(rec.time.seconds/60);rec.time.seconds%=60;if(rec.time.minutes>=60){rec.time.hours+=Math.floor(rec.time.minutes/60);rec.time.minutes%=60}}}}timer.textContent=formatTime()}function formatTime(){let{hours:hours,minutes:minutes,seconds:seconds,frames:frames}=rec.time;return`${String(hours).padStart(2,"0")}:${String(minutes).padStart(2,"0")}:${String(seconds).padStart(2,"0")}:${String(frames).padStart(2,"0")}`}$.createRecorder=opt=>{if(!rec)initRecorder(opt);return rec};$.record=opt=>{if(!rec){initRecorder(opt);rec.hide()}if(!$.recording)start();else if(rec.paused)resumeRecording()};$.pauseRecording=()=>{if(!$.recording||rec.paused)return;rec.mediaRecorder.pause();rec.paused=true;resetUI();btn0.title="Resume Recording";btn1.disabled=false};$.deleteRecording=()=>{stop();resetUI();q.recording=false};$.saveRecording=async fileName=>{if(!$.recording)return;await new Promise((resolve=>{rec.mediaRecorder.onstop=resolve;stop()}));let type=rec.encoderSettings.mimeType,extension=type.slice(6,type.indexOf(";")),dataUrl=URL.createObjectURL(new Blob(rec.chunks,{type:type})),iframe=document.createElement("iframe"),a=document.createElement("a");iframe.style.display="none";iframe.name="download_"+Date.now();document.body.append(iframe);a.target=iframe.name;a.href=dataUrl;fileName??=document.title+" "+(new Date).toLocaleString(undefined,{hour12:false}).replace(","," at").replaceAll("/","-").replaceAll(":","_");a.download=`${fileName}.${extension}`;await new Promise((resolve=>{iframe.onload=()=>{document.body.removeChild(iframe);resolve()};a.click()}));setTimeout((()=>URL.revokeObjectURL(dataUrl)),1e3);resetUI();q.recording=false}};Q5.modules.sound=($,q)=>{$.Sound=Q5.Sound;let sounds=[];$.loadSound=(url,cb)=>{q._preloadCount++;let s=new Q5.Sound;sounds.push(s);s._loader=(async()=>{let err;try{await s.load(url)}catch(e){err=e}q._preloadCount--;delete s._loader;if(err)throw err;if(cb)cb(s);return s})();if($._disablePreload)return s._loader;return s};$.loadAudio=(url,cb)=>{q._preloadCount++;let a=new Audio(url);a.crossOrigin="Anonymous";a.addEventListener("canplaythrough",(()=>{if(!a.loaded){q._preloadCount--;a.loaded=true;if(cb)cb(a)}}));let preloadSkip=()=>{a._preloadSkip=true;q._preloadCount--};a.addEventListener("suspend",preloadSkip);a.addEventListener("error",(e=>{preloadSkip();throw e}));return a};$.getAudioContext=()=>Q5.aud;$.userStartAudio=()=>{if(window.AudioContext){if(Q5._offlineAudio){Q5._offlineAudio=false;Q5.aud=new window.AudioContext;Q5.soundOut=Q5.aud.createGain();Q5.soundOut.connect(Q5.aud.destination);for(let s of sounds)s.init()}return Q5.aud.resume()}}};if(window.OfflineAudioContext){Q5.aud=new window.OfflineAudioContext(2,1,44100);Q5._offlineAudio=true;Q5.soundOut=Q5.aud.createGain();Q5.soundOut.connect(Q5.aud.destination)}Q5.Sound=class{constructor(){this.sources=new Set;this.loaded=this.paused=false}async load(url){this.url=url;let res=await fetch(url);this.buffer=await res.arrayBuffer();this.buffer=await Q5.aud.decodeAudioData(this.buffer)}init(){this.gainNode=Q5.aud.createGain();this.pannerNode=Q5.aud.createStereoPanner();this.gainNode.connect(this.pannerNode);this.pannerNode.connect(Q5.soundOut);this.loaded=true;if(this._volume)this.volume=this._volume;if(this._pan)this.pan=this._pan}_newSource(offset,duration){let source=Q5.aud.createBufferSource();source.buffer=this.buffer;source.connect(this.gainNode);source.loop=this._loop;source._startedAt=Q5.aud.currentTime;source._offset=offset;source._duration=duration;source.start(0,source._offset,source._duration);this.sources.add(source);source.onended=()=>{if(!this.paused){this.ended=true;this.sources.delete(source)}}}play(time=0,duration){if(!this.loaded)return;if(!this.paused){this._newSource(time,duration)}else{let timings=[];for(let source of this.sources){timings.push(source._offset,source._duration);this.sources.delete(source)}for(let i=0;i<timings.length;i+=2){this._newSource(timings[i],timings[i+1])}}this.paused=this.ended=false}pause(){if(!this.isPlaying())return;for(let source of this.sources){source.stop();let timePassed=Q5.aud.currentTime-source._startedAt;source._offset+=timePassed;if(source._duration)source._duration-=timePassed}this.paused=true}stop(){for(let source of this.sources){source.stop();this.sources.delete(source)}this.paused=false;this.ended=true}get volume(){return this._volume}set volume(level){if(this.loaded)this.gainNode.gain.value=level;this._volume=level}get pan(){return this._pan}set pan(value){if(this.loaded)this.pannerNode.pan.value=value;this._pan=value}get loop(){return this._loop}set loop(value){this.sources.forEach((source=>source.loop=value));this._loop=value}get playing(){return!this.paused&&this.sources.size>0}setVolume(level){this.volume=level}setPan(value){this.pan=value}setLoop(loop){this.loop=loop}isLoaded(){return this.loaded}isPlaying(){return this.playing}isPaused(){return this.paused}isLooping(){return this._loop}};Q5.modules.util=($,q)=>{$._loadFile=(url,cb,type)=>{q._preloadCount++;let ret={};ret._loader=new Promise(((resolve,reject)=>{fetch(url).then((res=>{if(!res.ok){reject("error loading file");return null}if(type=="json")return res.json();return res.text()})).then((f=>{if(type=="csv")f=$.CSV.parse(f);if(typeof f=="string")ret.text=f;else Object.assign(ret,f);delete ret._loader;if(cb)cb(f);q._preloadCount--;resolve(f)}))}));return ret};$.loadText=(url,cb)=>$._loadFile(url,cb,"text");$.loadJSON=(url,cb)=>$._loadFile(url,cb,"json");$.loadCSV=(url,cb)=>$._loadFile(url,cb,"csv");const imgRegex=/(jpe?g|png|gif|webp|avif|svg)/,fontRegex=/(ttf|otf|woff2?|eot|json)/,audioRegex=/(wav|flac|mp3|ogg|m4a|aac|aiff|weba)/;$.load=function(...urls){if(Array.isArray(urls[0]))urls=urls[0];let loaders=[];for(let url of urls){let ext=url.split(".").pop().toLowerCase();let obj;if(ext=="json"&&!url.includes("-msdf.")){obj=$.loadJSON(url)}else if(ext=="csv"){obj=$.loadCSV(url)}else if(imgRegex.test(ext)){obj=$.loadImage(url)}else if(fontRegex.test(ext)){obj=$.loadFont(url)}else if(audioRegex.test(ext)){obj=$.loadSound(url)}else{obj=$.loadText(url)}loaders.push(obj._loader)}if(urls.length==1)return loaders[0];return Promise.all(loaders)};async function saveFile(data,name,ext){name=name||"untitled";ext=ext||"png";if(imgRegex.test(ext)){data=await $._saveCanvas(data,ext)}else{let type="text/plain";if(ext=="json"){if(typeof data!="string")data=JSON.stringify(data);type="text/json"}data=new Blob([data],{type:type});data=URL.createObjectURL(data)}let a=document.createElement("a");a.href=data;a.download=name+"."+ext;a.click();setTimeout((()=>URL.revokeObjectURL(a.href)),1e3)}$.save=(a,b,c)=>{if(!a||typeof a=="string"&&(!b||!c&&b.length<5)){c=b;b=a;a=$.canvas}if(c)saveFile(a,b,c);else if(b){let lastDot=b.lastIndexOf(".");saveFile(a,b.slice(0,lastDot),b.slice(lastDot+1))}else saveFile(a)};$.CSV={};$.CSV.parse=(csv,sep=",",lineSep="\n")=>{if(!csv.length)return[];let a=[],lns=csv.split(lineSep),headers=lns[0].split(sep).map((h=>h.replaceAll('"',"")));for(let i=1;i<lns.length;i++){let o={},ln=lns[i].split(sep);headers.forEach(((h,i)=>o[h]=JSON.parse(ln[i])));a.push(o)}return a};if($.canvas&&!Q5._createServerCanvas){$.canvas.save=$.saveCanvas=$.save}if(typeof localStorage=="object"){$.storeItem=localStorage.setItem;$.getItem=localStorage.getItem;$.removeItem=localStorage.removeItem;$.clearStorage=localStorage.clear}$.year=()=>(new Date).getFullYear();$.day=()=>(new Date).getDay();$.hour=()=>(new Date).getHours();$.minute=()=>(new Date).getMinutes();$.second=()=>(new Date).getSeconds();$.nf=(n,l,r)=>{let neg=n<0;n=Math.abs(n);let parts=n.toFixed(r).split(".");parts[0]=parts[0].padStart(l,"0");let s=parts.join(".");if(neg)s="-"+s;return s}};Q5.modules.vector=$=>{$.Vector=Q5.Vector;$.createVector=(x,y,z)=>new $.Vector(x,y,z,$)};Q5.Vector=class{constructor(x,y,z,$){this.x=x||0;this.y=y||0;this.z=z||0;this._$=$||window;this._cn=null;this._cnsq=null}set(x,y,z){this.x=x?.x||x||0;this.y=x?.y||y||0;this.z=x?.z||z||0;return this}copy(){return new Q5.Vector(this.x,this.y,this.z)}_arg2v(x,y,z){if(x?.x!==undefined)return x;if(y!==undefined){return{x:x,y:y,z:z||0}}return{x:x,y:x,z:x}}_calcNorm(){this._cnsq=this.x*this.x+this.y*this.y+this.z*this.z;this._cn=Math.sqrt(this._cnsq)}add(){let u=this._arg2v(...arguments);this.x+=u.x;this.y+=u.y;this.z+=u.z;return this}rem(){let u=this._arg2v(...arguments);this.x%=u.x;this.y%=u.y;this.z%=u.z;return this}sub(){let u=this._arg2v(...arguments);this.x-=u.x;this.y-=u.y;this.z-=u.z;return this}mult(){let u=this._arg2v(...arguments);this.x*=u.x;this.y*=u.y;this.z*=u.z;return this}div(){let u=this._arg2v(...arguments);if(u.x)this.x/=u.x;else this.x=0;if(u.y)this.y/=u.y;else this.y=0;if(u.z)this.z/=u.z;else this.z=0;return this}mag(){this._calcNorm();return this._cn}magSq(){this._calcNorm();return this._cnsq}dot(){let u=this._arg2v(...arguments);return this.x*u.x+this.y*u.y+this.z*u.z}dist(){let u=this._arg2v(...arguments);let x=this.x-u.x;let y=this.y-u.y;let z=this.z-u.z;return Math.sqrt(x*x+y*y+z*z)}cross(){let u=this._arg2v(...arguments);let x=this.y*u.z-this.z*u.y;let y=this.z*u.x-this.x*u.z;let z=this.x*u.y-this.y*u.x;this.x=x;this.y=y;this.z=z;return this}normalize(){this._calcNorm();let n=this._cn;if(n!=0){this.x/=n;this.y/=n;this.z/=n}this._cn=1;this._cnsq=1;return this}limit(m){this._calcNorm();let n=this._cn;if(n>m){let t=m/n;this.x*=t;this.y*=t;this.z*=t;this._cn=m;this._cnsq=m*m}return this}setMag(m){this._calcNorm();let n=this._cn;let t=m/n;this.x*=t;this.y*=t;this.z*=t;this._cn=m;this._cnsq=m*m;return this}heading(){return this._$.atan2(this.y,this.x)}setHeading(ang){let mag=this.mag();this.x=mag*this._$.cos(ang);this.y=mag*this._$.sin(ang);return this}rotate(ang){let costh=this._$.cos(ang);let sinth=this._$.sin(ang);let vx=this.x*costh-this.y*sinth;let vy=this.x*sinth+this.y*costh;this.x=vx;this.y=vy;return this}angleBetween(){let u=this._arg2v(...arguments);let o=Q5.Vector.cross(this,u);let ang=this._$.atan2(o.mag(),this.dot(u));return ang*Math.sign(o.z||1)}lerp(){let args=[...arguments];let amt=args.at(-1);if(amt==0)return this;let u=this._arg2v(...args.slice(0,-1));this.x+=(u.x-this.x)*amt;this.y+=(u.y-this.y)*amt;this.z+=(u.z-this.z)*amt;return this}slerp(){let args=[...arguments];let amt=args.at(-1);if(amt==0)return this;let u=this._arg2v(...args.slice(0,-1));if(amt==1)return this.set(u);let v0Mag=this.mag();let v1Mag=u.mag();if(v0Mag==0||v1Mag==0){return this.mult(1-amt).add(u.mult(amt))}let axis=Q5.Vector.cross(this,u);let axisMag=axis.mag();let theta=Math.atan2(axisMag,this.dot(u));if(axisMag>0){axis.div(axisMag)}else if(theta<this._$.HALF_PI){return this.mult(1-amt).add(u.mult(amt))}else{if(this.z==0&&u.z==0)axis.set(0,0,1);else if(this.x!=0)axis.set(this.y,-this.x,0).normalize();else axis.set(1,0,0)}let ey=axis.cross(this);let lerpedMagFactor=1-amt+amt*v1Mag/v0Mag;let cosMultiplier=lerpedMagFactor*Math.cos(amt*theta);let sinMultiplier=lerpedMagFactor*Math.sin(amt*theta);this.x=this.x*cosMultiplier+ey.x*sinMultiplier;this.y=this.y*cosMultiplier+ey.y*sinMultiplier;this.z=this.z*cosMultiplier+ey.z*sinMultiplier;return this}reflect(n){n.normalize();return this.sub(n.mult(2*this.dot(n)))}array(){return[this.x,this.y,this.z]}equals(u,epsilon){epsilon??=Number.EPSILON||0;return Math.abs(u.x-this.x)<epsilon&&Math.abs(u.y-this.y)<epsilon&&Math.abs(u.z-this.z)<epsilon}fromAngle(th,l){if(l===undefined)l=1;this._cn=l;this._cnsq=l*l;this.x=l*this._$.cos(th);this.y=l*this._$.sin(th);this.z=0;return this}fromAngles(th,ph,l){if(l===undefined)l=1;this._cn=l;this._cnsq=l*l;const cosph=this._$.cos(ph);const sinph=this._$.sin(ph);const costh=this._$.cos(th);const sinth=this._$.sin(th);this.x=l*sinth*sinph;this.y=-l*costh;this.z=l*sinth*cosph;return this}random2D(){this._cn=this._cnsq=1;return this.fromAngle(Math.random()*Math.PI*2)}random3D(){this._cn=this._cnsq=1;return this.fromAngles(Math.random()*Math.PI*2,Math.random()*Math.PI*2)}toString(){return`[${this.x}, ${this.y}, ${this.z}]`}};Q5.Vector.add=(v,u)=>v.copy().add(u);Q5.Vector.cross=(v,u)=>v.copy().cross(u);Q5.Vector.dist=(v,u)=>Math.hypot(v.x-u.x,v.y-u.y,v.z-u.z);Q5.Vector.div=(v,u)=>v.copy().div(u);Q5.Vector.dot=(v,u)=>v.copy().dot(u);Q5.Vector.equals=(v,u,epsilon)=>v.equals(u,epsilon);Q5.Vector.lerp=(v,u,amt)=>v.copy().lerp(u,amt);Q5.Vector.slerp=(v,u,amt)=>v.copy().slerp(u,amt);Q5.Vector.limit=(v,m)=>v.copy().limit(m);Q5.Vector.heading=v=>this._$.atan2(v.y,v.x);Q5.Vector.magSq=v=>v.x*v.x+v.y*v.y+v.z*v.z;Q5.Vector.mag=v=>Math.sqrt(Q5.Vector.magSq(v));Q5.Vector.mult=(v,u)=>v.copy().mult(u);Q5.Vector.normalize=v=>v.copy().normalize();Q5.Vector.rem=(v,u)=>v.copy().rem(u);Q5.Vector.sub=(v,u)=>v.copy().sub(u);for(let k of["fromAngle","fromAngles","random2D","random3D"]){Q5.Vector[k]=(u,v,t)=>(new Q5.Vector)[k](u,v,t)}Q5.renderers.webgpu={};Q5.renderers.webgpu.canvas=($,q)=>{$._baseShaderCode=`\nstruct Q5 {\n\twidth: f32,\n\theight: f32,\n\thalfWidth: f32,\n\thalfHeight: f32,\n\tpixelDensity: f32,\n\tframeCount: f32,\n\ttime: f32,\n\tdeltaTime: f32,\n\tmouseX: f32,\n\tmouseY: f32,\n\tmouseIsPressed: f32,\n\tkeyCode: f32,\n\tkeyIsPressed: f32\n}`;let c=$.canvas;c.width=$.width=500;c.height=$.height=500;$._g=$.createGraphics(1,1,{renderer:"c2d"});if($.colorMode)$.colorMode("rgb",1);let encoder,pass,mainView,frameA,frameB,frameLayout,frameSampler,frameBindGroup,colorIndex=1,colorStackIndex=8;$._pipelineConfigs=[];$._pipelines=[];$._buffers=[];$._prevFramePL=0;$._framePL=0;let drawStack=$.drawStack=[];let colorStack=$.colorStack=new Float32Array(1e6);colorStack.set([0,0,0,1,1,1,1,1]);let mainLayout=Q5.device.createBindGroupLayout({label:"mainLayout",entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}}]});$.bindGroupLayouts=[mainLayout];let uniformBuffer=Q5.device.createBuffer({size:64,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let createMainView=()=>{let w=$.canvas.width,h=$.canvas.height,size=[w,h],format="bgra8unorm";mainView=Q5.device.createTexture({size:size,sampleCount:4,format:format,usage:GPUTextureUsage.RENDER_ATTACHMENT}).createView();let usage=GPUTextureUsage.COPY_SRC|GPUTextureUsage.COPY_DST|GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.RENDER_ATTACHMENT;$._frameA=frameA=Q5.device.createTexture({size:size,format:format,usage:usage});$._frameB=frameB=Q5.device.createTexture({size:size,format:format,usage:usage});$._frameShaderCode=$._baseShaderCode+`\nstruct VertexParams {\n\t@builtin(vertex_index) vertexIndex: u32\n}\nstruct FragParams {\n\t@builtin(position) position: vec4f,\n\t@location(0) texCoord: vec2f\n}\n\nconst ndc = array(vec2f(-1,-1), vec2f(1,-1), vec2f(-1,1), vec2f(1,1));\nconst quad = array(vec2f(0,1), vec2f(1,1), vec2f(0,0), vec2f(1,0));\n\n@group(0) @binding(0) var<uniform> q: Q5;\n@group(0) @binding(1) var samp: sampler;\n@group(0) @binding(2) var tex: texture_2d<f32>;\n\n@vertex\nfn vertexMain(v: VertexParams) -> FragParams {\n\tvar f: FragParams;\n\tf.position = vec4f(ndc[v.vertexIndex], 0.0, 1.0);\n\tf.texCoord = quad[v.vertexIndex];\n\treturn f;\n}\n\n@fragment\nfn fragMain(f: FragParams ) -> @location(0) vec4f {\n\treturn textureSample(tex, samp, f.texCoord);\n}`;let frameShader=Q5.device.createShaderModule({label:"frameShader",code:$._frameShaderCode});frameSampler=Q5.device.createSampler({magFilter:"linear",minFilter:"linear"});frameLayout=Q5.device.createBindGroupLayout({label:"frameLayout",entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,texture:{viewDimension:"2d",sampleType:"float"}}]});let framePipelineLayout=Q5.device.createPipelineLayout({bindGroupLayouts:[frameLayout]});$._pipelineConfigs[0]={layout:framePipelineLayout,vertex:{module:frameShader,entryPoint:"vertexMain"},fragment:{module:frameShader,entryPoint:"fragMain",targets:[{format:format}]},primitive:{topology:"triangle-strip"},multisample:{count:4}};$._pipelines[0]=Q5.device.createRenderPipeline($._pipelineConfigs[0])};$._createCanvas=(w,h,opt)=>{q.ctx=q.drawingContext=c.getContext("webgpu");opt.format??=navigator.gpu.getPreferredCanvasFormat();opt.device??=Q5.device;if(opt.alpha)opt.alphaMode="premultiplied";$.ctx.configure(opt);createMainView();return c};$._resizeCanvas=(w,h)=>{$._setCanvasSize(w,h);createMainView()};let addColor=(r,g,b,a=1)=>{if(typeof r=="string"||$._colorMode!="rgb"){r=$.color(r,g,b,a)}else if(b==undefined){a=g??1;g=b=r}if(r._q5Color){let c=r;if(c.r)({r:r,g:g,b:b,a:a}=c);else{a=c.a;if(c.c!=undefined)c=Q5.OKLCHtoRGB(c.l,c.c,c.h);else if(c.l!=undefined)c=Q5.HSLtoRGB(c.h,c.s,c.l);else c=Q5.HSLtoRGB(...Q5.HSBtoHSL(c.h,c.s,c.b));[r,g,b]=c}}let cs=colorStack,i=colorStackIndex;cs[i++]=r;cs[i++]=g;cs[i++]=b;cs[i++]=a;colorStackIndex=i;colorIndex++};$._stroke=0;$._fill=$._tint=$._globalAlpha=1;$._doFill=$._doStroke=true;$.fill=(r,g,b,a)=>{addColor(r,g,b,a);$._doFill=$._fillSet=true;$._fill=colorIndex};$.stroke=(r,g,b,a)=>{addColor(r,g,b,a);$._doStroke=$._strokeSet=true;$._stroke=colorIndex};$.tint=(r,g,b,a)=>{addColor(r,g,b,a);$._tint=colorIndex};$.opacity=a=>$._globalAlpha=a;$.noFill=()=>$._doFill=false;$.noStroke=()=>$._doStroke=false;$.noTint=()=>$._tint=1;$._strokeWeight=1;$._hsw=.5;$._scaledSW=1;$.strokeWeight=v=>{v=Math.abs(v);$._strokeWeight=v;$._scaledSW=v*$._scale;$._hsw=v/2};const MAX_TRANSFORMS=$._graphics?1e3:1e7,MATRIX_SIZE=16,transforms=new Float32Array(MAX_TRANSFORMS*MATRIX_SIZE);let matrix,matrices=[],matricesIndexStack=[];$._matrixDirty=false;matrices.push([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);transforms.set(matrices[0]);$.resetMatrix=()=>{matrix=matrices[0].slice();$._matrixIndex=0};$.resetMatrix();$.translate=(x,y,z)=>{if(!x&&!y&&!z)return;matrix[12]+=x;matrix[13]-=y;matrix[14]+=z||0;$._matrixDirty=true};$.rotate=a=>{if(!a)return;if($._angleMode)a*=$._DEGTORAD;let cosR=Math.cos(a),sinR=Math.sin(a),m=matrix,m0=m[0],m1=m[1],m4=m[4],m5=m[5];if(m0==1&&!m1&&!m4&&m5==1){m[0]=cosR;m[1]=-sinR;m[4]=sinR;m[5]=cosR}else{m[0]=m0*cosR+m1*sinR;m[1]=m1*cosR-m0*sinR;m[4]=m4*cosR+m5*sinR;m[5]=m5*cosR-m4*sinR}$._matrixDirty=true};$._scale=1;$.scale=(x=1,y,z=1)=>{y??=x;$._scale=Math.max(Math.abs(x),Math.abs(y));$._scaledSW=$._strokeWeight*$._scale;let m=matrix;m[0]*=x;m[1]*=x;m[2]*=x;m[3]*=x;m[4]*=y;m[5]*=y;m[6]*=y;m[7]*=y;m[8]*=z;m[9]*=z;m[10]*=z;m[11]*=z;$._matrixDirty=true};$.shearX=ang=>{if(!ang)return;if($._angleMode)ang*=$._DEGTORAD;let tanAng=Math.tan(ang),m=matrix,m0=m[0],m1=m[1],m4=m[4],m5=m[5];m[0]=m0+m4*tanAng;m[1]=m1+m5*tanAng;$._matrixDirty=true};$.shearY=ang=>{if(!ang)return;if($._angleMode)ang*=$._DEGTORAD;let tanAng=Math.tan(ang),m=matrix,m0=m[0],m1=m[1],m4=m[4],m5=m[5];m[4]=m4+m0*tanAng;m[5]=m5+m1*tanAng;$._matrixDirty=true};$.applyMatrix=(...args)=>{let m;if(args.length==1)m=args[0];else m=args;if(m.length==9){m=[m[0],m[1],0,m[2],m[3],m[4],0,m[5],0,0,1,0,m[6],m[7],0,m[8]]}else if(m.length!=16){throw new Error("Matrix must be a 3x3 or 4x4 array.")}matrix=m.slice();$._matrixDirty=true};$._saveMatrix=()=>{transforms.set(matrix,matrices.length*MATRIX_SIZE);$._matrixIndex=matrices.length;matrices.push(matrix.slice());$._matrixDirty=false};$.pushMatrix=()=>{if($._matrixDirty)$._saveMatrix();matricesIndexStack.push($._matrixIndex)};$.popMatrix=()=>{if(!matricesIndexStack.length){return console.warn("Matrix index stack is empty!")}let idx=matricesIndexStack.pop();matrix=matrices[idx].slice();$._matrixIndex=idx;$._matrixDirty=false};let _pushStyles=$.pushStyles;$.pushStyles=()=>{_pushStyles();$.strokeWeight($._strokeWeight)};$.push=()=>{$.pushMatrix();$.pushStyles()};$.pop=()=>{$.popMatrix();$.popStyles()};$._calcBox=(x,y,w,h,mode)=>{let l,r,t,b;if(!mode||mode=="corner"){l=x;r=x+w;t=-y;b=-(y+h)}else if(mode=="center"){let hw=w/2,hh=h/2;l=x-hw;r=x+hw;t=-(y-hh);b=-(y+hh)}else{l=x;r=w;t=-y;b=-h}return[l,r,t,b]};let blendFactors=["zero","one","src-alpha","one-minus-src-alpha","dst","dst-alpha","one-minus-dst-alpha","one-minus-src"];let blendOps=["add","subtract","reverse-subtract","min","max"];const blendModes={normal:[2,3,0,2,3,0],additive:[1,1,0,1,1,0]};$.blendConfigs={};for(const[name,mode]of Object.entries(blendModes)){$.blendConfigs[name]={color:{srcFactor:blendFactors[mode[0]],dstFactor:blendFactors[mode[1]],operation:blendOps[mode[2]]},alpha:{srcFactor:blendFactors[mode[3]],dstFactor:blendFactors[mode[4]],operation:blendOps[mode[5]]}}}$._blendMode="normal";$.blendMode=mode=>{if(mode==$._blendMode)return;if(mode=="source-over")mode="normal";if(mode=="lighter")mode="additive";mode=mode.toLowerCase().replace(/[ -]/g,"_");$._blendMode=mode;for(let i=0;i<$._pipelines.length;i++){$._pipelineConfigs[i].fragment.targets[0].blend=$.blendConfigs[mode];$._pipelines[i]=Q5.device.createRenderPipeline($._pipelineConfigs[i])}};let shouldClear;$.clear=()=>{shouldClear=true};$.background=(r,g,b,a)=>{$.push();$.resetMatrix();if(r.canvas){let img=r;$._imageMode="corner";$.image(img,-c.hw,-c.hh,c.w,c.h)}else{$._rectMode="corner";$.fill(r,g,b,a);$._doStroke=false;$.rect(-c.hw,-c.hh,c.w,c.h)}$.pop()};$._beginRender=()=>{const temp=frameA;frameA=frameB;frameB=temp;encoder=Q5.device.createCommandEncoder();$._pass=pass=encoder.beginRenderPass({label:"q5-webgpu",colorAttachments:[{view:mainView,resolveTarget:frameA.createView(),loadOp:"clear",storeOp:"store",clearValue:[0,0,0,0]}]});frameBindGroup=Q5.device.createBindGroup({layout:frameLayout,entries:[{binding:0,resource:{buffer:uniformBuffer}},{binding:1,resource:frameSampler},{binding:2,resource:frameB.createView()}]});if(!shouldClear){pass.setPipeline($._pipelines[$._prevFramePL]);pass.setBindGroup(0,frameBindGroup);pass.draw(4)}shouldClear=false};$._render=()=>{let transformBuffer=Q5.device.createBuffer({size:matrices.length*MATRIX_SIZE*4,usage:GPUBufferUsage.STORAGE,mappedAtCreation:true});new Float32Array(transformBuffer.getMappedRange()).set(transforms.slice(0,matrices.length*MATRIX_SIZE));transformBuffer.unmap();$._buffers.push(transformBuffer);let colorsBuffer=Q5.device.createBuffer({size:colorStackIndex*4,usage:GPUBufferUsage.STORAGE,mappedAtCreation:true});new Float32Array(colorsBuffer.getMappedRange()).set(colorStack.slice(0,colorStackIndex));colorsBuffer.unmap();$._buffers.push(colorsBuffer);$._uniforms=[$.width,$.height,$.halfWidth,$.halfHeight,$._pixelDensity,$.frameCount,performance.now(),$.deltaTime,$.mouseX,$.mouseY,$.mouseIsPressed?1:0,$.keyCode,$.keyIsPressed?1:0];Q5.device.queue.writeBuffer(uniformBuffer,0,new Float32Array($._uniforms));let mainBindGroup=Q5.device.createBindGroup({layout:mainLayout,entries:[{binding:0,resource:{buffer:uniformBuffer}},{binding:1,resource:{buffer:transformBuffer}},{binding:2,resource:{buffer:colorsBuffer}}]});pass.setBindGroup(0,mainBindGroup);for(let m of $._hooks.preRender)m();let drawVertOffset=0,imageVertOffset=0,textCharOffset=0,curPipelineIndex=-1;for(let i=0;i<drawStack.length;i+=2){let v=drawStack[i+1];if(curPipelineIndex!=drawStack[i]){curPipelineIndex=drawStack[i];pass.setPipeline($._pipelines[curPipelineIndex])}if(curPipelineIndex==4||curPipelineIndex>=4e3){let o=drawStack[i+2];pass.setBindGroup(1,$._fonts[o].bindGroup);pass.setBindGroup(2,$._textBindGroup);pass.draw(4,v,0,textCharOffset);textCharOffset+=v;i++}else if(curPipelineIndex==2||curPipelineIndex==3||curPipelineIndex>=2e3){pass.setBindGroup(1,$._textureBindGroups[v]);pass.draw(4,1,imageVertOffset);imageVertOffset+=4}else{pass.draw(v,1,drawVertOffset);drawVertOffset+=v}}};$._finishRender=async()=>{pass.end();pass=encoder.beginRenderPass({colorAttachments:[{view:mainView,resolveTarget:$.ctx.getCurrentTexture().createView(),loadOp:"clear",storeOp:"store",clearValue:[0,0,0,0]}]});frameBindGroup=Q5.device.createBindGroup({layout:frameLayout,entries:[{binding:0,resource:{buffer:uniformBuffer}},{binding:1,resource:frameSampler},{binding:2,resource:frameA.createView()}]});pass.setPipeline($._pipelines[$._framePL]);pass.setBindGroup(0,frameBindGroup);pass.draw(4);pass.end();Q5.device.queue.submit([encoder.finish()]);$._pass=pass=encoder=null;Q5.device.queue.onSubmittedWorkDone().then((()=>{for(let b of $._buffers)b.destroy();$._buffers=[]}));drawStack.splice(0,drawStack.length);colorIndex=1;colorStackIndex=8;matrices=[matrices[0]];matricesIndexStack=[];for(let m of $._hooks.postRender)m()}};Q5.initWebGPU=async()=>{if(!navigator.gpu){console.warn("q5 WebGPU not supported on this browser! Use Google Chrome or Edge.");return false}if(!Q5.requestedGPU){let adapter=await navigator.gpu.requestAdapter();if(!adapter){console.warn("q5 WebGPU could not start! No appropriate GPUAdapter found, vulkan may need to be enabled.");return false}Q5.device=await adapter.requestDevice();Q5.device.lost.then((e=>{console.error("WebGPU crashed!");console.error(e)}))}return true};Q5.webgpu=async function(scope,parent){if(!scope||scope=="global")Q5._hasGlobal=true;if(!await Q5.initWebGPU()){return new Q5(scope,parent,"webgpu-fallback")}return new Q5(scope,parent,"webgpu")};Q5.renderers.webgpu.shapes=$=>{$._shapesPL=1;$._shapesShaderCode=$._baseShaderCode+`\nstruct VertexParams {\n\t@builtin(vertex_index) vertexIndex : u32,\n\t@location(0) pos: vec2f,\n\t@location(1) colorIndex: f32,\n\t@location(2) matrixIndex: f32\n}\nstruct FragParams {\n\t@builtin(position) position: vec4f,\n\t@location(0) color: vec4f\n}\n\n@group(0) @binding(0) var<uniform> q: Q5;\n@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;\n@group(0) @binding(2) var<storage> colors : array<vec4f>;\n\nfn transformVertex(pos: vec2f, matrixIndex: f32) -> vec4f {\n\tvar vert = vec4f(pos, 0.0, 1.0);\n\tvert = transforms[i32(matrixIndex)] * vert;\n\tvert.x /= q.halfWidth;\n\tvert.y /= q.halfHeight;\n\treturn vert;\n}\n\n@vertex\nfn vertexMain(v: VertexParams) -> FragParams {\n\tvar vert = transformVertex(v.pos, v.matrixIndex);\n\n\tvar f: FragParams;\n\tf.position = vert;\n\tf.color = colors[i32(v.colorIndex)];\n\treturn f;\n}\n\n@fragment\nfn fragMain(f: FragParams) -> @location(0) vec4f {\n\treturn f.color;\n}\n`;let shapesShader=Q5.device.createShaderModule({label:"shapesShader",code:$._shapesShaderCode});let c=$.canvas,drawStack=$.drawStack,vertexStack=new Float32Array($._graphics?1e3:1e7),vertIndex=0;const TAU=Math.PI*2;const HALF_PI=Math.PI/2;let vertexBufferLayout={arrayStride:16,attributes:[{format:"float32x2",offset:0,shaderLocation:0},{format:"float32",offset:8,shaderLocation:1},{format:"float32",offset:12,shaderLocation:2}]};let pipelineLayout=Q5.device.createPipelineLayout({label:"shapesPipelineLayout",bindGroupLayouts:$.bindGroupLayouts});$._pipelineConfigs[1]={label:"shapesPipeline",layout:pipelineLayout,vertex:{module:shapesShader,entryPoint:"vertexMain",buffers:[vertexBufferLayout]},fragment:{module:shapesShader,entryPoint:"fragMain",targets:[{format:"bgra8unorm",blend:$.blendConfigs.normal}]},primitive:{topology:"triangle-strip",stripIndexFormat:"uint32"},multisample:{count:4}};$._pipelines[1]=Q5.device.createRenderPipeline($._pipelineConfigs[1]);const addVert=(x,y,ci,ti)=>{let v=vertexStack,i=vertIndex;v[i++]=x;v[i++]=y;v[i++]=ci;v[i++]=ti;vertIndex=i};const addRect=(x1,y1,x2,y2,x3,y3,x4,y4,ci,ti)=>{let v=vertexStack,i=vertIndex;v[i++]=x1;v[i++]=y1;v[i++]=ci;v[i++]=ti;v[i++]=x2;v[i++]=y2;v[i++]=ci;v[i++]=ti;v[i++]=x4;v[i++]=y4;v[i++]=ci;v[i++]=ti;v[i++]=x3;v[i++]=y3;v[i++]=ci;v[i++]=ti;vertIndex=i;drawStack.push($._shapesPL,4)};const addArc=(x,y,a,b,startAngle,endAngle,n,ci,ti)=>{let angleRange=endAngle-startAngle;let angleIncrement=angleRange/n;let t=startAngle;let v=vertexStack,i=vertIndex;for(let j=0;j<=n;j++){v[i++]=x;v[i++]=y;v[i++]=ci;v[i++]=ti;let vx=x+a*Math.cos(t);let vy=y+b*Math.sin(t);v[i++]=vx;v[i++]=vy;v[i++]=ci;v[i++]=ti;t+=angleIncrement}vertIndex=i;drawStack.push($._shapesPL,(n+1)*2)};const addArcStroke=(x,y,outerA,outerB,innerA,innerB,startAngle,endAngle,n,ci,ti)=>{let angleRange=endAngle-startAngle;let angleIncrement=angleRange/n;let t=startAngle;let v=vertexStack,i=vertIndex;for(let j=0;j<=n;j++){let vxOuter=x+outerA*Math.cos(t);let vyOuter=y+outerB*Math.sin(t);let vxInner=x+innerA*Math.cos(t);let vyInner=y+innerB*Math.sin(t);v[i++]=vxOuter;v[i++]=vyOuter;v[i++]=ci;v[i++]=ti;v[i++]=vxInner;v[i++]=vyInner;v[i++]=ci;v[i++]=ti;t+=angleIncrement}vertIndex=i;drawStack.push($._shapesPL,(n+1)*2)};$.rectMode=x=>$._rectMode=x;$.rect=(x,y,w,h,rr=0)=>{let[l,r,t,b]=$._calcBox(x,y,w,h,$._rectMode);let ci,ti;if($._matrixDirty)$._saveMatrix();ti=$._matrixIndex;if(!rr){if($._doFill){ci=$._fill;addRect(l,t,r,t,r,b,l,b,ci,ti)}if($._doStroke){ci=$._stroke;let sw=$._strokeWeight/2;let lsw=l-sw,rsw=r+sw,tsw=t+sw,bsw=b-sw,lpsw=l+sw,rpsw=r-sw,tpsw=t-sw,bpsw=b+sw;addRect(lsw,tpsw,rsw,tpsw,rsw,tsw,lsw,tsw,ci,ti);addRect(lsw,bsw,rsw,bsw,rsw,bpsw,lsw,bpsw,ci,ti);tsw=t-sw;bsw=b+sw;addRect(lsw,tsw,lpsw,tsw,lpsw,bsw,lsw,bsw,ci,ti);addRect(rpsw,tsw,rsw,tsw,rsw,bsw,rpsw,bsw,ci,ti)}return}l+=rr;r-=rr;t-=rr;b+=rr;rr=Math.min(rr,Math.min(w,h)/2);let n=getArcSegments(rr*$._scale);let trr=t+rr,brr=b-rr,lrr=l-rr,rrr=r+rr;if($._doFill){ci=$._fill;addArc(r,b,rr,rr,-HALF_PI,0,n,ci,ti);addArc(l,b,rr,rr,-Math.PI,-HALF_PI,n,ci,ti);addArc(l,t,rr,rr,Math.PI,HALF_PI,n,ci,ti);addArc(r,t,rr,rr,0,HALF_PI,n,ci,ti);addRect(l,trr,r,trr,r,brr,l,brr,ci,ti);addRect(l,t,lrr,t,lrr,b,l,b,ci,ti);addRect(rrr,t,r,t,r,b,rrr,b,ci,ti)}if($._doStroke){ci=$._stroke;let hsw=$._hsw;let outerA=rr+hsw,outerB=rr+hsw,innerA=rr-hsw,innerB=rr-hsw;addArcStroke(r,b,outerA,outerB,innerA,innerB,-HALF_PI,0,n,ci,ti);addArcStroke(l,b,outerA,outerB,innerA,innerB,-Math.PI,-HALF_PI,n,ci,ti);addArcStroke(l,t,outerA,outerB,innerA,innerB,Math.PI,HALF_PI,n,ci,ti);addArcStroke(r,t,outerA,outerB,innerA,innerB,0,HALF_PI,n,ci,ti);let lrrMin=lrr-hsw,lrrMax=lrr+hsw,rrrMin=rrr-hsw,rrrMax=rrr+hsw,trrMin=trr-hsw,trrMax=trr+hsw,brrMin=brr-hsw,brrMax=brr+hsw;addRect(lrrMin,t,lrrMax,t,lrrMax,b,lrrMin,b,ci,ti);addRect(rrrMin,t,rrrMax,t,rrrMax,b,rrrMin,b,ci,ti);addRect(l,trrMin,r,trrMin,r,trrMax,l,trrMax,ci,ti);addRect(l,brrMin,r,brrMin,r,brrMax,l,brrMax,ci,ti)}};$.square=(x,y,s)=>$.rect(x,y,s,s);$.plane=(x,y,w,h)=>{h??=w;let[l,r,t,b]=$._calcBox(x,y,w,h,"center");if($._matrixDirty)$._saveMatrix();addRect(l,t,r,t,r,b,l,b,$._fill,$._matrixIndex)};const getArcSegments=d=>d<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;$._ellipseMode=Q5.CENTER;$.ellipseMode=x=>$._ellipseMode=x;$.ellipse=(x,y,w,h)=>{let n=getArcSegments(Math.max(Math.abs(w),Math.abs(h))*$._scale);let a=w/2;let b=w==h?a:h/2;if($._matrixDirty)$._saveMatrix();let ti=$._matrixIndex;if($._doFill){addArc(x,-y,a,b,0,TAU,n,$._fill,ti)}if($._doStroke){let sw=$._strokeWeight/2;addArcStroke(x,-y,a+sw,b+sw,a-sw,b-sw,0,TAU,n,$._stroke,ti)}};$.circle=(x,y,d)=>$.ellipse(x,y,d,d);$.arc=(x,y,w,h,start,stop)=>{if(start===stop)return $.ellipse(x,y,w,h);if($._angleMode){start=$.radians(start);stop=$.radians(stop)}start%=TAU;stop%=TAU;if(start<0)start+=TAU;if(stop<0)stop+=TAU;if(start>stop)stop+=TAU;if(start==stop)return $.ellipse(x,y,w,h);let a,b;if($._ellipseMode==$.CENTER){a=w/2;b=h/2}else if($._ellipseMode==$.RADIUS){a=w;b=h}else if($._ellipseMode==$.CORNER){x+=w/2;y+=h/2;a=w/2;b=h/2}else if($._ellipseMode==$.CORNERS){x=(x+w)/2;y=(y+h)/2;a=(w-x)/2;b=(h-y)/2}let ti=$._matrixIndex;if($._matrixDirty)$._saveMatrix();let n=getArcSegments(Math.max(Math.abs(w),Math.abs(h))*$._scale);if($._doFill){addArc(x,-y,a,b,start,stop,n,$._fill,ti)}if($._doStroke){let sw=$._strokeWeight;addArcStroke(x,-y,a+sw,b+sw,a-sw,b-sw,start,stop,n,$._stroke,ti)}};$.point=(x,y)=>{if($._matrixDirty)$._saveMatrix();let ti=$._matrixIndex,ci=$._stroke,sw=$._strokeWeight;if($._scaledSW<2){let[l,r,t,b]=$._calcBox(x,y,sw,sw,"corner");addRect(l,t,r,t,r,b,l,b,ci,ti)}else{let n=getArcSegments($._scaledSW);sw/=2;addArc(x,-y,sw,sw,0,TAU,n,ci,ti)}};$._strokeJoin="round";$.strokeJoin=x=>{$._strokeJoin=x};$.line=(x1,y1,x2,y2)=>{if($._matrixDirty)$._saveMatrix();let ti=$._matrixIndex,ci=$._stroke,sw=$._strokeWeight,hsw=$._hsw;let dx=x2-x1,dy=y2-y1,length=Math.hypot(dx,dy);let px=-(dy/length)*hsw,py=dx/length*hsw;addRect(x1+px,-y1-py,x1-px,-y1+py,x2-px,-y2+py,x2+px,-y2-py,ci,ti);if($._scaledSW>2&&$._strokeJoin!="none"){let n=getArcSegments($._scaledSW);addArc(x1,-y1,hsw,hsw,0,TAU,n,ci,ti);addArc(x2,-y2,hsw,hsw,0,TAU,n,ci,ti)}};let shapeVertCount;let sv=[];let curveVertices=[];$.beginShape=()=>{shapeVertCount=0;sv=[];curveVertices=[]};$.vertex=(x,y)=>{if($._matrixDirty)$._saveMatrix();sv.push(x,-y,$._fill,$._matrixIndex);shapeVertCount++};$.curveVertex=(x,y)=>{if($._matrixDirty)$._saveMatrix();curveVertices.push({x:x,y:-y})};$.endShape=close=>{if(curveVertices.length>0){let points=[...curveVertices];if(points.length<4){while(points.length<4){points.unshift(points[0]);points.push(points[points.length-1])}}for(let i=0;i<points.length-3;i++){let p0=points[i];let p1=points[i+1];let p2=points[i+2];let p3=points[i+3];for(let t=0;t<=1;t+=.1){let t2=t*t;let t3=t2*t;let x=.5*(2*p1.x+(-p0.x+p2.x)*t+(2*p0.x-5*p1.x+4*p2.x-p3.x)*t2+(-p0.x+3*p1.x-3*p2.x+p3.x)*t3);let y=.5*(2*p1.y+(-p0.y+p2.y)*t+(2*p0.y-5*p1.y+4*p2.y-p3.y)*t2+(-p0.y+3*p1.y-3*p2.y+p3.y)*t3);sv.push(x,y,$._fill,$._matrixIndex);shapeVertCount++}}}if(shapeVertCount<3){throw new Error("A shape must have at least 3 vertices.")}if(close){let firstIndex=0;let lastIndex=(shapeVertCount-1)*4;let firstX=sv[firstIndex];let firstY=sv[firstIndex+1];let lastX=sv[lastIndex];let lastY=sv[lastIndex+1];if(firstX!==lastX||firstY!==lastY){sv.push(firstX,firstY,sv[firstIndex+2],sv[firstIndex+3]);shapeVertCount++}}if($._doFill){if(shapeVertCount==5){addVert(sv[0],sv[1],sv[2],sv[3]);addVert(sv[4],sv[5],sv[6],sv[7]);addVert(sv[12],sv[13],sv[14],sv[15]);addVert(sv[8],sv[9],sv[10],sv[11]);drawStack.push($._shapesPL,4)}else{for(let i=1;i<shapeVertCount-1;i++){let v0=0;let v1=i*4;let v2=(i+1)*4;addVert(sv[v0],sv[v0+1],sv[v0+2],sv[v0+3]);addVert(sv[v1],sv[v1+1],sv[v1+2],sv[v1+3]);addVert(sv[v2],sv[v2+1],sv[v2+2],sv[v2+3])}drawStack.push($._shapesPL,(shapeVertCount-2)*3)}}if($._doStroke){let hsw=$._hsw,n=getArcSegments($._scaledSW),ti=$._matrixIndex,ogStrokeJoin=$._strokeJoin;$._strokeJoin="none";for(let i=0;i<shapeVertCount-1;i++){let v1=i*4;let v2=(i+1)*4;$.line(sv[v1],-sv[v1+1],sv[v2],-sv[v2+1]);addArc(sv[v1],sv[v1+1],hsw,hsw,0,TAU,n,$._stroke,ti)}if(close){let v1=(shapeVertCount-1)*4;let v2=0;$.line(sv[v1],-sv[v1+1],sv[v2],-sv[v2+1])}$._strokeJoin=ogStrokeJoin}shapeVertCount=0;sv=[];curveVertices=[]};$.triangle=(x1,y1,x2,y2,x3,y3)=>{$.beginShape();$.vertex(x1,y1);$.vertex(x2,y2);$.vertex(x3,y3);$.endShape(true)};$.quad=(x1,y1,x2,y2,x3,y3,x4,y4)=>{$.beginShape();$.vertex(x1,y1);$.vertex(x2,y2);$.vertex(x3,y3);$.vertex(x4,y4);$.endShape(true)};$._hooks.preRender.push((()=>{$._pass.setPipeline($._pipelines[1]);let vertexBuffer=Q5.device.createBuffer({size:vertIndex*4,usage:GPUBufferUsage.VERTEX,mappedAtCreation:true});new Float32Array(vertexBuffer.getMappedRange()).set(vertexStack.slice(0,vertIndex));vertexBuffer.unmap();$._pass.setVertexBuffer(0,vertexBuffer);$._buffers.push(vertexBuffer)}));$._hooks.postRender.push((()=>{vertIndex=0}))};Q5.renderers.webgpu.image=($,q)=>{$._imagePL=2;$._videoPL=3;$._imageShaderCode=$._baseShaderCode+`\nstruct VertexParams {\n\t@builtin(vertex_index) vertexIndex : u32,\n\t@location(0) pos: vec2f,\n\t@location(1) texCoord: vec2f,\n\t@location(2) tintIndex: f32,\n\t@location(3) matrixIndex: f32,\n\t@location(4) imageAlpha: f32\n}\nstruct FragParams {\n\t@builtin(position) position: vec4f,\n\t@location(0) texCoord: vec2f,\n\t@location(1) tintColor: vec4f,\n\t@location(2) imageAlpha: f32\n}\n\n@group(0) @binding(0) var<uniform> q: Q5;\n@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;\n@group(0) @binding(2) var<storage> colors : array<vec4f>;\n\n@group(1) @binding(0) var samp: sampler;\n@group(1) @binding(1) var tex: texture_2d<f32>;\n\nfn transformVertex(pos: vec2f, matrixIndex: f32) -> vec4f {\n\tvar vert = vec4f(pos, 0f, 1f);\n\tvert = transforms[i32(matrixIndex)] * vert;\n\tvert.x /= q.halfWidth;\n\tvert.y /= q.halfHeight;\n\treturn vert;\n}\n\nfn applyTint(texColor: vec4f, tintColor: vec4f) -> vec4f {\n\t// apply the tint color to the sampled texture color at full strength\n\tlet tinted = vec4f(texColor.rgb * tintColor.rgb, texColor.a);\n\t// mix in the tint using the tint alpha as the blend strength\n\treturn mix(texColor, tinted, tintColor.a);\n}\n\n@vertex\nfn vertexMain(v: VertexParams) -> FragParams {\n\tvar vert = transformVertex(v.pos, v.matrixIndex);\n\n\tvar f: FragParams;\n\tf.position = vert;\n\tf.texCoord = v.texCoord;\n\tf.tintColor = colors[i32(v.tintIndex)];\n\tf.imageAlpha = v.imageAlpha;\n\treturn f;\n}\n\n@fragment\nfn fragMain(f: FragParams) -> @location(0) vec4f {\n\tvar texColor = textureSample(tex, samp, f.texCoord);\n\ttexColor.a *= f.imageAlpha;\n\treturn applyTint(texColor, f.tintColor);\n}\n`;let imageShader=Q5.device.createShaderModule({label:"imageShader",code:$._imageShaderCode});$._videoShaderCode=$._imageShaderCode.replace("texture_2d<f32>","texture_external").replace("textureSample","textureSampleBaseClampToEdge");let videoShader=Q5.device.createShaderModule({label:"videoShader",code:$._videoShaderCode});let vertexStack=new Float32Array($._graphics?1e3:1e7),vertIndex=0;let vertexBufferLayout={arrayStride:28,attributes:[{shaderLocation:0,offset:0,format:"float32x2"},{shaderLocation:1,offset:8,format:"float32x2"},{shaderLocation:2,offset:16,format:"float32"},{shaderLocation:3,offset:20,format:"float32"},{shaderLocation:4,offset:24,format:"float32"}]};let textureLayout=Q5.device.createBindGroupLayout({label:"textureLayout",entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,texture:{viewDimension:"2d",sampleType:"float"}}]});let videoTextureLayout=Q5.device.createBindGroupLayout({label:"videoTextureLayout",entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,externalTexture:{}}]});let imagePipelineLayout=Q5.device.createPipelineLayout({label:"imagePipelineLayout",bindGroupLayouts:[...$.bindGroupLayouts,textureLayout]});let videoPipelineLayout=Q5.device.createPipelineLayout({label:"videoPipelineLayout",bindGroupLayouts:[...$.bindGroupLayouts,videoTextureLayout]});$._pipelineConfigs[2]={label:"imagePipeline",layout:imagePipelineLayout,vertex:{module:imageShader,entryPoint:"vertexMain",buffers:[{arrayStride:0,attributes:[]},vertexBufferLayout]},fragment:{module:imageShader,entryPoint:"fragMain",targets:[{format:"bgra8unorm",blend:$.blendConfigs.normal}]},primitive:{topology:"triangle-strip",stripIndexFormat:"uint32"},multisample:{count:4}};$._pipelines[2]=Q5.device.createRenderPipeline($._pipelineConfigs[2]);$._pipelineConfigs[3]={label:"videoPipeline",layout:videoPipelineLayout,vertex:{module:videoShader,entryPoint:"vertexMain",buffers:[{arrayStride:0,attributes:[]},vertexBufferLayout]},fragment:{module:videoShader,entryPoint:"fragMain",targets:[{format:"bgra8unorm",blend:$.blendConfigs.normal}]},primitive:{topology:"triangle-strip",stripIndexFormat:"uint32"},multisample:{count:4}};$._pipelines[3]=Q5.device.createRenderPipeline($._pipelineConfigs[3]);$._textureBindGroups=[];$._saveCanvas=async(data,ext)=>{let texture=data.texture,w=texture.width,h=texture.height,bytesPerRow=Math.ceil(w*4/256)*256;let buffer=Q5.device.createBuffer({size:bytesPerRow*h,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ});$._buffers.push(buffer);let en=Q5.device.createCommandEncoder();en.copyTextureToBuffer({texture:texture},{buffer:buffer,bytesPerRow:bytesPerRow,rowsPerImage:h},{width:w,height:h});Q5.device.queue.submit([en.finish()]);await buffer.mapAsync(GPUMapMode.READ);let pad=new Uint8Array(buffer.getMappedRange());data=new Uint8Array(w*h*4);for(let y=0;y<h;y++){const p=y*bytesPerRow;const u=y*w*4;for(let x=0;x<w;x++){const pp=p+x*4;const up=u+x*4;data[up+0]=pad[pp+2];data[up+1]=pad[pp+1];data[up+2]=pad[pp+0];data[up+3]=pad[pp+3]}}buffer.unmap();let colorSpace=$.canvas.colorSpace;data=new Uint8ClampedArray(data.buffer);data=new ImageData(data,w,h,{colorSpace:colorSpace});let cnv=new $._Canvas(w,h);let ctx=cnv.getContext("2d",{colorSpace:colorSpace});ctx.putImageData(data,0,0);let blob=await cnv.convertToBlob({type:"image/"+ext});return await new Promise((resolve=>{let r=new FileReader;r.onloadend=()=>resolve(r.result);r.readAsDataURL(blob)}))};let makeSampler=filter=>{$._imageSampler=Q5.device.createSampler({magFilter:filter,minFilter:filter})};$.smooth=()=>makeSampler("linear");$.noSmooth=()=>makeSampler("nearest");$.smooth();let tIdx=0,vidFrames=0;$._addTexture=(img,texture)=>{let cnv=img.canvas||img;let textureSize=[cnv.width,cnv.height,1];if(!texture){texture=Q5.device.createTexture({size:textureSize,format:"bgra8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT});Q5.device.queue.copyExternalImageToTexture({source:cnv},{texture:texture,colorSpace:$.canvas.colorSpace},textureSize)}img.texture=texture;img.textureIndex=tIdx+vidFrames;$._textureBindGroups[img.textureIndex]=Q5.device.createBindGroup({label:img.src||"canvas",layout:textureLayout,entries:[{binding:0,resource:$._imageSampler},{binding:1,resource:texture.createView()}]});tIdx++};let Q5Image=Q5.Image;Q5.Image=function(w,h){let g=new Q5Image(...arguments);if(w>1&&h>1){$._addTexture(g);g.modified=true}return g};$.loadImage=(src,cb)=>{q._preloadCount++;let g=$._g.loadImage(src,(img=>{$._addTexture(img);q._preloadCount--;if(cb)cb(g)}));return g};$.createImage=$._g.createImage;let _createGraphics=$.createGraphics;$.createGraphics=(w,h,opt)=>{let g=_createGraphics(w,h,opt);if(g.canvas.renderer=="webgpu"){$._addTexture(g,g._frameA);$._addTexture(g,g._frameB);g._beginRender()}return g};$.imageMode=x=>$._imageMode=x;const addVert=(x,y,u,v,ci,ti,ia)=>{let s=vertexStack,i=vertIndex;s[i++]=x;s[i++]=y;s[i++]=u;s[i++]=v;s[i++]=ci;s[i++]=ti;s[i++]=ia;vertIndex=i};$.image=(img,dx=0,dy=0,dw,dh,sx=0,sy=0,sw,sh)=>{let isVideo;if(img.textureIndex==undefined){isVideo=img.tagName=="VIDEO";if(!isVideo||!img.width||!img.currentTime)return;if(img.flipped)$.scale(-1,1)}let cnv=img.canvas||img;if($._matrixDirty)$._saveMatrix();let w=cnv.width,h=cnv.height,pd=img._pixelDensity||1;if(img._graphics){let g=img;if(g.drawStack.length){g._render();g._finishRender();g.textureIndex+=g.frameCount%2==0?-1:1;g.resetMatrix();g._beginRender();g.frameCount++}}if(img.modified){Q5.device.queue.copyExternalImageToTexture({source:cnv},{texture:img.texture,colorSpace:$.canvas.colorSpace},[w,h,1]);img.modified=false}dw??=img.defaultWidth||img.videoWidth;dh??=img.defaultHeight||img.videoHeight;sw??=w;sh??=h;sx*=pd;sy*=pd;let[l,r,t,b]=$._calcBox(dx,dy,dw,dh,$._imageMode);let u0=sx/w,v0=sy/h,u1=(sx+sw)/w,v1=(sy+sh)/h,ti=$._matrixIndex,ci=$._tint,ia=$._globalAlpha;addVert(l,t,u0,v0,ci,ti,ia);addVert(r,t,u1,v0,ci,ti,ia);addVert(l,b,u0,v1,ci,ti,ia);addVert(r,b,u1,v1,ci,ti,ia);if(!isVideo){$.drawStack.push($._imagePL,img.textureIndex)}else{let externalTexture=Q5.device.importExternalTexture({source:img});$._textureBindGroups.push(Q5.device.createBindGroup({layout:videoTextureLayout,entries:[{binding:0,resource:$._imageSampler},{binding:1,resource:externalTexture}]}));$.drawStack.push($._videoPL,$._textureBindGroups.length-1);if(img.flipped)$.scale(-1,1)}};$._hooks.preRender.push((()=>{if(!vertIndex)return;$._pass.setPipeline($._pipelines[2]);let vertexBuffer=Q5.device.createBuffer({size:vertIndex*5,usage:GPUBufferUsage.VERTEX,mappedAtCreation:true});new Float32Array(vertexBuffer.getMappedRange()).set(vertexStack.slice(0,vertIndex));vertexBuffer.unmap();$._pass.setVertexBuffer(1,vertexBuffer);$._buffers.push(vertexBuffer);if(vidFrames){$._pass.setPipeline($._pipelines[3]);$._pass.setVertexBuffer(1,vertexBuffer)}}));$._hooks.postRender.push((()=>{vertIndex=0;$._textureBindGroups.splice(tIdx,vidFrames);vidFrames=0}))};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.webgpu.text=($,q)=>{$._textPL=4;$._textShaderCode=$._baseShaderCode+`\nstruct VertexParams {\n\t@builtin(vertex_index) vertexIndex : u32,\n\t@builtin(instance_index) instanceIndex : u32\n}\nstruct FragParams {\n\t@builtin(position) position : vec4f,\n\t@location(0) texCoord : vec2f,\n\t@location(1) fillColor : vec4f,\n\t@location(2) strokeColor : vec4f,\n\t@location(3) strokeWeight : f32\n}\nstruct Char {\n\ttexOffset: vec2f,\n\ttexExtent: vec2f,\n\tsize: vec2f,\n\toffset: vec2f,\n}\nstruct Text {\n\tpos: vec2f,\n\tscale: f32,\n\tmatrixIndex: f32,\n\tfillIndex: f32,\n\tstrokeIndex: f32,\n\tstrokeWeight: f32\n}\n\n@group(0) @binding(0) var<uniform> q: Q5;\n@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;\n@group(0) @binding(2) var<storage> colors : array<vec4f>;\n\n@group(1) @binding(0) var fontTexture: texture_2d<f32>;\n@group(1) @binding(1) var fontSampler: sampler;\n@group(1) @binding(2) var<storage> fontChars: array<Char>;\n\n@group(2) @binding(0) var<storage> textChars: array<vec4f>;\n@group(2) @binding(1) var<storage> textMetadata: array<Text>;\n\nconst quad = array(vec2f(0, -1), vec2f(1, -1), vec2f(0, 0), vec2f(1, 0));\nconst uvs = array(vec2f(0, 1), vec2f(1, 1), vec2f(0, 0), vec2f(1, 0));\n\nfn calcPos(i: u32, char: vec4f, fontChar: Char, text: Text) -> vec2f {\n\treturn ((quad[i] * fontChar.size + char.xy + fontChar.offset) *\n\t\ttext.scale) + text.pos;\n}\n\nfn calcUV(i: u32, fontChar: Char) -> vec2f {\n\treturn uvs[i] * fontChar.texExtent + fontChar.texOffset;\n}\n\nfn transformVertex(pos: vec2f, matrixIndex: f32) -> vec4f {\n\tvar vert = vec4f(pos, 0.0, 1.0);\n\tvert = transforms[i32(matrixIndex)] * vert;\n\tvert.x /= q.halfWidth;\n\tvert.y /= q.halfHeight;\n\treturn vert;\n}\n\nfn calcDist(texCoord: vec2f, edgeWidth: f32) -> f32 {\n\tlet c = textureSample(fontTexture, fontSampler, texCoord);\n\tlet sigDist = max(min(c.r, c.g), min(max(c.r, c.g), c.b)) - edgeWidth;\n\n\tlet pxRange = 4.0;\n\tlet sz = vec2f(textureDimensions(fontTexture, 0));\n\tlet dx = sz.x * length(vec2f(dpdxFine(texCoord.x), dpdyFine(texCoord.x)));\n\tlet dy = sz.y * length(vec2f(dpdxFine(texCoord.y), dpdyFine(texCoord.y)));\n\tlet toPixels = pxRange * inverseSqrt(dx * dx + dy * dy);\n\treturn sigDist * toPixels;\n}\n\n@vertex\nfn vertexMain(v : VertexParams) -> FragParams {\n\tlet char = textChars[v.instanceIndex];\n\tlet text = textMetadata[i32(char.w)];\n\tlet fontChar = fontChars[i32(char.z)];\n\tlet pos = calcPos(v.vertexIndex, char, fontChar, text);\n\n\tvar vert = transformVertex(pos, text.matrixIndex);\n\n\tvar f : FragParams;\n\tf.position = vert;\n\tf.texCoord = calcUV(v.vertexIndex, fontChar);\n\tf.fillColor = colors[i32(text.fillIndex)];\n\tf.strokeColor = colors[i32(text.strokeIndex)];\n\tf.strokeWeight = text.strokeWeight;\n\treturn f;\n}\n\n@fragment\nfn fragMain(f : FragParams) -> @location(0) vec4f {\n\tlet edge = 0.5;\n\tlet dist = calcDist(f.texCoord, edge);\n\n\tif (f.strokeWeight == 0.0) {\n\t\tlet fillAlpha = smoothstep(-edge, edge, dist);\n\t\tlet color = vec4f(f.fillColor.rgb, f.fillColor.a * fillAlpha);\n\t\tif (color.a < 0.01) {\n\t\t\tdiscard;\n\t\t}\n\t\treturn color;\n\t}\n\n\tlet halfStroke = f.strokeWeight / 2.0;\n\tlet fillAlpha = smoothstep(-edge, edge, dist - halfStroke);\n\tlet strokeAlpha = smoothstep(-edge, edge, dist + halfStroke);\n\tvar color = mix(f.strokeColor, f.fillColor, fillAlpha);\n\tcolor = vec4f(color.rgb, color.a * strokeAlpha);\n\tif (color.a < 0.01) {\n\t\tdiscard;\n\t}\n\treturn color;\n}\n`;let textShader=Q5.device.createShaderModule({label:"textShader",code:$._textShaderCode});let textBindGroupLayout=Q5.device.createBindGroupLayout({label:"textBindGroupLayout",entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}},{binding:1,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}}]});let fontSampler=Q5.device.createSampler({minFilter:"linear",magFilter:"linear",mipmapFilter:"linear",maxAnisotropy:16});let fontBindGroupLayout=Q5.device.createBindGroupLayout({label:"fontBindGroupLayout",entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,texture:{}},{binding:1,visibility:GPUShaderStage.FRAGMENT,sampler:{}},{binding:2,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}}]});let fontPipelineLayout=Q5.device.createPipelineLayout({bindGroupLayouts:[...$.bindGroupLayouts,fontBindGroupLayout,textBindGroupLayout]});$._pipelineConfigs[4]={label:"textPipeline",layout:fontPipelineLayout,vertex:{module:textShader,entryPoint:"vertexMain"},fragment:{module:textShader,entryPoint:"fragMain",targets:[{format:"bgra8unorm",blend:$.blendConfigs.normal}]},primitive:{topology:"triangle-strip",stripIndexFormat:"uint32"},multisample:{count:4}};$._pipelines[4]=Q5.device.createRenderPipeline($._pipelineConfigs[4]);class MsdfFont{constructor(bindGroup,lineHeight,chars,kernings){this.bindGroup=bindGroup;this.lineHeight=lineHeight;this.chars=chars;this.kernings=kernings;let charArray=Object.values(chars);this.charCount=charArray.length;this.defaultChar=charArray[0]}getChar(charCode){return this.chars[charCode]??this.defaultChar}getXAdvance(charCode,nextCharCode=-1){let char=this.getChar(charCode);if(nextCharCode>=0){let kerning=this.kernings.get(charCode);if(kerning){return char.xadvance+(kerning.get(nextCharCode)??0)}}return char.xadvance}}$._fonts=[];let fonts={};let createFont=async(fontJsonUrl,fontName,cb)=>{q._preloadCount++;let res=await fetch(fontJsonUrl);if(res.status==404){q._preloadCount--;return""}let atlas=await res.json();let slashIdx=fontJsonUrl.lastIndexOf("/");let baseUrl=slashIdx!=-1?fontJsonUrl.substring(0,slashIdx+1):"";res=await fetch(baseUrl+atlas.pages[0]);let img=await createImageBitmap(await res.blob());let imgSize=[img.width,img.height,1];let texture=Q5.device.createTexture({label:`MSDF ${fontName}`,size:imgSize,format:"rgba8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT});Q5.device.queue.copyExternalImageToTexture({source:img},{texture:texture},imgSize);if(typeof atlas.chars=="string"){atlas.chars=$.CSV.parse(atlas.chars," ");atlas.kernings=$.CSV.parse(atlas.kernings," ")}let charCount=atlas.chars.length;let charsBuffer=Q5.device.createBuffer({size:charCount*32,usage:GPUBufferUsage.STORAGE,mappedAtCreation:true});let fontChars=new Float32Array(charsBuffer.getMappedRange());let u=1/atlas.common.scaleW;let v=1/atlas.common.scaleH;let chars={};let o=0;for(let[i,char]of atlas.chars.entries()){chars[char.id]=char;chars[char.id].charIndex=i;fontChars[o]=char.x*u;fontChars[o+1]=char.y*v;fontChars[o+2]=char.width*u;fontChars[o+3]=char.height*v;fontChars[o+4]=char.width;fontChars[o+5]=char.height;fontChars[o+6]=char.xoffset;fontChars[o+7]=-char.yoffset;o+=8}charsBuffer.unmap();let fontBindGroup=Q5.device.createBindGroup({label:"fontBindGroup",layout:fontBindGroupLayout,entries:[{binding:0,resource:texture.createView()},{binding:1,resource:fontSampler},{binding:2,resource:{buffer:charsBuffer}}]});let kernings=new Map;if(atlas.kernings){for(let kerning of atlas.kernings){let charKerning=kernings.get(kerning.first);if(!charKerning){charKerning=new Map;kernings.set(kerning.first,charKerning)}charKerning.set(kerning.second,kerning.amount)}}$._font=new MsdfFont(fontBindGroup,atlas.common.lineHeight,chars,kernings);$._font.index=$._fonts.length;$._fonts.push($._font);fonts[fontName]=$._font;q._preloadCount--;if(cb)cb(fontName)};$._g.colorMode($.RGB,1);$.loadFont=(url,cb)=>{let ext=url.slice(url.lastIndexOf(".")+1);if(ext!="json")return $._g.loadFont(url,cb);let fontName=url.slice(url.lastIndexOf("/")+1,url.lastIndexOf("-"));let f={family:fontName};f._loader=createFont(url,fontName,(()=>{delete f._loader;if(cb)cb(f)}));if($._disablePreload)return f._loader;return f};$._loadDefaultFont=fontName=>{fonts[fontName]=null;if(navigator.onLine){$.loadFont(`https://q5js.org/fonts/${fontName}-msdf.json`)}else{$.loadFont(`/node_modules/q5/builtinFonts/${fontName}-msdf.json`)}};$._textSize=18;$._textAlign="left";$._textBaseline="alphabetic";let leadingSet=false,leading=22.5,leadDiff=4.5,leadPercent=1.25;$.textFont=fontName=>{if(!fontName)return $._font;if(typeof fontName!="string")fontName=fontName.family;let font=fonts[fontName];if(font)$._font=font;else if(font===undefined)$._loadDefaultFont(fontName)};$.textSize=size=>{$._textSize=size;if(!leadingSet){leading=size*leadPercent;leadDiff=leading-size}};$.textLeading=lineHeight=>{$._font.lineHeight=leading=lineHeight;leadDiff=leading-$._textSize;leadPercent=leading/$._textSize;leadingSet=true};$.textAlign=(horiz,vert)=>{$._textAlign=horiz;if(vert)$._textBaseline=vert};let charStack=[],textStack=[];let measureText=(font,text,charCallback)=>{let maxWidth=0,offsetX=0,offsetY=0,line=0,printedCharCount=0,lineWidths=[],nextCharCode=text.charCodeAt(0);for(let i=0;i<text.length;++i){let charCode=nextCharCode;nextCharCode=i<text.length-1?text.charCodeAt(i+1):-1;switch(charCode){case 10:lineWidths.push(offsetX);line++;maxWidth=Math.max(maxWidth,offsetX);offsetX=0;offsetY-=font.lineHeight*leadPercent;break;case 13:break;case 32:offsetX+=font.getXAdvance(charCode);break;case 9:offsetX+=font.getXAdvance(charCode)*2;break;default:if(charCallback){charCallback(offsetX,offsetY,line,font.getChar(charCode))}offsetX+=font.getXAdvance(charCode,nextCharCode);printedCharCount++}}lineWidths.push(offsetX);maxWidth=Math.max(maxWidth,offsetX);return{width:maxWidth,height:lineWidths.length*font.lineHeight*leadPercent,lineWidths:lineWidths,printedCharCount:printedCharCount}};$.text=(str,x,y,w,h)=>{if(!$._font){if($._font!==null)$.textFont("sans-serif");return}let type=typeof str;if(type!="string"){if(type=="object")str=str.toString();else str=str+""}if(str.length>w){let wrapped=[];let i=0;while(i<str.length&&wrapped.length<h){let max=i+w;if(max>=str.length){wrapped.push(str.slice(i));break}let end=str.lastIndexOf(" ",max);if(end==-1||end<i)end=max;wrapped.push(str.slice(i,end));i=end+1}str=wrapped.join("\n")}let spaces=0,hasNewline;for(let i=0;i<str.length;i++){let c=str[i];switch(c){case"\n":hasNewline=true;case"\r":case"\t":case" ":spaces++}}let charsData=[];let ta=$._textAlign,tb=$._textBaseline,textIndex=textStack.length,o=0,measurements;if(ta=="left"&&!hasNewline){measurements=measureText($._font,str,((textX,textY,line,char)=>{charsData[o]=textX;charsData[o+1]=textY;charsData[o+2]=char.charIndex;charsData[o+3]=textIndex;o+=4}));if(tb=="alphabetic")y-=$._textSize;else if(tb=="center")y-=$._textSize*.5;else if(tb=="bottom")y-=leading}else{measurements=measureText($._font,str);let offsetY=0;if(tb=="alphabetic")y-=$._textSize;else if(tb=="center")offsetY=measurements.height*.5;else if(tb=="bottom")offsetY=measurements.height;measureText($._font,str,((textX,textY,line,char)=>{let offsetX=0;if(ta=="center"){offsetX=measurements.width*-.5-(measurements.width-measurements.lineWidths[line])*-.5}else if(ta=="right"){offsetX=-measurements.lineWidths[line]}charsData[o]=textX+offsetX;charsData[o+1]=textY+offsetY;charsData[o+2]=char.charIndex;charsData[o+3]=textIndex;o+=4}))}charStack.push(charsData);let txt=[];if($._matrixDirty)$._saveMatrix();txt[0]=x;txt[1]=-y;txt[2]=$._textSize/44;txt[3]=$._matrixIndex;txt[4]=$._doFill&&$._fillSet?$._fill:0;txt[5]=$._stroke;txt[6]=$._doStroke&&$._strokeSet?$._strokeWeight:0;txt[7]=0;textStack.push(txt);$.drawStack.push($._textPL,measurements.printedCharCount,$._font.index)};$.textWidth=str=>{if(!$._font)return 0;return measureText($._font,str).width};$.createTextImage=(str,w,h)=>{$._g.textSize($._textSize);if($._doFill){let fi=$._fill*4;$._g.fill(colorStack.slice(fi,fi+4))}if($._doStroke){let si=$._stroke*4;$._g.stroke(colorStack.slice(si,si+4))}let img=$._g.createTextImage(str,w,h);if(img.textureIndex==undefined){$._createTexture(img);let _copy=img.copy;img.copy=function(){let copy=_copy();$._createTexture(copy);return copy}}return img};$.textImage=(img,x,y)=>{if(typeof img=="string")img=$.createTextImage(img);let og=$._imageMode;$._imageMode="corner";let ta=$._textAlign;if(ta=="center")x-=img.canvas.hw;else if(ta=="right")x-=img.width;let bl=$._textBaseline;if(bl=="alphabetic")y-=img._leading;else if(bl=="center")y-=img._middle;else if(bl=="bottom")y-=img._bottom;else if(bl=="top")y-=img._top;$.image(img,x,y);$._imageMode=og};$._hooks.preRender.push((()=>{if(!charStack.length)return;let totalTextSize=0;for(let charsData of charStack){totalTextSize+=charsData.length*4}let charBuffer=Q5.device.createBuffer({size:totalTextSize,usage:GPUBufferUsage.STORAGE,mappedAtCreation:true});new Float32Array(charBuffer.getMappedRange()).set(charStack.flat());charBuffer.unmap();let totalMetadataSize=textStack.length*8*4;let textBuffer=Q5.device.createBuffer({label:"textBuffer",size:totalMetadataSize,usage:GPUBufferUsage.STORAGE,mappedAtCreation:true});new Float32Array(textBuffer.getMappedRange()).set(textStack.flat());textBuffer.unmap();$._buffers.push(charBuffer,textBuffer);$._textBindGroup=Q5.device.createBindGroup({label:"textBindGroup",layout:textBindGroupLayout,entries:[{binding:0,resource:{buffer:charBuffer}},{binding:1,resource:{buffer:textBuffer}}]})}));$._hooks.postRender.push((()=>{charStack=[];textStack=[]}))};Q5.renderers.webgpu.shaders=$=>{let pipelineTypes=["frame","shapes","image","video","text"];let plCounters={frame:10,shapes:1e3,image:2e3,video:3e3,text:4e3};$._createShader=(code,type="shapes")=>{code=code.trim();let def=$["_"+type+"ShaderCode"];let defVertIdx=def.indexOf("@vertex");let defFragIdx=def.indexOf("@fragment");if(!code.includes("@fragment")){code=def.slice(0,defVertIdx)+code+"\n\n"+def.slice(defFragIdx)}else if(!code.includes("@vertex")){code=def.slice(0,defFragIdx)+code}else{code=def.slice(0,defVertIdx)+code}let shader=Q5.device.createShaderModule({label:type+"Shader",code:code});shader.type=type;let pipelineIndex=pipelineTypes.indexOf(type);let config=Object.assign({},$._pipelineConfigs[pipelineIndex]);config.vertex.module=config.fragment.module=shader;let pl=plCounters[type];$._pipelines[pl]=Q5.device.createRenderPipeline(config);$._pipelines[pl].shader=shader;shader.pipelineIndex=pl;plCounters[type]++;return shader};$.createShader=$.createShapesShader=$._createShader;$.createFrameShader=code=>$._createShader(code,"frame");$.createImageShader=code=>$._createShader(code,"image");$.createVideoShader=code=>$._createShader(code,"video");$.createTextShader=code=>$._createShader(code,"text");$.shader=shader=>{if(shader.applyBeforeDraw)$._prevFramePL=shader.pipelineIndex;else $["_"+shader.type+"PL"]=shader.pipelineIndex};$.resetShader=(type="shapes")=>{if(type=="frame")$._prevFramePL=0;$["_"+type+"PL"]=pipelineTypes.indexOf(type)};$.resetShaders=()=>{$._prevFramePL=$._framePL=0;$._shapesPL=1;$._imagePL=2;$._videoPL=3;$._textPL=4}};
8
+ function Q5(e,t,r){let a=this;a._q5=!0,a._parent=t,"webgpu-fallback"==r?(a._webgpuFallback=!0,a._renderer="c2d"):a._renderer=r||Q5.render,a._preloadCount=0;let n,o="auto"==e;if(e??="global","auto"==e){if(!(window.setup||window.update||window.draw))return;e="global"}a._scope=e,"global"==e&&(Q5._hasGlobal=a._isGlobal=!0,n=Q5._esm?globalThis:Q5._server?global:window),"graphics"==e&&(a._graphics=!0);let i=new Proxy(a,{set:(e,t,r)=>(a[t]=r,a._isGlobal&&(n[t]=r),!0)});a.canvas=a.ctx=a.drawingContext=null,a.pixels=[];let s=null,l=!0;a.frameCount=0,a.deltaTime=16,a._targetFrameRate=0,a._targetFrameDuration=16.666666666666668,a._frameRate=a._fps=60,a._loop=!0,a._hooks={postCanvas:[],preRender:[],postRender:[]};let d=0;a.millis=()=>performance.now()-d,a.noCanvas=()=>{a.canvas?.remove&&a.canvas.remove(),a.canvas=0,i.ctx=i.drawingContext=0},window&&(a.windowWidth=window.innerWidth,a.windowHeight=window.innerHeight,a.deviceOrientation=window.screen?.orientation?.type),a._incrementPreload=()=>i._preloadCount++,a._decrementPreload=()=>i._preloadCount--,a.disablePreloadSystem=()=>a._disablePreload=!0,a._draw=e=>{let t=e||performance.now();if(a._lastFrameTime??=t-a._targetFrameDuration,a._didResize&&(a.windowResized(),a._didResize=!1),a._loop)if(l)s=h(a._draw);else{let e=t+a._targetFrameDuration,r=e-performance.now();for(;r<0;)r+=a._targetFrameDuration;log(r),s=setTimeout((()=>a._draw(e)),r)}else if(a.frameCount&&!a._redraw)return;if(a.frameCount&&l){if(t-a._lastFrameTime<a._targetFrameDuration-4)return}i.deltaTime=t-a._lastFrameTime,a._frameRate=1e3/a.deltaTime,i.frameCount++;let r=performance.now();a.resetMatrix(),a._beginRender&&a._beginRender();for(let e of Q5.methods.pre)e.call(a);try{a.draw()}catch(e){throw Q5.errorTolerant||a.noLoop(),e}for(let e of Q5.methods.post)e.call(a);a.postProcess(),a._render&&a._render(),a._finishRender&&a._finishRender(),i.pmouseX=a.mouseX,i.pmouseY=a.mouseY,i.moveX=i.moveY=0,a._lastFrameTime=t;let n=performance.now();a._fps=Math.round(1e3/(n-r))},a.noLoop=()=>{a._loop=!1,s&&(l?cancelAnimationFrame(s):clearTimeout(s)),s=null},a.loop=()=>{a._loop=!0,a._setupDone&&null==s&&a._draw()},a.isLooping=()=>a._loop,a.redraw=(e=1)=>{a._redraw=!0;for(let t=0;t<e;t++)a._draw();a._redraw=!1},a.remove=()=>{a.noLoop(),a.canvas.remove()},a.frameRate=e=>(e&&(a._targetFrameRate=e,a._targetFrameDuration=1e3/e,a._loop&&a._setupDone&&null!=s&&(l?cancelAnimationFrame(s):clearTimeout(s),s=null),l=e<=60,setTimeout((()=>a._draw()),a._targetFrameDuration)),a._frameRate),a.getTargetFrameRate=()=>a._targetFrameRate||60,a.getFPS=()=>a._fps,a.Element=function(e){this.elt=e},a._elements=[],a.describe=()=>{},a.log=a.print=console.log;for(let e in Q5.modules)Q5.modules[e](a,i);let c=Q5.renderers[a._renderer];for(let e in c)c[e](a,i);for(let e in Q5)"_"!=e[1]&&e[1]==e[1].toUpperCase()&&(a[e]=Q5[e]);if(a._webgpuFallback&&a.colorMode("rgb",1),a._graphics)return;if("global"==e){let e=Object.assign({},a);delete e.Color,Object.assign(Q5,e),delete Q5.Q5}for(let e of Q5.methods.init)e.call(a);for(let[e,t]of Object.entries(Q5.prototype))"_"!=e[0]&&"function"==typeof a[e]&&(a[e]=t.bind(a));if("global"==e){let e=Object.getOwnPropertyNames(a);for(let t of e)"_"!=t[0]&&(n[t]=a[t])}"function"==typeof e&&e(a),Q5._instanceCount++;let h=window.requestAnimationFrame||function(e){const t=a._lastFrameTime+a._targetFrameDuration;return setTimeout((()=>{e(t)}),t-performance.now())},u=n||a;a._isTouchAware=u.touchStarted||u.touchMoved||u.mouseReleased,a._isGlobal&&(a.preload=u.preload,a.setup=u.setup,a.draw=u.draw,a.postProcess=u.postProcess),a.preload??=()=>{},a.setup??=()=>{},a.draw??=()=>{},a.postProcess??=()=>{};let p=["setup","postProcess","mouseMoved","mousePressed","mouseReleased","mouseDragged","mouseClicked","mouseWheel","keyPressed","keyReleased","keyTyped","touchStarted","touchMoved","touchEnded","windowResized"];for(let e of p)u[e]?a._isGlobal&&(a[e]=t=>u[e](t)):a[e]=()=>{};async function f(){if(a._startDone=!0,a._preloadCount>0||a._g?._preloadCount>0)return h(f);d=performance.now(),await a.setup(),a._setupDone=!0,a.frameCount||(null===a.ctx&&a.createCanvas(200,200),h(a._draw))}function g(){try{a.preload(),a._startDone||f()}catch(e){throw a._askAI&&a._askAI(e),e}}o?g():setTimeout(g,32)}function createCanvas(e,t,r){if(!Q5._hasGlobal){(new Q5).createCanvas(e,t,r)}}Q5.render="c2d",Q5.renderers={},Q5.modules={},Q5._server="object"==typeof process,Q5._esm=void 0===this,Q5._instanceCount=0,Q5._friendlyError=(e,t)=>{Q5.disableFriendlyErrors||console.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._server&&(global.p5??=global.Q5=Q5),"object"==typeof window?window.p5??=window.Q5=Q5:global.window=0,Q5.version=Q5.VERSION="2.23","object"==typeof document&&document.addEventListener("DOMContentLoaded",(()=>{Q5._hasGlobal||new Q5("auto")})),Q5.modules.canvas=(e,t)=>{e._Canvas=window.OffscreenCanvas||function(){return document.createElement("canvas")},Q5._server?Q5._createServerCanvas&&(t.canvas=Q5._createServerCanvas(100,100)):"image"!=e._scope&&"graphics"!=e._scope||(t.canvas=new e._Canvas(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(e.width=200,e.height=200,e._pixelDensity=1,e.displayDensity=()=>window.devicePixelRatio||1,r&&(r.width=200,r.height=200,"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,n){"object"==typeof t&&(n=t,t=null),n??=arguments[3],"string"==typeof n&&(n={renderer:n});let o=Object.assign({},Q5.canvasOptions);if("object"==typeof n&&Object.assign(o,n),"image"!=e._scope)if("graphics"==e._scope)e._pixelDensity=this._pixelDensity;else if(window.IntersectionObserver){let t=!1;new IntersectionObserver((a=>{r.visible=a[0].isIntersecting,t||(e._wasLooping=e._loop,t=!0),r.visible?e._wasLooping&&!e._loop&&e.loop():(e._wasLooping=e._loop,e.noLoop())})).observe(r)}e._setCanvasSize(t,a),Object.assign(r,o);let i=e._createCanvas(r.w,r.h,o);if(e._hooks)for(let t of e._hooks.postCanvas)t();return e._addEventMethods&&e._addEventMethods(r),i},e.createGraphics=function(t,r,a={}){"string"==typeof a&&(a={renderer:a});let n=new Q5("graphics",void 0,a.renderer||(e._webgpuFallback?"webgpu-fallback":e._renderer));a.alpha??=!0,a.colorSpace??=e.canvas.colorSpace,n.createCanvas.call(e,t,r,a);let o=n._pixelDensity*e._defaultImageScale;return n.defaultWidth=t*o,n.defaultHeight=r*o,n},e._setCanvasSize=(a,n)=>{n??=a??window.innerHeight,a??=window.innerWidth,r.w=a=Math.ceil(a),r.h=n=Math.ceil(n),t.halfWidth=r.hw=a/2,t.halfHeight=r.hh=n/2,r.width=Math.ceil(a*e._pixelDensity),r.height=Math.ceil(n*e._pixelDensity),e._da?e.flexibleCanvas(e._dau):(t.width=a,t.height=n),e.displayMode&&!r.displayMode?e.displayMode():e._adjustDisplay()},e._setImageSize=(a,n)=>{t.width=r.w=a,t.height=r.h=n,t.halfWidth=r.hw=a/2,t.halfHeight=r.hh=n/2,r.width=Math.ceil(a*e._pixelDensity),r.height=Math.ceil(n*e._pixelDensity)},e.defaultImageScale=t=>t?e._defaultImageScale=t:e._defaultImageScale,e.defaultImageScale(.5),"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._didResize=!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)},r&&!Q5._createServerCanvas&&(r.resize=e.resizeCanvas),e.pixelDensity=t=>t&&t!=e._pixelDensity?(e._pixelDensity=t,e._resizeCanvas(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=["_fill","_stroke","_strokeWeight","_doStroke","_doFill","_strokeSet","_fillSet","_shadow","_doShadow","_shadowOffsetX","_shadowOffsetY","_shadowBlur","_tint","_imageMode","_rectMode","_ellipseMode","_textSize","_textAlign","_textBaseline"],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]},window&&"graphics"!=e._scope&&window.addEventListener("resize",(()=>{e._didResize=!0,t.windowWidth=window.innerWidth,t.windowHeight=window.innerHeight,t.deviceOrientation=window.screen?.orientation?.type}))}},Q5.CENTER="center",Q5.LEFT="left",Q5.RIGHT="right",Q5.TOP="top",Q5.BOTTOM="bottom",Q5.BASELINE="alphabetic",Q5.MIDDLE="middle",Q5.NORMAL="normal",Q5.ITALIC="italic",Q5.BOLD="bold",Q5.BOLDITALIC="italic bold",Q5.ROUND="round",Q5.SQUARE="butt",Q5.PROJECT="square",Q5.MITER="miter",Q5.BEVEL="bevel",Q5.CHORD_OPEN=0,Q5.PIE_OPEN=1,Q5.PIE=2,Q5.CHORD=3,Q5.RADIUS="radius",Q5.CORNER="corner",Q5.CORNERS="corners",Q5.OPEN=0,Q5.CLOSE=1,Q5.VIDEO="video",Q5.AUDIO="audio",Q5.LANDSCAPE="landscape",Q5.PORTRAIT="portrait",Q5.BLEND="source-over",Q5.REMOVE="destination-out",Q5.ADD="lighter",Q5.DARKEST="darken",Q5.LIGHTEST="lighten",Q5.DIFFERENCE="difference",Q5.SUBTRACT="subtract",Q5.EXCLUSION="exclusion",Q5.MULTIPLY="multiply",Q5.SCREEN="screen",Q5.REPLACE="copy",Q5.OVERLAY="overlay",Q5.HARD_LIGHT="hard-light",Q5.SOFT_LIGHT="soft-light",Q5.DODGE="color-dodge",Q5.BURN="color-burn",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.SEPIA=9,Q5.BRIGHTNESS=10,Q5.SATURATION=11,Q5.CONTRAST=12,Q5.HUE_ROTATE=13,Q5.C2D=Q5.P2D=Q5.P2DHDR="c2d",Q5.WEBGL="webgl",Q5.WEBGPU="webgpu",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.c2d={},Q5.renderers.c2d.canvas=(e,t)=>{let r=e.canvas;if(e.colorMode&&e.colorMode("srgb"!=Q5.canvasOptions.colorSpace?"rgb":"srgb",255),e._createCanvas=function(a,n,o){if(r)return t.ctx=t.drawingContext=r.getContext("2d",o),"image"!=e._scope&&(e.ctx.fillStyle=e._fill="white",e.ctx.strokeStyle=e._stroke="black",e.ctx.lineCap="round",e.ctx.lineJoin="miter",e.ctx.textAlign="left",e._strokeWeight=1),e.ctx.scale(e._pixelDensity,e._pixelDensity),e.ctx.save(),r;console.error("q5 canvas could not be created. skia-canvas and jsdom packages not found.")},e.clear=()=>{e.ctx.save(),e.ctx.resetTransform(),e.ctx.clearRect(0,0,e.canvas.width,e.canvas.height),e.ctx.restore()},"image"==e._scope)return;e.background=function(t){e.ctx.save(),e.ctx.resetTransform(),e.ctx.globalAlpha=1,t.canvas?e.image(t,0,0,e.canvas.width,e.canvas.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._resizeCanvas=(t,a)=>{let n,o={};for(let t in e.ctx)"function"!=typeof e.ctx[t]&&(o[t]=e.ctx[t]);if(delete o.canvas,e.frameCount>1){n=new e._Canvas(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),n&&e.ctx.drawImage(n,0,0,n.w,n.h)},e.fill=function(t){if(e._doFill=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=e._fill=t.toString()},e.stroke=function(t){if(e._doStroke=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=e._stroke=t.toString()},e.strokeWeight=t=>{t||(e._doStroke=!1),e._da&&(t*=e._da),e.ctx.lineWidth=e._strokeWeight=t||1e-4},e.noFill=()=>e._doFill=!1,e.noStroke=()=>e._doStroke=!1,e.opacity=t=>e.ctx.globalAlpha=t,e._doShadow=!1,e._shadowOffsetX=e._shadowOffsetY=e._shadowBlur=10,e.shadow=function(t){Q5.Color&&(t._q5Color||("string"!=typeof t?t=e.color(...arguments):e._namedColors[t]&&(t=e.color(...e._namedColors[t])))),e.ctx.shadowColor=e._shadow=t.toString(),e._doShadow=!0,e.ctx.shadowOffsetX||=e._shadowOffsetX,e.ctx.shadowOffsetY||=e._shadowOffsetY,e.ctx.shadowBlur||=e._shadowBlur},e.shadowBox=(t,r,a)=>{e.ctx.shadowOffsetX=e._shadowOffsetX=t,e.ctx.shadowOffsetY=e._shadowOffsetY=r||t,e.ctx.shadowBlur=e._shadowBlur=a||0},e.noShadow=()=>{e._doShadow=!1,e.ctx.shadowOffsetX=e.ctx.shadowOffsetY=e.ctx.shadowBlur=0},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)=>{t.x&&(r=t.y,t=t.x),r??=t,e.ctx.scale(t,r)},e.applyMatrix=(t,r,a,n,o,i)=>e.ctx.transform(t,r,a,n,o,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&&(e.ctx.resetTransform(),e.scale(e._pixelDensity),e._webgpuFallback&&e.translate(e.canvas.hw,e.canvas.hh))},e.pushMatrix=()=>e.ctx.save(),e.popMatrix=()=>e.ctx.restore();let a=e.popStyles;e.popStyles=()=>{a(),e.ctx.fillStyle=e._fill,e.ctx.strokeStyle=e._stroke,e.ctx.lineWidth=e._strokeWeight,e.ctx.shadowColor=e._shadow,e.ctx.shadowOffsetX=e._doShadow?e._shadowOffsetX:0,e.ctx.shadowOffsetY=e._doShadow?e._shadowOffsetY:0,e.ctx.shadowBlur=e._doShadow?e._shadowBlur:0},e.push=()=>{e.ctx.save(),e.pushStyles()},e.pop=()=>{e.ctx.restore(),a()}},Q5.renderers.c2d.shapes=e=>{e._doStroke=!0,e._doFill=!0,e._strokeSet=!1,e._fillSet=!1,e._ellipseMode=Q5.CENTER,e._rectMode=Q5.CORNER,e._curveDetail=20,e._curveAlpha=0;let t=!0,r=[];function a(){e._doFill&&e.ctx.fill(),e._doStroke&&e.ctx.stroke()}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.line=(t,r,a,n)=>{e._doStroke&&(e._da&&(t*=e._da,r*=e._da,a*=e._da,n*=e._da),e.ctx.beginPath(),e.ctx.moveTo(t,r),e.ctx.lineTo(a,n),e.ctx.stroke())};const n=2*Math.PI;function o(t,r,a,o,i,s,l){if(e._angleMode&&(i=e.radians(i),s=e.radians(s)),(i%=n)<0&&(i+=n),(s%=n)<0&&(s+=n),i>s&&(s+=n),i==s)return e.ellipse(t,r,a,o);if(a/=2,o/=2,e._doFill||l!=e.PIE_OPEN||(l=e.CHORD_OPEN),e.ctx.beginPath(),e.ctx.ellipse(t,r,a,o,0,i,s),l!=e.PIE&&l!=e.PIE_OPEN||e.ctx.lineTo(t,r),e._doFill&&e.ctx.fill(),e._doStroke){if(l!=e.PIE&&l!=e.CHORD||e.ctx.closePath(),l!=e.PIE_OPEN)return e.ctx.stroke();e.ctx.beginPath(),e.ctx.ellipse(t,r,a,o,0,i,s),e.ctx.stroke()}}function i(t,r,o,i){e.ctx.beginPath(),e.ctx.ellipse(t,r,o/2,i/2,0,0,n),a()}function s(t,r,n,o,i,l,d,c){return void 0===i?function(t,r,n,o){e._da&&(t*=e._da,r*=e._da,n*=e._da,o*=e._da),e.ctx.beginPath(),e.ctx.rect(t,r,n,o),a()}(t,r,n,o):void 0===l?s(t,r,n,o,i,i,i,i):(e._da&&(t*=e._da,r*=e._da,n*=e._da,o*=e._da,i*=e._da,l*=e._da,c*=e._da,d*=e._da),e.ctx.roundRect(t,r,n,o,[i,l,d,c]),void a())}e.arc=(t,r,a,n,i,s,l)=>{if(i==s)return e.ellipse(t,r,a,n);e._da&&(t*=e._da,r*=e._da,a*=e._da,n*=e._da),l??=e.PIE_OPEN,e._ellipseMode==e.CENTER?o(t,r,a,n,i,s,l):e._ellipseMode==e.RADIUS?o(t,r,2*a,2*n,i,s,l):e._ellipseMode==e.CORNER?o(t+a/2,r+n/2,a,n,i,s,l):e._ellipseMode==e.CORNERS&&o((t+a)/2,(r+n)/2,a-t,n-r,i,s,l)},e.ellipse=(t,r,a,n)=>{n??=a,e._da&&(t*=e._da,r*=e._da,a*=e._da,n*=e._da),e._ellipseMode==e.CENTER?i(t,r,a,n):e._ellipseMode==e.RADIUS?i(t,r,2*a,2*n):e._ellipseMode==e.CORNER?i(t+a/2,r+n/2,a,n):e._ellipseMode==e.CORNERS&&i((t+a)/2,(r+n)/2,a-t,n-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,n),a()):e.ellipse(t,r,o,o)},e.point=(t,r)=>{e._doStroke&&(t.x&&(r=t.y,t=t.x),e._da&&(t*=e._da,r*=e._da),e.ctx.beginPath(),e.ctx.moveTo(t,r),e.ctx.lineTo(t,r),e.ctx.stroke())},e.rect=(t,r,a,n=a,o,i,l,d)=>{e._rectMode==e.CENTER?s(t-a/2,r-n/2,a,n,o,i,l,d):e._rectMode==e.RADIUS?s(t-a,r-n,2*a,2*n,o,i,l,d):e._rectMode==e.CORNER?s(t,r,a,n,o,i,l,d):e._rectMode==e.CORNERS&&s(t,r,a-t,n-r,o,i,l,d)},e.square=(t,r,a,n,o,i,s)=>e.rect(t,r,a,a,n,o,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,n)=>{e._da&&(a*=e._da,n*=e._da),r=[],t?e.ctx.moveTo(a,n):e.ctx.lineTo(a,n),t=!1},e.bezierVertex=(t,a,n,o,i,s)=>{e._da&&(t*=e._da,a*=e._da,n*=e._da,o*=e._da,i*=e._da,s*=e._da),r=[],e.ctx.bezierCurveTo(t,a,n,o,i,s)},e.quadraticVertex=(t,a,n,o)=>{e._da&&(t*=e._da,a*=e._da,n*=e._da,o*=e._da),r=[],e.ctx.quadraticCurveTo(t,a,n,o)},e.bezier=(t,r,a,n,o,i,s,l)=>{e.beginShape(),e.vertex(t,r),e.bezierVertex(a,n,o,i,s,l),e.endShape()},e.triangle=(t,r,a,n,o,i)=>{e.beginShape(),e.vertex(t,r),e.vertex(a,n),e.vertex(o,i),e.endShape(e.CLOSE)},e.quad=(t,r,a,n,o,i,s,l)=>{e.beginShape(),e.vertex(t,r),e.vertex(a,n),e.vertex(o,i),e.vertex(s,l),e.endShape(e.CLOSE)},e.endShape=t=>{r=[],t&&e.ctx.closePath(),a()},e.curveVertex=(a,n)=>{if(e._da&&(a*=e._da,n*=e._da),r.push([a,n]),r.length<4)return;let o=r.at(-4),i=r.at(-3),s=r.at(-2),l=r.at(-1),d=i[0]+(s[0]-o[0])/6,c=i[1]+(s[1]-o[1])/6,h=s[0]-(l[0]-i[0])/6,u=s[1]-(l[1]-i[1])/6;t&&(e.ctx.moveTo(i[0],i[1]),t=!1),e.ctx.bezierCurveTo(d,c,h,u,s[0],s[1])},e.curve=(t,r,a,n,o,i,s,l)=>{e.beginShape(),e.curveVertex(t,r),e.curveVertex(a,n),e.curveVertex(o,i),e.curveVertex(s,l),e.endShape()},e.curvePoint=(e,t,r,a,n)=>{const o=n*n*n,i=n*n;return e*(-.5*o+i-.5*n)+t*(1.5*o-2.5*i+1)+r*(-1.5*o+2*i+.5*n)+a*(.5*o-.5*i)},e.bezierPoint=(e,t,r,a,n)=>{const o=1-n;return Math.pow(o,3)*e+3*Math.pow(o,2)*n*t+3*o*Math.pow(n,2)*r+Math.pow(n,3)*a},e.curveTangent=(e,t,r,a,n)=>{const o=n*n;return e*(-3*o/2+2*n-.5)+t*(9*o/2-5*n)+r*(-9*o/2+4*n+.5)+a*(3*o/2-n)},e.bezierTangent=(e,t,r,a,n)=>{const o=1-n;return 3*a*Math.pow(n,2)-3*r*Math.pow(n,2)+6*r*o*n-6*t*o*n+3*t*Math.pow(o,2)-3*e*Math.pow(o,2)},e.erase=function(t=255,r=255){e.ctx.save(),e.ctx.globalCompositeOperation="destination-out",e.ctx.fillStyle=`rgb(0 0 0 / ${t/255})`,e.ctx.strokeStyle=`rgb(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.c2d.image=(e,t)=>{Q5.Image??=class{constructor(e,r,a={}){let n=this;n._scope="image",n.canvas=n.ctx=n.drawingContext=null,n.pixels=[],Q5.modules.canvas(n,n);let o=Q5.renderers.c2d;for(let e of["canvas","image","soft_filters"])o[e]&&o[e](n,n);n._pixelDensity=a.pixelDensity||1,n.createCanvas(e,r,a);let i=n._pixelDensity*t._defaultImageScale;n.defaultWidth=e*i,n.defaultHeight=r*i,delete n.createCanvas,n._loop=!1}get w(){return this.width}get h(){return this.height}},e._tint=null;let r=null;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,n){if(r.canvas)return r;if("gif"==r.slice(-3).toLowerCase())throw new Error("q5 doesn't support GIFs. Use a video or p5play animation instead. https://github.com/q5js/q5.js/issues/84");t._preloadCount++;let o=[...arguments].at(-1);"object"==typeof o?(n=o,a=null):n=null;let i=e.createImage(1,1,n),s=i._pixelDensity,l=new window.Image;return l.crossOrigin="Anonymous",i._loader=new Promise(((r,n)=>{l.onload=()=>{l._pixelDensity=s,i.defaultWidth=l.width*e._defaultImageScale,i.defaultHeight=l.height*e._defaultImageScale,i.naturalWidth=l.naturalWidth||l.width,i.naturalHeight=l.naturalHeight||l.height,i._setImageSize(Math.ceil(i.naturalWidth/s),Math.ceil(i.naturalHeight/s)),i.ctx.drawImage(l,0,0),t._preloadCount--,a&&a(i),delete i._loader,r(i)},l.onerror=e=>{t._preloadCount--,n(e)}})),i.src=l.src=r,e._disablePreload?i._loader:i},e.imageMode=t=>e._imageMode=t,e.image=(t,r,a,n,o,i=0,s=0,l,d)=>{if(!t)return;let c=t.canvas||t;n??=t.defaultWidth||c.width||t.videoWidth,o??=t.defaultHeight||c.height||t.videoHeight,"center"==e._imageMode&&(r-=.5*n,a-=.5*o),e._da&&(r*=e._da,a*=e._da,n*=e._da,o*=e._da,i*=e._da,s*=e._da,l*=e._da,d*=e._da);let h=t._pixelDensity||1;if(l?l*=h:l=c.width||c.videoWidth,d?d*=h:d=c.height||c.videoHeight,e._tint){if(t._retint||t._tint!=e._tint){t._tintImg??=e.createImage(t.w,t.h,{pixelDensity:h}),t._tintImg.width==t.width&&t._tintImg.height==t.height||t._tintImg.resize(t.w,t.h);let r=t._tintImg.ctx;r.globalCompositeOperation="copy",r.fillStyle=e._tint,r.fillRect(0,0,t.width,t.height),t.canvas.alpha&&(r.globalCompositeOperation="destination-in",r.drawImage(c,0,0,t.width,t.height)),r.globalCompositeOperation="multiply",r.drawImage(c,0,0,t.width,t.height),t._tint=e._tint,t._retint=!1}c=t._tintImg.canvas}t.flipped&&(e.ctx.save(),e.ctx.translate(r+n,0),e.ctx.scale(-1,1),r=0),e.ctx.drawImage(c,i*h,s*h,l,d,r,a,n,o),t.flipped&&e.ctx.restore()},e.filter=(t,r)=>{e.ctx.save();let a="";if(e.ctx.filter){if("string"==typeof t)a=t;else if(t==Q5.GRAY)a="saturate(0%)";else if(t==Q5.INVERT)a="invert(100%)";else if(t==Q5.BLUR){a=`blur(${Math.ceil(r*e._pixelDensity)||1}px)`}else if(t==Q5.THRESHOLD){r??=.5,a=`saturate(0%) brightness(${Math.floor(.5/Math.max(r,1e-5)*100)}%) contrast(1000000%)`}else if(t==Q5.SEPIA)a=`sepia(${r??1})`;else if(t==Q5.BRIGHTNESS)a=`brightness(${r??1})`;else if(t==Q5.SATURATION)a=`saturate(${r??1})`;else if(t==Q5.CONTRAST)a=`contrast(${r??1})`;else if(t==Q5.HUE_ROTATE){a=`hue-rotate(${r}${0==e._angleMode?"rad":"deg"})`}if(a&&(e.ctx.filter=a,"none"==e.ctx.filter))throw new Error(`Invalid filter format: ${t}`)}a||e._softFilter(t,r),e.ctx.globalCompositeOperation="source-over",e.ctx.drawImage(e.canvas,0,0,e.canvas.w,e.canvas.h),e.ctx.restore(),e.modified=e._retint=!0},"image"==e._scope&&(e.resize=(t,r)=>{let a=e.canvas,n=new e._Canvas(a.width,a.height);n.getContext("2d",{colorSpace:a.colorSpace}).drawImage(a,0,0),e._setImageSize(t,r),e.defaultWidth=a.width*e._defaultImageScale,e.defaultHeight=a.height*e._defaultImageScale,e.ctx.clearRect(0,0,a.width,a.height),e.ctx.drawImage(n,0,0,a.width,a.height),e.modified=e._retint=!0}),e._getImageData=(t,r,a,n)=>e.ctx.getImageData(t,r,a,n,{colorSpace:e.canvas.colorSpace}),e.trim=()=>{let t=e._pixelDensity||1,r=e.canvas.width,a=e.canvas.height,n=e._getImageData(0,0,r,a).data,o=r,i=0,s=a,l=0,d=3;for(let e=0;e<a;e++)for(let t=0;t<r;t++)0!==n[d]&&(t<o&&(o=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),o=Math.floor(o/t),i=Math.floor(i/t),e.get(o,s,i-o+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.modified=e._retint=!0},e.inset=(t,r,a,n,o,i,s,l)=>{let d=e._pixelDensity||1;e.ctx.drawImage(e.canvas,t*d,r*d,a*d,n*d,o,i,s,l),e.modified=e._retint=!0},e.copy=()=>{let t=e.get();for(let r in e)"function"==typeof e[r]||/(canvas|ctx|texture|textureIndex)/.test(r)||(t[r]=e[r]);return t},e.get=(t,r,a,n)=>{let o=e._pixelDensity||1;if(void 0!==t&&void 0===a){let a=e._getImageData(t*o,r*o,1,1).data;return[a[0],a[1],a[2],a[3]/255]}t=Math.floor(t||0)*o,r=Math.floor(r||0)*o,a??=e.width,n??=e.height;let i=e.createImage(a,n,{pixelDensity:o});return i.ctx.drawImage(e.canvas,t,r,a*o,n*o,0,0,a,n),i.width=a,i.height=n,i},e.set=(t,r,a)=>{if(t=Math.floor(t),r=Math.floor(r),e.modified=e._retint=!0,a.canvas){let n=e._tint;return e._tint=null,e.image(a,t,r),void(e._tint=n)}e.pixels.length||e.loadPixels();let n=e._pixelDensity||1;for(let o=0;o<n;o++)for(let i=0;i<n;i++){let s=4*((r*n+o)*e.canvas.width+t*n+i);e.pixels[s]=a.r,e.pixels[s+1]=a.g,e.pixels[s+2]=a.b,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.modified=e._retint=!0)},e.smooth=()=>e.ctx.imageSmoothingEnabled=!0,e.noSmooth=()=>e.ctx.imageSmoothingEnabled=!1,"image"!=e._scope&&(e._saveCanvas=async(e,t)=>{if((e=e.canvas||e)instanceof OffscreenCanvas){const r=await e.convertToBlob({type:"image/"+t});return await new Promise((e=>{const t=new FileReader;t.onloadend=()=>e(t.result),t.readAsDataURL(r)}))}return e.toDataURL("image/"+t)},e.tint=function(t){e._tint=(t._q5Color?t:e.color(...arguments)).toString()},e.noTint=()=>e._tint=null)},Q5.renderers.c2d.soft_filters=e=>{let t=null;function r(){let r=e.canvas.width*e.canvas.height*4;t&&t.length==r||(t=new Uint8ClampedArray(r))}e._softFilter=(a,n)=>{e._filters||(e._filters=[],e._filters[Q5.THRESHOLD]=(e,t)=>{void 0===t?t=127.5:t*=255;for(let r=0;r<e.length;r+=4){const a=.2126*e[r]+.7152*e[r+1]+.0722*e[r+2];e[r]=e[r+1]=e[r+2]=a>=t?255:0}},e._filters[Q5.GRAY]=e=>{for(let t=0;t<e.length;t+=4){const r=.2126*e[t]+.7152*e[t+1]+.0722*e[t+2];e[t]=e[t+1]=e[t+2]=r}},e._filters[Q5.OPAQUE]=e=>{for(let t=0;t<e.length;t+=4)e[t+3]=255},e._filters[Q5.INVERT]=e=>{for(let t=0;t<e.length;t+=4)e[t]=255-e[t],e[t+1]=255-e[t+1],e[t+2]=255-e[t+2]},e._filters[Q5.POSTERIZE]=(e,t=4)=>{let r=t-1;for(let a=0;a<e.length;a+=4)e[a]=255*(e[a]*t>>8)/r,e[a+1]=255*(e[a+1]*t>>8)/r,e[a+2]=255*(e[a+2]*t>>8)/r},e._filters[Q5.DILATE]=(a,n)=>{n??=Math.max,r(),t.set(a);let[o,i]=[e.canvas.width,e.canvas.height];for(let e=0;e<i;e++)for(let r=0;r<o;r++){let s=4*Math.max(r-1,0),l=4*Math.min(r+1,o-1),d=4*Math.max(e-1,0)*o,c=4*Math.min(e+1,i-1)*o,h=4*e*o,u=4*r;for(let e=0;e<4;e++){let r=e+d,o=e+c,i=e+h;a[h+u+e]=n(t[r+u],t[i+s],t[i+u],t[i+l],t[o+u])}}},e._filters[Q5.ERODE]=t=>{e._filters[Q5.DILATE](t,Math.min)},e._filters[Q5.BLUR]=(a,n)=>{n=n||1,n=Math.floor(n*e._pixelDensity),r(),t.set(a);let o=2*n+1,i=function(e){let t=new Float32Array(e),r=.3*n+.8,a=r*r*2;for(let n=0;n<e;n++){let o=n-e/2,i=Math.exp(-o*o/a)/(2.5066282746*r);t[n]=i}return t}(o),[s,l]=[e.canvas.width,e.canvas.height];for(let e=0;e<l;e++)for(let r=0;r<s;r++){let l=0,d=0,c=0,h=0;for(let a=0;a<o;a++){let o=4*(e*s+Math.min(Math.max(r-n+a,0),s-1));l+=t[o]*i[a],d+=t[o+1]*i[a],c+=t[o+2]*i[a],h+=t[o+3]*i[a]}let u=4*(e*s+r);a[u]=l,a[u+1]=d,a[u+2]=c,a[u+3]=h}t.set(a);for(let e=0;e<l;e++)for(let r=0;r<s;r++){let d=0,c=0,h=0,u=0;for(let a=0;a<o;a++){let o=4*(Math.min(Math.max(e-n+a,0),l-1)*s+r);d+=t[o]*i[a],c+=t[o+1]*i[a],h+=t[o+2]*i[a],u+=t[o+3]*i[a]}let p=4*(e*s+r);a[p]=d,a[p+1]=c,a[p+2]=h,a[p+3]=u}});let o=e._getImageData(0,0,e.canvas.width,e.canvas.height);e._filters[a](o.data,n),e.ctx.putImageData(o,0,0)}},Q5.renderers.c2d.text=(e,t)=>{e._textAlign="left",e._textBaseline="alphabetic",e._textSize=12;let r="sans-serif",a=!1,n=15,o=3,i="normal",s=!1,l=0,d=[],c=!1,h=!1,u=0,p=12e3,f=e._textCache={};e.loadFont=(r,a)=>{t._preloadCount++;let n=r.split("/").pop().split(".")[0].replace(" ",""),o=new FontFace(n,`url(${r})`);return document.fonts.add(o),o._loader=(async()=>{let e;try{await o.load()}catch(t){e=t}if(t._preloadCount--,delete o._loader,e)throw e;return a&&a(o),o})(),e.textFont(n),e._disablePreload?o._loader:o},e.textFont=e=>{if(e&&"string"!=typeof e&&(e=e.family),!e||e==r)return r;r=e,s=!0,l=-1},e.textSize=t=>{if(null==t||t==e._textSize)return e._textSize;e._da&&(t*=e._da),e._textSize=t,s=!0,l=-1,a||(n=1.25*t,o=n-t)},e.textStyle=e=>{if(!e||e==i)return i;i=e,s=!0,l=-1},e.textLeading=t=>null==t?n||1.25*e._textSize:(a=!0,t==n?n:(e._da&&(t*=e._da),n=t,o=t-e._textSize,void(l=-1))),e.textAlign=(t,r)=>{e.ctx.textAlign=e._textAlign=t,r&&(e.ctx.textBaseline=e._textBaseline=r==e.CENTER?"middle":r)};const g=()=>{e.ctx.font=`${i} ${e._textSize}px ${r}`,s=!1};e.textWidth=t=>(s&&g(),e.ctx.measureText(t).width),e.textAscent=t=>(s&&g(),e.ctx.measureText(t).actualBoundingBoxAscent),e.textDescent=t=>(s&&g(),e.ctx.measureText(t).actualBoundingBoxDescent),e.textFill=e.fill,e.textStroke=e.stroke;e.textCache=(e,t)=>(t&&(p=t),void 0!==e&&(c=e),c),e.createTextImage=(t,r,a)=>{h=!0;let n=e.text(t,0,0,r,a);return h=!1,n};let _=[];e.text=(t,a,g,m,x)=>{if(void 0===t||!e._doFill&&!e._doStroke)return;t=t.toString(),e._da&&(a*=e._da,g*=e._da);let v,y,b,w,S=e.ctx;if(s&&(S.font=`${i} ${e._textSize}px ${r}`,s=!1),(c||h)&&(-1==l&&(()=>{let t=r+e._textSize+i+n,a=5381;for(let e=0;e<t.length;e++)a=33*a^t.charCodeAt(e);l=a>>>0})(),v=f[t],v&&(v=v[l]),v)){if(v._fill==e._fill&&v._stroke==e._stroke&&v._strokeWeight==e._strokeWeight)return h?v:e.textImage(v,a,g);v.clear()}if(-1==t.indexOf("\n")?_[0]=t:_=t.split("\n"),t.length>m){let e=[];for(let t of _){let r=0;for(;r<t.length;){let a=r+m;if(a>=t.length){e.push(t.slice(r));break}let n=t.lastIndexOf(" ",a);(-1===n||n<r)&&(n=a),e.push(t.slice(r,n)),r=n+1}}_=e}if(c||h){if(y=0,b=n*_.length,v)v.modified=!0;else{let r=e.ctx.textBaseline;e.ctx.textBaseline="alphabetic";let a=S.measureText(" "),i=a.fontBoundingBoxAscent,s=a.fontBoundingBoxDescent;e.ctx.textBaseline=r,v=e.createImage.call(e,Math.ceil(S.measureText(t).width),Math.ceil(b+s),{pixelDensity:e._pixelDensity}),v._ascent=i,v._descent=s,v._top=s+o,v._middle=v._top+.5*i,v._bottom=v._top+i,v._leading=n}v._fill=e._fill,v._stroke=e._stroke,v._strokeWeight=e._strokeWeight,S=v.ctx,S.font=e.ctx.font,S.fillStyle=e._fill,S.strokeStyle=e._stroke,S.lineWidth=e.ctx.lineWidth}else y=a,b=g;e._fillSet||(w=S.fillStyle,S.fillStyle="black");let C=0;for(let t of _)if(e._doStroke&&e._strokeSet&&S.strokeText(t,y,b),e._doFill&&S.fillText(t,y,b),b+=n,C++,C>=x)break;if(_=[],e._fillSet||(S.fillStyle=w),c||h){if(d.push(l),(f[t]??={})[l]=v,u++,u>p){let e=Math.ceil(u/2),t=d.splice(0,e);for(let e in f){e=f[e];for(let r of t)delete e[r]}u-=e}if(h)return v;e.textImage(v,a,g)}},e.textImage=(t,r,a)=>{"string"==typeof t&&(t=e.createTextImage(t));let n=e._imageMode;e._imageMode="corner";let o=e._textAlign;"center"==o?r-=t.canvas.hw:"right"==o&&(r-=t.width);let i=e._textBaseline;"alphabetic"==i?a-=t._leading:"middle"==i?a-=t._middle:"bottom"==i?a-=t._bottom:"top"==i&&(a-=t._top),e.image(t,r,a),e._imageMode=n}},Q5.modules.ai=e=>{e.askAI=(e="")=>{throw Q5.disableFriendlyErrors=!1,Error("Ask AI ✨ "+e)},e._askAI=async e=>{let t=e.message?.includes("Ask AI ✨"),r=e.stack?.split("\n");if(!e.stack||r.length<=1)return;let a=1,n="(";for(-1==navigator.userAgent.indexOf("Chrome")&&(a=0,n="@");r[a].indexOf("q5")>=0;)a++;let o=r[a].split(n).at(-1);o.startsWith("blob:")&&(o=o.slice(5));let i=o.split(":"),s=parseInt(i.at(-2));t&&s++,i[i.length-1]=i.at(-1).split(")")[0];let l=i.slice(0,-2).join(":"),d=l.split("/").at(-1);try{let r=(await(await fetch(l)).text()).split("\n"),a=r[s-1].trim(),n="",o=1;for(;n.length<1600&&(s-o>=0&&(n=r[s-o].trim()+"\n"+n),s+o<r.length);)n+=r[s+o].trim()+"\n",o++;let i="https://chatgpt.com/?q=using+q5.js+not+p5.js+"+(t&&e.message.length>10?e.message.slice(10):"Whats+wrong+with+this+line%3F+short+answer")+(t?"":"%0A%0A"+encodeURIComponent(e.name+": "+e.message))+"%0A%0ALine%3A+"+encodeURIComponent(a)+"%0A%0AExcerpt+for+context%3A%0A%0A"+encodeURIComponent(n);if(console.warn("Error in "+d+" on line "+s+":\n\n"+a),console.warn("Ask AI ✨ "+i),t)return window.open(i,"_blank")}catch(e){}}},Q5.modules.color=(e,t)=>{e.RGB=e.RGBA=e._colorMode="rgb",e.HSL="hsl",e.HSB="hsb",e.OKLCH="oklch",e.SRGB="srgb",e.DISPLAY_P3="display-p3",e.colorMode=(r,a,n)=>{e._colorMode=r;let o="srgb"==e.canvas.colorSpace||"srgb"==n;a??=o?"integer":"float",e._colorFormat="float"==a||1==a?1:255,"oklch"==r?t.Color=Q5.ColorOKLCH:"hsl"==r?t.Color=o?Q5.ColorHSL:Q5.ColorHSL_P3:"hsb"==r?t.Color=o?Q5.ColorHSB:Q5.ColorHSB_P3:(255==e._colorFormat?t.Color=o?Q5.ColorRGB_8:Q5.ColorRGB_P3_8:t.Color=o?Q5.ColorRGB:Q5.ColorRGB_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,n)=>{let o=e.Color;if(t._q5Color)return new o(...t.levels);if(null==r){if("string"==typeof t){if("#"==t[0])t.length<=5?(t.length>4&&(n=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&&(n=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]){let e=new o(0,0,0);return e._css=t,e.toString=function(){return this._css},e}[t,r,a,n]=e._namedColors[t]}1==e._colorFormat&&(t/=255,r&&(r/=255),a&&(a/=255),n&&(n/=255))}Array.isArray(t)&&([t,r,a,n]=t)}return null==a?e._colorMode==Q5.OKLCH?new o(t,0,0,r):new o(t,t,t,r):new o(t,r,a,n)},e.red=e=>e.r,e.green=e=>e.g,e.blue=e=>e.b,e.alpha=e=>e.a,e.lightness=t=>{if(t.l)return t.l;let r=100*(.2126*t.r+.7152*t.g+.0722*t.b);return 255==e._colorFormat?r/255:r},e.hue=t=>{if(t.h)return t.h;let r=t.r,a=t.g,n=t.b;255==e._colorFormat&&(r/=255,a/=255,n/=255);let o,i=Math.max(r,a,n),s=Math.min(r,a,n);return o=i==s?0:i==r?60*(a-n)/(i-s):i==a?60*(n-r)/(i-s)+120:60*(r-a)/(i-s)+240,o<0&&(o+=360),o},e.lerpColor=(t,r,a)=>{if(a=Math.max(0,Math.min(1,a)),"rgb"==e._colorMode)return new e.Color(e.lerp(t.r,r.r,a),e.lerp(t.g,r.g,a),e.lerp(t.b,r.b,a),e.lerp(t.a,r.a,a));{let n=r.h-t.h;n>180&&(n-=360),n<-180&&(n+=360);let o=t.h+a*n;return o<0&&(o+=360),o>360&&(o-=360),new e.Color(e.lerp(t.l,r.l,a),e.lerp(t.c,r.c,a),o,e.lerp(t.a,r.a,a))}}},Q5.Color=class{constructor(){this._q5Color=!0}get alpha(){return this.a}set alpha(e){this.a=e}},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}get levels(){return[this.l,this.c,this.h,this.a]}equals(e){return e&&this.l==e.l&&this.c==e.c&&this.h==e.h&&this.a==e.a}isSameColor(e){return e&&this.l==e.l&&this.c==e.c&&this.h==e.h}toString(){return`oklch(${this.l} ${this.c} ${this.h} / ${this.a})`}get lightness(){return this.l}set lightness(e){this.l=e}get chroma(){return this.c}set chroma(e){this.c=e}get hue(){return this.h}set hue(e){this.h=e}},Q5.ColorRGB=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]}equals(e){return e&&this.r==e.r&&this.g==e.g&&this.b==e.b&&this.a==e.a}isSameColor(e){return e&&this.r==e.r&&this.g==e.g&&this.b==e.b}toString(){return`color(srgb ${this.r} ${this.g} ${this.b} / ${this.a})`}get red(){return this.r}set red(e){this.r=e}get green(){return this.g}set green(e){this.g=e}get blue(){return this.b}set blue(e){this.b=e}},Q5.ColorRGB_P3=class extends Q5.ColorRGB{toString(){return`color(display-p3 ${this.r} ${this.g} ${this.b} / ${this.a})`}},Q5.ColorRGB_8=class extends Q5.ColorRGB{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}toString(){return`rgb(${this.r} ${this.g} ${this.b} / ${this.a/255})`}},Q5.ColorRGB_P3_8=class extends Q5.ColorRGB_8{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.ColorHSL=class extends Q5.Color{constructor(e,t,r,a){super(),this.h=e,this.s=t,this.l=r,this.a=a??1}get levels(){return[this.h,this.s,this.l,this.a]}equals(e){return e&&this.h==e.h&&this.s==e.s&&this.l==e.l&&this.a==e.a}isSameColor(e){return e&&this.h==e.h&&this.s==e.s&&this.l==e.l}toString(){return`hsl(${this.h} ${this.s} ${this.l} / ${this.a})`}get hue(){return this.h}set hue(e){this.h=e}get saturation(){return this.s}set saturation(e){this.s=e}get lightness(){return this.l}set lightness(e){this.l=e}},Q5.ColorHSL_P3=class extends Q5.ColorHSL{toString(){return`color(display-p3 ${Q5.HSLtoRGB(this.h,this.s,this.l).join(" ")} / ${this.a})`}},Q5.ColorHSB=class extends Q5.ColorHSL{constructor(e,t,r,a){super(e,t,r,a),delete this.l,this.b=r}get levels(){return[this.h,this.s,this.b,this.a]}equals(e){return e&&this.h==e.h&&this.s==e.s&&this.b==e.b&&this.a==e.a}isSameColor(e){return e&&this.h==e.h&&this.s==e.s&&this.b==e.b}toString(){return`hsl(${Q5.HSBtoHSL(this.h,this.s,this.b).join(" ")} / ${this.a})`}get v(){return this.b}set v(e){this.b=e}get brightness(){return this.b}set brightness(e){this.b=e}get value(){return this.b}set value(e){this.b=e}},Q5.ColorHSB_P3=class extends Q5.ColorHSB{toString(){return`color(display-p3 ${Q5.HSLtoRGB(...Q5.HSBtoHSL(this.h,this.s,this.b)).join(" ")} / ${this.a})`}},Q5.HSLtoRGB=(e,t,r)=>{r/=100;let a=t/100*Math.min(r,1-r),n=(t,n=(t+e/30)%12)=>r-a*Math.max(Math.min(n-3,9-n,1),-1);return[n(0),n(8),n(4)]},Q5.HSBtoHSL=(e,t,r,a=r*(1-t/200))=>[e,a&&100!=a?(r-a)/Math.min(a,100-a)*100:0,a];{const e=(e,t)=>[e[0]*t[0]+e[1]*t[1]+e[2]*t[2],e[3]*t[0]+e[4]*t[1]+e[5]*t[2],e[6]*t[0]+e[7]*t[1]+e[8]*t[2]],t=(e,t,r)=>[e,isNaN(r)?0:t*Math.cos(r*Math.PI/180),isNaN(r)?0:t*Math.sin(r*Math.PI/180)],r=e=>e.map((e=>Math.max(0,Math.min(1,Math.abs(e)>.0031308?(e<0?-1:1)*(1.055*Math.abs(e)**(1/2.4)-.055):12.92*e)))),a=t=>{const r=e([1,.3963377773761749,.2158037573099136,1,-.1055613458156586,-.0638541728258133,1,-.0894841775298119,-1.2914855480194092],t);return e([1.2268798758459243,-.5578149944602171,.2813910456659647,-.0405757452148008,1.112286803280317,-.0717110580655164,-.0763729366746601,-.4214933324022432,1.5869240198367816],r.map((e=>e**3)))},n=t=>e([3.2409699419045226,-1.537383177570094,-.4986107602930034,-.9692436362808796,1.8759675015077202,.04155505740717559,.05563007969699366,-.20397695888897652,1.0569715142428786],t);Q5.OKLCHtoRGB=(e,o,i)=>r(n(a(t(e,o,i))))}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._server||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.defaultImageScale(1),e.noSmooth&&e.noSmooth(),e.textFont&&e.textFont("monospace")),"default"==t.displayMode||"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="smooth",n=1)=>{"string"==typeof n&&(n=parseFloat(n.slice(1))),"center"==r&&(r="centered"),Object.assign(t,{displayMode:r,renderQuality:a,displayScale:n}),e.ctx&&e.pushStyles(),e._adjustDisplay(),e.ctx&&e.popStyles()},e.fullscreen=e=>{if(void 0===e)return document.fullscreenElement;e?document.body.requestFullscreen():document.body.exitFullscreen()}},Q5.modules.dom=(e,t)=>{e.elementMode=t=>e._elementMode=t,e.createElement=(t,r)=>{let a=document.createElement(t);return"center"==e._elementMode&&(a.style.transform="translate(-50%, -50%)"),r&&(a.innerHTML=r),Object.defineProperty(a,"x",{get:()=>a._x,set:t=>{let r=a.style.position;r&&"relative"!=r||(a.style.position="absolute");let n=e.canvas.offsetLeft+t;a.style.left=n+"px",a._x=n}}),Object.defineProperty(a,"y",{get:()=>a._y,set:t=>{let r=a.style.position;r&&"relative"!=r||(a.style.position="absolute");let n=e.canvas.offsetTop+t;a.style.top=n+"px",a._y=n}}),Object.defineProperty(a,"width",{get:()=>parseFloat(a.style.width||0),set:e=>a.style.width=e+"px"}),Object.defineProperty(a,"height",{get:()=>parseFloat(a.style.height||0),set:e=>a.style.height=e+"px"}),a.position=(e,t,r)=>(r&&(a.style.position=r),a.x=e,a.y=t,a),Object.defineProperty(a,"size",{writable:!0}),a.size=(e,t)=>(a.width=e,a.height=t,a),a.center=()=>(a.style.position="absolute",a.x=e.canvas.hw,a.y=e.canvas.hh,a),a.show=()=>(a.style.display="",a),a.hide=()=>(a.style.display="none",a),a.parent=e=>(e.append(a),a),e._addEventMethods(a),e._elements.push(a),e.canvas?e.canvas.parentElement.append(a):document.body.append(a),a},e.createEl=e.createElement,e._addEventMethods=e=>{let t=e.addEventListener;e.mousePressed=e=>t("mousedown",e),e.mouseReleased=e=>t("mouseup",e),e.mouseClicked=e=>t("click",e),e.mouseMoved=e=>t("mousemove",e),e.mouseWheel=e=>t("wheel",e)},e.createA=(t,r,a)=>{let n=e.createEl("a",r);return n.href=t,n.target=a?"_blank":"_self",n},e.createButton=t=>e.createEl("button",t),e.createCheckbox=(t="",r=!1)=>{let a=e.createEl("input");a.type="checkbox",a.checked=r;let n=e.createEl("label",t);return n.addEventListener("click",(()=>{a.checked=!a.checked,a.dispatchEvent(new Event("input",{bubbles:!0})),a.dispatchEvent(new Event("change",{bubbles:!0}))})),a.insertAdjacentElement("afterend",n),a.label=n,a},e.createColorPicker=(t="#ffffff")=>{let r=e.createEl("input");return r.type="color",r.value=t.toString(),r},e.createDiv=t=>e.createEl("div",t),e.createImg=t=>{let r=e.createEl("img");return r.crossOrigin="anonymous",r.src=t,r},e.createInput=(t="",r="text")=>{let a=e.createEl("input");return a.value=t,a.type=r,a.style.boxSizing="border-box",a},e.createP=t=>e.createEl("p",t);let r=0;e.createRadio=t=>{let a=e.createEl("div");return a.name=t||"radio"+r++,a.buttons=[],Object.defineProperty(a,"value",{get:()=>a.selected?.value,set:e=>{let t=a.buttons.find((t=>t.value==e));t&&(t.checked=!0,a.selected=t)}}),a.option=(t,r)=>{let n=e.createEl("input");n.type="radio",n.name=a.name,n.value=r||t,n.addEventListener("input",(()=>a.selected=n));let o=e.createEl("label",t);return o.addEventListener("click",(()=>{n.checked=!0,a.selected=n,n.dispatchEvent(new Event("input",{bubbles:!0})),n.dispatchEvent(new Event("change",{bubbles:!0}))})),n.label=o,a.append(n),a.append(o),a.buttons.push(n),a},a},e.createSelect=t=>{let r=e.createEl("select");if(t){let a=e.createEl("option",t);a.disabled=!0,a.selected=!0,r.append(a)}return Object.defineProperty(r,"selected",{get:()=>r.multiple?Array.from(r.selectedOptions).map((e=>e.textContent)):r.selectedOptions[0]?.textContent,set:e=>{if(r.multiple)Array.from(r.options).forEach((t=>{t.selected=e.includes(t.textContent)}));else{const t=Array.from(r.options).find((t=>t.textContent===e));t&&(t.selected=!0)}}}),Object.defineProperty(r,"value",{get:()=>r.multiple?Array.from(r.selectedOptions).map((e=>e.value)):r.selectedOptions[0]?.value,set:e=>{if(r.multiple)r.options.forEach((t=>t.selected=e.includes(t.value)));else{let t;for(let a=0;a<r.options.length;a++)if(r.options[a].value==e){t=r.options[a];break}t&&(t.selected=!0)}}}),r.option=(t,a)=>{let n=e.createEl("option",t);return n.value=a||t,r.append(n),r},r},e.createSlider=(t,r,a,n)=>{let o=e.createEl("input");return o.type="range",o.min=t,o.max=r,o.value=a,o.step=n,o.val=()=>parseFloat(o.value),o},e.createSpan=t=>e.createEl("span",t),e.createVideo=r=>{let a=e.createEl("video");return a.crossOrigin="anonymous",a._load=()=>{a.width||=a.videoWidth,a.height||=a.videoHeight,a.defaultWidth=a.width*e._defaultImageScale,a.defaultHeight=a.height*e._defaultImageScale,a.ready=!0},r&&(t._preloadCount++,a._loader=new Promise((e=>{a.addEventListener("loadeddata",(()=>{a._load(),t._preloadCount--,e(a)})),a.src=r})),e._disablePreload)?a._loader:a},e.createCapture=function(r,a=!0,n){t._preloadCount++;let o="string"==typeof r?{[r]:!0}:r||{video:!0,audio:!0};!0===o.video&&(o.video={width:3840,height:2160}),o.video.facingMode??="user";let i=e.createVideo();return i.playsinline=i.autoplay=!0,a&&(i.flipped=!0,i.style.transform="scale(-1, 1)"),i.loadPixels=()=>{let t=e.createGraphics(i.videoWidth,i.videoHeight,{renderer:"c2d"});t.image(i,0,0),t.loadPixels(),i.pixels=t.pixels,t.remove()},i._loader=(async()=>{let e;try{e=await navigator.mediaDevices.getUserMedia(o)}catch(e){throw t._preloadCount--,e}return i.srcObject=e,await new Promise((e=>i.addEventListener("loadeddata",e))),i._load(),n&&n(i),t._preloadCount--,i})(),e._disablePreload?i._loader:i},e.findElement=e=>document.querySelector(e),e.findElements=e=>document.querySelectorAll(e)},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="",e.keyIsPressed=!1,e.mouseIsPressed=!1,e.key="",e.keyCode=0,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=[Q5.LEFT,Q5.CENTER,Q5.RIGHT],n=e.canvas;e._startAudio=()=>{Q5.aud&&"running"==Q5.aud?.state||e.userStartAudio()},e._updateMouse=r=>{if(!r.changedTouches){if(n){let a=n.getBoundingClientRect(),o=n.scrollWidth/e.width||1,i=n.scrollHeight/e.height||1;t.mouseX=(r.clientX-a.left)/o,t.mouseY=(r.clientY-a.top)/i,"webgpu"==n.renderer&&(t.mouseX-=n.hw,t.mouseY-=n.hh)}else t.mouseX=r.clientX,t.mouseY=r.clientY;t.moveX=r.movementX,t.moveY=r.movementY}};let o=0;function i(t){const r=e.canvas.getBoundingClientRect(),a=e.canvas.scrollWidth/e.width||1,n=e.canvas.scrollHeight/e.height||1;return{x:(t.clientX-r.left)/a,y:(t.clientY-r.top)/n,id:t.identifier}}if(e._onmousedown=r=>{o++,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._onwheel=t=>{e._updateMouse(t),t.delta=t.deltaY,(0==e.mouseWheel(t)||e._noScroll)&&t.preventDefault()},e.cursor=(t,r,a)=>{let n="";t.includes(".")&&(t=`url("${t}")`,n=", auto"),void 0!==r&&(t+=" "+r+" "+a),e.canvas.style.cursor=t+n},e.noCursor=()=>e.canvas.style.cursor="none",e.noScroll=()=>e._noScroll=!0,window&&(e.lockMouse=document.body?.requestPointerLock,e.unlockMouse=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(i),e._isTouchAware||(t.mouseX=e.touches[0].x,t.mouseY=e.touches[0].y,t.mouseIsPressed=!0,t.mouseButton=e.LEFT,e.mousePressed(r)),e.touchStarted(r)},e._ontouchmove=r=>{t.touches=[...r.touches].map(i),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(i),e._isTouchAware||e.touches.length||(t.mouseIsPressed=!1,e.mouseReleased(r)||r.preventDefault()),e.touchEnded(r)||r.preventDefault()},n){let t=n.addEventListener.bind(n);t("mousedown",(t=>e._onmousedown(t))),t("wheel",(t=>e._onwheel(t))),t("click",(t=>e._onclick(t))),t("touchstart",(t=>e._ontouchstart(t))),t("touchmove",(t=>e._ontouchmove(t))),t("touchend",(t=>e._ontouchend(t))),t("touchcancel",(t=>e._ontouchend(t)))}if(window){let t=window.addEventListener;t("keydown",(t=>e._onkeydown(t)),!1),t("keyup",(t=>e._onkeyup(t)),!1),n||(t("mousedown",(t=>e._onmousedown(t))),t("wheel",(t=>e._onwheel(t))),t("click",(t=>e._onclick(t)))),t("mousemove",(t=>e._onmousemove(t)),!1),t("mouseup",(t=>{o>0&&(o--,e._onmouseup(t))}))}},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.TWO_PI=e.TAU=2*Math.PI,e.abs=Math.abs,e.ceil=Math.ceil,e.exp=Math.exp,e.floor=e.int=Math.floor,e.loge=Math.log,e.mag=Math.hypot,e.max=Math.max,e.min=Math.min,e.pow=Math.pow,e.sqrt=Math.sqrt,e.SHR3=1,e.LCG=2,e.round=(e,t=0)=>{let r=10**t;return Math.round(e*r)/r};let r=e._angleMode=0;e.angleMode=t=>(r=e._angleMode=0==t||"radians"==t?0:1,r?"degrees":"radians");let a=e._DEGTORAD=Math.PI/180,n=e._RADTODEG=180/Math.PI;function o(){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,n,o)=>{let i=a+1*(e-t)/(r-t)*(n-a);return o?a<n?Math.min(Math.max(i,a),n):Math.min(Math.max(i,n),a):i},e.dist=function(){let e=arguments;return 2==e.length?Math.hypot(e[0].x-e[1].x,e[0].y-e[1].y):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.lerp=(e,t,r)=>e*(1-r)+t*r,e.constrain=(e,t,r)=>Math.min(Math.max(e,t),r),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*n:t},e.acos=e=>{let t=Math.acos(e);return r?t*n:t},e.atan=e=>{let t=Math.atan(e);return r?t*n:t},e.atan2=(e,t)=>{let a=Math.atan2(e,t);return r?a*n:a};let i=o();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())],"c2d"!=e._renderer||e._webgpuFallback?(e.randomX=(t=0)=>e.random(-e.canvas.hw-t,e.canvas.hw+t),e.randomY=(t=0)=>e.random(-e.canvas.hh-t,e.canvas.hh+t)):(e.randomX=(t=0)=>e.random(-t,e.canvas.w+t),e.randomY=(t=0)=>e.random(-t,e.canvas.h+t)),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=o()),i.setSeed()};var s=new function(){var e,t,r,a=new Array(128),n=new Array(256),o=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,n,i,l,d=3.44262;;){if(t=r*o[e],0==e){do{i=h(),l=h(),t=.2904764*-Math.log(i),n=-Math.log(l)}while(n+n<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*o[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())<n[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*o[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,f=p,g=.003949659822581572;for(e=u/Math.exp(-.5*c*c),a[0]=Math.floor(c/e*r),a[1]=0,o[0]=e/r,o[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),o[t]=c/r;for(e=g/Math.exp(-p),n[0]=Math.floor(p/e*i),n[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(g/p+Math.exp(-p)),n[t+1]=Math.floor(p/f*i),f=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.NoiseGenerator=Q5.PerlinNoise,e.noiseMode=e=>{t.NoiseGenerator=Q5[e[0].toUpperCase()+e.slice(1)+"Noise"],l=null},e.noiseSeed=t=>{l=new e.NoiseGenerator(t)},e.noise=(t=0,r=0,a=0)=>(l??=new e.NoiseGenerator,l.noise(t,r,a)),e.noiseDetail=(t,r)=>{l??=new e.NoiseGenerator,t>0&&(l.octaves=t),r>0&&(l.falloff=r)}},Q5.NoiseGenerator=class{},Q5.PerlinNoise=class extends Q5.NoiseGenerator{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 n=255;n>0;n--)t=(e=16807*e%2147483647)%(n+1),r=a[n],a[n]=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,n=0,o=1,i=1,s=0;for(let l=0;l<a.octaves;l++){const l=255&Math.floor(e*o),d=255&Math.floor(t*o),c=255&Math.floor(r*o),h=e*o-Math.floor(e*o),u=t*o-Math.floor(t*o),p=r*o-Math.floor(r*o),f=a.fade(h),g=a.fade(u),_=a.fade(p),m=a.p[l]+d,x=a.p[m]+c,v=a.p[m+1]+c,y=a.p[l+1]+d,b=a.p[y]+c,w=a.p[y+1]+c,S=a.mix(a.dot(a.grad3[a.p[x]%12],h,u,p),a.dot(a.grad3[a.p[b]%12],h-1,u,p),f),C=a.mix(a.dot(a.grad3[a.p[v]%12],h,u-1,p),a.dot(a.grad3[a.p[w]%12],h-1,u-1,p),f),M=a.mix(a.dot(a.grad3[a.p[x+1]%12],h,u,p-1),a.dot(a.grad3[a.p[b+1]%12],h-1,u,p-1),f),Q=a.mix(a.dot(a.grad3[a.p[v+1]%12],h,u-1,p-1),a.dot(a.grad3[a.p[w+1]%12],h-1,u-1,p-1),f),P=a.mix(S,C,g),E=a.mix(M,Q,g);n+=a.mix(P,E,_)*i,s+=i,i*=a.falloff,o*=2}return(n/s+1)/2}},Q5.modules.record=(e,t)=>{let r,a,n,o,i,s,l;function d(t={}){document.head.insertAdjacentHTML("beforeend","<style>\n.rec {\n\tdisplay: flex;\n\tz-index: 1000;\n\tgap: 6px;\n\tbackground: #1a1b1d;\n\tpadding: 6px 8px;\n\tborder-radius: 21px;\n\tbox-shadow: #0000001a 0px 4px 12px;\n\tborder: 2px solid transparent; \n\topacity: 0.6;\n\ttransition: all 0.3s;\n\twidth: 134px;\n\toverflow: hidden;\n}\n\n.rec:hover {\n\twidth: unset;\n\topacity: 0.96;\n}\n\n.rec.recording { border-color: #cc3e44; }\n\n.rec button,\n.rec select { cursor: pointer; }\n\n.rec button,\n.rec select,\n.rec input,\n.rec span {\n\tfont-family: sans-serif;\n\tfont-size: 14px;\n\tpadding: 2px 10px;\n\tborder-radius: 18px;\n\toutline: none;\n\tbackground: #232529;\n\tcolor: #d4dae6;\n\tbox-shadow: #0000001a 0px 4px 12px;\n\tborder: 1px solid #46494e;\n\tvertical-align: middle;\n\tline-height: 18px;\n\ttransition: all 0.3s;\n}\n\n.rec .audio-toggle {\n\tfont-size: 16px;\n\tpadding: 2px 10px;\n}\n\n.rec .bitrate input {\n\tborder-radius: 18px 0 0 18px;\n\tborder-right: 0;\n\twidth: 40px;\n\tpadding: 2px 5px 2px 10px;\n\ttext-align: right;\n}\n\n.rec .bitrate span {\n\tborder-radius: 0 18px 18px 0;\n\tborder-left: 0;\n\tpadding: 2px 10px 2px 5px;\n\tbackground: #333;\n}\n\n.rec .record-button { \n\tcolor: #cc3e44;\n\tfont-size: 18px;\n}\n\n.rec select:hover,\n.rec button:hover { background: #32343b; }\n\n.rec button:disabled {\n\topacity: 0.5;\n\tcolor: #969ba5;\n\tcursor: not-allowed;\n}\n</style>"),r=e.createEl("div"),r.className="rec",r.innerHTML='\n<button class="record-button"></button>\n<span class="record-timer"></span>\n<button></button>\n',[a,o,n]=r.children,r.x=r.y=8,r.resetTimer=()=>r.time={hours:0,minutes:0,seconds:0,frames:0},r.resetTimer();let d="video/mp4; codecs=";r.formats={"H.264":d+'"avc1.42E01E"',VP9:d+"vp9"};let u=d+'"avc1.640034"';e.canvas.width*e.canvas.height>32e5&&MediaRecorder.isTypeSupported(u)&&(r.formats["H.264"]=u),Object.assign(r.formats,t.formats),i=e.createSelect("format");for(const e in r.formats)i.option(e,r.formats[e]);i.title="Video Format",r.append(i);let g=e.createEl("div");g.className="bitrate",g.style.display="flex",r.append(g),s=e.createInput();let _=document.createElement("span");function m(){r.encoderSettings.mimeType=i.value}function x(){r.encoderSettings.videoBitsPerSecond=1e6*s.value}_.textContent="mbps",s.title=_.title="Video Bitrate",g.append(s),g.append(_),l=e.createEl("button"),l.className="audio-toggle active",l.textContent="🔊",l.title="Toggle Audio Recording",r.append(l),r.captureAudio=!0,l.addEventListener("click",(()=>{r.captureAudio=!r.captureAudio,l.textContent=r.captureAudio?"🔊":"🔇",l.classList.toggle("active",r.captureAudio)})),r.encoderSettings={},i.addEventListener("change",m),s.addEventListener("change",x),Object.defineProperty(r,"bitrate",{get:()=>s.value,set:e=>{s.value=e,x()}}),Object.defineProperty(r,"format",{get:()=>i.selected,set:e=>{e=e.toUpperCase(),r.formats[e]&&(i.selected=e,m())}}),r.format="H.264";let v=e.canvas.height;r.bitrate=v>=4320?96:v>=2160?64:v>=1440?48:v>=1080?32:v>=720?26:16,a.addEventListener("click",(()=>{e.recording?r.paused?h():e.pauseRecording():c()})),n.addEventListener("click",(()=>{r.paused?e.saveRecording():e.deleteRecording()})),p(),e.registerMethod("post",f)}function c(){if(!e.recording){if(e.userStartAudio(),!r.stream){r.frameRate??=e.getTargetFrameRate();let t=e.canvas.captureStream(r.frameRate);if(r.videoTrack=t.getVideoTracks()[0],r.captureAudio&&e.getAudioContext){let t=e.getAudioContext(),a=t.createMediaStreamDestination();t.destination.input?t.destination.input.connect(a):Q5.soundOut.connect(a),r.audioTrack=a.stream.getAudioTracks()[0],r.stream=new MediaStream([r.videoTrack,r.audioTrack])}else r.stream=t}r.mediaRecorder=new MediaRecorder(r.stream,r.encoderSettings),r.chunks=[],r.mediaRecorder.addEventListener("dataavailable",(e=>{e.data.size>0&&r.chunks.push(e.data)})),r.mediaRecorder.start(),t.recording=!0,r.paused=!1,r.classList.add("recording"),r.resetTimer(),p(!0)}}function h(){e.recording&&r.paused&&(r.mediaRecorder.resume(),r.paused=!1,p(!0))}function u(){e.recording&&(r.resetTimer(),r.mediaRecorder.stop(),t.recording=!1,r.paused=!1,r.classList.remove("recording"))}function p(e){a.textContent=e?"⏸":"⏺",a.title=(e?"Pause":"Start")+" Recording",n.textContent=e?"🗑️":"💾",n.title=(e?"Delete":"Save")+" Recording",n.disabled=!e}function f(){if(e.recording&&!r.paused){r.time.frames++;let t=e.getTargetFrameRate();r.time.frames>=t&&(r.time.seconds+=Math.floor(r.time.frames/t),r.time.frames%=t,r.time.seconds>=60&&(r.time.minutes+=Math.floor(r.time.seconds/60),r.time.seconds%=60,r.time.minutes>=60&&(r.time.hours+=Math.floor(r.time.minutes/60),r.time.minutes%=60)))}o.textContent=function(){let{hours:e,minutes:t,seconds:a,frames:n}=r.time;return`${String(e).padStart(2,"0")}:${String(t).padStart(2,"0")}:${String(a).padStart(2,"0")}:${String(n).padStart(2,"0")}`}()}e.recording=!1,e.createRecorder=e=>(r||d(e),r),e.record=t=>{r||(d(t),r.hide()),e.recording?r.paused&&h():c()},e.pauseRecording=()=>{e.recording&&!r.paused&&(r.mediaRecorder.pause(),r.paused=!0,p(),a.title="Resume Recording",n.disabled=!1)},e.deleteRecording=()=>{u(),p(),t.recording=!1},e.saveRecording=async a=>{if(!e.recording)return;await new Promise((e=>{r.mediaRecorder.onstop=e,u()}));let n=r.encoderSettings.mimeType,o=n.slice(6,n.indexOf(";")),i=URL.createObjectURL(new Blob(r.chunks,{type:n})),s=document.createElement("iframe"),l=document.createElement("a");s.style.display="none",s.name="download_"+Date.now(),document.body.append(s),l.target=s.name,l.href=i,a??=document.title+" "+(new Date).toLocaleString(void 0,{hour12:!1}).replace(","," at").replaceAll("/","-").replaceAll(":","_"),l.download=`${a}.${o}`,await new Promise((e=>{s.onload=()=>{document.body.removeChild(s),e()},l.click()})),setTimeout((()=>URL.revokeObjectURL(i)),1e3),p(),t.recording=!1}},Q5.modules.sound=(e,t)=>{e.Sound=Q5.Sound;let r=[];e.loadSound=(a,n)=>{t._preloadCount++;let o=new Q5.Sound;return r.push(o),o._loader=(async()=>{let e;try{await o.load(a)}catch(t){e=t}if(t._preloadCount--,delete o._loader,e)throw e;return n&&n(o),o})(),e._disablePreload?o._loader:o},e.loadAudio=(e,r)=>{t._preloadCount++;let a=new Audio(e);a.crossOrigin="Anonymous",a.addEventListener("canplaythrough",(()=>{a.loaded||(t._preloadCount--,a.loaded=!0,r&&r(a))}));let n=()=>{a._preloadSkip=!0,t._preloadCount--};return a.addEventListener("suspend",n),a.addEventListener("error",(e=>{throw n(),e})),a},e.getAudioContext=()=>Q5.aud,e.userStartAudio=()=>{if(window.AudioContext){if(Q5._offlineAudio){Q5._offlineAudio=!1,Q5.aud=new window.AudioContext,Q5.soundOut=Q5.aud.createGain(),Q5.soundOut.connect(Q5.aud.destination);for(let e of r)e.init()}return Q5.aud.resume()}}},window.OfflineAudioContext&&(Q5.aud=new window.OfflineAudioContext(2,1,44100),Q5._offlineAudio=!0,Q5.soundOut=Q5.aud.createGain(),Q5.soundOut.connect(Q5.aud.destination)),Q5.Sound=class{constructor(){this.sources=new Set,this.loaded=this.paused=!1}async load(e){this.url=e;let t=await fetch(e);this.buffer=await t.arrayBuffer(),this.buffer=await Q5.aud.decodeAudioData(this.buffer)}init(){this.gainNode=Q5.aud.createGain(),this.pannerNode=Q5.aud.createStereoPanner(),this.gainNode.connect(this.pannerNode),this.pannerNode.connect(Q5.soundOut),this.loaded=!0,this._volume&&(this.volume=this._volume),this._pan&&(this.pan=this._pan)}_newSource(e,t){let r=Q5.aud.createBufferSource();r.buffer=this.buffer,r.connect(this.gainNode),r.loop=this._loop,r._startedAt=Q5.aud.currentTime,r._offset=e,r._duration=t,r.start(0,r._offset,r._duration),this.sources.add(r),r.onended=()=>{this.paused||(this.ended=!0,this.sources.delete(r))}}play(e=0,t){if(this.loaded){if(this.paused){let e=[];for(let t of this.sources)e.push(t._offset,t._duration),this.sources.delete(t);for(let t=0;t<e.length;t+=2)this._newSource(e[t],e[t+1])}else this._newSource(e,t);this.paused=this.ended=!1}}pause(){if(this.isPlaying()){for(let e of this.sources){e.stop();let t=Q5.aud.currentTime-e._startedAt;e._offset+=t,e._duration&&(e._duration-=t)}this.paused=!0}}stop(){for(let e of this.sources)e.stop(),this.sources.delete(e);this.paused=!1,this.ended=!0}get volume(){return this._volume}set volume(e){this.loaded&&(this.gainNode.gain.value=e),this._volume=e}get pan(){return this._pan}set pan(e){this.loaded&&(this.pannerNode.pan.value=e),this._pan=e}get loop(){return this._loop}set loop(e){this.sources.forEach((t=>t.loop=e)),this._loop=e}get playing(){return!this.paused&&this.sources.size>0}setVolume(e){this.volume=e}setPan(e){this.pan=e}setLoop(e){this.loop=e}isLoaded(){return this.loaded}isPlaying(){return this.playing}isPaused(){return this.paused}isLooping(){return this._loop}},Q5.modules.util=(e,t)=>{e._loadFile=(r,a,n)=>{t._preloadCount++;let o={};return o._loader=new Promise(((i,s)=>{fetch(r).then((e=>e.ok?"json"==n?e.json():e.text():(s("error loading file"),null))).then((r=>{"csv"==n&&(r=e.CSV.parse(r)),"string"==typeof r?o.text=r:Object.assign(o,r),delete o._loader,a&&a(r),t._preloadCount--,i(r)}))})),o},e.loadText=(t,r)=>e._loadFile(t,r,"text"),e.loadJSON=(t,r)=>e._loadFile(t,r,"json"),e.loadCSV=(t,r)=>e._loadFile(t,r,"csv");const r=/(jpe?g|png|gif|webp|avif|svg)/,a=/(ttf|otf|woff2?|eot|json)/,n=/(wav|flac|mp3|ogg|m4a|aac|aiff|weba)/;async function o(t,a,n){if(a=a||"untitled",n=n||"png",r.test(n))t=await e._saveCanvas(t,n);else{let e="text/plain";"json"==n&&("string"!=typeof t&&(t=JSON.stringify(t)),e="text/json"),t=new Blob([t],{type:e}),t=URL.createObjectURL(t)}let o=document.createElement("a");o.href=t,o.download=a+"."+n,o.click(),setTimeout((()=>URL.revokeObjectURL(o.href)),1e3)}e.load=function(...t){Array.isArray(t[0])&&(t=t[0]);let o=[];for(let i of t){let t,s=i.split(".").pop().toLowerCase();t="json"!=s||i.includes("-msdf.")?"csv"==s?e.loadCSV(i):r.test(s)?e.loadImage(i):a.test(s)?e.loadFont(i):n.test(s)?e.loadSound(i):e.loadText(i):e.loadJSON(i),o.push(t._loader)}return 1==t.length?o[0]:Promise.all(o)},e.save=(t,r,a)=>{if((!t||"string"==typeof t&&(!r||!a&&r.length<5))&&(a=r,r=t,t=e.canvas),a)o(t,r,a);else if(r){let e=r.lastIndexOf(".");o(t,r.slice(0,e),r.slice(e+1))}else o(t)},e.CSV={},e.CSV.parse=(e,t=",",r="\n")=>{if(!e.length)return[];let a=[],n=e.split(r),o=n[0].split(t).map((e=>e.replaceAll('"',"")));for(let e=1;e<n.length;e++){let r={},i=n[e].split(t);o.forEach(((e,t)=>r[e]=JSON.parse(i[t]))),a.push(r)}return a},e.canvas&&!Q5._createServerCanvas&&(e.canvas.save=e.saveCanvas=e.save),"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(),e.nf=(e,t,r)=>{let a=e<0,n=(e=Math.abs(e)).toFixed(r).split(".");n[0]=n[0].padStart(t,"0");let o=n.join(".");return a&&(o="-"+o),o}},Q5.modules.vector=e=>{e.Vector=Q5.Vector,e.createVector=(t,r,a)=>new e.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,n=this.x*r+this.y*t;return this.x=a,this.y=n,this}angleBetween(){let e=this._arg2v(...arguments),t=Q5.Vector.cross(this,e);return this._$.atan2(t.mag(),this.dot(e))*Math.sign(t.z||1)}lerp(){let e=[...arguments],t=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(),n=r.mag();if(0==a||0==n)return this.mult(1-t).add(r.mult(t));let o=Q5.Vector.cross(this,r),i=o.mag(),s=Math.atan2(i,this.dot(r));if(i>0)o.div(i);else{if(s<this._$.HALF_PI)return this.mult(1-t).add(r.mult(t));0==this.z&&0==r.z?o.set(0,0,1):0!=this.x?o.set(this.y,-this.x,0).normalize():o.set(1,0,0)}let l=o.cross(this),d=1-t+t*n/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),n=this._$.sin(t),o=this._$.cos(e),i=this._$.sin(e);return this.x=r*i*n,this.y=-r*o,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)=>{e._baseShaderCode="\nstruct Q5 {\n\twidth: f32,\n\theight: f32,\n\thalfWidth: f32,\n\thalfHeight: f32,\n\tpixelDensity: f32,\n\tframeCount: f32,\n\ttime: f32,\n\tdeltaTime: f32,\n\tmouseX: f32,\n\tmouseY: f32,\n\tmouseIsPressed: f32,\n\tkeyCode: f32,\n\tkeyIsPressed: f32\n}";let r=e.canvas;r.width=e.width=500,r.height=e.height=500,e._g=e.createGraphics(1,1,{renderer:"c2d"}),e.colorMode&&e.colorMode("rgb",1);let a,n,o,i,s,l,d,c,h=1,u=8;e._pipelineConfigs=[],e._pipelines=[],e._buffers=[],e._prevFramePL=0,e._framePL=0;let p=e.drawStack=[],f=e.colorStack=new Float32Array(1e6);f.set([0,0,0,1,1,1,1,1]);let g=Q5.device.createBindGroupLayout({label:"mainLayout",entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}}]});e.bindGroupLayouts=[g];let _=Q5.device.createBuffer({size:64,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),m=()=>{let t=[e.canvas.width,e.canvas.height],r="bgra8unorm";o=Q5.device.createTexture({size:t,sampleCount:4,format:r,usage:GPUTextureUsage.RENDER_ATTACHMENT}).createView();let a=GPUTextureUsage.COPY_SRC|GPUTextureUsage.COPY_DST|GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.RENDER_ATTACHMENT;e._frameA=i=Q5.device.createTexture({size:t,format:r,usage:a}),e._frameB=s=Q5.device.createTexture({size:t,format:r,usage:a}),e._frameShaderCode=e._baseShaderCode+"\nstruct VertexParams {\n\t@builtin(vertex_index) vertexIndex: u32\n}\nstruct FragParams {\n\t@builtin(position) position: vec4f,\n\t@location(0) texCoord: vec2f\n}\n\nconst ndc = array(vec2f(-1,-1), vec2f(1,-1), vec2f(-1,1), vec2f(1,1));\nconst quad = array(vec2f(0,1), vec2f(1,1), vec2f(0,0), vec2f(1,0));\n\n@group(0) @binding(0) var<uniform> q: Q5;\n@group(0) @binding(1) var samp: sampler;\n@group(0) @binding(2) var tex: texture_2d<f32>;\n\n@vertex\nfn vertexMain(v: VertexParams) -> FragParams {\n\tvar f: FragParams;\n\tf.position = vec4f(ndc[v.vertexIndex], 0.0, 1.0);\n\tf.texCoord = quad[v.vertexIndex];\n\treturn f;\n}\n\n@fragment\nfn fragMain(f: FragParams ) -> @location(0) vec4f {\n\treturn textureSample(tex, samp, f.texCoord);\n}";let n=Q5.device.createShaderModule({label:"frameShader",code:e._frameShaderCode});d=Q5.device.createSampler({magFilter:"linear",minFilter:"linear"}),l=Q5.device.createBindGroupLayout({label:"frameLayout",entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,texture:{viewDimension:"2d",sampleType:"float"}}]});let c=Q5.device.createPipelineLayout({bindGroupLayouts:[l]});e._pipelineConfigs[0]={layout:c,vertex:{module:n,entryPoint:"vertexMain"},fragment:{module:n,entryPoint:"fragMain",targets:[{format:r}]},primitive:{topology:"triangle-strip"},multisample:{count:4}},e._pipelines[0]=Q5.device.createRenderPipeline(e._pipelineConfigs[0])};e._createCanvas=(a,n,o)=>(t.ctx=t.drawingContext=r.getContext("webgpu"),o.format??=navigator.gpu.getPreferredCanvasFormat(),o.device??=Q5.device,o.alpha&&(o.alphaMode="premultiplied"),e.ctx.configure(o),m(),r),e._resizeCanvas=(t,r)=>{e._setCanvasSize(t,r),m()};let x=(t,r,a,n=1)=>{if("string"==typeof t||"rgb"!=e._colorMode?t=e.color(t,r,a,n):null==a&&(n=r??1,r=a=t),t._q5Color){let e=t;e.r?({r:t,g:r,b:a,a:n}=e):(n=e.a,e=null!=e.c?Q5.OKLCHtoRGB(e.l,e.c,e.h):null!=e.l?Q5.HSLtoRGB(e.h,e.s,e.l):Q5.HSLtoRGB(...Q5.HSBtoHSL(e.h,e.s,e.b)),[t,r,a]=e)}let o=f,i=u;o[i++]=t,o[i++]=r,o[i++]=a,o[i++]=n,u=i,h++};e._stroke=0,e._fill=e._tint=e._globalAlpha=1,e._doFill=e._doStroke=!0,e.fill=(t,r,a,n)=>{x(t,r,a,n),e._doFill=e._fillSet=!0,e._fill=h},e.stroke=(t,r,a,n)=>{x(t,r,a,n),e._doStroke=e._strokeSet=!0,e._stroke=h},e.tint=(t,r,a,n)=>{x(t,r,a,n),e._tint=h},e.opacity=t=>e._globalAlpha=t,e.noFill=()=>e._doFill=!1,e.noStroke=()=>e._doStroke=!1,e.noTint=()=>e._tint=1,e._strokeWeight=1,e._hsw=.5,e._scaledSW=1,e.strokeWeight=t=>{t=Math.abs(t),e._strokeWeight=t,e._scaledSW=t*e._scale,e._hsw=t/2};const v=e._graphics?1e3:1e7,y=new Float32Array(16*v);let b,w=[],S=[];e._matrixDirty=!1,w.push([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),y.set(w[0]),e.resetMatrix=()=>{b=w[0].slice(),e._matrixIndex=0},e.resetMatrix(),e.translate=(t,r,a)=>{(t||r||a)&&(b[12]+=t,b[13]-=r,b[14]+=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),n=b,o=n[0],i=n[1],s=n[4],l=n[5];1!=o||i||s||1!=l?(n[0]=o*r+i*a,n[1]=i*r-o*a,n[4]=s*r+l*a,n[5]=l*r-s*a):(n[0]=r,n[1]=-a,n[4]=a,n[5]=r),e._matrixDirty=!0},e._scale=1,e.scale=(t=1,r,a=1)=>{r??=t,e._scale=Math.max(Math.abs(t),Math.abs(r)),e._scaledSW=e._strokeWeight*e._scale;let n=b;n[0]*=t,n[1]*=t,n[2]*=t,n[3]*=t,n[4]*=r,n[5]*=r,n[6]*=r,n[7]*=r,n[8]*=a,n[9]*=a,n[10]*=a,n[11]*=a,e._matrixDirty=!0},e.shearX=t=>{if(!t)return;e._angleMode&&(t*=e._DEGTORAD);let r=Math.tan(t),a=b,n=a[0],o=a[1],i=a[4],s=a[5];a[0]=n+i*r,a[1]=o+s*r,e._matrixDirty=!0},e.shearY=t=>{if(!t)return;e._angleMode&&(t*=e._DEGTORAD);let r=Math.tan(t),a=b,n=a[0],o=a[1],i=a[4],s=a[5];a[4]=i+n*r,a[5]=s+o*r,e._matrixDirty=!0},e.applyMatrix=(...t)=>{let r;if(r=1==t.length?t[0]:t,9==r.length)r=[r[0],r[1],0,r[2],r[3],r[4],0,r[5],0,0,1,0,r[6],r[7],0,r[8]];else if(16!=r.length)throw new Error("Matrix must be a 3x3 or 4x4 array.");b=r.slice(),e._matrixDirty=!0},e._saveMatrix=()=>{y.set(b,16*w.length),e._matrixIndex=w.length,w.push(b.slice()),e._matrixDirty=!1},e.pushMatrix=()=>{e._matrixDirty&&e._saveMatrix(),S.push(e._matrixIndex)},e.popMatrix=()=>{if(!S.length)return console.warn("Matrix index stack is empty!");let t=S.pop();b=w[t].slice(),e._matrixIndex=t,e._matrixDirty=!1};let C=e.pushStyles;e.pushStyles=()=>{C(),e.strokeWeight(e._strokeWeight)},e.push=()=>{e.pushMatrix(),e.pushStyles()},e.pop=()=>{e.popMatrix(),e.popStyles()},e._calcBox=(e,t,r,a,n)=>{let o,i,s,l;if(n&&"corner"!=n)if("center"==n){let n=r/2,d=a/2;o=e-n,i=e+n,s=-(t-d),l=-(t+d)}else o=e,i=r,s=-t,l=-a;else o=e,i=e+r,s=-t,l=-(t+a);return[o,i,s,l]};let M=["zero","one","src-alpha","one-minus-src-alpha","dst","dst-alpha","one-minus-dst-alpha","one-minus-src"],Q=["add","subtract","reverse-subtract","min","max"];const P={normal:[2,3,0,2,3,0],additive:[1,1,0,1,1,0]};e.blendConfigs={};for(const[t,r]of Object.entries(P))e.blendConfigs[t]={color:{srcFactor:M[r[0]],dstFactor:M[r[1]],operation:Q[r[2]]},alpha:{srcFactor:M[r[3]],dstFactor:M[r[4]],operation:Q[r[5]]}};let E;e._blendMode="normal",e.blendMode=t=>{if(t!=e._blendMode){"source-over"==t&&(t="normal"),"lighter"==t&&(t="additive"),t=t.toLowerCase().replace(/[ -]/g,"_"),e._blendMode=t;for(let r=0;r<e._pipelines.length;r++)e._pipelineConfigs[r].fragment.targets[0].blend=e.blendConfigs[t],e._pipelines[r]=Q5.device.createRenderPipeline(e._pipelineConfigs[r])}},e.clear=()=>{E=!0},e.background=(t,a,n,o)=>{if(e.push(),e.resetMatrix(),t.canvas){let a=t;e._imageMode="corner",e.image(a,-r.hw,-r.hh,r.w,r.h)}else e._rectMode="corner",e.fill(t,a,n,o),e._doStroke=!1,e.rect(-r.hw,-r.hh,r.w,r.h);e.pop()},e._beginRender=()=>{const t=i;i=s,s=t,a=Q5.device.createCommandEncoder(),e._pass=n=a.beginRenderPass({label:"q5-webgpu",colorAttachments:[{view:o,resolveTarget:i.createView(),loadOp:"clear",storeOp:"store",clearValue:[0,0,0,0]}]}),c=Q5.device.createBindGroup({layout:l,entries:[{binding:0,resource:{buffer:_}},{binding:1,resource:d},{binding:2,resource:s.createView()}]}),E||(n.setPipeline(e._pipelines[e._prevFramePL]),n.setBindGroup(0,c),n.draw(4)),E=!1},e._render=()=>{let t=Q5.device.createBuffer({size:16*w.length*4,usage:GPUBufferUsage.STORAGE,mappedAtCreation:!0});new Float32Array(t.getMappedRange()).set(y.slice(0,16*w.length)),t.unmap(),e._buffers.push(t);let r=Q5.device.createBuffer({size:4*u,usage:GPUBufferUsage.STORAGE,mappedAtCreation:!0});new Float32Array(r.getMappedRange()).set(f.slice(0,u)),r.unmap(),e._buffers.push(r),e._uniforms=[e.width,e.height,e.halfWidth,e.halfHeight,e._pixelDensity,e.frameCount,performance.now(),e.deltaTime,e.mouseX,e.mouseY,e.mouseIsPressed?1:0,e.keyCode,e.keyIsPressed?1:0],Q5.device.queue.writeBuffer(_,0,new Float32Array(e._uniforms));let a=Q5.device.createBindGroup({layout:g,entries:[{binding:0,resource:{buffer:_}},{binding:1,resource:{buffer:t}},{binding:2,resource:{buffer:r}}]});n.setBindGroup(0,a);for(let t of e._hooks.preRender)t();let o=0,i=0,s=0,l=-1;for(let t=0;t<p.length;t+=2){let r=p[t+1];if(l!=p[t]&&(l=p[t],n.setPipeline(e._pipelines[l])),4==l||l>=4e3){let a=p[t+2];n.setBindGroup(1,e._fonts[a].bindGroup),n.setBindGroup(2,e._textBindGroup),n.draw(4,r,0,s),s+=r,t++}else 2==l||3==l||l>=2e3?(n.setBindGroup(1,e._textureBindGroups[r]),n.draw(4,1,i),i+=4):(n.draw(r,1,o),o+=r)}},e._finishRender=async()=>{n.end(),n=a.beginRenderPass({colorAttachments:[{view:o,resolveTarget:e.ctx.getCurrentTexture().createView(),loadOp:"clear",storeOp:"store",clearValue:[0,0,0,0]}]}),c=Q5.device.createBindGroup({layout:l,entries:[{binding:0,resource:{buffer:_}},{binding:1,resource:d},{binding:2,resource:i.createView()}]}),n.setPipeline(e._pipelines[e._framePL]),n.setBindGroup(0,c),n.draw(4),n.end(),Q5.device.queue.submit([a.finish()]),e._pass=n=a=null,Q5.device.queue.onSubmittedWorkDone().then((()=>{for(let t of e._buffers)t.destroy();e._buffers=[]})),p.splice(0,p.length),h=1,u=8,w=[w[0]],S=[];for(let t of e._hooks.postRender)t()}},Q5.initWebGPU=async()=>{if(!navigator.gpu)return console.warn("q5 WebGPU not supported on this browser! Use Google Chrome or Edge."),!1;if(!Q5.requestedGPU){let e=await navigator.gpu.requestAdapter();if(!e)return console.warn("q5 WebGPU could not start! No appropriate GPUAdapter found, vulkan may need to be enabled."),!1;Q5.device=await e.requestDevice(),Q5.device.lost.then((e=>{console.error("WebGPU crashed!"),console.error(e)}))}return!0},Q5.WebGPU=async function(e,t){return e&&"global"!=e||(Q5._hasGlobal=!0),await Q5.initWebGPU()?new Q5(e,t,"webgpu"):new Q5(e,t,"webgpu-fallback")},Q5.webgpu=Q5.WebGPU,Q5.renderers.webgpu.shapes=e=>{e._shapesPL=1,e._shapesShaderCode=e._baseShaderCode+"\nstruct VertexParams {\n\t@builtin(vertex_index) vertexIndex : u32,\n\t@location(0) pos: vec2f,\n\t@location(1) colorIndex: f32,\n\t@location(2) matrixIndex: f32\n}\nstruct FragParams {\n\t@builtin(position) position: vec4f,\n\t@location(0) color: vec4f\n}\n\n@group(0) @binding(0) var<uniform> q: Q5;\n@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;\n@group(0) @binding(2) var<storage> colors : array<vec4f>;\n\nfn transformVertex(pos: vec2f, matrixIndex: f32) -> vec4f {\n\tvar vert = vec4f(pos, 0.0, 1.0);\n\tvert = transforms[i32(matrixIndex)] * vert;\n\tvert.x /= q.halfWidth;\n\tvert.y /= q.halfHeight;\n\treturn vert;\n}\n\n@vertex\nfn vertexMain(v: VertexParams) -> FragParams {\n\tvar vert = transformVertex(v.pos, v.matrixIndex);\n\n\tvar f: FragParams;\n\tf.position = vert;\n\tf.color = colors[i32(v.colorIndex)];\n\treturn f;\n}\n\n@fragment\nfn fragMain(f: FragParams) -> @location(0) vec4f {\n\treturn f.color;\n}\n";let t=Q5.device.createShaderModule({label:"shapesShader",code:e._shapesShaderCode}),r=(e.canvas,e.drawStack),a=new Float32Array(e._graphics?1e3:1e7),n=0;const o=2*Math.PI,i=Math.PI/2;let s=Q5.device.createPipelineLayout({label:"shapesPipelineLayout",bindGroupLayouts:e.bindGroupLayouts});e._pipelineConfigs[1]={label:"shapesPipeline",layout:s,vertex:{module:t,entryPoint:"vertexMain",buffers:[{arrayStride:16,attributes:[{format:"float32x2",offset:0,shaderLocation:0},{format:"float32",offset:8,shaderLocation:1},{format:"float32",offset:12,shaderLocation:2}]}]},fragment:{module:t,entryPoint:"fragMain",targets:[{format:"bgra8unorm",blend:e.blendConfigs.normal}]},primitive:{topology:"triangle-strip",stripIndexFormat:"uint32"},multisample:{count:4}},e._pipelines[1]=Q5.device.createRenderPipeline(e._pipelineConfigs[1]);const l=(e,t,r,o)=>{let i=a,s=n;i[s++]=e,i[s++]=t,i[s++]=r,i[s++]=o,n=s},d=(t,o,i,s,l,d,c,h,u,p)=>{let f=a,g=n;f[g++]=t,f[g++]=o,f[g++]=u,f[g++]=p,f[g++]=i,f[g++]=s,f[g++]=u,f[g++]=p,f[g++]=c,f[g++]=h,f[g++]=u,f[g++]=p,f[g++]=l,f[g++]=d,f[g++]=u,f[g++]=p,n=g,r.push(e._shapesPL,4)},c=(t,o,i,s,l,d,c,h,u)=>{let p=(d-l)/c,f=l,g=a,_=n;for(let e=0;e<=c;e++){g[_++]=t,g[_++]=o,g[_++]=h,g[_++]=u;let e=t+i*Math.cos(f),r=o+s*Math.sin(f);g[_++]=e,g[_++]=r,g[_++]=h,g[_++]=u,f+=p}n=_,r.push(e._shapesPL,2*(c+1))},h=(t,o,i,s,l,d,c,h,u,p,f)=>{let g=(h-c)/u,_=c,m=a,x=n;for(let e=0;e<=u;e++){let e=t+i*Math.cos(_),r=o+s*Math.sin(_),a=t+l*Math.cos(_),n=o+d*Math.sin(_);m[x++]=e,m[x++]=r,m[x++]=p,m[x++]=f,m[x++]=a,m[x++]=n,m[x++]=p,m[x++]=f,_+=g}n=x,r.push(e._shapesPL,2*(u+1))};e.rectMode=t=>e._rectMode=t,e.rect=(t,r,a,n,o=0)=>{let s,l,[p,f,g,_]=e._calcBox(t,r,a,n,e._rectMode);if(e._matrixDirty&&e._saveMatrix(),l=e._matrixIndex,!o){if(e._doFill&&(s=e._fill,d(p,g,f,g,f,_,p,_,s,l)),e._doStroke){s=e._stroke;let t=e._strokeWeight/2,r=p-t,a=f+t,n=g+t,o=_-t,i=p+t,c=f-t,h=g-t,u=_+t;d(r,h,a,h,a,n,r,n,s,l),d(r,o,a,o,a,u,r,u,s,l),n=g-t,o=_+t,d(r,n,i,n,i,o,r,o,s,l),d(c,n,a,n,a,o,c,o,s,l)}return}p+=o,f-=o,g-=o,_+=o,o=Math.min(o,Math.min(a,n)/2);let m=u(o*e._scale),x=g+o,v=_-o,y=p-o,b=f+o;if(e._doFill&&(s=e._fill,c(f,_,o,o,-i,0,m,s,l),c(p,_,o,o,-Math.PI,-i,m,s,l),c(p,g,o,o,Math.PI,i,m,s,l),c(f,g,o,o,0,i,m,s,l),d(p,x,f,x,f,v,p,v,s,l),d(p,g,y,g,y,_,p,_,s,l),d(b,g,f,g,f,_,b,_,s,l)),e._doStroke){s=e._stroke;let t=e._hsw,r=o+t,a=o+t,n=o-t,c=o-t;h(f,_,r,a,n,c,-i,0,m,s,l),h(p,_,r,a,n,c,-Math.PI,-i,m,s,l),h(p,g,r,a,n,c,Math.PI,i,m,s,l),h(f,g,r,a,n,c,0,i,m,s,l);let u=y-t,w=y+t,S=b-t,C=b+t,M=x-t,Q=x+t,P=v-t,E=v+t;d(u,g,w,g,w,_,u,_,s,l),d(S,g,C,g,C,_,S,_,s,l),d(p,M,f,M,f,Q,p,Q,s,l),d(p,P,f,P,f,E,p,E,s,l)}},e.square=(t,r,a)=>e.rect(t,r,a,a),e.plane=(t,r,a,n)=>{n??=a;let[o,i,s,l]=e._calcBox(t,r,a,n,"center");e._matrixDirty&&e._saveMatrix(),d(o,s,i,s,i,l,o,l,e._fill,e._matrixIndex)};const u=e=>e<4?6:e<6?8:e<10?10:e<16?12:e<20?14:e<22?16:e<24?18:e<28?20:e<34?22:e<42?24:e<48?26:e<56?28:e<64?30:e<72?32:e<84?34:e<96?36:e<98?38:e<113?40:e<149?44:e<199?48:e<261?52:e<353?56:e<461?60:e<585?64:e<1200?70:e<1800?80:e<2400?90:100;let p;e._ellipseMode=Q5.CENTER,e.ellipseMode=t=>e._ellipseMode=t,e.ellipse=(t,r,a,n)=>{let i=u(Math.max(Math.abs(a),Math.abs(n))*e._scale),s=a/2,l=a==n?s:n/2;e._matrixDirty&&e._saveMatrix();let d=e._matrixIndex;if(e._doFill&&c(t,-r,s,l,0,o,i,e._fill,d),e._doStroke){let a=e._strokeWeight/2;h(t,-r,s+a,l+a,s-a,l-a,0,o,i,e._stroke,d)}},e.circle=(t,r,a)=>e.ellipse(t,r,a,a),e.arc=(t,r,a,n,i,s)=>{if(i===s)return e.ellipse(t,r,a,n);if(e._angleMode&&(i=e.radians(i),s=e.radians(s)),(i%=o)<0&&(i+=o),(s%=o)<0&&(s+=o),i>s&&(s+=o),i==s)return e.ellipse(t,r,a,n);let l,d;e._ellipseMode==e.CENTER?(l=a/2,d=n/2):e._ellipseMode==e.RADIUS?(l=a,d=n):e._ellipseMode==e.CORNER?(t+=a/2,r+=n/2,l=a/2,d=n/2):e._ellipseMode==e.CORNERS&&(l=(a-(t=(t+a)/2))/2,d=(n-(r=(r+n)/2))/2);let p=e._matrixIndex;e._matrixDirty&&e._saveMatrix();let f=u(Math.max(Math.abs(a),Math.abs(n))*e._scale);if(e._doFill&&c(t,-r,l,d,i,s,f,e._fill,p),e._doStroke){let a=e._strokeWeight;h(t,-r,l+a,d+a,l-a,d-a,i,s,f,e._stroke,p)}},e.point=(t,r)=>{e._matrixDirty&&e._saveMatrix();let a=e._matrixIndex,n=e._stroke,i=e._strokeWeight;if(e._scaledSW<2){let[o,s,l,c]=e._calcBox(t,r,i,i,"corner");d(o,l,s,l,s,c,o,c,n,a)}else{let s=u(e._scaledSW);i/=2,c(t,-r,i,i,0,o,s,n,a)}},e._strokeJoin="round",e.strokeJoin=t=>{e._strokeJoin=t},e.line=(t,r,a,n)=>{e._matrixDirty&&e._saveMatrix();let i=e._matrixIndex,s=e._stroke,l=(e._strokeWeight,e._hsw),h=a-t,p=n-r,f=Math.hypot(h,p),g=-p/f*l,_=h/f*l;if(d(t+g,-r-_,t-g,-r+_,a-g,-n+_,a+g,-n-_,s,i),e._scaledSW>2&&"none"!=e._strokeJoin){let d=u(e._scaledSW);c(t,-r,l,l,0,o,d,s,i),c(a,-n,l,l,0,o,d,s,i)}};let f=[],g=[];e.beginShape=()=>{p=0,f=[],g=[]},e.vertex=(t,r)=>{e._matrixDirty&&e._saveMatrix(),f.push(t,-r,e._fill,e._matrixIndex),p++},e.curveVertex=(t,r)=>{e._matrixDirty&&e._saveMatrix(),g.push({x:t,y:-r})},e.endShape=t=>{if(g.length>0){let t=[...g];if(t.length<4)for(;t.length<4;)t.unshift(t[0]),t.push(t[t.length-1]);for(let r=0;r<t.length-3;r++){let a=t[r],n=t[r+1],o=t[r+2],i=t[r+3];for(let t=0;t<=1;t+=.1){let r=t*t,s=r*t,l=.5*(2*n.x+(-a.x+o.x)*t+(2*a.x-5*n.x+4*o.x-i.x)*r+(-a.x+3*n.x-3*o.x+i.x)*s),d=.5*(2*n.y+(-a.y+o.y)*t+(2*a.y-5*n.y+4*o.y-i.y)*r+(-a.y+3*n.y-3*o.y+i.y)*s);f.push(l,d,e._fill,e._matrixIndex),p++}}}if(p<3)throw new Error("A shape must have at least 3 vertices.");if(t){let e=0,t=4*(p-1),r=f[e],a=f[e+1],n=f[t],o=f[t+1];r===n&&a===o||(f.push(r,a,f[e+2],f[e+3]),p++)}if(e._doFill)if(5==p)l(f[0],f[1],f[2],f[3]),l(f[4],f[5],f[6],f[7]),l(f[12],f[13],f[14],f[15]),l(f[8],f[9],f[10],f[11]),r.push(e._shapesPL,4);else{for(let e=1;e<p-1;e++){let t=0,r=4*e,a=4*(e+1);l(f[t],f[t+1],f[t+2],f[t+3]),l(f[r],f[r+1],f[r+2],f[r+3]),l(f[a],f[a+1],f[a+2],f[a+3])}r.push(e._shapesPL,3*(p-2))}if(e._doStroke){let r=e._hsw,a=u(e._scaledSW),n=e._matrixIndex,i=e._strokeJoin;e._strokeJoin="none";for(let t=0;t<p-1;t++){let i=4*t,s=4*(t+1);e.line(f[i],-f[i+1],f[s],-f[s+1]),c(f[i],f[i+1],r,r,0,o,a,e._stroke,n)}if(t){let t=4*(p-1),r=0;e.line(f[t],-f[t+1],f[r],-f[r+1])}e._strokeJoin=i}p=0,f=[],g=[]},e.triangle=(t,r,a,n,o,i)=>{e.beginShape(),e.vertex(t,r),e.vertex(a,n),e.vertex(o,i),e.endShape(!0)},e.quad=(t,r,a,n,o,i,s,l)=>{e.beginShape(),e.vertex(t,r),e.vertex(a,n),e.vertex(o,i),e.vertex(s,l),e.endShape(!0)},e._hooks.preRender.push((()=>{e._pass.setPipeline(e._pipelines[1]);let t=Q5.device.createBuffer({size:4*n,usage:GPUBufferUsage.VERTEX,mappedAtCreation:!0});new Float32Array(t.getMappedRange()).set(a.slice(0,n)),t.unmap(),e._pass.setVertexBuffer(0,t),e._buffers.push(t)})),e._hooks.postRender.push((()=>{n=0}))},Q5.renderers.webgpu.image=(e,t)=>{e._imagePL=2,e._videoPL=3,e._imageShaderCode=e._baseShaderCode+"\nstruct VertexParams {\n\t@builtin(vertex_index) vertexIndex : u32,\n\t@location(0) pos: vec2f,\n\t@location(1) texCoord: vec2f,\n\t@location(2) tintIndex: f32,\n\t@location(3) matrixIndex: f32,\n\t@location(4) imageAlpha: f32\n}\nstruct FragParams {\n\t@builtin(position) position: vec4f,\n\t@location(0) texCoord: vec2f,\n\t@location(1) tintColor: vec4f,\n\t@location(2) imageAlpha: f32\n}\n\n@group(0) @binding(0) var<uniform> q: Q5;\n@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;\n@group(0) @binding(2) var<storage> colors : array<vec4f>;\n\n@group(1) @binding(0) var samp: sampler;\n@group(1) @binding(1) var tex: texture_2d<f32>;\n\nfn transformVertex(pos: vec2f, matrixIndex: f32) -> vec4f {\n\tvar vert = vec4f(pos, 0f, 1f);\n\tvert = transforms[i32(matrixIndex)] * vert;\n\tvert.x /= q.halfWidth;\n\tvert.y /= q.halfHeight;\n\treturn vert;\n}\n\nfn applyTint(texColor: vec4f, tintColor: vec4f) -> vec4f {\n\t// apply the tint color to the sampled texture color at full strength\n\tlet tinted = vec4f(texColor.rgb * tintColor.rgb, texColor.a);\n\t// mix in the tint using the tint alpha as the blend strength\n\treturn mix(texColor, tinted, tintColor.a);\n}\n\n@vertex\nfn vertexMain(v: VertexParams) -> FragParams {\n\tvar vert = transformVertex(v.pos, v.matrixIndex);\n\n\tvar f: FragParams;\n\tf.position = vert;\n\tf.texCoord = v.texCoord;\n\tf.tintColor = colors[i32(v.tintIndex)];\n\tf.imageAlpha = v.imageAlpha;\n\treturn f;\n}\n\n@fragment\nfn fragMain(f: FragParams) -> @location(0) vec4f {\n\tvar texColor = textureSample(tex, samp, f.texCoord);\n\ttexColor.a *= f.imageAlpha;\n\treturn applyTint(texColor, f.tintColor);\n}\n";let r=Q5.device.createShaderModule({label:"imageShader",code:e._imageShaderCode});e._videoShaderCode=e._imageShaderCode.replace("texture_2d<f32>","texture_external").replace("textureSample","textureSampleBaseClampToEdge");let a=Q5.device.createShaderModule({label:"videoShader",code:e._videoShaderCode}),n=new Float32Array(e._graphics?1e3:1e7),o=0,i={arrayStride:28,attributes:[{shaderLocation:0,offset:0,format:"float32x2"},{shaderLocation:1,offset:8,format:"float32x2"},{shaderLocation:2,offset:16,format:"float32"},{shaderLocation:3,offset:20,format:"float32"},{shaderLocation:4,offset:24,format:"float32"}]},s=Q5.device.createBindGroupLayout({label:"textureLayout",entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,texture:{viewDimension:"2d",sampleType:"float"}}]}),l=Q5.device.createBindGroupLayout({label:"videoTextureLayout",entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,externalTexture:{}}]}),d=Q5.device.createPipelineLayout({label:"imagePipelineLayout",bindGroupLayouts:[...e.bindGroupLayouts,s]}),c=Q5.device.createPipelineLayout({label:"videoPipelineLayout",bindGroupLayouts:[...e.bindGroupLayouts,l]});e._pipelineConfigs[2]={label:"imagePipeline",layout:d,vertex:{module:r,entryPoint:"vertexMain",buffers:[{arrayStride:0,attributes:[]},i]},fragment:{module:r,entryPoint:"fragMain",targets:[{format:"bgra8unorm",blend:e.blendConfigs.normal}]},primitive:{topology:"triangle-strip",stripIndexFormat:"uint32"},multisample:{count:4}},e._pipelines[2]=Q5.device.createRenderPipeline(e._pipelineConfigs[2]),e._pipelineConfigs[3]={label:"videoPipeline",layout:c,vertex:{module:a,entryPoint:"vertexMain",buffers:[{arrayStride:0,attributes:[]},i]},fragment:{module:a,entryPoint:"fragMain",targets:[{format:"bgra8unorm",blend:e.blendConfigs.normal}]},primitive:{topology:"triangle-strip",stripIndexFormat:"uint32"},multisample:{count:4}},e._pipelines[3]=Q5.device.createRenderPipeline(e._pipelineConfigs[3]),e._textureBindGroups=[],e._saveCanvas=async(t,r)=>{let a=t.texture,n=a.width,o=a.height,i=256*Math.ceil(4*n/256),s=Q5.device.createBuffer({size:i*o,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ});e._buffers.push(s);let l=Q5.device.createCommandEncoder();l.copyTextureToBuffer({texture:a},{buffer:s,bytesPerRow:i,rowsPerImage:o},{width:n,height:o}),Q5.device.queue.submit([l.finish()]),await s.mapAsync(GPUMapMode.READ);let d=new Uint8Array(s.getMappedRange());t=new Uint8Array(n*o*4);for(let e=0;e<o;e++){const r=e*i,a=e*n*4;for(let e=0;e<n;e++){const n=r+4*e,o=a+4*e;t[o+0]=d[n+2],t[o+1]=d[n+1],t[o+2]=d[n+0],t[o+3]=d[n+3]}}s.unmap();let c=e.canvas.colorSpace;t=new Uint8ClampedArray(t.buffer),t=new ImageData(t,n,o,{colorSpace:c});let h=new e._Canvas(n,o);h.getContext("2d",{colorSpace:c}).putImageData(t,0,0);let u=await h.convertToBlob({type:"image/"+r});return await new Promise((e=>{let t=new FileReader;t.onloadend=()=>e(t.result),t.readAsDataURL(u)}))};let h=t=>{e._imageSampler=Q5.device.createSampler({magFilter:t,minFilter:t})};e.smooth=()=>h("linear"),e.noSmooth=()=>h("nearest"),e.smooth();let u=0,p=0;e._addTexture=(t,r)=>{let a=t.canvas||t,n=[a.width,a.height,1];r||(r=Q5.device.createTexture({size:n,format:"bgra8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT}),Q5.device.queue.copyExternalImageToTexture({source:a},{texture:r,colorSpace:e.canvas.colorSpace},n)),t.texture=r,t.textureIndex=u+p,e._textureBindGroups[t.textureIndex]=Q5.device.createBindGroup({label:t.src||"canvas",layout:s,entries:[{binding:0,resource:e._imageSampler},{binding:1,resource:r.createView()}]}),u++};let f=Q5.Image;Q5.Image=function(t,r){let a=new f(...arguments);return t>1&&r>1&&(e._addTexture(a),a.modified=!0),a},e.loadImage=(r,a)=>{t._preloadCount++;let n=e._g.loadImage(r,(r=>{e._addTexture(r),t._preloadCount--,a&&a(n)}));return n},e.createImage=e._g.createImage;let g=e.createGraphics;e.createGraphics=(t,r,a)=>{let n=g(t,r,a);return"webgpu"==n.canvas.renderer&&(e._addTexture(n,n._frameA),e._addTexture(n,n._frameB),n._beginRender()),n},e.imageMode=t=>e._imageMode=t;const _=(e,t,r,a,i,s,l)=>{let d=n,c=o;d[c++]=e,d[c++]=t,d[c++]=r,d[c++]=a,d[c++]=i,d[c++]=s,d[c++]=l,o=c};e.image=(t,r=0,a=0,n,o,i=0,s=0,d,c)=>{let h;if(null==t.textureIndex){if(h="VIDEO"==t.tagName,!h||!t.width||!t.currentTime)return;t.flipped&&e.scale(-1,1)}let u=t.canvas||t;e._matrixDirty&&e._saveMatrix();let p=u.width,f=u.height,g=t._pixelDensity||1;if(t._graphics){let e=t;e.drawStack.length&&(e._render(),e._finishRender(),e.textureIndex+=e.frameCount%2==0?-1:1,e.resetMatrix(),e._beginRender(),e.frameCount++)}t.modified&&(Q5.device.queue.copyExternalImageToTexture({source:u},{texture:t.texture,colorSpace:e.canvas.colorSpace},[p,f,1]),t.modified=!1),n??=t.defaultWidth||t.videoWidth,o??=t.defaultHeight||t.videoHeight,d??=p,c??=f,i*=g,s*=g;let[m,x,v,y]=e._calcBox(r,a,n,o,e._imageMode),b=i/p,w=s/f,S=(i+d)/p,C=(s+c)/f,M=e._matrixIndex,Q=e._tint,P=e._globalAlpha;if(_(m,v,b,w,Q,M,P),_(x,v,S,w,Q,M,P),_(m,y,b,C,Q,M,P),_(x,y,S,C,Q,M,P),h){let r=Q5.device.importExternalTexture({source:t});e._textureBindGroups.push(Q5.device.createBindGroup({layout:l,entries:[{binding:0,resource:e._imageSampler},{binding:1,resource:r}]})),e.drawStack.push(e._videoPL,e._textureBindGroups.length-1),t.flipped&&e.scale(-1,1)}else e.drawStack.push(e._imagePL,t.textureIndex)},e._hooks.preRender.push((()=>{if(!o)return;e._pass.setPipeline(e._pipelines[2]);let t=Q5.device.createBuffer({size:5*o,usage:GPUBufferUsage.VERTEX,mappedAtCreation:!0});new Float32Array(t.getMappedRange()).set(n.slice(0,o)),t.unmap(),e._pass.setVertexBuffer(1,t),e._buffers.push(t),p&&(e._pass.setPipeline(e._pipelines[3]),e._pass.setVertexBuffer(1,t))})),e._hooks.postRender.push((()=>{o=0,e._textureBindGroups.splice(u,p),p=0}))},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.webgpu.text=(e,t)=>{e._textPL=4,e._textShaderCode=e._baseShaderCode+"\nstruct VertexParams {\n\t@builtin(vertex_index) vertexIndex : u32,\n\t@builtin(instance_index) instanceIndex : u32\n}\nstruct FragParams {\n\t@builtin(position) position : vec4f,\n\t@location(0) texCoord : vec2f,\n\t@location(1) fillColor : vec4f,\n\t@location(2) strokeColor : vec4f,\n\t@location(3) strokeWeight : f32\n}\nstruct Char {\n\ttexOffset: vec2f,\n\ttexExtent: vec2f,\n\tsize: vec2f,\n\toffset: vec2f,\n}\nstruct Text {\n\tpos: vec2f,\n\tscale: f32,\n\tmatrixIndex: f32,\n\tfillIndex: f32,\n\tstrokeIndex: f32,\n\tstrokeWeight: f32\n}\n\n@group(0) @binding(0) var<uniform> q: Q5;\n@group(0) @binding(1) var<storage> transforms: array<mat4x4<f32>>;\n@group(0) @binding(2) var<storage> colors : array<vec4f>;\n\n@group(1) @binding(0) var fontTexture: texture_2d<f32>;\n@group(1) @binding(1) var fontSampler: sampler;\n@group(1) @binding(2) var<storage> fontChars: array<Char>;\n\n@group(2) @binding(0) var<storage> textChars: array<vec4f>;\n@group(2) @binding(1) var<storage> textMetadata: array<Text>;\n\nconst quad = array(vec2f(0, -1), vec2f(1, -1), vec2f(0, 0), vec2f(1, 0));\nconst uvs = array(vec2f(0, 1), vec2f(1, 1), vec2f(0, 0), vec2f(1, 0));\n\nfn calcPos(i: u32, char: vec4f, fontChar: Char, text: Text) -> vec2f {\n\treturn ((quad[i] * fontChar.size + char.xy + fontChar.offset) *\n\t\ttext.scale) + text.pos;\n}\n\nfn calcUV(i: u32, fontChar: Char) -> vec2f {\n\treturn uvs[i] * fontChar.texExtent + fontChar.texOffset;\n}\n\nfn transformVertex(pos: vec2f, matrixIndex: f32) -> vec4f {\n\tvar vert = vec4f(pos, 0.0, 1.0);\n\tvert = transforms[i32(matrixIndex)] * vert;\n\tvert.x /= q.halfWidth;\n\tvert.y /= q.halfHeight;\n\treturn vert;\n}\n\nfn calcDist(texCoord: vec2f, edgeWidth: f32) -> f32 {\n\tlet c = textureSample(fontTexture, fontSampler, texCoord);\n\tlet sigDist = max(min(c.r, c.g), min(max(c.r, c.g), c.b)) - edgeWidth;\n\n\tlet pxRange = 4.0;\n\tlet sz = vec2f(textureDimensions(fontTexture, 0));\n\tlet dx = sz.x * length(vec2f(dpdxFine(texCoord.x), dpdyFine(texCoord.x)));\n\tlet dy = sz.y * length(vec2f(dpdxFine(texCoord.y), dpdyFine(texCoord.y)));\n\tlet toPixels = pxRange * inverseSqrt(dx * dx + dy * dy);\n\treturn sigDist * toPixels;\n}\n\n@vertex\nfn vertexMain(v : VertexParams) -> FragParams {\n\tlet char = textChars[v.instanceIndex];\n\tlet text = textMetadata[i32(char.w)];\n\tlet fontChar = fontChars[i32(char.z)];\n\tlet pos = calcPos(v.vertexIndex, char, fontChar, text);\n\n\tvar vert = transformVertex(pos, text.matrixIndex);\n\n\tvar f : FragParams;\n\tf.position = vert;\n\tf.texCoord = calcUV(v.vertexIndex, fontChar);\n\tf.fillColor = colors[i32(text.fillIndex)];\n\tf.strokeColor = colors[i32(text.strokeIndex)];\n\tf.strokeWeight = text.strokeWeight;\n\treturn f;\n}\n\n@fragment\nfn fragMain(f : FragParams) -> @location(0) vec4f {\n\tlet edge = 0.5;\n\tlet dist = calcDist(f.texCoord, edge);\n\n\tif (f.strokeWeight == 0.0) {\n\t\tlet fillAlpha = smoothstep(-edge, edge, dist);\n\t\tlet color = vec4f(f.fillColor.rgb, f.fillColor.a * fillAlpha);\n\t\tif (color.a < 0.01) {\n\t\t\tdiscard;\n\t\t}\n\t\treturn color;\n\t}\n\n\tlet halfStroke = f.strokeWeight / 2.0;\n\tlet fillAlpha = smoothstep(-edge, edge, dist - halfStroke);\n\tlet strokeAlpha = smoothstep(-edge, edge, dist + halfStroke);\n\tvar color = mix(f.strokeColor, f.fillColor, fillAlpha);\n\tcolor = vec4f(color.rgb, color.a * strokeAlpha);\n\tif (color.a < 0.01) {\n\t\tdiscard;\n\t}\n\treturn color;\n}\n";let r=Q5.device.createShaderModule({label:"textShader",code:e._textShaderCode}),a=Q5.device.createBindGroupLayout({label:"textBindGroupLayout",entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}},{binding:1,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}}]}),n=Q5.device.createSampler({minFilter:"linear",magFilter:"linear",mipmapFilter:"linear",maxAnisotropy:16}),o=Q5.device.createBindGroupLayout({label:"fontBindGroupLayout",entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,texture:{}},{binding:1,visibility:GPUShaderStage.FRAGMENT,sampler:{}},{binding:2,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}}]}),i=Q5.device.createPipelineLayout({bindGroupLayouts:[...e.bindGroupLayouts,o,a]});e._pipelineConfigs[4]={label:"textPipeline",layout:i,vertex:{module:r,entryPoint:"vertexMain"},fragment:{module:r,entryPoint:"fragMain",targets:[{format:"bgra8unorm",blend:e.blendConfigs.normal}]},primitive:{topology:"triangle-strip",stripIndexFormat:"uint32"},multisample:{count:4}},e._pipelines[4]=Q5.device.createRenderPipeline(e._pipelineConfigs[4]);class s{constructor(e,t,r,a){this.bindGroup=e,this.lineHeight=t,this.chars=r,this.kernings=a;let n=Object.values(r);this.charCount=n.length,this.defaultChar=n[0]}getChar(e){return this.chars[e]??this.defaultChar}getXAdvance(e,t=-1){let r=this.getChar(e);if(t>=0){let a=this.kernings.get(e);if(a)return r.xadvance+(a.get(t)??0)}return r.xadvance}}e._fonts=[];let l={};e._g.colorMode(e.RGB,1),e.loadFont=(r,a)=>{if("json"!=r.slice(r.lastIndexOf(".")+1))return e._g.loadFont(r,a);let i=r.slice(r.lastIndexOf("/")+1,r.lastIndexOf("-")),d={family:i};return d._loader=(async(r,a,i)=>{t._preloadCount++;let d=await fetch(r);if(404==d.status)return t._preloadCount--,"";let c=await d.json(),h=r.lastIndexOf("/"),u=-1!=h?r.substring(0,h+1):"";d=await fetch(u+c.pages[0]);let p=await createImageBitmap(await d.blob()),f=[p.width,p.height,1],g=Q5.device.createTexture({label:`MSDF ${a}`,size:f,format:"rgba8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT});Q5.device.queue.copyExternalImageToTexture({source:p},{texture:g},f),"string"==typeof c.chars&&(c.chars=e.CSV.parse(c.chars," "),c.kernings=e.CSV.parse(c.kernings," "));let _=c.chars.length,m=Q5.device.createBuffer({size:32*_,usage:GPUBufferUsage.STORAGE,mappedAtCreation:!0}),x=new Float32Array(m.getMappedRange()),v=1/c.common.scaleW,y=1/c.common.scaleH,b={},w=0;for(let[e,t]of c.chars.entries())b[t.id]=t,b[t.id].charIndex=e,x[w]=t.x*v,x[w+1]=t.y*y,x[w+2]=t.width*v,x[w+3]=t.height*y,x[w+4]=t.width,x[w+5]=t.height,x[w+6]=t.xoffset,x[w+7]=-t.yoffset,w+=8;m.unmap();let S=Q5.device.createBindGroup({label:"fontBindGroup",layout:o,entries:[{binding:0,resource:g.createView()},{binding:1,resource:n},{binding:2,resource:{buffer:m}}]}),C=new Map;if(c.kernings)for(let e of c.kernings){let t=C.get(e.first);t||(t=new Map,C.set(e.first,t)),t.set(e.second,e.amount)}e._font=new s(S,c.common.lineHeight,b,C),e._font.index=e._fonts.length,e._fonts.push(e._font),l[a]=e._font,t._preloadCount--,i&&i(a)})(r,i,(()=>{delete d._loader,a&&a(d)})),e._disablePreload?d._loader:d},e._loadDefaultFont=t=>{l[t]=null,navigator.onLine?e.loadFont(`https://q5js.org/fonts/${t}-msdf.json`):e.loadFont(`/node_modules/q5/builtinFonts/${t}-msdf.json`)},e._textSize=18,e._textAlign="left",e._textBaseline="alphabetic";let d=!1,c=22.5,h=4.5,u=1.25;e.textFont=t=>{if(!t)return e._font;"string"!=typeof t&&(t=t.family);let r=l[t];r?e._font=r:void 0===r&&e._loadDefaultFont(t)},e.textSize=t=>{if(null==t)return e._textSize;e._textSize=t,d||(c=t*u,h=c-t)},e.textLeading=t=>{e._font.lineHeight=c=t,h=c-e._textSize,u=c/e._textSize,d=!0},e.textAlign=(t,r)=>{e._textAlign=t,r&&(e._textBaseline=r)};let p=[],f=[],g=(e,t,r)=>{let a=0,n=0,o=0,i=0,s=0,l=[],d=t.charCodeAt(0);for(let c=0;c<t.length;++c){let h=d;switch(d=c<t.length-1?t.charCodeAt(c+1):-1,h){case 10:l.push(n),i++,a=Math.max(a,n),n=0,o-=e.lineHeight*u;break;case 13:break;case 32:n+=e.getXAdvance(h);break;case 9:n+=2*e.getXAdvance(h);break;default:r&&r(n,o,i,e.getChar(h)),n+=e.getXAdvance(h,d),s++}}return l.push(n),a=Math.max(a,n),{width:a,height:l.length*e.lineHeight*u,lineWidths:l,printedCharCount:s}};e.text=(t,r,a,n,o)=>{if(!e._font)return void(null!==e._font&&e.textFont("sans-serif"));let i=typeof t;if("string"!=i&&("object"==i?t=t.toString():t+=""),t.length>n){let e=[],r=0;for(;r<t.length&&e.length<o;){let a=r+n;if(a>=t.length){e.push(t.slice(r));break}let o=t.lastIndexOf(" ",a);(-1==o||o<r)&&(o=a),e.push(t.slice(r,o)),r=o+1}t=e.join("\n")}let s;for(let e=0;e<t.length;e++){switch(t[e]){case"\n":s=!0;case"\r":case"\t":case" ":0}}let l,d=[],h=e._textAlign,u=e._textBaseline,_=f.length,m=0;if("left"!=h||s){l=g(e._font,t);let r=0;"alphabetic"==u?a-=e._textSize:"center"==u?r=.5*l.height:"bottom"==u&&(r=l.height),g(e._font,t,((e,t,a,n)=>{let o=0;"center"==h?o=-.5*l.width- -.5*(l.width-l.lineWidths[a]):"right"==h&&(o=-l.lineWidths[a]),d[m]=e+o,d[m+1]=t+r,d[m+2]=n.charIndex,d[m+3]=_,m+=4}))}else l=g(e._font,t,((e,t,r,a)=>{d[m]=e,d[m+1]=t,d[m+2]=a.charIndex,d[m+3]=_,m+=4})),"alphabetic"==u?a-=e._textSize:"center"==u?a-=.5*e._textSize:"bottom"==u&&(a-=c);p.push(d);let x=[];e._matrixDirty&&e._saveMatrix(),x[0]=r,x[1]=-a,x[2]=e._textSize/44,x[3]=e._matrixIndex,x[4]=e._doFill&&e._fillSet?e._fill:0,x[5]=e._stroke,x[6]=e._doStroke&&e._strokeSet?e._strokeWeight:0,x[7]=0,f.push(x),e.drawStack.push(e._textPL,l.printedCharCount,e._font.index)},e.textWidth=t=>e._font?g(e._font,t).width:0,e.createTextImage=(t,r,a)=>{if(e._g.textSize(e._textSize),e._doFill){let t=4*e._fill;e._g.fill(colorStack.slice(t,t+4))}if(e._doStroke){let t=4*e._stroke;e._g.stroke(colorStack.slice(t,t+4))}let n=e._g.createTextImage(t,r,a);if(null==n.textureIndex){e._createTexture(n);let t=n.copy;n.copy=function(){let r=t();return e._createTexture(r),r}}return n},e.textImage=(t,r,a)=>{"string"==typeof t&&(t=e.createTextImage(t));let n=e._imageMode;e._imageMode="corner";let o=e._textAlign;"center"==o?r-=t.canvas.hw:"right"==o&&(r-=t.width);let i=e._textBaseline;"alphabetic"==i?a-=t._leading:"center"==i?a-=t._middle:"bottom"==i?a-=t._bottom:"top"==i&&(a-=t._top),e.image(t,r,a),e._imageMode=n},e._hooks.preRender.push((()=>{if(!p.length)return;let t=0;for(let e of p)t+=4*e.length;let r=Q5.device.createBuffer({size:t,usage:GPUBufferUsage.STORAGE,mappedAtCreation:!0});new Float32Array(r.getMappedRange()).set(p.flat()),r.unmap();let n=8*f.length*4,o=Q5.device.createBuffer({label:"textBuffer",size:n,usage:GPUBufferUsage.STORAGE,mappedAtCreation:!0});new Float32Array(o.getMappedRange()).set(f.flat()),o.unmap(),e._buffers.push(r,o),e._textBindGroup=Q5.device.createBindGroup({label:"textBindGroup",layout:a,entries:[{binding:0,resource:{buffer:r}},{binding:1,resource:{buffer:o}}]})})),e._hooks.postRender.push((()=>{p=[],f=[]}))},Q5.renderers.webgpu.shaders=e=>{let t=["frame","shapes","image","video","text"],r={frame:10,shapes:1e3,image:2e3,video:3e3,text:4e3};e._createShader=(a,n="shapes")=>{a=a.trim();let o=e["_"+n+"ShaderCode"],i=o.indexOf("@vertex"),s=o.indexOf("@fragment");a=a.includes("@fragment")?a.includes("@vertex")?o.slice(0,i)+a:o.slice(0,s)+a:o.slice(0,i)+a+"\n\n"+o.slice(s);let l=Q5.device.createShaderModule({label:n+"Shader",code:a});l.type=n;let d=t.indexOf(n),c=Object.assign({},e._pipelineConfigs[d]);c.vertex.module=c.fragment.module=l;let h=r[n];return e._pipelines[h]=Q5.device.createRenderPipeline(c),e._pipelines[h].shader=l,l.pipelineIndex=h,r[n]++,l},e.createShader=e.createShapesShader=e._createShader,e.createFrameShader=t=>e._createShader(t,"frame"),e.createImageShader=t=>e._createShader(t,"image"),e.createVideoShader=t=>e._createShader(t,"video"),e.createTextShader=t=>e._createShader(t,"text"),e.shader=t=>{t.applyBeforeDraw?e._prevFramePL=t.pipelineIndex:e["_"+t.type+"PL"]=t.pipelineIndex},e.resetShader=(r="shapes")=>{"frame"==r&&(e._prevFramePL=0),e["_"+r+"PL"]=t.indexOf(r)},e.resetShaders=()=>{e._prevFramePL=e._framePL=0,e._shapesPL=1,e._imagePL=2,e._videoPL=3,e._textPL=4}};