diff --git a/.DS_Store b/.DS_Store index 0ce6a1e8..a620e330 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/lang/en/learn/index.md b/lang/en/learn/index.md index 206d302c..ad2a0bf5 100644 --- a/lang/en/learn/index.md +++ b/lang/en/learn/index.md @@ -1,6 +1,6 @@ # 0-0 -[**_Learn p5play: An Introduction to Object Oriented Programming_**](.) was written by Quinton Ashley, the creator of p5play v3. It's packed with beginner friendly reference documentation and interactive code examples. +[**_Learn p5play: An Introduction to Object Oriented Programming_**](.) was written by Quinton Ashley, the creator of p5play v3. It's packed with beginner friendly reference documentation and interactive code examples! # 0-1 diff --git a/lang/en/learn/sprite.md b/lang/en/learn/sprite.md index e481ddfa..bfdbe517 100644 --- a/lang/en/learn/sprite.md +++ b/lang/en/learn/sprite.md @@ -1,6 +1,6 @@ # 0-0 -## Setup +## Setup and Draw The code inside the [q5.js](https://q5js.org) (or [p5.js](https://p5js.org)) `setup` function runs when the program starts. The `new Canvas()` constructor creates a section of the screen that the program can draw on. diff --git a/learn/.DS_Store b/learn/.DS_Store index aa22e5b3..cd5d60b7 100644 Binary files a/learn/.DS_Store and b/learn/.DS_Store differ diff --git a/learn/animation.html b/learn/animation.html index 5a6f46ac..a9f55c82 100644 --- a/learn/animation.html +++ b/learn/animation.html @@ -49,7 +49,7 @@

How to load animations

function setup() { new Canvas(500, 160); - cloudAni = loadAni('assets/cloud_breathing1.png', 9); + cloudAni = loadAni('assets/cloud_breathing1.webp', 9); } function draw() { @@ -71,13 +71,13 @@

How to load animations

new Canvas(500, 160); shapeShifterAni = loadAnimation( - 'assets/asterisk.png', - 'assets/triangle.png', - 'assets/square.png', - 'assets/cloud.png', - 'assets/star.png', - 'assets/mess.png', - 'assets/monster.png' + 'assets/asterisk.webp', + 'assets/triangle.webp', + 'assets/square.webp', + 'assets/cloud.webp', + 'assets/star.webp', + 'assets/mess.webp', + 'assets/monster.webp' ); shapeShifterAni.frameDelay = 10; @@ -103,7 +103,7 @@

How to load animations

function setup() { new Canvas(500, 200); - splatAni = loadAnimation('assets/explode_sprite_sheet.png', { frameSize: [171, 158], frames: 11 }); + splatAni = loadAnimation('assets/explode_sprite_sheet.webp', { frameSize: [342, 316], frames: 11 }); } function draw() { @@ -128,15 +128,18 @@

Animating

function setup() { new Canvas(500, 160); - ani = loadAni('assets/asterisk_explode0001.png', 11); + ani = loadAni('assets/asterisk_explode01.webp', 11); } function draw() { clear(); - if (kb.presses('s')) ani.stop(); - if (kb.presses('p')) ani.play(); - if (kb.presses('o')) ani.play(0); + if (kb.presses('space')) { + if (ani.playing) ani.pause(); + else ani.play(); + } + + if (kb.presses('p')) ani.play(0); if (kb.presses('ArrowDown')) ani.frameDelay--; if (kb.presses('ArrowUp')) ani.frameDelay++; if (kb.presses('r')) ani.rewind(); @@ -185,8 +188,8 @@

Control a Sprite's Animation

new Canvas(500, 160); ghost = new Sprite(250, 80, 120); - ghost.addAni('fly', 'assets/ghost_walk01.png', 3); - ghost.addAni('idle', 'assets/ghost_standing01.png', 7); + ghost.addAni('fly', 'assets/ghost_walk01.webp', 3); + ghost.addAni('idle', 'assets/ghost_standing01.webp', 7); } function draw() { @@ -231,7 +234,7 @@

Groups with Animations

new Canvas(500, 160); splats = new Group(); - splats.addAni('assets/asterisk_explode0001.png', 11); + splats.addAni('assets/asterisk_explode0001.webp', 11); } function draw() { @@ -248,7 +251,8 @@

Groups with Animations

Sprite Sheets with Multiple Animations

To load multiple animations from the same sprite sheet image, first set the - spriteSheet property of the sprite or group.

+ spriteSheet property of the sprite or group. +

Next, use the addAnimations / addAnis function. They accept an object that uses animation names as keys and sprite sheet atlases as values.

Using an atlas object is way easier than manually specifying the coordinates of every frame!

@@ -256,12 +260,14 @@

Sprite Sheets with Multiple Anim

x, y, pos, w/width, h/height, size/frameSize, row, col, frames/frameCount, - delay/frameDelay, and rotation.

+ delay/frameDelay, and rotation. +

In the "hero" example the size of the hero sprite is set to 32x32 pixels in the - Sprite constructor. That size is used as a multiplier to the row value given.

+ Sprite constructor. That size is used as a multiplier to the row value given. +

The ani.offset property is used to adjust the position of an animation relative to the sprite's position.

-

Click this link to see the full questKid +

Click this link to see the full questKid sprite sheet used in the example.

If you'd like to truly appreciate p5play, compare the example code to anis

function preload() { hero = new Sprite(125, 48, 32, 32); - hero.spriteSheet = 'assets/questKid.png'; + hero.spriteSheet = 'assets/questKid.webp'; hero.anis.offset.x = 2; hero.anis.frameDelay = 32; hero.anis.demoMode = true; @@ -304,7 +310,8 @@

anis

} function setup() { - new Canvas(250, 96, 'pixelated x2'); + new Canvas(250, 96); + displayMode('default', 'pixelated', 2) allSprites.pixelPerfect = true; } @@ -323,7 +330,7 @@

anis

function preload() { hero = new Sprite(62, 24, 32, 32); - hero.spriteSheet = 'assets/questKid.png'; + hero.spriteSheet = 'assets/questKid.webp'; hero.anis.offset.x = 2; hero.anis.frameDelay = 8; hero.friction = 0; @@ -339,7 +346,8 @@

anis

} function setup() { - new Canvas(124, 48, 'pixelated x4'); + new Canvas(124, 48); + displayMode('normal', 'pixelated', 4); allSprites.pixelPerfect = true; } @@ -370,7 +378,7 @@

Animation Sequencing

function preload() { hero = new Sprite(62, 24, 32, 32); - hero.spriteSheet = 'assets/questKid.png'; + hero.spriteSheet = 'assets/questKid.webp'; hero.anis.offset.x = 2; hero.anis.offset.y = 2; hero.anis.frameDelay = 8; @@ -450,7 +458,7 @@

Advanced Animation Sequencing

function preload() { hero = new Sprite(90, 24, 32, 32); - hero.spriteSheet = 'assets/questKid.png'; + hero.spriteSheet = 'assets/questKid.webp'; hero.anis.offset.x = 2; hero.anis.offset.y = 2; hero.anis.frameDelay = 8; @@ -505,15 +513,15 @@

Advanced Animation Sequencing

- - - + + - - + + diff --git a/learn/assets/asterisk.png b/learn/assets/asterisk.png deleted file mode 100644 index d5d6874d..00000000 Binary files a/learn/assets/asterisk.png and /dev/null differ diff --git a/learn/assets/asterisk.webp b/learn/assets/asterisk.webp new file mode 100644 index 00000000..c6edfd3e Binary files /dev/null and b/learn/assets/asterisk.webp differ diff --git a/learn/assets/asterisk_explode0001.png b/learn/assets/asterisk_explode0001.png deleted file mode 100644 index e703790d..00000000 Binary files a/learn/assets/asterisk_explode0001.png and /dev/null differ diff --git a/learn/assets/asterisk_explode0002.png b/learn/assets/asterisk_explode0002.png deleted file mode 100644 index 8b2e6d39..00000000 Binary files a/learn/assets/asterisk_explode0002.png and /dev/null differ diff --git a/learn/assets/asterisk_explode0003.png b/learn/assets/asterisk_explode0003.png deleted file mode 100644 index 9e56c738..00000000 Binary files a/learn/assets/asterisk_explode0003.png and /dev/null differ diff --git a/learn/assets/asterisk_explode0004.png b/learn/assets/asterisk_explode0004.png deleted file mode 100644 index 2689d0e7..00000000 Binary files a/learn/assets/asterisk_explode0004.png and /dev/null differ diff --git a/learn/assets/asterisk_explode0005.png b/learn/assets/asterisk_explode0005.png deleted file mode 100644 index b85bf056..00000000 Binary files a/learn/assets/asterisk_explode0005.png and /dev/null differ diff --git a/learn/assets/asterisk_explode0006.png b/learn/assets/asterisk_explode0006.png deleted file mode 100644 index 9a0c9f67..00000000 Binary files a/learn/assets/asterisk_explode0006.png and /dev/null differ diff --git a/learn/assets/asterisk_explode0007.png b/learn/assets/asterisk_explode0007.png deleted file mode 100644 index 0e9c0883..00000000 Binary files a/learn/assets/asterisk_explode0007.png and /dev/null differ diff --git a/learn/assets/asterisk_explode0008.png b/learn/assets/asterisk_explode0008.png deleted file mode 100644 index bf453c40..00000000 Binary files a/learn/assets/asterisk_explode0008.png and /dev/null differ diff --git a/learn/assets/asterisk_explode0009.png b/learn/assets/asterisk_explode0009.png deleted file mode 100644 index c591407a..00000000 Binary files a/learn/assets/asterisk_explode0009.png and /dev/null differ diff --git a/learn/assets/asterisk_explode0010.png b/learn/assets/asterisk_explode0010.png deleted file mode 100644 index c0c2b397..00000000 Binary files a/learn/assets/asterisk_explode0010.png and /dev/null differ diff --git a/learn/assets/asterisk_explode0011.png b/learn/assets/asterisk_explode0011.png deleted file mode 100644 index bdb29b18..00000000 Binary files a/learn/assets/asterisk_explode0011.png and /dev/null differ diff --git a/learn/assets/asterisk_explode01.webp b/learn/assets/asterisk_explode01.webp new file mode 100644 index 00000000..21edb97b Binary files /dev/null and b/learn/assets/asterisk_explode01.webp differ diff --git a/learn/assets/asterisk_explode02.webp b/learn/assets/asterisk_explode02.webp new file mode 100644 index 00000000..c49f9f6d Binary files /dev/null and b/learn/assets/asterisk_explode02.webp differ diff --git a/learn/assets/asterisk_explode03.webp b/learn/assets/asterisk_explode03.webp new file mode 100644 index 00000000..d6fc80b6 Binary files /dev/null and b/learn/assets/asterisk_explode03.webp differ diff --git a/learn/assets/asterisk_explode04.webp b/learn/assets/asterisk_explode04.webp new file mode 100644 index 00000000..2ca9e023 Binary files /dev/null and b/learn/assets/asterisk_explode04.webp differ diff --git a/learn/assets/asterisk_explode05.webp b/learn/assets/asterisk_explode05.webp new file mode 100644 index 00000000..dddf7dbc Binary files /dev/null and b/learn/assets/asterisk_explode05.webp differ diff --git a/learn/assets/asterisk_explode06.webp b/learn/assets/asterisk_explode06.webp new file mode 100644 index 00000000..70309937 Binary files /dev/null and b/learn/assets/asterisk_explode06.webp differ diff --git a/learn/assets/asterisk_explode07.webp b/learn/assets/asterisk_explode07.webp new file mode 100644 index 00000000..d98e310e Binary files /dev/null and b/learn/assets/asterisk_explode07.webp differ diff --git a/learn/assets/asterisk_explode08.webp b/learn/assets/asterisk_explode08.webp new file mode 100644 index 00000000..aee97bc1 Binary files /dev/null and b/learn/assets/asterisk_explode08.webp differ diff --git a/learn/assets/asterisk_explode09.webp b/learn/assets/asterisk_explode09.webp new file mode 100644 index 00000000..3bfe4d26 Binary files /dev/null and b/learn/assets/asterisk_explode09.webp differ diff --git a/learn/assets/asterisk_explode10.webp b/learn/assets/asterisk_explode10.webp new file mode 100644 index 00000000..bff227cb Binary files /dev/null and b/learn/assets/asterisk_explode10.webp differ diff --git a/learn/assets/asterisk_explode11.webp b/learn/assets/asterisk_explode11.webp new file mode 100644 index 00000000..18d4e0b8 Binary files /dev/null and b/learn/assets/asterisk_explode11.webp differ diff --git a/learn/assets/cloud.png b/learn/assets/cloud.png deleted file mode 100644 index 68f996c9..00000000 Binary files a/learn/assets/cloud.png and /dev/null differ diff --git a/learn/assets/cloud.webp b/learn/assets/cloud.webp new file mode 100644 index 00000000..5c30a81f Binary files /dev/null and b/learn/assets/cloud.webp differ diff --git a/learn/assets/cloud_breathing1.png b/learn/assets/cloud_breathing1.png deleted file mode 100644 index 1287270e..00000000 Binary files a/learn/assets/cloud_breathing1.png and /dev/null differ diff --git a/learn/assets/cloud_breathing1.webp b/learn/assets/cloud_breathing1.webp new file mode 100644 index 00000000..097c9480 Binary files /dev/null and b/learn/assets/cloud_breathing1.webp differ diff --git a/learn/assets/cloud_breathing2.png b/learn/assets/cloud_breathing2.png deleted file mode 100644 index d58fdbbf..00000000 Binary files a/learn/assets/cloud_breathing2.png and /dev/null differ diff --git a/learn/assets/cloud_breathing2.webp b/learn/assets/cloud_breathing2.webp new file mode 100644 index 00000000..e12cc67d Binary files /dev/null and b/learn/assets/cloud_breathing2.webp differ diff --git a/learn/assets/cloud_breathing3.png b/learn/assets/cloud_breathing3.png deleted file mode 100644 index f218cf47..00000000 Binary files a/learn/assets/cloud_breathing3.png and /dev/null differ diff --git a/learn/assets/cloud_breathing3.webp b/learn/assets/cloud_breathing3.webp new file mode 100644 index 00000000..aa3878f0 Binary files /dev/null and b/learn/assets/cloud_breathing3.webp differ diff --git a/learn/assets/cloud_breathing4.png b/learn/assets/cloud_breathing4.png deleted file mode 100644 index ea7ff4d3..00000000 Binary files a/learn/assets/cloud_breathing4.png and /dev/null differ diff --git a/learn/assets/cloud_breathing4.webp b/learn/assets/cloud_breathing4.webp new file mode 100644 index 00000000..04b952a5 Binary files /dev/null and b/learn/assets/cloud_breathing4.webp differ diff --git a/learn/assets/cloud_breathing5.png b/learn/assets/cloud_breathing5.png deleted file mode 100644 index 946fd0f7..00000000 Binary files a/learn/assets/cloud_breathing5.png and /dev/null differ diff --git a/learn/assets/cloud_breathing5.webp b/learn/assets/cloud_breathing5.webp new file mode 100644 index 00000000..0bb5f92f Binary files /dev/null and b/learn/assets/cloud_breathing5.webp differ diff --git a/learn/assets/cloud_breathing6.png b/learn/assets/cloud_breathing6.png deleted file mode 100644 index b28acd56..00000000 Binary files a/learn/assets/cloud_breathing6.png and /dev/null differ diff --git a/learn/assets/cloud_breathing6.webp b/learn/assets/cloud_breathing6.webp new file mode 100644 index 00000000..ade69d2b Binary files /dev/null and b/learn/assets/cloud_breathing6.webp differ diff --git a/learn/assets/cloud_breathing7.png b/learn/assets/cloud_breathing7.png deleted file mode 100644 index 1e3c6be7..00000000 Binary files a/learn/assets/cloud_breathing7.png and /dev/null differ diff --git a/learn/assets/cloud_breathing7.webp b/learn/assets/cloud_breathing7.webp new file mode 100644 index 00000000..368071ee Binary files /dev/null and b/learn/assets/cloud_breathing7.webp differ diff --git a/learn/assets/cloud_breathing8.png b/learn/assets/cloud_breathing8.png deleted file mode 100644 index 6da96bbb..00000000 Binary files a/learn/assets/cloud_breathing8.png and /dev/null differ diff --git a/learn/assets/cloud_breathing8.webp b/learn/assets/cloud_breathing8.webp new file mode 100644 index 00000000..fdd8c69c Binary files /dev/null and b/learn/assets/cloud_breathing8.webp differ diff --git a/learn/assets/cloud_breathing9.png b/learn/assets/cloud_breathing9.png deleted file mode 100644 index 82856a5c..00000000 Binary files a/learn/assets/cloud_breathing9.png and /dev/null differ diff --git a/learn/assets/cloud_breathing9.webp b/learn/assets/cloud_breathing9.webp new file mode 100644 index 00000000..d08fcd99 Binary files /dev/null and b/learn/assets/cloud_breathing9.webp differ diff --git a/learn/assets/explode_sprite_sheet.png b/learn/assets/explode_sprite_sheet.png deleted file mode 100644 index abac1312..00000000 Binary files a/learn/assets/explode_sprite_sheet.png and /dev/null differ diff --git a/learn/assets/explode_sprite_sheet.webp b/learn/assets/explode_sprite_sheet.webp new file mode 100644 index 00000000..30e5eef6 Binary files /dev/null and b/learn/assets/explode_sprite_sheet.webp differ diff --git a/learn/assets/face.png b/learn/assets/face.png deleted file mode 100644 index 17b96fc3..00000000 Binary files a/learn/assets/face.png and /dev/null differ diff --git a/learn/assets/face.webp b/learn/assets/face.webp new file mode 100644 index 00000000..bbae122a Binary files /dev/null and b/learn/assets/face.webp differ diff --git a/learn/assets/ghost_standing01.png b/learn/assets/ghost_standing01.png deleted file mode 100644 index 048c1246..00000000 Binary files a/learn/assets/ghost_standing01.png and /dev/null differ diff --git a/learn/assets/ghost_standing01.webp b/learn/assets/ghost_standing01.webp new file mode 100644 index 00000000..7e4c1f10 Binary files /dev/null and b/learn/assets/ghost_standing01.webp differ diff --git a/learn/assets/ghost_standing02.png b/learn/assets/ghost_standing02.png deleted file mode 100644 index c10ce4f5..00000000 Binary files a/learn/assets/ghost_standing02.png and /dev/null differ diff --git a/learn/assets/ghost_standing02.webp b/learn/assets/ghost_standing02.webp new file mode 100644 index 00000000..a61e8e8b Binary files /dev/null and b/learn/assets/ghost_standing02.webp differ diff --git a/learn/assets/ghost_standing03.png b/learn/assets/ghost_standing03.png deleted file mode 100644 index 2774ef72..00000000 Binary files a/learn/assets/ghost_standing03.png and /dev/null differ diff --git a/learn/assets/ghost_standing03.webp b/learn/assets/ghost_standing03.webp new file mode 100644 index 00000000..01f9402f Binary files /dev/null and b/learn/assets/ghost_standing03.webp differ diff --git a/learn/assets/ghost_standing04.png b/learn/assets/ghost_standing04.png deleted file mode 100644 index ddf1865c..00000000 Binary files a/learn/assets/ghost_standing04.png and /dev/null differ diff --git a/learn/assets/ghost_standing04.webp b/learn/assets/ghost_standing04.webp new file mode 100644 index 00000000..3d4f2297 Binary files /dev/null and b/learn/assets/ghost_standing04.webp differ diff --git a/learn/assets/ghost_standing05.png b/learn/assets/ghost_standing05.png deleted file mode 100644 index 98ce7190..00000000 Binary files a/learn/assets/ghost_standing05.png and /dev/null differ diff --git a/learn/assets/ghost_standing05.webp b/learn/assets/ghost_standing05.webp new file mode 100644 index 00000000..3109cfba Binary files /dev/null and b/learn/assets/ghost_standing05.webp differ diff --git a/learn/assets/ghost_standing06.png b/learn/assets/ghost_standing06.png deleted file mode 100644 index cd76c544..00000000 Binary files a/learn/assets/ghost_standing06.png and /dev/null differ diff --git a/learn/assets/ghost_standing06.webp b/learn/assets/ghost_standing06.webp new file mode 100644 index 00000000..fff3f5c5 Binary files /dev/null and b/learn/assets/ghost_standing06.webp differ diff --git a/learn/assets/ghost_standing07.png b/learn/assets/ghost_standing07.png deleted file mode 100644 index 7a0db946..00000000 Binary files a/learn/assets/ghost_standing07.png and /dev/null differ diff --git a/learn/assets/ghost_standing07.webp b/learn/assets/ghost_standing07.webp new file mode 100644 index 00000000..18178b27 Binary files /dev/null and b/learn/assets/ghost_standing07.webp differ diff --git a/learn/assets/ghost_walk01.png b/learn/assets/ghost_walk01.png deleted file mode 100644 index dad9cbcf..00000000 Binary files a/learn/assets/ghost_walk01.png and /dev/null differ diff --git a/learn/assets/ghost_walk01.webp b/learn/assets/ghost_walk01.webp new file mode 100644 index 00000000..dbdf5bf6 Binary files /dev/null and b/learn/assets/ghost_walk01.webp differ diff --git a/learn/assets/ghost_walk02.png b/learn/assets/ghost_walk02.png deleted file mode 100644 index 8a64eb42..00000000 Binary files a/learn/assets/ghost_walk02.png and /dev/null differ diff --git a/learn/assets/ghost_walk02.webp b/learn/assets/ghost_walk02.webp new file mode 100644 index 00000000..61df89f6 Binary files /dev/null and b/learn/assets/ghost_walk02.webp differ diff --git a/learn/assets/ghost_walk03.png b/learn/assets/ghost_walk03.png deleted file mode 100644 index 0d2c8186..00000000 Binary files a/learn/assets/ghost_walk03.png and /dev/null differ diff --git a/learn/assets/ghost_walk03.webp b/learn/assets/ghost_walk03.webp new file mode 100644 index 00000000..241e8d39 Binary files /dev/null and b/learn/assets/ghost_walk03.webp differ diff --git a/learn/assets/ghost_walk04.png b/learn/assets/ghost_walk04.png deleted file mode 100644 index f081b5b6..00000000 Binary files a/learn/assets/ghost_walk04.png and /dev/null differ diff --git a/learn/assets/ghost_walk04.webp b/learn/assets/ghost_walk04.webp new file mode 100644 index 00000000..213e7aff Binary files /dev/null and b/learn/assets/ghost_walk04.webp differ diff --git a/learn/assets/mess.png b/learn/assets/mess.png deleted file mode 100644 index fcfa89b9..00000000 Binary files a/learn/assets/mess.png and /dev/null differ diff --git a/learn/assets/mess.webp b/learn/assets/mess.webp new file mode 100644 index 00000000..3bd22799 Binary files /dev/null and b/learn/assets/mess.webp differ diff --git a/learn/assets/monster.png b/learn/assets/monster.png deleted file mode 100644 index b74a7097..00000000 Binary files a/learn/assets/monster.png and /dev/null differ diff --git a/learn/assets/monster.webp b/learn/assets/monster.webp new file mode 100644 index 00000000..22eb974e Binary files /dev/null and b/learn/assets/monster.webp differ diff --git a/learn/assets/questKid.png b/learn/assets/questKid.png deleted file mode 100644 index 32544c6d..00000000 Binary files a/learn/assets/questKid.png and /dev/null differ diff --git a/learn/assets/questKid.webp b/learn/assets/questKid.webp new file mode 100644 index 00000000..5b8af33c Binary files /dev/null and b/learn/assets/questKid.webp differ diff --git a/learn/assets/square.png b/learn/assets/square.png deleted file mode 100644 index ec3eef56..00000000 Binary files a/learn/assets/square.png and /dev/null differ diff --git a/learn/assets/square.webp b/learn/assets/square.webp new file mode 100644 index 00000000..53664e0f Binary files /dev/null and b/learn/assets/square.webp differ diff --git a/learn/assets/star.png b/learn/assets/star.png deleted file mode 100644 index c1ad05d8..00000000 Binary files a/learn/assets/star.png and /dev/null differ diff --git a/learn/assets/star.webp b/learn/assets/star.webp new file mode 100644 index 00000000..ebe0b281 Binary files /dev/null and b/learn/assets/star.webp differ diff --git a/learn/assets/triangle.png b/learn/assets/triangle.png deleted file mode 100644 index af66d5db..00000000 Binary files a/learn/assets/triangle.png and /dev/null differ diff --git a/learn/assets/triangle.webp b/learn/assets/triangle.webp new file mode 100644 index 00000000..850880cc Binary files /dev/null and b/learn/assets/triangle.webp differ diff --git a/learn/sprite.html b/learn/sprite.html index 321fa057..fdab2a9e 100644 --- a/learn/sprite.html +++ b/learn/sprite.html @@ -34,9 +34,9 @@
-

Setup

-

The code inside the q5.js (or p5.js) setup function runs when the +

Setup and Draw

+

The code inside the q5.js (or p5.js) setup function runs when the program starts. The new Canvas() constructor creates a section of the screen that the program can draw on.

The q5 draw function is run 60 times per second by default. The background @@ -176,7 +176,8 @@

Sprite physics

Setting a sprite's collider type to 'none' makes it have no collider.

The collider type can also be set using the first letter of the collider type name: 'd', - 's', 'k', or 'n'.

+ 's', 'k', or 'n'. +

Click the reload icon on the top right corner of a code example to replay it!

All the other movement methods on this page change the sprite's velocity, aka - vel, which is its rate of motion along the x and y axis.

+ vel, which is its rate of motion along the x and y axis. +

vel is Q5.Vector, you can use any vector functions on it.

Restart this example to see the player sprite hit the block!

@@ -476,7 +478,8 @@

Sprite movement

Yet, you may find it's more convenient to move a sprite by setting its direction and - speed.

+ speed. +

You can also set a sprite's direction using an angle value or direction name such as: 'up', 'down', 'left', 'right', 'upLeft', 'upRight', 'downLeft', 'downRight'.

@@ -853,7 +856,8 @@

Sprite rotation

All of the other rotation methods on this page work by changing the sprite's - rotationSpeed.

+ rotationSpeed. +

- - - + + + - - + + diff --git a/learn/style.css b/learn/style.css index 0bb90dc1..134588d2 100644 --- a/learn/style.css +++ b/learn/style.css @@ -57,7 +57,6 @@ body.dark { body.dark { --pink0: oklch(0.657 0.294 16.698); - --pink1: oklch(0.657 0.294 16); --pink1: oklch(0.6 0.28 16); --pink2: oklch(0.11 0.28 16); diff --git a/package.json b/package.json index 7d43a0fb..eeb1001c 100644 --- a/package.json +++ b/package.json @@ -36,5 +36,5 @@ "version": "git add -A", "postversion": "git push" }, - "version": "1.12.16" + "version": "1.13.0" } diff --git a/tests/SpriteAnimation.test.js b/tests/SpriteAnimation.test.js index 38e6ee07..601a2dc7 100644 --- a/tests/SpriteAnimation.test.js +++ b/tests/SpriteAnimation.test.js @@ -77,9 +77,9 @@ test('SpriteAnimation : List mode', () => { let ani0; p.preload = () => { ani0 = new p.SpriteAnimation( - host + '/learn/assets/asterisk.png', - host + '/learn/assets/triangle.png', - host + '/learn/assets/square.png' + host + '/learn/assets/asterisk.webp', + host + '/learn/assets/triangle.webp', + host + '/learn/assets/square.webp' ); }; p.setup = () => { @@ -100,7 +100,7 @@ test('SpriteAnimation : Sequence mode', () => { const sketch = (p) => { let ani0; p.preload = () => { - ani0 = new p.SpriteAnimation(host + '/learn/assets/cloud_breathing1.png', 9); + ani0 = new p.SpriteAnimation(host + '/learn/assets/cloud_breathing1.webp', 9); }; p.setup = () => { new p.Canvas(400, 400); @@ -120,7 +120,7 @@ test('SpriteAnimation : SpriteSheet mode', () => { const sketch = (p) => { let spriteSheet0; p.preload = () => { - spriteSheet0 = p.loadImage(host + '/learn/assets/questKid.png'); + spriteSheet0 = p.loadImage(host + '/learn/assets/questKid.webp'); }; p.setup = () => { new p.Canvas(400, 400); diff --git a/v3/p5play.d.ts b/v3/p5play.d.ts index 8bad3127..81a6aa5f 100644 --- a/v3/p5play.d.ts +++ b/v3/p5play.d.ts @@ -1752,18 +1752,10 @@ class Group extends Array { * @type {Number} */ d: number; - /** - * @type {Number} - */ - diameter: number; /** * @type {Boolean} */ dynamic: boolean; - /** - * @type {Number} - */ - height: number; /** * @type {String} */ @@ -1784,10 +1776,6 @@ class Group extends Array { * @type {Boolean} */ static: boolean; - /** - * @type {Number} - */ - width: number; /** * Each group has a unique id number. Don't change it! * Its useful for debugging. @@ -1883,6 +1871,21 @@ class Group extends Array { * @type {Number} */ get amount(): number; + set diameter(val: number); + /** + * @type {Number} + */ + get diameter(): number; + set width(val: number); + /** + * @type {Number} + */ + get width(): number; + set height(val: number); + /** + * @type {Number} + */ + get height(): number; set velocity(val: p5.Vector); /** * The sprite's velocity vector {x, y} diff --git a/v3/p5play.js b/v3/p5play.js index e7dd36e7..bc2c9c06 100644 --- a/v3/p5play.js +++ b/v3/p5play.js @@ -1,6 +1,6 @@ /** * p5play - * @version 3.23 + * @version 3.24 * @author quinton-ashley * @license AGPL-3.0 */ @@ -4596,11 +4596,13 @@ p5.prototype.registerMethod('init', function p5playInit() { if (!isNaN(args[1])) num2 = Number(args[1]); else to = args[1]; + let extIndex = from.lastIndexOf('.'); let digits1 = 0; let digits2 = 0; - // skip extension work backwards to find the numbers - for (let i = from.length - 5; i >= 0; i--) { + // start from ext "." + // work backwards to find where the numbers end + for (let i = extIndex - 1; i >= 0; i--) { if (!isNaN(from.charAt(i))) digits1++; else break; } @@ -4612,9 +4614,10 @@ p5.prototype.registerMethod('init', function p5playInit() { } } - let prefix1 = from.slice(0, -4 - digits1); + let ext = from.slice(extIndex); + let prefix1 = from.slice(0, extIndex - digits1); let prefix2; - if (to) prefix2 = to.slice(0, -4 - digits2); + if (to) prefix2 = to.slice(0, extIndex - digits2); // images don't belong to the same sequence // they are just two separate images with numbers @@ -4622,13 +4625,8 @@ p5.prototype.registerMethod('init', function p5playInit() { this.push($.loadImage(from)); this.push($.loadImage(to)); } else { - // Our numbers likely have leading zeroes, which means that some - // browsers (e.g., PhantomJS) will interpret them as base 8 (octal) - // instead of decimal. To fix this, we'll explicity tell parseInt to - // use a base of 10 (decimal). For more details on this issue, see - // http://stackoverflow.com/a/8763427/2422398. - let num1 = parseInt(from.slice(-4 - digits1, -4), 10); - num2 ??= parseInt(to.slice(-4 - digits2, -4), 10); + let num1 = parseInt(from.slice(extIndex - digits1, extIndex), 10); + num2 ??= parseInt(to.slice(extIndex - digits2, extIndex), 10); // swap if inverted if (num2 < num1) { @@ -4643,14 +4641,14 @@ p5.prototype.registerMethod('init', function p5playInit() { for (let i = num1; i <= num2; i++) { // Use nf() to number format 'i' into the amount of digits // ex: 14 with 4 digits is 0014 - fileName = prefix1 + $.nf(i, digits1) + '.png'; + fileName = prefix1 + $.nf(i, digits1) + ext; this.push($.loadImage(fileName)); } } // case: case img1, img2 else { for (let i = num1; i <= num2; i++) { // Use nf() to number format 'i' into four digits - fileName = prefix1 + i + '.png'; + fileName = prefix1 + i + ext; this.push($.loadImage(fileName)); } } @@ -4741,11 +4739,6 @@ p5.prototype.registerMethod('init', function p5playInit() { h = frameSize[1]; } - if (owner instanceof $.Group) { - owner.w ??= owner.width; - owner.h ??= owner.height; - } - let tileSize = owner.tileSize; if (!w || !h) { @@ -4937,26 +4930,24 @@ p5.prototype.registerMethod('init', function p5playInit() { $.push(); $.imageMode('center'); - let _x = x + this.offset.x; - let _y = y + this.offset.y; - - if (r) { - $.translate(_x, _y); - _x = _y = 0; - $.rotate(r); - } + $.translate(this.x, this.y); + $.rotate(r); $.scale(sx * this._scale._x, sy * this._scale._y); + + let ox = this.offset.x; + let oy = this.offset.y; + let img = this[this._frame]; if (img !== undefined) { if (this.spriteSheet) { let { x, y, w, h } = img; // image info if (!this.demoMode) { - $.image(this.spriteSheet, _x, _y, w, h, x, y, w, h); + $.image(this.spriteSheet, ox, oy, w, h, x, y, w, h); } else { $.image( this.spriteSheet, - _x, - _y, + ox, + oy, this.spriteSheet.w, this.spriteSheet.h, x - this.spriteSheet.w / 2 + w / 2, @@ -4964,7 +4955,7 @@ p5.prototype.registerMethod('init', function p5playInit() { ); } } else { - $.image(img, _x, _y); + $.image(img, ox, oy); } } else { console.warn( @@ -5484,18 +5475,10 @@ p5.prototype.registerMethod('init', function p5playInit() { * @type {Number} */ this.d; - /** - * @type {Number} - */ - this.diameter; /** * @type {Boolean} */ this.dynamic; - /** - * @type {Number} - */ - this.height; /** * @type {String} */ @@ -5516,10 +5499,6 @@ p5.prototype.registerMethod('init', function p5playInit() { * @type {Boolean} */ this.static; - /** - * @type {Number} - */ - this.width; /** * Each group has a unique id number. Don't change it! @@ -5646,7 +5625,7 @@ p5.prototype.registerMethod('init', function p5playInit() { } for (let prop of $.Sprite.propsAll) { - if (prop == 'ani' || prop == 'velocity') continue; + if (prop == 'ani' || prop == 'velocity' || prop == 'width' || prop == 'height' || prop == 'diameter') continue; Object.defineProperty(this, prop, { get() { @@ -5835,6 +5814,34 @@ p5.prototype.registerMethod('init', function p5playInit() { } } + /** + * @type {Number} + */ + get diameter() { + return this.d; + } + set diameter(val) { + this.d = val; + } + /** + * @type {Number} + */ + get width() { + return this.w; + } + set width(val) { + this.w = val; + } + /** + * @type {Number} + */ + get height() { + return this.h; + } + set height(val) { + this.h = val; + } + /** * The sprite's velocity vector {x, y} * @type {p5.Vector} diff --git a/v3/p5play.min.js b/v3/p5play.min.js index eacda4ea..bad350d9 100644 --- a/v3/p5play.min.js +++ b/v3/p5play.min.js @@ -1,7 +1,7 @@ /** * p5play - * @version 3.23 + * @version 3.24 * @author quinton-ashley * @license AGPL-3.0 */ -if("object"!=typeof planck){if("object"!=typeof process)throw"planck.js must be loaded before p5play";global.planck=require("./planck.min.js")}p5.prototype.registerMethod("init",(function(){const t=this,e=planck;if("object"!=typeof process&&0!=window._p5play_gtagged){let t=document.createElement("script");t.src="https://www.googletagmanager.com/gtag/js?id=G-EHXNCTSYLK",t.async=!0,document.head.append(t),window._p5play_gtagged=!0,t.onload=()=>{window.dataLayer??=[],window.gtag=function(){dataLayer.push(arguments)},gtag("js",new Date),gtag("config","G-EHXNCTSYLK"),gtag("event","p5play_v3_22")}}t.angleMode("degrees");const i=(i,s,r)=>new e.Vec2(i*r/t.world.meterSize,s*r/t.world.meterSize),s=(i,s,r)=>new e.Vec2(i/r*t.world.meterSize,s/r*t.world.meterSize),r=t=>Math.abs(t)<=e.Settings.linearSlop,o=(t,i)=>Math.abs(t-Math.round(t))<=(i||e.Settings.linearSlop)?Math.round(t):t,h=(e,i)=>{let s="degrees"==t._angleMode?360:t.TWO_PI,r=(e-i)%s,o=(s-Math.abs(r))*-Math.sign(r);return(Math.abs(r)-1){let e=navigator.userAgent.substring(t+10,t+12);this.os.platform="iOS",this.os.version=e}else{let t=navigator.userAgentData?.platform;!t&&navigator.platform&&(t=navigator.platform.slice(3),"Mac"==t?t="macOS":"Win"==t?t="Windows":"Lin"==t&&(t="Linux")),this.os.platform=t}}this.renderStats=!1,this._renderStats={x:10,y:20,font:"monospace"},this._fps=60,this._fpsArr=[60],this._collides={},this._colliding={},this._collided={},this._overlaps={},this._overlapping={},this._overlapped={}}onImageLoad(){}},this.p5play=new t.P5Play,delete t.P5Play;const a=console.log;this.log=console.log,this.Sprite=class{constructor(i,s,r,h,n){this._isSprite=!0,this.idNum;let a,u,c=[...arguments];if(void 0!==c[0]&&c[0]._isGroup&&(a=c[0],c=c.slice(1)),void 0!==c[0]&&("string"==typeof c[0]||c[0]instanceof t.SpriteAnimation||c[0]instanceof p5.Image)&&(u=c[0],c=c.slice(1)),1==c.length&&"number"==typeof c[0])throw new b("Sprite",0,[c[0]]);if(Array.isArray(c[0])){if(i=void 0,s=void 0,r=c[0],h=void 0,n=c[1],Array.isArray(n))throw new b("Sprite",1,[`[[${r}], [${h}]]`])}else i=c[0],s=c[1],r=c[2],h=c[3],n=c[4];"string"==typeof r&&(n=r,r=void 0),"string"==typeof h&&(!function(t){if("d"==t||"s"==t||"k"==t||"n"==t)return!0;let e=t.slice(0,2);return"dy"==e||"st"==e||"ki"==e||"no"==e}(h)?r=p(r,h):n=h,h=void 0),this.idNum=t.p5play.spritesCreated,this._uid=1e3+this.idNum,t.p5play.sprites[this._uid]=this,t.p5play.spritesCreated++,this.groups=[],this.animations=new t.SpriteAnimations,this.joints=[],this.joints.removeAll=()=>{for(;this.joints.length;)this.joints.at(-1).remove()},this.watch,this.mod={},this._removed=!1,this._life=2147483647,this._visible=!0,this._pixelPerfect=!1,this._aniChangeCount=0,this._draw=()=>this.__draw(),this._hasOverlap={},this._collisions={},this._overlappers={},a??=t.allSprites,this._tile="",this.tileSize=a.tileSize||1;let _=this;this._position={x:0,y:0},this._pos=t.createVector.call(t),Object.defineProperty(this._pos,"x",{get(){if(!_.body)return _._position.x;let e=_.body.getPosition().x/_.tileSize*t.world.meterSize;return t.p5play.friendlyRounding?o(e):e},set(i){if(_.body){let s=new e.Vec2(i*_.tileSize/t.world.meterSize,_.body.getPosition().y);_.body.setPosition(s)}_._position.x=i}}),Object.defineProperty(this._pos,"y",{get(){if(!_.body)return _._position.y;let e=_.body.getPosition().y/_.tileSize*t.world.meterSize;return t.p5play.friendlyRounding?o(e):e},set(i){if(_.body){let s=new e.Vec2(_.body.getPosition().x,i*_.tileSize/t.world.meterSize);_.body.setPosition(s)}_._position.y=i}}),this._canvasPos=t.createVector.call(t),Object.defineProperty(this._canvasPos,"x",{get(){let e=_._pos.x-t.camera.x;return"2d"==t.canvas.renderer&&(e+=t.canvas.hw/t.camera._zoom),e}}),Object.defineProperty(this._canvasPos,"y",{get(){let e=_._pos.y-t.camera.y;return"2d"==t.canvas.renderer&&(e+=t.canvas.hh/t.camera._zoom),e}}),this._velocity={x:0,y:0},this._direction=0,this._vel=t.createVector.call(t),Object.defineProperties(this._vel,{x:{get(){let e;return e=_.body?_.body.getLinearVelocity().x:_._velocity.x,e/=_.tileSize,t.p5play.friendlyRounding?o(e):e},set(t){t*=_.tileSize,_.body?_.body.setLinearVelocity(new e.Vec2(t,_.body.getLinearVelocity().y)):_._velocity.x=t,(t||this.y)&&(_._direction=this.heading())}},y:{get(){let e;return e=_.body?_.body.getLinearVelocity().y:_._velocity.y,e/=_.tileSize,t.p5play.friendlyRounding?o(e):e},set(t){t*=_.tileSize,_.body?_.body.setLinearVelocity(new e.Vec2(_.body.getLinearVelocity().x,t)):_._velocity.y=t,(t||this.x)&&(_._direction=this.heading())}}}),this._mirror={_x:1,_y:1,get x(){return this._x<0},set x(t){_.watch&&(_.mod[20]=!0),this._x=t?-1:1},get y(){return this._y<0},set y(t){_.watch&&(_.mod[20]=!0),this._y=t?-1:1}},this._heading="right",this._layer=a._layer,this._layer??=t.allSprites._getTopLayer()+1,a.dynamic&&(n??="dynamic"),a.kinematic&&(n??="kinematic"),a.static&&(n??="static"),n??=a.collider,n&&"string"==typeof n||(n="dynamic"),this.collider=n,i??=a.x,void 0===i&&(i="2d"==t.canvas?.renderer?t.canvas.hw/this.tileSize:0,r&&(this._vertexMode=!0)),s??=a.y,void 0===s&&(s="2d"==t.canvas?.renderer?t.canvas.hh/this.tileSize:0);let g=!1;if(void 0===r&&(r=a.w||a.width||a.d||a.diameter||a.v||a.vertices,h||a.d||a.diameter||(h=a.h||a.height,g=!0)),"function"==typeof i&&(i=i(a.length)),"function"==typeof s&&(s=s(a.length)),"function"==typeof r&&(r=r(a.length)),"function"==typeof h&&(h=h(a.length)),this.x=i,this.y=s,!a._isAllSpritesGroup&&!u){for(let t in a.animations){u=t;break}u||(u=a._img,"function"==typeof u&&(u=u(a.length)),u&&(this._img=!0))}for(let e=a;e;e=t.p5play.groups[e.parent])this.groups.push(e);if(this.groups.reverse(),u){let e=this.tileSize;this._img||u instanceof p5.Image?(this.image="string"!=typeof u?u:new t.EmojiImage(u,r),r||1==this._img.w&&1==this._img.h||(r=this._img.w/e,h??=this._img.h/e)):("string"==typeof u?this._changeAni(u):this._ani=u.clone(),r||1==this._ani.w&&1==this._ani.h||(r=this._ani.w/e,h??=this._ani.h/e))}if(this.groups=[],this.mouse=new t._SpriteMouse,this._rotation=0,this._rotationSpeed=0,this._bearing=0,this._scale=new l,Object.defineProperty(this._scale,"x",{get(){return this._x},set(t){if(t==this._x)return;_.watch&&(_.mod[26]=!0);let e=Math.abs(t/this._x);_._w*=e,_._hw*=e,_._resizeColliders({x:e,y:1}),this._x=t,this._avg=.5*(this._x+this._y)}}),Object.defineProperty(this._scale,"y",{get(){return this._y},set(t){if(t==this._y)return;_.watch&&(_.mod[26]=!0);let e=Math.abs(t/this._y);_._h&&(this._h*=e,this._hh*=e),_._resizeColliders({x:1,y:e}),this._y=t,this._avg=.5*(this._x+this._y)}}),this._offset={_x:0,_y:0,get x(){return this._x},set x(t){t!=this._x&&(_.watch&&(_.mod[21]=!0),_._offsetCenterBy(t-this._x,0))},get y(){return this._y},set y(t){t!=this._y&&(_.watch&&(_.mod[21]=!0),_._offsetCenterBy(0,t-this._y))}},this._massUndef=!0,void 0===r&&(this._dimensionsUndef=!0,this._widthUndef=!0,r=this.tileSize>1?1:50,void 0===h&&(this._heightUndef=!0)),g&&(h??=this.tileSize>1?1:50),this._shape=a.shape,3!=this.__collider)this._vertexMode?this.addCollider(r):this.addCollider(0,0,r,h),this.shape=this._shape;else{if(this.w=r,Array.isArray(r))throw new Error('Cannot set the collider type of a sprite with a polygon or chain shape to "none". To achieve the same effect, use .overlaps(allSprites) to have your sprite overlap with the allSprites group.');void 0!==r&&void 0===h?this.shape="circle":(this.shape="box",this.h=h)}this.prevPos={x:i,y:s},this.prevRotation=0,this._dest={x:i,y:s},this._destIdx=0,this._debug=!1,this.text,a._isAllSpritesGroup||t.allSprites.push(this),a.push(this);let f=a.vel.x||0,m=a.vel.y||0;"function"==typeof f&&(f=f(a.length-1)),"function"==typeof m&&(m=m(a.length-1)),this.vel.x=f,this.vel.y=m;let y=["ani","collider","x","y","w","h","d","diameter","dynamic","height","kinematic","static","vel","width"];for(let e of t.Sprite.propsAll){if(y.includes(e))continue;let i=a[e];void 0!==i&&("function"==typeof i&&d(i)&&(i=i(a.length-1)),"object"==typeof i?i instanceof p5.Color?this[e]=t.color(...i.levels):this[e]=Object.assign({},i):this[e]=i)}y=["add","animation","animations","autoCull","contains","GroupSprite","Group","idNum","length","mod","mouse","p","parent","Sprite","Subgroup","subgroups","velocity"];for(let e=0;e1?1:50,n??=h,d=i(h-.08,n-.08,this.tileSize)),"box"==l)u=e.Box(d.x/2,d.y/2,i(s,o,this.tileSize),0);else if("circle"==l)u=e.Circle(i(s,o,this.tileSize),d.x/2);else if(a){let _,g,f=[{x:0,y:0}],m={x:0,y:0},y={x:0,y:0},w={x:0,y:0},v=Array.isArray(a[0]);function x(){m.xw.x&&(w.x=m.x),m.y>w.y&&(w.y=m.y)}if(v){this._vertexMode&&(_=a[0][0],g=a[0][1],this.fixture&&this._relativeOrigin?(_=this.x-this._relativeOrigin.x,g=this.y-this._relativeOrigin.y,f.pop()):(this.x=_,this.y=g));for(let S=0;S0?1:-1;A=Math.abs(A);let k=0;for(let M=0;Me.Settings.maxPolygonVertices||"chain"==this._shape)&&(l="chain"),"polygon"==l?u=e.Polygon(f):"chain"==l&&(u=e.Chain(f,!1))}if(this.shape??=l,this.fixtureList){this._extents??={t:this.hh,b:this.hh,l:this._hw,r:this._hw};let G=this._extents,N=s-.5*h,E=s+.5*h,R=o-.5*n,U=o+.5*n;NG.r&&(G.r=E),RG.b&&(G.b=U),this._totalWidth=G.r-G.l,this._totalHeight=G.b-G.t;let V=Math.abs;this._largestExtent=Math.max(V(G.l),V(G.r),V(G.t),V(G.b))}else this._w=h,this._hw=.5*h,1!=this.__shape&&(this._h=n,this._hh=.5*n);return u}removeColliders(){this.body&&(this._removeContacts(0),this._removeFixtures(0))}removeSensors(){this.body&&(this._removeContacts(1),this._removeFixtures(1),this._hasSensors=!1)}_removeFixtures(e){let i;for(let s=this.fixtureList;s;s=s.getNext())if(void 0===e||s.m_isSensor==e){let e=s.m_next;s.destroyProxies(t.world.m_broadPhase),i?i.m_next=e:this.body.m_fixtureList=e}else i=s}_removeContacts(e){if(!this.body)return;let i=this.body.m_contactList;for(;i;){let s=i.contact;i=i.next,void 0!==e&&s.m_fixtureA.m_isSensor!=e||t.world.destroyContact(s)}}_offsetCenterBy(t,e){if(!t&&!e)return;if(this._offset._x+=t,this._offset._y+=e,!this.body)return;let s=i(t,e,this.tileSize);this.__offsetCenterBy(s.x,s.y)}__offsetCenterBy(t,e){for(let i=this.body.m_fixtureList;i;i=i.m_next){let s=i.m_shape;if("circle"!=s.m_type){let i=s.m_vertices;for(let s of i)s.x+=t,s.y+=e}else s.m_p.x+=t,s.m_p.y+=e}}_cloneBodyProps(){let t={},e=["bounciness","density","drag","friction","heading","isSuperFast","rotation","rotationDrag","rotationLock","rotationSpeed","scale","vel","x","y"];this._massUndef&&this._dimensionsUndef||e.push("mass");for(let i of e)"object"==typeof this[i]?t[i]=Object.assign({},this[i]):t[i]=this[i];return t}get animation(){return this._ani}set animation(t){this.changeAni(t)}get ani(){return this._ani}set ani(t){this.changeAni(t)}get anis(){return this.animations}get autoDraw(){return this._autoDraw}set autoDraw(t){this._autoDraw=t}get allowSleeping(){return this.body?.isSleepingAllowed()}set allowSleeping(t){this.watch&&(this.mod[5]=!0),this.body&&this.body.setSleepingAllowed(t)}get autoUpdate(){return this._autoUpdate}set autoUpdate(t){this._autoUpdate=t}get bounciness(){if(this.fixture)return this.fixture.getRestitution()}set bounciness(t){this.watch&&(this.mod[7]=!0);for(let e=this.fixtureList;e;e=e.getNext())e.setRestitution(t)}get collider(){return this._collider}set collider(e){if(e==this._collider)return;let i=(e=e.toLowerCase())[0];if("d"==i&&(e="dynamic"),"s"==i&&(e="static"),"k"==i&&(e="kinematic"),"n"==i&&(e="none"),e==this._collider)return;if("none"==e&&("chain"==this._shape||"polygon"==this._shape))return void console.error('Cannot set the collider type of a polygon or chain collider to "none". To achieve the same effect, use .overlaps(allSprites) to have your sprite overlap with the allSprites group.');if(this._removed)throw new Error("Cannot change the collider type of a sprite that was removed.");let s=this.__collider;this._collider=e,this.__collider=["d","s","k","n"].indexOf(i),this.watch&&(this.mod[8]=!0),void 0!==s&&(3!=this.__collider?(this.body&&this.body.setType(e),3==s&&(this.addCollider(),this.x=this._position.x,this.y=this._position.y,this.vel.x=this._velocity.x,this.vel.y=this._velocity.y,this.rotation=this._rotation,this.rotationSpeed=this._rotationSpeed)):(this.removeColliders(),this.fixture?.m_isSensor?this.body.m_gravityScale=0:(this._position.x=this.x,this._position.y=this.y,this._velocity.x=this.vel.x,this._velocity.y=this.vel.y,this._rotation=this.rotation,this._rotationSpeed=this.rotationSpeed,t.world.destroyBody(this.body),this.body=null)))}_parseColor(e){return e instanceof p5.Color?e:"object"!=typeof e?1==e.length?t.colorPal(e):t.color(e):t.color(...e.levels)}get color(){return this._color}set color(t){this.watch&&(this.mod[9]=!0),this._color=this._parseColor(t)}get colour(){return this._color}set colour(t){this.color=t}get fill(){return this._color}set fill(t){this.color=t}get fillColor(){return this._color}set fillColor(t){this.color=t}get stroke(){return this._stroke}set stroke(t){this.watch&&(this.mod[29]=!0),this._stroke=this._parseColor(t)}get strokeColor(){return this._stroke}set strokeColor(t){this.stroke=t}get strokeWeight(){return this._strokeWeight}set strokeWeight(t){this.watch&&(this.mod[30]=!0),this._strokeWeight=t}get textColor(){return this._textFill}set textColor(t){this.watch&&(this.mod[32]=!0),this._textFill=this._parseColor(t)}get textColour(){return this._textFill}set textColour(t){this.textColor=t}get textFill(){return this._textFill}set textFill(t){this.textColor=t}get textSize(){return this._textSize}set textSize(t){this.watch&&(this.mod[33]=!0),this._textSize=t}get textStroke(){return this._textStroke}set textStroke(t){this.watch&&(this.mod[34]=!0),this._textStroke=this._parseColor(t)}get textStrokeWeight(){return this._textStrokeWeight}set textStrokeWeight(t){this.watch&&(this.mod[35]=!0),this._textStrokeWeight=t}get tile(){return this._tile}set tile(t){this.watch&&(this.mod[36]=!0),this._tile=t}get tileSize(){return this._tileSize}set tileSize(t){this.watch&&(this.mod[37]=!0),this._tileSize=t}get bearing(){return this._bearing}set bearing(t){this.watch&&(this.mod[6]=!0),this._bearing=t}get debug(){return this._debug}set debug(t){this.watch&&(this.mod[10]=!0),this._debug=t}get density(){if(this.fixture)return this.fixture.getDensity()}set density(t){this.watch&&(this.mod[11]=!0);for(let e=this.fixtureList;e;e=e.getNext())e.setDensity(t)}_getDirectionAngle(e){e=e.toLowerCase().replaceAll(/[ _-]/g,"");let i={up:-90,down:90,left:180,right:0,upright:-45,rightup:-45,upleft:-135,leftup:-135,downright:45,rightdown:45,downleft:135,leftdown:135,forward:this.rotation,backward:this.rotation+180}[e];return"radians"==t._angleMode&&(i=t.radians(i)),i}get direction(){return 0!==this.vel.x||0!==this.vel.y?t.atan2(this.vel.y,this.vel.x):this._isTurtleSprite?this.rotation:this._direction}set direction(e){this.watch&&(this.mod[12]=!0),"string"==typeof e&&(this._heading=e,e=this._getDirectionAngle(e)),this._direction=e,this._isTurtleSprite&&(this.rotation=e);let i=this.speed;this.vel.x=t.cos(e)*i,this.vel.y=t.sin(e)*i}get drag(){return this.body?.getLinearDamping()}set drag(t){this.watch&&(this.mod[13]=!0),this.body&&this.body.setLinearDamping(t)}get draw(){return this._display}set draw(t){this._userDefinedDraw=!0,this._draw=t}get dynamic(){return this.body?.isDynamic()}set dynamic(t){this.collider=t?"dynamic":"kinematic"}get fixture(){return this.fixtureList}get fixtureList(){return this.body?this.body.m_fixtureList:null}get friction(){if(this.fixture)return this.fixture.getFriction()}set friction(t){this.watch&&(this.mod[14]=!0);for(let e=this.fixtureList;e;e=e.getNext())e.setFriction(t)}get heading(){return this._heading}set heading(t){this.direction=t}get img(){return this._img||this._ani?.frameImage}set img(t){this.image=t}get image(){return this._img||this._ani?.frameImage}set image(e){"string"==typeof e&&(e=e.includes(".")?t.loadImage(e):new t.EmojiImage(e,this.w)),this._img=this._extendImage(e)}_extendImage(t){return t.offset??={x:0,y:0},t._scale??={x:1,y:1},t.scale||Object.defineProperty(t,"scale",{get:()=>t._scale,set:e=>{"number"==typeof e&&(e={x:e,y:e}),t._scale=e}}),t}get isMoving(){return 0!=this.vel.x||0!=this.vel.y}get isSuperFast(){return this.body?.isBullet()}set isSuperFast(t){this.watch&&(this.mod[16]=!0),this.body&&this.body.setBullet(t)}get kinematic(){return this.body?.isKinematic()}set kinematic(t){this.collider=t?"kinematic":"dynamic"}get layer(){return this._layer}set layer(t){this.watch&&(this.mod[17]=!0),this._layer=t}get life(){return this._life}set life(t){this.watch&&(this.mod[18]=!0),this._life=t}get mass(){return this.body?.getMass()}set mass(t){if(!this.body)return;this.watch&&(this.mod[19]=!0);const i={I:0,center:new e.Vec2(this.body.getLocalCenter()),mass:0};this.body.getMassData(i),i.mass=t>0?t:1e-8,this.body.setMassData(i),delete this._massUndef}resetMass(){if(!this.body)return;let t=new e.Vec2(this.body.getLocalCenter());this.watch&&(this.mod[19]=!0),this.body.resetMassData(),this.body.setMassData({mass:this.body.getMass(),center:t,I:this.body.getInertia()})}resetCenterOfMass(){this.watch&&(this.mod[19]=!0),this.body.resetMassData();let{x:t,y:e}=this.body.getLocalCenter();if(0==t&&0==e)return;this.__offsetCenterBy(-t,-e),this.body.resetMassData();let i=this.body.getPosition();this.body.setPosition({x:i.x+t,y:i.y+e})}get mirror(){return this._mirror}set mirror(t){this.watch&&(this.mod[20]=!0),void 0!==t.x&&(this._mirror.x=t.x),void 0!==t.y&&(this._mirror.y=t.y)}get offset(){return this._offset}set offset(t){t.x??=this._offset._x,t.y??=this._offset._y,t.x==this._offset._x&&t.y==this._offset._y||(this.watch&&(this.mod[21]=!0),this._offsetCenterBy(t.x-this._offset._x,t.y-this._offset._y))}get opacity(){return this._opacity??1}set opacity(t){this.watch&&(this.mod[41]=!0),this._opacity=t}get previousPosition(){return this.prevPos}set previousPosition(t){this.prevPos=t}get previousRotation(){return this.prevRotation}set previousRotation(t){this.prevRotation=t}get pixelPerfect(){return this._pixelPerfect}set pixelPerfect(t){this.watch&&(this.mod[22]=!0),this._pixelPerfect=t}get removed(){return this._removed}set removed(t){t&&!this._removed&&(this.watch&&(this.mod[23]=!0),this._removed=!0,this._remove())}get rotation(){if(!this.body)return this._rotation||0;let i=this.body.getAngle();return"degrees"==t._angleMode&&(i=t.degrees(i)),t.p5play.friendlyRounding?o(i,e.Settings.angularSlop):i}set rotation(e){this.body?("degrees"==t._angleMode&&(e=t.radians(e%360)),this.body.setAngle(e),this.body.synchronizeTransform()):this._rotation=e}get rotationDrag(){return this.body?.getAngularDamping()}set rotationDrag(t){this.body&&(this.watch&&(this.mod[24]=!0),this.body.setAngularDamping(t))}get rotationLock(){return this.body?.isFixedRotation()}set rotationLock(t){if(!this.body)return;this.watch&&(this.mod[25]=!0);let e=this.mass;this.body.setFixedRotation(t),this.mass=e}get rotationSpeed(){if(this.body){let e=this.body.getAngularVelocity()/60;return"degrees"==t._angleMode?t.degrees(e):e}return this._rotationSpeed}set rotationSpeed(e){this.body?(e*=60,"degrees"==t._angleMode&&(e=t.radians(e)),this.body.setAngularVelocity(e)):this._rotationSpeed=e}get scale(){return this._scale}set scale(t){if(0==t&&(t=.01),"number"==typeof t?t={x:t,y:t}:(t.x??=this._scale._x,t.y??=this._scale._y),t.x==this._scale._x&&t.y==this._scale._y)return;this.watch&&(this.mod[26]=!0);let e={x:Math.abs(t.x/this._scale._x),y:Math.abs(t.y/this._scale._y)};this._w*=e.x,this._hw*=e.x,this._h&&(this._h*=e.y,this._hh*=e.y),this._resizeColliders(e),this._scale._x=t.x,this._scale._y=t.y,this._scale._avg=t.x}get sleeping(){if(this.body)return!this.body.isAwake()}set sleeping(t){this.body&&(this.watch&&(this.mod[28]=!0),this.body.setAwake(!t))}get speed(){return t.createVector(this.vel.x,this.vel.y).mag()}set speed(e){let i=this.direction;this.vel.x=t.cos(i)*e,this.vel.y=t.sin(i)*e}get static(){return this.body?.isStatic()}set static(t){this.collider=t?"static":"dynamic"}get tint(){return this._tint}set tint(t){this.watch&&(this.mod[42]=!0),this._tint=this._parseColor(t)}get tintColor(){return this._tint}set tintColor(t){this.tint=t}set vertices(t){if(3==this.__collider)throw new Error('Cannot set vertices of a sprite with collider type of "none".');this.watch&&(this.mod[27]=!0),this._removeFixtures(),this._originMode="start",this.addCollider(t),this._hasSensors&&this.addDefaultSensors()}get vertices(){return this._getVertices()}_getVertices(e){let i=this.fixture.getShape(),s=[...i.m_vertices];"polygon"==i.m_type&&s.unshift(s.at(-1));let r=this.x,h=this.y;for(let i=0;i=2)return void console.error('Cannot set the collider shape to chain or polygon if the sprite has a collider type of "none". To achieve the same effect, use .overlaps(allSprites) to have your sprite overlap with the allSprites group.');let s,r,o=this.__shape;if(this.__shape=i,this._shape=e,this.watch&&(this.mod[27]=!0),void 0===o)return;if(0==this.__shape?(this._h=this._w,this._hh=this._hw):(this._h=void 0,this._hh=void 0),1!=o&&1!=this.__shape?s=this._getVertices(!0):r=this._w,this._removeFixtures(),3!=this.__collider)if(s)this._originMode??="center",this.addCollider(s);else if(1==o){let t=this._w*Math.sin(Math.PI/12);this.addCollider(0,0,[t,-30,12])}else this.addCollider();this._hasSensors&&this.addDefaultSensors();let h=this._offset._x,n=this._offset._y;(h||n)&&(this._offset._x=0,this._offset._y=0,this._offsetCenterBy(h,n))}get update(){return this._update}set update(t){this._customUpdate=t}get vel(){return this._vel}set vel(t){this.vel.x=t.x,this.vel.y=t.y}get velocity(){return this._vel}set velocity(t){this.vel=t}get gravityScale(){return this.body?.getGravityScale()}set gravityScale(t){this.body&&(this.watch&&(this.mod[42]=!0),this.body.setGravityScale(t))}_update(){this._ani?.update&&this._ani.update();for(let t in this.mouse)-1==this.mouse[t]&&(this.mouse[t]=0);this._customUpdate&&this._customUpdate(),this.autoUpdate&&(this.autoUpdate=null)}_step(){this.life-=t.world.timeScale,2147483647!=this._life&&this._life<=0&&this.remove(),this.body||this._removed||(this.rotation+=this._rotationSpeed,this.x+=this.vel.x,this.y+=this.vel.y),this.watch&&(this.x!=this.prevX&&(this.mod[0]=this.mod[2]=!0),this.y!=this.prevY&&(this.mod[1]=this.mod[2]=!0),this.rotation!=this.prevRotation&&(this.mod[3]=this.mod[4]=!0)),(this.body||this._removed)&&this.__step()}__step(){let e,i=this;for(let s in n)for(let r in this[s]){if(r>=1e3){if(i._isGroup||i._uid>=r)continue;e=t.p5play.sprites[r]}else{if(i._isGroup&&i._uid>=r)continue;e=t.p5play.groups[r]}let o=i[s][r]+1;e&&0!=o&&-2!=o?(this[s][r]=o,e[s][i._uid]=o):(delete i[s][r],e&&delete e[s][i._uid])}}___step(){let e,i,s,r,o=this,h=!0;for(let a in n){for(let l in this[a]){if(l>=1e3){if(o._isGroup||o._uid>=l)continue;e=t.p5play.sprites[l]}else{if(o._isGroup&&o._uid>=l)continue;e=t.p5play.groups[l]}if(o._isGroup||e?._isGroup)continue;if(s=o._hasOverlap[e._uid]??e._hasOverlap[o._uid],h&&!1!==s||!h&&!0!==s)continue;let d=o[a][l];for(let s=0;s<3;s++){if(0==s&&1!=d&&-3!=d)continue;if(1==s&&-1==d)continue;if(2==s&&d>=1)continue;i=n[a][s];let h=t.p5play[i][o._uid];if(h){r=h[e._uid],r&&r.call(o,o,e,d);for(let t of e.groups)r=h[t._uid],r&&r.call(o,o,e,d)}let l=t.p5play[i][e._uid];if(l){r=l[o._uid],r&&r.call(e,e,o,d);for(let t of o.groups)r=l[t._uid],!r||h&&r==h[t._uid]||r.call(e,e,o,d)}}}h=!1}if(this._removed&&0==Object.keys(this._collisions).length&&0==Object.keys(this._overlappers).length){this._isSprite?delete t.p5play.sprites[this._uid]:t.p5play.targetVersion>=16&&delete t.p5play.groups[this._uid];for(let e in n)for(let i of n[e])delete t.p5play[i][this._uid]}}__draw(){if(!t.p5play.disableImages)if(this._ani)this._ani.draw(this._offset._x,this._offset._y,0,this._scale._x,this._scale._y);else if(this._img){let e=this._img,i=1!=this._scale._x||1!=this._scale._y||1!=e.scale.x||1!=e.scale.y;i&&(t.push(),t.scale(this._scale._x*e.scale.x,this._scale._y*e.scale.y)),t.image(e,this._offset._x+e.offset.x,this._offset._y+e.offset.y),i&&t.pop()}if(!this._ani&&!this._img||this.debug||t.p5play.disableImages)if(this.debug&&(t.noFill(),t.stroke(0,255,0),t.line(0,-2,0,2),t.line(-2,0,2,0)),3!=this.__collider){this.debug||0===this._strokeWeight?t.noStroke():2==this.__shape?t.stroke(this.stroke||this.color):this._stroke&&t.stroke(this._stroke);for(let e=this.fixtureList;e;e=e.getNext()){if(this.debug)e.m_isSensor?t.stroke(255,255,0):t.stroke(0,255,0);else if(e.m_isSensor)continue;this._drawFixture(e)}}else 0!==this._strokeWeight&&t.stroke(this._stroke||120),0==this.__shape?t.rect(this._offset._x,this._offset._y,this.w*this.tileSize,this.h*this.tileSize):1==this.__shape&&t.circle(this._offset._x,this._offset._y,this.d*this.tileSize);void 0!==this.text&&(t.textAlign(t.CENTER,t.CENTER),t.fill(this._textFill),this._textStrokeWeight&&t.strokeWeight(this._textStrokeWeight),this._textStroke?t.stroke(this._textStroke):t.noStroke(),t.textSize(this.textSize*this.tileSize),t.text(this.text,0,0))}_display(){let e,i=this.x*this.tileSize+t.world.origin.x,s=this.y*this.tileSize+t.world.origin.y;if(!this._userDefinedDraw){let e;if(e=this._totalWidth?Math.max(this._totalWidth,this._totalHeight):void 0!==this._h?Math.max(this._w,this._h):this._w,this.ani&&!t.p5play.disableImages&&(e=Math.max(e,this.ani.w,this.ani.h)),"chain"!=this.shape&&t.camera.isActive&&(i+et.camera.bound.max.x||s+et.camera.bound.max.y))return void(this._visible=null)}if(this._visible=!0,t.p5play.spritesDrawn++,this._pixelPerfect){let e,r;this.ani&&this.ani.length&&!t.p5play.disableImages?(e=this.ani[this.ani._frame].w,r=this.ani[this.ani._frame].h):(e=this._w,r=this._h),i=e%2==0?Math.round(i):Math.round(i-.5)+.5,s=r%2==0?Math.round(s):Math.round(s-.5)+.5}else i=o(i),s=o(s);for(let t of this.joints)t.visible?this._uid==t.spriteA._uid?(!t.spriteB._visible||this.layer<=t.spriteB.layer)&&t._display():(!t.spriteA._visible||this.layer{let s,r;do{if(await t.sleep(),c!=this._destIdx)return!1;let o=this.direction<0?this.direction+360:this.direction;if(u&&(o<=a||o>=l)||Math.abs(this.vel.x)<=d&&Math.abs(this.vel.y)<=d)return!1;e&&(s=this.vel.x>0?this._dest.x-this.x:this.x-this._dest.x),i&&(r=this.vel.y>0?this._dest.y-this.y:this.y-this._dest.y)}while(e&&s>p||i&&r>p);return this.x=this._dest.x,this.y=this._dest.y,this.vel.x=0,this.vel.y=0,!0})()}rotateTowards(t,e){if(1==this.__collider)return void new b(0);let i,s,r,o=arguments;"number"!=typeof o[0]?(i=o[0].x,s=o[0].y,e=o[1],r=o[2]):arguments.length>2&&(i=o[0],s=o[1],e=o[2],r=o[3]),void 0!==i?t=this.angleToFace(i,s,r):t-=this.rotation,e??=.1,this.rotationSpeed=t*e}angleTo(e,i){if("object"==typeof e){let s=e;if(s==t.mouse&&!t.mouse.isActive)return 0;if(void 0===s.x||void 0===s.y)return console.error("sprite.angleTo ERROR: rotation destination not defined, object given with no x or y properties"),0;i=s.y,e=s.x}return t.atan2(i-this.y,e-this.x)}rotationToFace(t,e,i){return"object"==typeof t&&(i=e,e=t.y,t=t.x),Math.abs(t-this.x)<.01&&Math.abs(e-this.y)<.01?0:this.angleTo(t,e)+(i||0)}angleToFace(t,e,i){let s=this.rotationToFace(t,e,i);return h(s,this.rotation)}rotateTo(e,i,s){if(1==this.__collider)return void new b(0);let r=arguments;if("number"!=typeof r[0]?e=this.rotationToFace(r[0].x,r[0].y,s):r.length>2&&(s=r[3],i=r[2],e=this.rotationToFace(r[0],r[1],s)),e==this.rotation)return;let o="degrees"==t._angleMode?360:t.TWO_PI;return(e=(e-this.rotation)%o)<0&&i>0&&(e+=o),e>0&&i<0&&(e-=o),i??=this.rotationSpeed||Math.sign(e),this.rotate(e,i)}rotateMinTo(t,e,i){if(1==this.__collider)return void new b(0);let s=arguments;return"number"!=typeof s[0]?t=this.rotationToFace(s[0].x,s[0].y,i):s.length>2&&(i=s[3],e=s[2],t=this.rotationToFace(s[0],s[1],i)),t!=this.rotation?(t=h(t,this.rotation),e??=this.rotationSpeed>.1?this.rotationSpeed:1,e=Math.abs(e)*Math.sign(t),this.rotate(t,e)):void 0}rotate(e,i){if(1==this.__collider)return void new b(0);if(isNaN(e))return void new b(1,[e]);if(0==e)return;i??=this.rotationSpeed||1;let s=e>0&&i>0;s||(e=-Math.abs(e),i=-Math.abs(i)),this.rotationSpeed=i;let r=Math.abs(i),o=this.rotation+e;this._rotateIdx??=0,this._rotateIdx++;let h=this._rotateIdx;return(async()=>{let e=.01;do{let n=Math.abs(o-this.rotation);if(r>n&&(this.rotationSpeed=n*Math.sign(i)),await t.sleep(),this._rotateIdx!=h)return!1;if(s&&this.rotationSpeed-.01)return!1}while((s&&o>this.rotation||!s&&o1)e=[...arguments];else if(e instanceof t.SpriteAnimation){if(e==this._ani)return;e=[e]}else if(!Array.isArray(e)){if(e==this._ani?.name)return;e=[e]}let i,s;this._aniChangeCount++;for(let r=0;r1&&("!"==o.name[0]&&(o.name=o.name.slice(1),o.start=-1,o.end=0),"<"!=o.name[0]&&">"!=o.name[0]||(o.name=o.name.slice(1),o.flipX=!0),"^"==o.name[0]&&(o.name=o.name.slice(1),o.flipY=!0),"**"==o.name&&(i=!0,e=e.slice(0,-1)),";;"==o.name&&(s=!0,e=e.slice(0,-1)))}let r=this._aniChangeCount;do{for(let t=0;t1&&(i.start=0),await this._playSequencedAni(i)}}while(i&&r==this._aniChangeCount);1!=e.length&&s&&this._ani.stop()}_playSequencedAni(t){return new Promise((e=>{let{name:i,start:s,end:r,flipX:o,flipY:h}=t;this._changeAni(i),o&&(this._ani.scale.x=-this._ani.scale.x),h&&(this._ani.scale.y=-this._ani.scale.y),s<0&&(s=this._ani.length+s),void 0!==s&&(this._ani._frame=s),void 0!==r?this._ani.goToFrame(r):this._ani._frame==this._ani.lastFrame&&e(),this._ani._onComplete=this._ani._onChange=()=>{o&&(this._ani.scale.x=-this._ani.scale.x),h&&(this._ani.scale.y=-this._ani.scale.y),this._ani._onComplete=this._ani._onChange=null,e()}}))}changeAnimation(){return this.changeAni(...arguments)}_changeAni(e){this._ani?._onChange&&this._ani._onChange(),this._ani?.onChange&&this._ani.onChange();let i=this.animations[e];if(!i)for(let t=this.groups.length-1;t>=0;t--){if(i=this.groups[t].animations[e],i){i=i.clone();break}}if(!i)throw t.noLoop(),new b("Sprite.changeAnimation",[e]);this._ani=i,this._ani.name=e,this.resetAnimationsOnChange&&(this._ani._frame=0)}remove(){this.removed=!0}_remove(){this.body&&t.world.destroyBody(this.body),this.body=null;for(let t of this.groups)t.remove(this)}toString(){return"s"+this.idNum}_setContactCB(e,i,s,r){let o;o=0==s?n._collisions[r]:n._overlappers[r];let h=t.p5play[o],a=h[this._uid]??={};a[e._uid]!=i&&(a[e._uid]=i,a=h[e._uid],a&&a[this._uid]&&(delete a[this._uid],0==Object.keys(a).length&&delete h[e._uid]))}_validateCollideParams(t,e){if(!t)throw new b("Sprite.collide",2);if(!t._isSprite&&!t._isGroup)throw new b("Sprite.collide",0,[t]);if(e&&"function"!=typeof e)throw new b("Sprite.collide",1,[e])}_ensureCollide(t,e,i){if(!1!==this._hasOverlap[t._uid]&&(this._hasOverlap[t._uid]=!1),!1!==t._hasOverlap[this._uid]&&(t._hasOverlap[this._uid]=!1,t._isGroup))for(let e of t)e._hasOverlap[this._uid]=!1,this._hasOverlap[e._uid]=!1}collide(t,e){return this.collides(t,e)}collides(t,e){return this._validateCollideParams(t,e),this._ensureCollide(t),e&&this._setContactCB(t,e,0,0),1==this._collisions[t._uid]||this._collisions[t._uid]<=-3}colliding(t,e){this._validateCollideParams(t,e),this._ensureCollide(t),e&&this._setContactCB(t,e,0,1);let i=this._collisions[t._uid];return i<=-3?1:i>0?i:0}collided(t,e){return this._validateCollideParams(t,e),this._ensureCollide(t),e&&this._setContactCB(t,e,0,2),this._collisions[t._uid]<=-1}_validateOverlapParams(t,e){if(!t)throw new b("Sprite.overlap",2);if(!t._isSprite&&!t._isGroup)throw new b("Sprite.overlap",0,[t]);if(e&&"function"!=typeof e)throw new b("Sprite.overlap",1,[e])}_ensureOverlap(t){if(this._hasSensors||this.addDefaultSensors(),!t._hasSensors)if(t._isSprite)t.addDefaultSensors();else{for(let e of t)e._hasSensors||e.addDefaultSensors();t._hasSensors=!0}if(this._hasOverlap[t._uid]||(this._removeContactsWith(t),this._hasOverlap[t._uid]=!0),!t._hasOverlap[this._uid]&&(t._removeContactsWith(this),t._hasOverlap[this._uid]=!0,t._isGroup))for(let e of t)e._hasOverlap[this._uid]=!0,this._hasOverlap[e._uid]=!0}overlap(t,e){return this.overlaps(t,e)}overlaps(t,e){return this._validateOverlapParams(t,e),this._ensureOverlap(t),e&&this._setContactCB(t,e,1,0),1==this._overlappers[t._uid]||this._overlappers[t._uid]<=-3}overlapping(t,e){this._validateOverlapParams(t,e),this._ensureOverlap(t),e&&this._setContactCB(t,e,1,1);let i=this._overlappers[t._uid];return i<=-3?1:i>0?i:0}overlapped(t,e){return this._validateOverlapParams(t,e),this._ensureOverlap(t),e&&this._setContactCB(t,e,1,2),this._overlappers[t._uid]<=-1}_removeContactsWith(t){if(t._isGroup)for(let e of t)this._removeContactsWith(e);else this.__removeContactsWith(t)}__removeContactsWith(e){if(this.body)for(let i=this.body.getContactList();i;i=i.next){let s=i.contact;s.m_fixtureA.m_body.sprite._uid!=e._uid&&s.m_fixtureB.m_body.sprite._uid!=e._uid||t.world.destroyContact(s)}}_sortFixtures(){let t,e,i=null,s=null;for(let r=this.fixtureList;r;r=r.getNext())r.m_isSensor?(s?s.m_next=r:s=r,e=r):(i?i.m_next=r:i=r,t=r);s&&(e.m_next=null),i&&(t.m_next=s),this.body.m_fixtureList=i||s}addDefaultSensors(){if(this._hasSensors)return;let t;if(this.body&&this.fixtureList){for(let e=this.fixtureList;e;e=e.getNext())e.m_isSensor||(t=e.m_shape,this.body.createFixture({shape:t,isSensor:!0}));this._sortFixtures()}else this.addSensor();this._hasSensors=!0}distanceTo(e){return t.dist(this.x,this.y,e.x,e.y)}},t.Sprite.propTypes={x:"Float64",y:"Float64",vel:"Vec2",rotation:"number",rotationSpeed:"number",allowSleeping:"boolean",bearing:"number",bounciness:"number",collider:"Uint8",color:"color",debug:"boolean",density:"number",direction:"number",drag:"number",friction:"number",h:"number",isSuperFast:"boolean",layer:"number",life:"Int32",mass:"number",mirror:"Vec2_boolean",offset:"Vec2",pixelPerfect:"boolean",removed:"boolean",rotationDrag:"number",rotationLock:"boolean",scale:"Vec2",shape:"Uint8",sleeping:"boolean",stroke:"color",strokeWeight:"number",text:"string",textColor:"color",textSize:"number",textStroke:"color",textStrokeWeight:"number",tile:"string",tileSize:"number",tint:"color",visible:"boolean",w:"number",opacity:"number",gravityScale:"number"},t.Sprite.props=Object.keys(t.Sprite.propTypes),t.Sprite.propsAll=t.Sprite.props.concat(["autoDraw","autoUpdate","d","diameter","dynamic","fill","height","heading","kinematic","resetAnimationsOnChange","speed","spriteSheet","static","width"]),t.Sprite.colliderTypes=["d","s","k","n"],t.Sprite.shapeTypes=["box","circle","chain","polygon"],t.Turtle=function(e){if(t.allSprites.tileSize>1)throw new Error("Turtle can't be used when allSprites.tileSize is greater than 1.");e??=25;let i=new t.Sprite(e,e,[[e,.4*e],[-e,.4*e],[0,.8*-e]]);i.color="green",i._isTurtleSprite=!0,i._prevPos={x:i.x,y:i.y};let s=i.move;return i.move=function(){return this._prevPos.x=this.x,this._prevPos.y=this.y,s.call(this,...arguments)},i},this.SpriteAnimation=class extends Array{constructor(){super();let e,i=[...arguments];if(this.name="default","object"==typeof i[0]&&(i[0]._isSprite||i[0]._isGroup)&&(e=i[0],i=i.slice(1),this._addedToSpriteOrGroup=!0),e??=t.allSprites,"string"!=typeof i[0]||1!=i[0].length&&i[0].includes(".")||(this.name=i[0],i=i.slice(1)),this._frame=0,this._cycles=0,this.targetFrame=-1,this.offset={x:e.anis.offset.x??0,y:e.anis.offset.y??0},this._frameDelay=e.anis.frameDelay||4,this.demoMode=e.anis.demoMode??!1,this.playing=!0,this.visible=!0,this.looping=e.anis.looping??!0,this.endOnFirstFrame=e.anis.endOnFirstFrame??!1,this.frameChanged=!1,this.onComplete=this.onChange=null,this._onComplete=this._onChange=null,this.rotation=e.anis.rotation??0,this._scale=new l,0!=i.length&&"number"!=typeof i[0]){if(e.animations[this.name]=this,e._ani=this,Array.isArray(i[0])&&"string"==typeof i[0][0]&&(i=[...i[0]]),2!=i.length||"string"!=typeof i[0]||"string"!=typeof i[1]&&"number"!=typeof i[1])if("string"==typeof i.at(-1)||i.at(-1)instanceof p5.Image)for(let s=0;s=3)throw new b("SpriteAnimation",1);o=i[0],r=i[1]}else r=i[0];let h=this;if(o instanceof p5.Image&&1!=o.width&&1!=o.height)this.spriteSheet=o,n();else{let a;a="string"==typeof o?o:o.url,t._incrementPreload(),this.spriteSheet=t.loadImage(a,(()=>{n(),t._decrementPreload()})),"string"==typeof o&&(e.spriteSheet=this.spriteSheet)}function n(){Array.isArray(r)&&(r=4==r.length?{pos:r.slice(0,2),size:r.slice(2)}:{pos:r});let{w:i,h:s,width:o,height:n,size:a,row:l,col:d,line:p,x:u,y:c,pos:_,frames:g,frameCount:f,frameDelay:m,frameSize:y,delay:w,rotation:v}=r;y??=a||e.anis.frameSize,w&&(h.frameDelay=w),m&&(h.frameDelay=m),v&&(h.rotation=v),g&&Array.isArray(g)?f=g.length:f??=g||1,i??=o||e.anis.w,s??=n||e.anis.h,u??=d||0,c??=p||l||0,_&&(u=_[0],c=_[1]),"number"==typeof y?i=s=y:y&&(i=y[0],s=y[1]),e instanceof t.Group&&(e.w??=e.width,e.h??=e.height);let x=e.tileSize;if(i&&s?(i*=x,s*=x):!e._dimensionsUndef&&e.w&&e.h?(i??=e.w*x,s??=e.h*x):1!=x?(i??=x,s??=x):f?(i??=h.spriteSheet.width/f,s??=h.spriteSheet.height):i=s=h.spriteSheet.width=h.spriteSheet.width&&(u=0,c+=s,c>=h.spriteSheet.height&&(c=0))}}}else{let d,p,u=i[0];isNaN(i[1])?d=i[1]:p=Number(i[1]);let c=0,_=0;for(let m=u.length-5;m>=0&&!isNaN(u.charAt(m));m--)c++;if(d)for(let y=d.length-5;y>=0&&!isNaN(d.charAt(y));y--)_++;let g,f=u.slice(0,-4-c);if(d&&(g=d.slice(0,-4-_)),d&&f!=g)this.push(t.loadImage(u)),this.push(t.loadImage(d));else{let w,v=parseInt(u.slice(-4-c,-4),10);if(p??=parseInt(d.slice(-4-_,-4),10),p=this.length)throw new b("SpriteAnimation.frame",[t,this.length]);this._frame=t,this._cycles=0}get frameDelay(){return this._frameDelay}set frameDelay(t){t<=0&&(t=1),this._frameDelay=t}get scale(){return this._scale}set scale(t){"number"==typeof t&&(t={x:t,y:t}),this._scale._x=t.x,this._scale._y=t.y,this._scale._avg=t.x}clone(){this.length||console.error(`The animation named "${this.name}" must be loaded before it can be properly copied. Sprites need their own copy of a group's animation. Try loading the animation in the preload function and creating new group sprites in the setup function.`);let e=new t.SpriteAnimation;e.spriteSheet=this.spriteSheet;for(let t=0;tthis._frame&&-1!==this.targetFrame?this._frame++:this.targetFrame=this.lastFrame?this._frame=0:this._frame++:this._frame{this._onComplete=()=>{this._onComplete=null,t()}}))}pause(t){this.playing=!1,t&&(this._frame=t)}stop(t){this.playing=!1,t&&(this._frame=t)}rewind(){return this.looping=!1,this.goToFrame(0)}loop(){this.looping=!0,this.playing=!0}noLoop(){this.looping=!1}nextFrame(){this._frame0?this._frame=this._frame-1:this.looping&&(this._frame=this.length-1),this.targetFrame=-1,this.playing=!1,this._cycles=0}goToFrame(t){if(!(t<0||t>=this.length))return this.targetFrame=t,this._cycles=0,this.targetFrame!==this._frame&&(this.playing=!0),new Promise((t=>{this._onComplete=()=>{this._onComplete=null,t()}}))}get lastFrame(){return this.length-1}get frameImage(){let e=this[this._frame];if(e instanceof p5.Image)return e;let{x:i,y:s,w:r,h:o}=e,h=t.createImage(r,o);return h.copy(this.spriteSheet,this.offset.x,this.offset.y,r,o,i,s,r,o),h}get w(){return this.width}get width(){let t=this[this._frame];return t instanceof p5.Image?t.width:t?t.w:1}get h(){return this.height}get height(){let t=this[this._frame];return t instanceof p5.Image?t.height:t?t.h:1}},t.SpriteAnimation.props=["demoMode","endOnFirstFrame","frameDelay","frameSize","looping","offset","rotation","scale"],this.SpriteAnimations=class{#t={};constructor(){let e=this,i=[...t.SpriteAnimation.props],s=["offset","scale"];for(let t of i)Object.defineProperty(this,t,{get:()=>e.#t[t],set(i){e.#t[t]=i;for(let s in e){let r=e[s];r instanceof SpriteAnimation&&(r[t]=i)}}});for(let t of s){this.#t[t]={_x:0,_y:0};for(let i of["x","y"])Object.defineProperty(this.#t[t],i,{get:()=>e.#t[t]["_"+i],set(s){e.#t[t]["_"+i]=s;for(let r in e){let o=e[r];o instanceof SpriteAnimation&&(o[t][i]=s)}}})}}},this.Group=class extends Array{constructor(...e){let i;if(e[0]instanceof t.Group&&(i=e[0],e=e.slice(1)),super(...e),"number"==typeof e[0])return;for(let e of this)if(!(e instanceof t.Sprite))throw new Error("A group can only contain sprites");if(this._isGroup=!0,this.x,this.y,this.vel,this.rotation,this.rotationSpeed,this.autoDraw,this.allowSleeping,this.autoUpdate,this.bounciness,this.collider,this.color,this.debug,this.density,this.direction,this.drag,this.friction,this.h,this.isSuperFast,this.layer,this.life,this.mass,this.mirror,this.offset,this.pixelPerfect,this.removed,this.rotationDrag,this.rotationLock,this.scale,this.shape,this.sleeping,this.stroke,this.strokeWeight,this.text,this.textColor,this.tile,this.tileSize,this.visible,this.w,this.bearing,this.d,this.diameter,this.dynamic,this.height,this.heading,this.kinematic,this.resetAnimationsOnChange,this.speed,this.static,this.width,this.idNum,t.p5play.groupsCreated<999)this.idNum=t.p5play.groupsCreated;else{for(let e=1;et&&(t=e._layer);return t}get ani(){return this._ani}set ani(t){this.addAni(t);for(let e of this)e.changeAni(t)}get animation(){return this._ani}set animation(t){this.ani=t}get anis(){return this.animations}get img(){return this._img}set img(t){this.image=t}get image(){return this._img}set image(e){"function"!=typeof e?("string"==typeof e&&(e=e.includes(".")?t.loadImage(e):new t.EmojiImage(e,this.w||this.width||this.d||this.diameter)),this._img=t.Sprite.prototype._extendImage(e)):this._img=e}get amount(){return this.length}set amount(t){let e=t-this.length,i=e>0;e=Math.abs(e);for(let t=0;t0?i:0}collided(t,e){return this._validateCollideParams(t,e),this._ensureCollide(t),e&&this._setContactCB(t,e,0,2),this._collisions[t._uid]<=-1}_validateOverlapParams(t,e){if(e&&"function"!=typeof e)throw new b("Group.overlap",1,[e]);if(!t)throw new b("Group.overlap",2);if(!t._isGroup&&!t._isSprite)throw new b("Group.overlap",0,[t])}_ensureOverlap(t){if(!this._hasSensors){for(let t of this)t._hasSensors||t.addDefaultSensors();this._hasSensors=!0}if(!t._hasSensors)if(t._isSprite)t.addDefaultSensors();else{for(let e of t)e._hasSensors||e.addDefaultSensors();t._hasSensors=!0}if(1!=this._hasOverlap[t._uid]){this._removeContactsWith(t),this._hasOverlap[t._uid]=!0;for(let e of this)if(e._hasOverlap[t._uid]=!0,t._hasOverlap[e._uid]=!0,this._uid==t._uid)for(let i of t)e._hasOverlap[i._uid]=!0,i._hasOverlap[e._uid]=!0}if(1!=t._hasOverlap[this._uid]&&(t._removeContactsWith(this),t._hasOverlap[this._uid]=!0,t._isGroup))for(let e of t){e._hasOverlap[this._uid]=!0,this._hasOverlap[e._uid]=!0;for(let t of this)e._hasOverlap[t._uid]=!0,t._hasOverlap[e._uid]=!0}}overlap(t,e){return this.overlaps(t,e)}overlaps(t,e){return this._validateOverlapParams(t,e),this._ensureOverlap(t),e&&this._setContactCB(t,e,1,0),1==this._overlappers[t._uid]||this._overlappers[t._uid]<=-3}overlapping(t,e){this._validateOverlapParams(t,e),this._ensureOverlap(t),e&&this._setContactCB(t,e,1,1);let i=this._overlappers[t._uid];return i<=-3?1:i>0?i:0}overlapped(t,e){return this._validateOverlapParams(t,e),this._ensureOverlap(t),e&&this._setContactCB(t,e,1,2),this._overlappers[t._uid]<=-1}_removeContactsWith(t){for(let e of this)e._removeContactsWith(t)}applyForce(){for(let t of this)t.applyForce(...arguments)}applyForceScaled(){for(let t of this)t.applyForceScaled(...arguments)}attractTo(){for(let t of this)t.attractTo(...arguments)}applyTorque(){for(let t of this)t.applyTorque(...arguments)}move(t,e,i){let s=[];for(let r of this)s.push(r.move(t,e,i));return Promise.all(s)}moveTo(e,i,s){if("number"!=typeof e){let r=e;if(r==t.mouse&&!t.mouse.isActive)return;s=i,i=r.y,e=r.x}let r=this._resetCentroid(),o=[];for(let t of this){let h={x:t.x-r.x+e,y:t.y-r.y+i};o.push(t.moveTo(h.x,h.y,s))}return Promise.all(o)}moveTowards(e,i,s){if("number"!=typeof e){let r=e;if(r==t.mouse&&!t.mouse.isActive)return;s=i,i=r.y,e=r.x}if(void 0!==e||void 0!==i){this._resetCentroid();for(let t of this){void 0===t.distCentroid&&this._resetDistancesFromCentroid();let r={x:t.distCentroid.x+e,y:t.distCentroid.y+i};t.moveTowards(r.x,r.y,s)}}}moveAway(e,i,s){if("number"!=typeof e){let r=e;if(r==t.mouse&&!t.mouse.isActive)return;s=i,i=r.y,e=r.x}if(void 0!==e||void 0!==i){this._resetCentroid();for(let t of this){void 0===t.distCentroid&&this._resetDistancesFromCentroid();let r={x:t.distCentroid.x+e,y:t.distCentroid.y+i};t.moveAway(r.x,r.y,s)}}}push(...e){this.removed&&(console.warn("Adding a sprite to a group that was removed. Use `group.removeAll()` to remove all of a group's sprites without removing the group itself. Restoring the group in p5play's memory."),t.p5play.groups[this._uid]=this,this.removed=!1);for(let i of e){if(!(i instanceof t.Sprite))throw new Error("You can only add sprites to a group, not "+typeof i);if(i.removed){console.error("Can't add a removed sprite to a group");continue}let e;for(let s in this._hasOverlap){let r=this._hasOverlap[s];r&&!i._hasSensors&&i.addDefaultSensors(),e=s>=1e3?t.p5play.sprites[s]:t.p5play.groups[s],e&&!e.removed&&(r?e._ensureOverlap(i):e._ensureCollide(i))}for(let e in n){let s=n[e];for(let e of s){let s=t.p5play[e],r=s[this._uid];if(!r)continue;let o=s[i._uid]??={};for(let t in r)o[t]=r[t]}}super.push(i),this.parent&&t.p5play.groups[this.parent].push(i),i.groups.push(this)}return this.length}size(){return this.length}toString(){return"g"+this.idNum}cull(e,i,s,r,o){if(void 0===s){o=i,e=i=s=r=e}if(isNaN(e)||isNaN(i)||isNaN(s)||isNaN(r))throw new TypeError("The culling boundary must be defined with numbers");if(o&&"function"!=typeof o)throw new TypeError("The callback to group.cull must be a function");let h=t.camera.x-t.canvas.hw/t.camera.zoom,n=t.camera.y-t.canvas.hh/t.camera.zoom,a=-s+h,l=-e+n,d=t.width+r+h,p=t.height+i+n,u=0;for(let t=0;td||e.y>p)&&(u++,o?o(e,u):e.remove(),e.removed&&t--))}return u}remove(t){if(void 0===t)return this.removeAll(),void(this._isAllSpritesGroup||(this.removed=!0));let e;if(e="number"==typeof t?t>=0?t:this.length+t:this.indexOf(t),-1==e)return;let i=this[e];return this.splice(e,1),i}splice(e,i){let s=super.splice(e,i);if(!s)return;let r=[];for(let t of s){if(t.removed)continue;let e=this._uid;do{r.push(e);let i=t.groups.findIndex((t=>t._uid==e)),s=t.groups.splice(i,1);e=s[0].parent}while(e)}for(let e of r){let i=t.p5play.groups[e];for(let e in n)for(let s in i[e]){if(0==i[e][s])continue;let r;r=s>=1e3?t.p5play.sprites[s]:t.p5play.groups[s];let o=!1;for(let t of i)if(t[e][r._uid]>0){o=!0;break}o||(i[e][r._uid]=-2,r[e][i._uid]=-2)}}return s}pop(){return this.remove(this.length-1)}shift(){return this.remove(0)}unshift(){return console.error("unshift is not supported for groups"),this.length}removeAll(){for(;this.length>0;)this.at(-1).remove()}_step(){this.__step()}draw(){let e=[...this];e.sort(((t,e)=>t._layer-e._layer));for(let i=0;i2)return console.error("world.timeScale must be between 0 and 2");this._timeScale!=t&&(this._timeScale=t,this._updateTimeStep())}_updateTimeStep(){this._timeStep=1/(t._targetFrameRate||60)*this._timeScale}get velocityThreshold(){return e.Settings.velocityThreshold}set velocityThreshold(t){e.Settings.velocityThreshold=t}step(e,i,s){for(let e of t.allSprites)e.prevPos.x=e.x,e.prevPos.y=e.y,e.prevRotation=e.rotation;super.step(e||this._timeStep,i||this.velocityIterations,s||this.positionIterations),this.physicsTime+=e||this._timeStep;let r=Object.values(t.p5play.sprites),o=Object.values(t.p5play.groups);for(let t of r)t._step();for(let t of o)t._step();for(let t of r)t.___step();for(let t of o)t.___step();t.canvas.dispatchEvent&&t.canvas.dispatchEvent(this.steppedEvent),this.autoStep&&(this.autoStep=null)}get realTime(){return t.millis()/1e3}getSpritesAt(i,s,r,o){o??=!0;const h=new e.Vec2(i/t.world.meterSize,s/t.world.meterSize),n=new e.AABB;n.lowerBound=new e.Vec2(h.x-.001,h.y-.001),n.upperBound=new e.Vec2(h.x+.001,h.y+.001);let a=[];if(this.queryAABB(n,(t=>(t.getShape().testPoint(t.getBody().getTransform(),h)&&a.push(t),!0))),0==a.length)return[];r??=t.allSprites;let l=[];for(let t of a){const e=t.m_body.sprite;e._cameraActiveWhenDrawn==o&&(l.find((t=>t._uid==e._uid))||l.push(e))}return l.sort(((t,e)=>-1*(t._layer-e._layer))),l}getSpriteAt(t,e,i){return this.getSpritesAt(t,e,i)[0]}getMouseSprites(){let e=this.getSpritesAt(t.mouse.x,t.mouse.y);if(t.camera._wasOff){let i=this.getSpritesAt(t.mouse.canvasPos.x,t.mouse.canvasPos.y,t.allSprites,!1);i.length&&(e=[...i,...e])}return e}_beginContact(t){let e=t.m_fixtureA,i=t.m_fixtureB,s="_collisions";e.m_isSensor&&(s="_overlappers"),e=e.m_body.sprite,i=i.m_body.sprite,e[s][i._uid]=0,i[s][e._uid]=0;for(let t of i.groups)(!e[s][t._uid]||e[s][t._uid]<0)&&(e[s][t._uid]=0,t[s][e._uid]=0);for(let t of e.groups){(!i[s][t._uid]||i[s][t._uid]<0)&&(i[s][t._uid]=0,t[s][i._uid]=0);for(let e of i.groups)(!t[s][e._uid]||t[s][e._uid]<0)&&(t[s][e._uid]=0,e[s][t._uid]=0)}}_endContact(t){let e=t.m_fixtureA,i=t.m_fixtureB,s="_collisions";e.m_isSensor&&(s="_overlappers"),e=e.m_body.sprite,i=i.m_body.sprite,e[s][i._uid]=0!=e[s][i._uid]?-2:-4,i[s][e._uid]=0!=i[s][e._uid]?-2:-4;for(let t of i.groups){let i=!1;for(let r of t)if(r[s][e._uid]>=0){i=!0;break}i||(t[s][e._uid]=0!=t[s][e._uid]?-2:-4,e[s][t._uid]=0!=e[s][t._uid]?-2:-4)}for(let t of e.groups){let e=!1;for(let r of t)if(r[s][i._uid]>=0){e=!0;break}if(!e){t[s][i._uid]=0!=t[s][i._uid]?-2:-4,i[s][t._uid]=0!=i[s][t._uid]?-2:-4;for(let e of i.groups)t[s][e._uid]=0!=t[s][e._uid]?-2:-4,e[s][t._uid]=0!=e[s][t._uid]?-2:-4}}}_findContact(t,e,i){let s=e[t][i._uid];if(s)return s;for(let r of i.groups)if(s=e[t][r._uid],s)return s;for(let r of e.groups){if(s=r[t][i._uid],s)return s;for(let e of i.groups)if(r._uid==e._uid&&(s=r[t][e._uid],s))return s}return!1}get allowSleeping(){return this.getAllowSleeping()}set allowSleeping(t){this.setAllowSleeping(t)}rayCast(t,e,i){return this.rayCastAll(t,e,i,(()=>!0))[0]}rayCastAll(e,s,r,o){let h,n=t.allSprites.tileSize,a=i(e.x,e.y,n);if("number"==typeof arguments[1])h=i(e.x+r*t.cos(s),e.y+r*t.sin(s),n);else{let t=arguments[1];o??=arguments[2],h=i(t.x,t.y,n)}let l=[],d=1;super.rayCast(a,h,(function(t,e,i,s){let r=t.getBody().sprite,h=o&&o(r);return l.push({sprite:r,fraction:s}),h?(st.fraction-e.fraction));let p=[];for(let t of l)t.fraction<=d&&p.push(t.sprite);return p}},this.Camera=class{constructor(){this._pos=t.createVector.call(t),this.__pos={x:0,y:0,rounded:{}},this.isActive=!1,this.bound={min:{x:0,y:0},max:{x:0,y:0}},this._zoomIdx=-1,this._zoom=1,this._destIdx=0}get pos(){return this._pos}set pos(t){this.x=t.x,this.y=t.y}get position(){return this._pos}set position(t){this.x=t.x,this.y=t.y}_calcBoundsX(e){let i=t.canvas.hw/this._zoom;this.bound.min.x=e-i,this.bound.max.x=e+i}_calcBoundsY(e){let i=t.canvas.hh/this._zoom;this.bound.min.y=e-i,this.bound.max.y=e+i}get x(){return this._pos.x}set x(e){if(void 0===e||isNaN(e))return;this._pos.x=e;let i=-e;"2d"==t.canvas.renderer&&(i+=t.canvas.hw/this._zoom),this.__pos.x=i,t.allSprites.pixelPerfect&&(this.__pos.rounded.x=Math.round(i)),this._calcBoundsX(e)}get y(){return this._pos.y}set y(e){if(void 0===e||isNaN(e))return;this._pos.y=e;let i=-e;"2d"==t.canvas.renderer&&(i+=t.canvas.hh/this._zoom),this.__pos.y=i,t.allSprites.pixelPerfect&&(this.__pos.rounded.y=Math.round(i)),this._calcBoundsY(e)}moveTo(e,i,s){if(void 0===e)return;if(isNaN(e)&&(s=i,i=e.y,e=e.x),s??=1,s<=0)return console.warn("camera.moveTo: speed should be a positive number"),Promise.resolve(!1);let r=i-this.y,o=e-this.x,h=Math.sqrt(r*r+o*o),n=s/h,a=o*n,l=r*n;this._destIdx++;let d=this._destIdx,p=Math.ceil(h/s);return(async()=>{for(let e=0;e{for(let e=0;e0&&(e=e<.1?t.map(e,0,.1,30,4):e<.5?t.map(e,.1,.5,4,2.5):e<.8?t.map(e,.5,.8,2.5,1):e<.9?t.map(e,.8,.9,1,.5):t.map(e,.9,1,.5,.2)),this._springiness=e,"wheel"==this.type?this._j.setSpringFrequencyHz(e):this._j.setFrequency(e)}get damping(){return"wheel"!=this.type?this._j.getDampingRatio():this._j.getSpringDampingRatio()}set damping(t){"wheel"==this.type?this._j.setSpringDampingRatio(t):this._j.setDampingRatio(t)}get speed(){return this._j.getJointSpeed()}set speed(t){this._j.isMotorEnabled()||this._j.enableMotor(!0),this._j.setMotorSpeed(t)}get motorSpeed(){return this._j.getMotorSpeed()}get enableMotor(){return this._j.isMotorEnabled()}set enableMotor(t){this._j.enableMotor(t)}get maxPower(){return this._j.getMaxMotorTorque()}set maxPower(t){!this._j.isMotorEnabled()&&t&&this._j.enableMotor(!0),this._j.setMaxMotorTorque(t),t||this._j.enableMotor(!1)}get power(){return this._j.getMotorTorque()}get collideConnected(){return this._j.getCollideConnected()}set collideConnected(t){this._j.m_collideConnected=t}get reactionForce(){return this._j.getReactionForce(t.world._timeStep)}get reactionTorque(){return this._j.getReactionTorque(t.world._timeStep)}remove(){this._removed||(this.spriteA.joints.splice(this.spriteA.joints.indexOf(this),1),this.spriteB.joints.splice(this.spriteB.joints.indexOf(this),1),t.world.destroyJoint(this._j),this._removed=!0)}},this.GlueJoint=class extends t.Joint{constructor(t,e){super(...arguments,"glue")}},this.DistanceJoint=class extends t.Joint{constructor(t,i){super(...arguments,"distance");let s=e.DistanceJoint({},t.body,i.body,t.body.getWorldCenter(),i.body.getWorldCenter());this._createJoint(s)}_display(){let t,e;(this.offsetA.x||this.offsetA.y)&&(t=this.spriteA.body.getWorldPoint(this._j.m_localAnchorA),t=s(t.x,t.y,this.spriteA.tileSize)),(this.offsetB.x||this.offsetB.y)&&(e=this.spriteB.body.getWorldPoint(this._j.m_localAnchorB),e=s(e.x,e.y,this.spriteB.tileSize)),this._draw(t?t.x:this.spriteA.x,t?t.y:this.spriteA.y,e?e.x:this.spriteB.x,e?e.y:this.spriteB.y),this.visible=null}},this.WheelJoint=class extends t.Joint{constructor(i,s){super(...arguments,"wheel");let r=e.WheelJoint({maxMotorTorque:1e3,frequencyHz:4,dampingRatio:.7},i.body,s.body,s.body.getWorldCenter(),new e.Vec2(0,1));this._createJoint(r),this._angle="degrees"==t._angleMode?90:1.5707963267948966}_display(){let e,i,r=this.spriteA.x,o=this.spriteA.y;if(this.offsetB.x||this.offsetB.y){let t=this.spriteB.body.getWorldPoint(this._j.m_localAnchorB);t=s(t.x,t.y,this.spriteB.tileSize),e=t.x,i=t.y}else e=this.spriteB.x,i=this.spriteB.y;let h=t.tan(this.spriteA.rotation),n=t.tan(this._angle+this.spriteA.rotation),a=(i-o+h*r-n*e)/(h-n),l=h*(a-r)+o;this._draw(a,l,e,i),this.visible=null}get angle(){return this._angle}set angle(i){i!=this._angle&&(this._angle=i,this._j.m_localXAxisA=new e.Vec2(t.cos(i),t.sin(i)),this._j.m_localXAxisA.normalize(),this._j.m_localYAxisA=e.Vec2.crossNumVec2(1,this._j.m_localXAxisA))}},this.HingeJoint=class extends t.Joint{constructor(t,i){super(...arguments,"hinge");let s=e.RevoluteJoint({},t.body,i.body,t.body.getWorldCenter());this._createJoint(s)}_display(){const e=this.offsetA.x,i=this.offsetA.y,s=this.spriteA.rotation,r=e*t.cos(s)-i*t.sin(s),o=e*t.sin(s)+i*t.cos(s);this._draw(this.spriteA.x+r,this.spriteA.y+o),this.visible=null}get range(){return this.upperLimit-this.lowerLimit}set range(t){t/=2,this.upperLimit=t,this.lowerLimit=-t}get lowerLimit(){let e=this._j.getLowerLimit();return"radians"==t._angleMode?e:t.degrees(e)}set lowerLimit(e){this._j.isLimitEnabled()||this._j.enableLimit(!0),this.spriteA.body.setAwake(!0),this.spriteB.body.setAwake(!0),"degrees"==t._angleMode&&(e=t.radians(e)),this._j.m_lowerAngle=e}get upperLimit(){let e=this._j.getUpperLimit();return"radians"==t._angleMode?e:t.degrees(e)}set upperLimit(e){this._j.isLimitEnabled()||this._j.enableLimit(!0),this.spriteA.body.setAwake(!0),this.spriteB.body.setAwake(!0),"degrees"==t._angleMode&&(e=t.radians(e)),this._j.m_upperAngle=e}get angle(){let e=this._j.getJointAngle();return"radians"==t._angleMode?e:t.radians(e)}},t.RevoluteJoint=t.HingeJoint,this.SliderJoint=class extends t.Joint{constructor(t,i){super(...arguments,"slider");let s=e.PrismaticJoint({lowerTranslation:-1,upperTranslation:1,enableLimit:!0,maxMotorForce:50,motorSpeed:0,enableMotor:!0},t.body,i.body,t.body.getWorldCenter(),new e.Vec2(1,0));this._createJoint(s),this._angle=0}get angle(){return this._angle}set angle(i){i!=this._angle&&(this._angle=i,this._j.m_localXAxisA=new e.Vec2(t.cos(i),t.sin(i)),this._j.m_localXAxisA.normalize(),this._j.m_localYAxisA=e.Vec2.crossNumVec2(1,this._j.m_localXAxisA))}get range(){return this.upperLimit-this.lowerLimit}set range(t){t/=2,this.upperLimit=t,this.lowerLimit=-t}get lowerLimit(){return this._j.getLowerLimit()/this.spriteA.tileSize*t.world.meterSize}set lowerLimit(e){this._j.isLimitEnabled()||this._j.enableLimit(!0),e=e*this.spriteA.tileSize/t.world.meterSize,this._j.setLimits(e,this._j.getUpperLimit())}get upperLimit(){return this._j.getUpperLimit()/this.spriteA.tileSize*t.world.meterSize}set upperLimit(e){this._j.isLimitEnabled()||this._j.enableLimit(!0),e=e*this.spriteA.tileSize/t.world.meterSize,this._j.setLimits(this._j.getLowerLimit(),e)}},t.PrismaticJoint=t.SliderJoint,this.RopeJoint=class extends t.Joint{constructor(t,i){super(...arguments,"rope");let s=e.RopeJoint({maxLength:1},t.body,i.body,t.body.getWorldCenter());this._createJoint(s),this._j.m_localAnchorB.x=0,this._j.m_localAnchorB.y=0}get maxLength(){return e=this._j.getMaxLength(),i=this.spriteA.tileSize,e/i*t.world.meterSize;var e,i}set maxLength(e){var i,s;this._j.setMaxLength((i=e,s=this.spriteA.tileSize,i*s/t.world.meterSize))}};class l{constructor(){let t=this;Object.defineProperties(this,{x:{get:()=>t._x,set(e){e!=t._x&&(t._x=e,t._avg=.5*(t._x+t._y))},configurable:!0,enumerable:!0},y:{get:()=>t._y,set(e){e!=t._y&&(t._y=e,t._avg=.5*(t._x+t._y))},configurable:!0,enumerable:!0},_x:{value:1,enumerable:!1,writable:!0},_y:{value:1,enumerable:!1,writable:!0},_avg:{value:1,enumerable:!1,writable:!0}})}valueOf(){return this._avg}}!function(){let t=new Float32Array(1),e=new Int32Array(t.buffer)}();function d(t){return!/^(?:(?:\/\*[^(?:\*\/)]*\*\/\s*)|(?:\/\/[^\r\n]*))*\s*(?:(?:(?:async\s(?:(?:\/\*[^(?:\*\/)]*\*\/\s*)|(?:\/\/[^\r\n]*))*\s*)?function|class)(?:\s|(?:(?:\/\*[^(?:\*\/)]*\*\/\s*)|(?:\/\/[^\r\n]*))*)|(?:[_$\w][\w0-9_$]*\s*(?:\/\*[^(?:\*\/)]*\*\/\s*)*\s*\()|(?:\[\s*(?:\/\*[^(?:\*\/)]*\*\/\s*)*\s*(?:(?:['][^']+['])|(?:["][^"]+["]))\s*(?:\/\*[^(?:\*\/)]*\*\/\s*)*\s*\]\())/.test(t.toString())}function p(t,e){let i=t,s=e.toLowerCase();if("triangle"==s?i=[i,-120,3]:"square"==s?i=[i,-90,4]:"pentagon"==s?i=[i,-72,5]:"hexagon"==s?i=[i,-60,6]:"septagon"==s?i=[i,-51.4285714286,7]:"octagon"==s?i=[i,-45,8]:"enneagon"==s?i=[i,-40,9]:"decagon"==s?i=[i,-36,10]:"hendecagon"==s?i=[i,-32.7272727273,11]:"dodecagon"==s&&(i=[i,-30,12]),i==t)throw new Error("Invalid, not a regular polygon: "+e);return i}if(t.p5play.palettes=[{a:"aqua",b:"black",c:"crimson",d:"darkviolet",e:"peachpuff",f:"olive",g:"green",h:"hotpink",i:"indigo",j:"navy",k:"khaki",l:"lime",m:"magenta",n:"brown",o:"orange",p:"pink",q:"turquoise",r:"red",s:"skyblue",t:"tan",u:"blue",v:"violet",w:"white",x:"gold",y:"yellow",z:"gray"}],this.colorPal=(e,i)=>{if(e instanceof p5.Color)return e;"number"==typeof i&&(i=t.p5play.palettes[i]),i??=t.p5play.palettes[0];let s=i[e];return s?t.color(s):t.color(0,0,0,0)},this.EmojiImage=function(e,i){t.push(),t.textSize(i);let s=t.createGraphics(i,1.25*i);s.textSize(i),s.textAlign(t.CENTER),s.text(e,i/2,i);let r=s.drawingContext,o=s._pixelDensity||1,h=s.canvas.width,n=s.canvas.height,a=r.getImageData(0,0,h,n).data,l=h,d=0,p=n,u=0,c=3;for(let t=0;td&&(d=e),tu&&(u=t)),c+=4;return p=Math.floor(p/o),u=Math.floor(u/o),l=Math.floor(l/o),d=Math.floor(d/o),s=s.get(l,p,d-l+1,u-p+1),t.pop(),s.url=e,s},this.spriteArt=(e,i,s)=>{i??=1,"number"==typeof s&&(s=t.p5play.palettes[s]),s??=t.p5play.palettes[0];let r=e;"string"==typeof e&&(r=(e=(e=(e=e.trim()).replace(/\r*\n\t+/g,"\n")).replace(/\s+$/g,"")).split("\n"));let o=0;for(let t of r)t.length>o&&(o=t.length);let h=r.length,n=t.createImage(o*i,h*i);n.loadPixels();for(let t=0;tnew Promise(t?e=>{setTimeout(e,t)}:requestAnimationFrame),this.sleep=e=>e?t.delay(e):new Promise((e=>{if(t.canvas.dispatchEvent){t.canvas.addEventListener("p5play_worldStepped",(function i(){t.canvas.removeEventListener("p5play_worldStepped",i),e()}))}else setTimeout(e,1e3*t.world._timeStep)})),this.play=t=>{if(!t?.play)throw new Error("Tried to play your sound but it wasn't a sound object.");return new Promise((e=>{t.play(),t.onended((()=>e()))}))},window.location){let e=location.hostname;switch(e){case"":case"127.0.0.1":case"localhost":case"p5play.org":case"editor.p5js.org":case"codepen.io":case"codera.app":case"aug4th.com":case"cdpn.io":case"glitch.com":case"replit.com":case"stackblitz.com":case"jsfiddle.net":case"aijs.io":case"preview-aijs.web.app":case"quinton-ashley.github.io":break;default:if(/^[\d\.]+$/.test(e)||e.endsWith("stackblitz.io")||e.endsWith("glitch.me")||e.endsWith("replit.dev")||e.endsWith("codehs.com")||e.endsWith("openprocessing.org")||location.origin.endsWith("preview.p5js.org"))break;!async function(){if(document.getElementById("p5play-intro"))return;t._incrementPreload();let e=document.createElement("div");e.id="p5play-intro",e.style="position: absolute; width: 100%; height: 100%; top: 0; left: 0; z-index: 1000; background-color: black;";let i=document.createElement("img");i.style="position: absolute; top: 50%; left: 50%; width: 80vmin; height: 40vmin; margin-left: -40vmin; margin-top: -20vmin; z-index: 1001; opacity: 1; scale: 1; transition: scale 1.5s, opacity 0.4s ease-in-out;",i.onerror=()=>{i.style.imageRendering="pixelated",i.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAABACAYAAADS1n9/AAABbGlDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAACiRfZC/S0JhGIWfm4VgNkQNDg13igYr0SCXBjWQIkisQG26Xn+C2sfVCKMtWkPoP8igOWgoIgxaGhqCqCGitqamgpaSL+69hS51lvfhcDgcXujxaEKUeoFypWbEo2E1kUypzhcUFCxpelWEYrEFk39vlxT4uLezt+Nm12u7uRvciV6Wj88XNx88k/wvVyZb1YEvwKcLowaKF4ht1ITJW8CwkUimQGmYnLf5wOS0zSdWZjkeAeUaUPWClgHlFfCmu/x8F5dL6/rPMnO9O1tZWTJ7gBFmKVJFUEKjjkqMwB/5KSsfYQ1BHYMieQrUUAkhrIYsKnNU0JnAi4ofH3785p/tuo+7n/95O972M8y0pJRnHW++BUfT4DrteGNBGOyHq1OhGZplOYCeXA7eDmEgCUM34Fqt5gJ+e707DH1PUr6PgnMP2g0pP/elbDfB8QgXlW8Y/mq9pjC8gwAABSxJREFUeJztnb9y2zAMxulcpnbNntfJ3D5n97xO966Z3aNP9NHgBxAgQVmO8bvLNZZIiCI+gH8kpyl4bk7P3gErOJ/PZ0+zp9NpmZ9CAM54O7+wSgQhAEdWOb+wQgSvzZHAj5+/50x9/WkOeRMZwIkm+medXyAi8M4CL82R4KkIATjQRL8nJJN4XysEsAKv9L8DIYAnJyaBk8CUTDLA51/bbP7jHWSQRZPByADeTDp/tM4ozT4AVHSwO1kEMBMY/dTLFNcMcN5oSgTHYHBi2fPrS4qo98Mh/a+C8/ErdyJYw8cbb/bzH/ncGQY8aOYAnpThZ4XGerZdrn209fxIe6rVQw52Oif4NquAfF+d+Y6NSeej9C9F/714WAHkyP5uoxcSCBKSic5WMhwCciTlcnUaRSmVRlw5x0UiVx6VqW1Ru1zbaHl6TXS9Efae3GmuNzpXYDMA7VT6OxKE9nhPKNy1ZlHbEdL/qPNRdHsy2i5WAIk41yt6emM1Jw5OcL12eg4VR1rWmRCGAVEAGjhncseLQ7SOebZV6t4TxWEBcFHHOayO7PoHUcpy/y5FSP+jWJ06KoKRDAUngZxDUXrVlOsdR0jX8vjsxaqI1dilG0ciWdjgHcN4GqgERdcR1/VayjwgBFDzQG/yJEaASKgSIYBnAgg8BKAARRWKvkcjDwMhgAKIjkcACREJlgOuAu5K7Qgwaz0KeQaOOn9vTCsBwLwApMiZdOBROpnj3u2bdX5aPQfwaOBuDIr1HveYryldl30wBO4RZ4AS1aXCbFr2skezTa5b2+7Z7Z2nNjZKh3Jja3HGHtlAcnwyOj+/HIIFUACd0TizbhzTQU1ddAzYg+WYY5d0TM5dXql6A2VzO7n0jUS6kTtXuseVQ4Im01icXxgfApgOuvy8pevPjD3VuRrhRpu29trG2GI7eWPFkKCJerZdzH2UV8NUAsiqR8pnG5YdJjjNZA+8aYvqIq6dQqNfC9N5YofvDNuO3HbQ/tNG+dwVQOmwS8QAg/kY26lABF17Aqq65DgSlSkzMR2ZpM53hmsve32mvehLIvIcoFyIaUB9vhZB3bBmbJ6cLJkfrb4PRj+FmSAeCsbxiXF+0mSAG5WhDtjSfT32S3TtUb6wsMS6Qkd4TtKQoI62b0FTPkW3EQQ6G908KgcB5aA9BKir4WFf59q4ZNneF0eYZ/4SUxtB4lg88rVoLnqEa7CAOqz9J0Y9Caw/N44FnX0zYQPHRXsI4RqQ0Zk/B1iNUB5RYKohgN4svNG8GiApCpbr2QN2uHN08nmBGSK4ttyLkd1D1TBgxGUV4F1OOk/PSWUTENsRqJ3ovo1M5gHo+4A13/YPRd4sS2c7V/m1795WMJvZlNvIUv1RTtzXw2mqncXbnsSSqCJwIuCua3GetX4zBBj+ntDlBCeCYGNg2Vo7UXIeR6nv9fSPE0EIoAdwfs095xis85NeAC/SyWDSCQLXJ6cT9T2Ajo+MQOhkgWTMBMh55iecPSxDQHBLEwCG7WfJkd13CYS6mvpXrJPAoKURQdILATnSkrKbjTJLugc7piGAQWZEkDS7dMIj5utWulQf2SNIzk8hgD6zIoBQRy36n0U0k/sQgAIogjT/Z9saHO1pV3YhACUuImCcNWRPsGVZ1ocAjEAh9JwmOAsyaG9kPycEMAAUQWIcp3CWt71gB84SP34JJ7Gzm0I1A/a0hGomsTigF6VWZ3pEfQjAAY3jLM7yticRAnAEOW7GUd72ECEAZ2qneTjL294NKaX/gKttC9Kft4MAAAAASUVORK5CYII="};let s=window._p5play_intro_image;""==s||s?.includes("made_with_p5play")?((s.includes("bit.")||s.includes("pixel"))&&(i.style.imageRendering="pixelated"),i.src=s):i.src="https://p5play.org/assets/made_with_p5play.webp",await new Promise((t=>i.onload=t)),e.append(i),document.body.append(e),await t.delay(),i.offsetHeight,i.style.scale=1.2,await t.delay(1100),i.style.opacity=0,await t.delay(400),e.style.display="none",e.remove(),document.getElementById("p5play-intro")?.remove(),t._decrementPreload()}()}}let u=p5.disableFriendlyErrors;p5.disableFriendlyErrors=!0;const c=t.createCanvas;this.createCanvas=function(){let e,i,s,r=[...arguments];if("string"==typeof r[0])if(r[0].includes(":")){let t=r[0].split(":"),i=Number(t[0]),s=Number(t[1]),o=window.innerWidth,h=window.innerWidth*(s/i);h>window.innerHeight&&(o=window.innerHeight*(i/s),h=window.innerHeight),r[0]=Math.round(o),r.splice(1,0,Math.round(h)),e="fullscreen"}else r=[0,0,...r];if(r[0]||(r[0]=window.innerWidth,r[1]=window.innerHeight,e="fullscreen"),"string"==typeof r[2]){let t=r[2].toLowerCase().split(" ");"pixelated"==t[0]?(i="pixelated",t[1]?(e="centered",s=Number(t[1].slice(1))):e="fullscreen",r.splice(2,1)):"fullscreen"==t[0]&&(e="fullscreen",r.splice(2,1))}let o=c.call(t,...r);t.ctx=t.drawingContext;let h=o.canvas||o;return o.GL&&(h.renderer="webgl"),"webgpu"!=h.renderer&&(h.renderer="2d"),h.tabIndex=0,h.w=r[0],h.h=r[1],h.addEventListener&&(h.addEventListener("keydown",(function(t){" "!=t.key&&"/"!=t.key&&"ArrowUp"!=t.key&&"ArrowDown"!=t.key&&"ArrowLeft"!=t.key&&"ArrowRight"!=t.key||t.preventDefault()})),h.addEventListener("mouseover",(()=>{this.mouse.isOnCanvas=!0,this.mouse.isActive=!0})),h.addEventListener("mouseleave",(()=>{this.mouse.isOnCanvas=!1})),h.addEventListener("touchstart",(t=>t.preventDefault())),h.addEventListener("contextmenu",(t=>t.preventDefault()))),h.save??=t.saveCanvas.bind(t),h.resize??=t.resizeCanvas.bind(t),h.hw=.5*h.w,h.hh=.5*h.h,h.mouse={x:t.mouseX,y:t.mouseY},"2d"==h.renderer?(t.camera.x=t.camera.ogX=h.hw,t.camera.y=t.camera.ogY=h.hh):(t.camera.x=0,t.camera.y=0,"webgl"==h.renderer&&(t._textCache=!1),t.p5play._renderStats={x:10-h.hw,y:20-h.hh}),u||(p5.disableFriendlyErrors=!1),t.displayMode(e,i,s),o},this.Canvas=class{constructor(t,e,i,s){this.w,this.width,this.h,this.height,this.hw,this.hh,this.mouse}resize(){}save(){}},this.canvas=t.canvas,t.Canvas=function(){return t.createCanvas(...arguments).canvas};const _=t.resizeCanvas;this.resizeCanvas=(e,i)=>{e??=window.innerWidth,i??=window.innerHeight,_.call(t,e,i);let s=t.canvas;s.w=s.width/t.pixelDensity(),s.h=s.height/t.pixelDensity(),s.hw=.5*s.w,s.hh=.5*s.h,s.fullscreen&&(s.w/s.h>window.innerWidth/window.innerHeight?(s.style.width="100%!important",s.style.height="auto!important"):(s.style.width="auto!important",s.style.height="100%!important")),"2d"==s.renderer?(t.camera.x=s.hw,t.camera.y=s.hh):(t.camera.x=0,t.camera.y=0)};const g=t.frameRate;this.frameRate=function(e){let i=g.call(t,e);return e&&t.world._updateTimeStep(),i};const f=t.background;this.background=function(){let e=arguments;1==e.length&&1==e[0]?.length?f.call(t,t.colorPal(e[0])):f.call(t,...e)};const m=t.fill;this.fill=function(){let e=arguments;1==e.length&&1==e[0]?.length?m.call(t,t.colorPal(e[0])):m.call(t,...e)};const y=t.stroke;this.stroke=function(){let e=arguments;1==e.length&&1==e[0]?.length?y.call(t,t.colorPal(e[0])):y.call(t,...e)};const w=t.loadImage;this.loadImage=this.loadImg=function(){if(t.p5play.disableImages)return t._decrementPreload(),{w:16,width:16,h:16,height:16,pixels:[]};let e,i=arguments,s=i[0],r=t.p5play.images[s];if("function"==typeof i[i.length-1]&&(e=i[i.length-1]),r)return 1==r.width&&1==r.height||!r.pixels.length?e?(r.cbs.push(e),r.calls++):t._decrementPreload():(e&&e(),t._decrementPreload()),r;return r=w.call(t,s,(e=>{e.w||(Object.defineProperty(e,"w",{get:function(){return this.width}}),Object.defineProperty(e,"h",{get:function(){return this.height}}));for(let t of e.cbs)t(e);for(let i=1;i\nhtml, body {\n\tmargin: 0;\n\tpadding: 0;\n}\n.p5Canvas {\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.p5-pixelated {\n\timage-rendering: pixelated;\n\tfont-smooth: never;\n\t-webkit-font-smoothing: none;\n}\n.p5-centered,\n.p5-maxed,\n.p5-fullscreen {\n display: flex;\n\talign-items: center;\n\tjustify-content: center;\n}\nmain.p5-centered,\nmain.p5-maxed,\n.p5-fullscreen {\n\theight: 100vh;\n}\nmain {\n\toverscroll-behavior: none;\n}\n"),t._adjustDisplay=()=>{let e=t.canvas,i=e.style,s=e.parentElement;i&&s&&e.displayMode&&("pixelated"==e.renderQuality&&(e.classList.add("p5-pixelated"),t.pixelDensity(1),t.noSmooth&&t.noSmooth(),t.textFont&&t.textFont("monospace")),"normal"==e.displayMode?(s.classList.remove("p5-centered","p5-maxed","p5-fullscreen"),i.width=e.w*e.displayScale+"px",i.height=e.h*e.displayScale+"px"):(s.classList.add("p5-"+e.displayMode),s=s.getBoundingClientRect(),e.w/e.h>s.width/s.height?("centered"==e.displayMode?(i.width=e.w*e.displayScale+"px",i.maxWidth="100%"):i.width="100%",i.height="auto",i.maxHeight=""):(i.width="auto",i.maxWidth="","centered"==e.displayMode?(i.height=e.h*e.displayScale+"px",i.maxHeight="100%"):i.height="100%")))},t.displayMode=(e="normal",i="default",s=1)=>{let r=t.canvas;"string"==typeof s&&(s=parseFloat(s.slice(1))),Object.assign(r,{displayMode:e,renderQuality:i,displayScale:s}),t._adjustDisplay()});let x={generic:["Ah! I found an error","Oh no! Something went wrong","Oof! Something went wrong","Houston, we have a problem","Whoops, having trouble here"],Sprite:{constructor:{base:"Sorry I'm unable to make a new Sprite",0:"What is $0 for? If you're trying to specify the x position of the sprite, please specify the y position as well.",1:"If you're trying to specify points for a chain Sprite, please use an array of position arrays.\n$0",2:"Invalid input parameters: $0"},hw:{0:"I can't change the halfWidth of a Sprite directly, change the sprite's width instead."},hh:{1:"I can't change the halfHeight of a Sprite directly, change the sprite's height instead."},rotate:{0:"Can't use this function on a sprite with a static collider, try changing the sprite's collider type to kinematic.",1:'Can\'t use "$0" for the angle of rotation, it must be a number.'},rotateTo:{},rotateMinTo:{},rotateTowards:{},changeAnimation:'I can\'t find any animation named "$0".',collide:{0:"I can't make that sprite collide with $0. Sprites can only collide with another sprite or a group.",1:"The collision callback has to be a function.",2:"You're trying to check for an collision with a sprite or group that doesn't exist!"},overlap:{0:"I can't make that sprite overlap with $0. Sprites can only overlap with another sprite or a group.",1:"The overlap callback has to be a function.",2:"You're trying to check for an overlap with a sprite or group that doesn't exist!"}},SpriteAnimation:{constructor:{base:"Hey so, I tried to make a new SpriteAnimation but couldn't",1:"The name of the animation must be the first input parameter."},frame:"Index $0 out of bounds. That means there is no frame $0 in this animation. It only has $1 frames!"},Group:{constructor:{base:"Hmm awkward! Well it seems I can't make that new Group you wanted"}}};x.Group.collide=x.Sprite.collide,x.Group.overlap=x.Sprite.overlap,x.Sprite.rotateTo[0]=x.Sprite.rotateMinTo[0]=x.Sprite.rotateTowards[0]=x.Sprite.rotate[0];class b extends Error{constructor(t,e,i){super(),"string"!=typeof t&&(i=e,e=t,t=(t=this.stack.match(/\n\s*at ([^\(]*)/)[1]).slice(0,-1)),"number"!=typeof e&&(i=e,e=void 0),"new"==t.slice(0,3)&&(t=t.slice(4));let s=(t=t.split("."))[0];t=t[1]||"constructor";let r=this.stack.match(/\/([^p\/][^5][^\/:]*:[^\/:]+):/);r&&(r=r[1].split(":"),r=" in "+r[0]+" at line "+r[1]),r=" using "+s+"."+t+". ",i=i||[];let o,h=x[s][t];o=h.base?h.base+r:x.generic[Math.floor(Math.random()*x.generic.length)]+r,void 0!==e&&(h=h[e]),h&&(h=h.replace(/\$([0-9]+)/g,((t,e)=>i[e])),o+=h),p5._friendlyError(o,t)}}this.allSprites=new t.Group,this.world=new t.World,this.camera=new t.Camera,this.InputDevice=class{constructor(){this.holdThreshold=12,this._default=0}_ac(t){return t}presses(t){return t??=this._default,void 0===this[t]&&(t=this._ac(t)),1==this[t]||-3==this[t]}pressing(t){return t??=this._default,void 0===this[t]&&(t=this._ac(t)),-3==this[t]?1:this[t]>0?this[t]:0}pressed(t){return this.released(t)}holds(t){return t??=this._default,void 0===this[t]&&(t=this._ac(t)),this[t]==this.holdThreshold}holding(t){return t??=this._default,void 0===this[t]&&(t=this._ac(t)),this[t]>=this.holdThreshold?this[t]:0}held(t){return t??=this._default,void 0===this[t]&&(t=this._ac(t)),-2==this[t]}released(t){return t??=this._default,void 0===this[t]&&(t=this._ac(t)),this[t]<=-1}releases(t){return this.released(t)}},this._Mouse=class extends t.InputDevice{constructor(){super(),this._default="left";let e=this;this._pos=t.createVector.call(t),Object.defineProperty(this._pos,"x",{get:()=>e.x,set(t){e.x=t}}),Object.defineProperty(this._pos,"y",{get:()=>e.y,set(t){e.y=t}}),this.x=0,this.y=0,this.canvasPos={},this.left=0,this.center=0,this.right=0,this.drag={left:0,center:0,right:0},this._dragFrame={left:!1,center:!1,right:!1},this.isOnCanvas=!1,this.isActive=!1,this._visible=!0,this._cursor="default",this._ogX=0,this._ogY=0}_ac(t){return"left"==(t=t.toLowerCase()).slice(0,4)?t="left":"right"==t.slice(0,5)?t="right":"middle"==t.slice(0,6)&&(t="center"),t}_update(){t.mouse.canvasPos.x=t.mouseX,t.mouse.canvasPos.y=t.mouseY,t.camera.x==t.camera.ogX&&t.camera.y==t.camera.ogY&&1==t.camera.zoom?(this.x=t.mouseX,this.y=t.mouseY):"webgpu"!=t.canvas.renderer?(this.x=(t.mouseX-t.canvas.hw)/t.camera.zoom+t.camera.x,this.y=(t.mouseY-t.canvas.hh)/t.camera.zoom+t.camera.y):(this.x=t.mouseX/t.camera.zoom+t.camera.x,this.y=t.mouseY/t.camera.zoom+t.camera.y)}get pos(){return this._pos}get position(){return this._pos}get cursor(){return t.canvas.style.cursor}set cursor(e){e!=this._cursor&&(t.cursor(e),this._cursor=e)}get visible(){return this._visible}set visible(e){this._visible=e,t.canvas.style.cursor=e?"default":"none"}drags(t){return t??=this._default,1==this.drag[t]}dragging(t){return t??=this._default,this.drag[t]>0?this.drag[t]:0}dragged(t){return t??=this._default,this.drag[t]<=-1}},this.mouse=new t._Mouse,this._SpriteMouse=class extends t._Mouse{constructor(){super(),delete this.canvasPos,this.hover=0}hovers(){return 1==this.hover}hovering(){return this.hover>0?this.hover:0}hovered(){return this.hover<=-1}};const S=function(e){if(t.mouse.isActive=!0,t.mouse[e]++,t.world.mouseSprites.length){let i=t.world.mouseSprite?.mouse;i&&(i[e]=0,i.hover=0,i.drag[e]=0),ms=t.world.mouseSprites[0],t.world.mouseSprite=ms,i=ms.mouse,i[e]=1,i.hover<=0&&(i.hover=1)}},A=t._onmousedown;t._onmousedown=function(e){if(!t._setupDone)return;let i="left";1===e.button?i="center":2===e.button&&(i="right"),S.call(t,i),A.call(t,e)};const C=function(e){let i=t.mouse;i[e]>0&&(i._dragFrame[e]=!0)},k=t._onmousemove;t._onmousemove=function(e){if(!t._setupDone)return;let i="left";1===e.button?i="center":2===e.button&&(i="right"),C.call(t,i),k.call(t,e)};const M=function(e){let i=t.mouse;i[e]>=i.holdThreshold?i[e]=-2:i[e]>1?i[e]=-1:i[e]=-3,i.drag[e]>0&&(i.drag[e]=-1);let s=t.world.mouseSprite?.mouse;s&&(s.hover>1?(s[e]>=t.mouse.holdThreshold?s[e]=-2:s[e]>1?s[e]=-1:s[e]=-3,s.drag[e]>0&&(s.drag[e]=-1)):(s[e]=0,s.drag[e]=0))},z=t._onmouseup;if(t._onmouseup=function(e){if(!t._setupDone)return;let i="left";1===e.button?i="center":2===e.button&&(i="right"),M.call(t,i),z.call(t,e)},this._Touch=class extends t.InputDevice{constructor(e){super(),this.x,this.y,this.id=e.identifier,this._default="duration",this.holdThreshold=t.touches.holdThreshold,this.duration=1,this.drag=0,this._dragFrame=!1,this.canvasPos={},this._update(e)}_update(e){let i=t.canvas;const s=i.getBoundingClientRect(),r=i.scrollWidth/i.w||1,o=i.scrollHeight/i.h||1,h=this.canvasPos.x=(e.clientX-s.left)/r,n=this.canvasPos.y=(e.clientY-s.top)/o;t.camera.x==i.hw&&t.camera.y==i.hh&&1==t.camera.zoom?(this.x=h,this.y=n):(this.x=(h-i.hw)/t.camera.zoom+t.camera.x,this.y=(n-i.hh)/t.camera.zoom+t.camera.y),this.force=e.force}},this.touches=[],t.touches.holdThreshold=12,t._ontouchstart=function(e){if(t._setupDone){t.getAudioContext&&"suspended"==t.getAudioContext()?.state&&t.userStartAudio();for(let i of e.changedTouches)t.touches.push(new t._Touch(i)),1==t.touches.length&&(t.mouseX=t.touches[0].x,t.mouseY=t.touches[0].y,t.mouse._update(),t.world.mouseSprites=t.world.getMouseSprites(),t._onmousedown(e));t.touchStarted&&!t.touchStarted(e)&&e.preventDefault()}},t._ontouchmove=function(e){if(t._setupDone){for(let i of e.changedTouches){let s=t.touches.find((t=>t.id==i.identifier));s._update(i),s._dragFrame=!0,s.id==t.touches[0].id&&(t.mouseX=t.touches[0].x,t.mouseY=t.touches[0].y,t.mouse._update(),t._onmousemove(e))}t.touchMoved&&!t.touchMoved(e)&&e.preventDefault()}},t._ontouchend=function(e){if(t._setupDone){for(let i of e.changedTouches){let s=t.touches.find((t=>t.id==i.identifier));s._update(i),s.duration>=s.holdThreshold?s.duration=-2:s.duration>1?s.duration=-1:s.duration=-3,s.drag>0&&(s.drag=-1),s.id==t.touches[0].id&&(t.mouseX=t.touches[0].x,t.mouseY=t.touches[0].y,t.mouse._update(),t._onmouseup(e))}t.touchEnded&&!t.touchEnded(e)&&e.preventDefault()}},this._Keyboard=class extends t.InputDevice{constructor(){super(),this._default=" ",this.alt=0,this.arrowUp=0,this.arrowDown=0,this.arrowLeft=0,this.arrowRight=0,this.backspace=0,this.capsLock=0,this.control=0,this.enter=0,this.meta=0,this.shift=0,this.tab=0;let t=this._simpleKeyControls={arrowUp:"up",arrowDown:"down",arrowLeft:"left",arrowRight:"right"};t.w=t.W="up",t.s=t.S="down",t.a=t.A="left",t.d=t.D="right",t.i=t.I="up2",t.k=t.K="down2",t.j=t.J="left2",t.l=t.L="right2"}get visible(){return this._inp==document.activeElement}set visible(t){this._inp||(this._inp=Object.assign(document.createElement("input"),{type:"text",style:"position: fixed; height: 0; padding: 0; border: none; opacity: 0.0001; pointer-events: none;"}),document.body.appendChild(this._inp)),this._visible=t,t?this._inp.focus():this._inp.blur()}_ac(t){if(1!=t.length){if(!isNaN(t)){if(38==t)return"arrowUp";if(40==t)return"arrowDown";if(37==t)return"arrowLeft";if(39==t)return"arrowRight";if(t>=10)throw new Error("Use key names with the keyboard input functions, not keyCode numbers!");return t}t=t.replaceAll(/[ _-]/g,"")}if(1!=(t=t.toLowerCase()).length){if("arrowup"==t)return"arrowUp";if("arrowdown"==t)return"arrowDown";if("arrowleft"==t)return"arrowLeft";if("arrowright"==t)return"arrowRight";if("capslock"==t)return"capsLock"}return t}_pre(t){(!this[t]||this[t]<0)&&(this[t]=1)}_rel(t){this[t]>=this.holdThreshold?this[t]=-2:this[t]>1?this[t]=-1:this[t]=-3}get cmd(){return this.meta}get command(){return this.meta}get ctrl(){return this.control}get space(){return this[" "]}get spacebar(){return this[" "]}get opt(){return this.alt}get option(){return this.alt}get win(){return this.meta}get windows(){return this.meta}},this.kb=new t._Keyboard,this.keyboard=t.kb,"object"==typeof navigator&&navigator.keyboard){const e=navigator.keyboard;window==window.top?e.getLayoutMap().then((e=>{"w"!=e.get("KeyW")&&(t.p5play.standardizeKeyboard=!0)})):t.p5play.standardizeKeyboard=!0}else t.p5play.standardizeKeyboard=!0;function T(t){let e=t.code;return 4==e.length&&"Key"==e.slice(0,3)?e[3].toLowerCase():t.key}const j=t._onkeydown;t._onkeydown=function(t){let e=t.key;if(this.p5play.standardizeKeyboard&&(e=T(t)),e.length>1)e=e[0].toLowerCase()+e.slice(1);else{let t=e.toLowerCase(),i=e.toUpperCase();t!=i&&(e!=i?this.kb._pre(i):this.kb._pre(t))}this.kb._pre(e);let i=this.kb._simpleKeyControls[e];i&&this.kb._pre(i),j.call(this,t)};const O=t._onkeyup;t._onkeyup=function(t){let e=t.key;if(this.p5play.standardizeKeyboard&&(e=T(t)),e.length>1)e=e[0].toLowerCase()+e.slice(1);else{let t=e.toLowerCase(),i=e.toUpperCase();t!=i&&(e!=i?this.kb._rel(i):this.kb._rel(t))}this.kb._rel(e);let i=this.kb._simpleKeyControls[e];if(i&&this.kb._rel(i),t.shiftKey){let t=e.toLowerCase();this.kb[t]>0&&this.kb._rel(t)}O.call(this,t)},this.Contro=class extends t.InputDevice{constructor(t){super(),this._default="a",this.connected=!0,this.a=0,this.b=0,this.x=0,this.y=0,this.l=0,this.r=0,this.lt=0,this.rt=0,this.select=0,this.start=0,this.lsb=0,this.rsb=0,this.up=0,this.down=0,this.left=0,this.right=0,this.leftStick={x:0,y:0},this.rightStick={x:0,y:0},this.leftTrigger=0,this.rightTrigger=0,this.buttonMapping={a:0,b:1,x:2,y:3,l:4,r:5,lt:6,rt:7,select:8,start:9,lsb:10,rsb:11,up:12,down:13,left:14,right:15},this.axeMapping={leftStick:{x:0,y:1},rightStick:{x:2,y:3},leftTrigger:4,rightTrigger:5},this.isMock=!1,"string"!=typeof t?(this.gamepad=t,this.id=t.id):(this.gamepad={},this.id=t,this.isMock=!0),this._axeTriggers=this.gamepad.axes&&void 0!==this.gamepad.axes[this.axeMapping.leftTrigger],this.hasAnalogTriggers=this._axeTriggers||void 0,this.id.includes("GuliKit")&&(this.buttonMapping.a=1,this.buttonMapping.b=0,this.buttonMapping.x=3,this.buttonMapping.y=2)}_ac(t){return"lb"==(t=t.toLowerCase())?t="l":"rb"==t?t="r":"leftstickbutton"==t?t="lsb":"rightstickbutton"==t&&(t="rsb"),t}_update(){if(this.isMock)return;if(this.gamepad=navigator.getGamepads()[this.gamepad.index],!this.gamepad?.connected)return;let t=this.gamepad;for(let e in this.buttonMapping){let i=this.buttonMapping[e],s=t.buttons[i];s&&(s.pressed?this[e]++:this[e]=this[e]>0?-1:0)}return this.leftStick.x=t.axes[this.axeMapping.leftStick.x],this.leftStick.y=t.axes[this.axeMapping.leftStick.y],this.rightStick.x=t.axes[this.axeMapping.rightStick.x],this.rightStick.y=t.axes[this.axeMapping.rightStick.y],this._axeTriggers?(this.leftTrigger=t.axes[this.axeMapping.leftTrigger],this.rightTrigger=t.axes[this.axeMapping.rightTrigger]):(this.leftTrigger=t.buttons[this.buttonMapping.lt].value,this.rightTrigger=t.buttons[this.buttonMapping.rt].value,void 0===this.hasAnalogTriggers&&(this.leftTrigger||this.rightTrigger)&&(this.hasAnalogTriggers=!Number.isInteger(this.leftTrigger)||!Number.isInteger(this.rightTrigger))),!0}_reset(){for(let t in this.buttonMapping)this[t]=0;this.leftStick.x=0,this.leftStick.y=0,this.rightStick.x=0,this.rightStick.y=0,this.leftTrigger=0,this.rightTrigger=0}get cross(){return this.a}get circle(){return this.b}get square(){return this.x}get triangle(){return this.y}get ls(){return this.leftStick}get rs(){return this.rightStick}get lb(){return this.l}get rb(){return this.r}get l1(){return this.l}get r1(){return this.r}get zl(){return this.lt}get zr(){return this.rt}get l2(){return this.leftTrigger}get r2(){return this.rightTrigger}get leftStickButton(){return this.lsb}get rightStickButton(){return this.rsb}get l3(){return this.lsb}get r3(){return this.rsb}},this._Contros=class extends Array{constructor(){if(super(),window&&(window.addEventListener("gamepadconnected",(t=>{this._onConnect(t.gamepad)})),window.addEventListener("gamepaddisconnected",(t=>{this._onDisconnect(t.gamepad)}))),"object"!=typeof navigator||!navigator.getGamepads)return;let t=navigator.getGamepads();for(let e of t)e&&this._onConnect(e)}swap(e,i){let s=this[e];this[e]=this[i],this[i]=s,0!=e&&0!=i||(t.contro=this[0],!t._q5&&t._isGlobal&&(window.contro=this[0]))}remove(t){this[t]=null}onConnect(t){return!0}onDisconnect(t){return!1}_onConnect(e){if(e){for(let t=0;tt.p5play._fps,this.renderStats=(t,e)=>{console.error("p5play: renderStats() function is deprecated. Use `p5play.renderStats = true` instead.")}})),p5.prototype.registerMethod("pre",(function(){const t=this;t._q5||(t.p5play._preDrawFrameTime=performance.now()),t.p5play.spritesDrawn=0,t.mouse._update(),t.contros._update()})),p5.prototype.registerMethod("post",(function(){const t=this;if(t.p5play._inPostDraw=!0,t.allSprites.autoCull&&t.allSprites.cull(1e4),t.allSprites._autoDraw&&(t.camera.on(),t.allSprites.draw(),t.camera.off()),t.allSprites._autoDraw??=!0,t.p5play.renderStats){let e=t.p5play._renderStats;if(e.fontSize||(1==t.allSprites.tileSize||t.allSprites.tileSize>16?e.fontSize=16:e.fontSize=10,e.gap=1.25*e.fontSize),!t.p5play._fpsAvg||t.frameCount%20==0){let e=0,i=t.p5play._fpsArr.length;for(let s=0;s55?t.color(30,255,30):r>25?t.color(255,100,30):t.color(255,30,30),t.p5play._statsColor=s}t.p5play._fpsArr.push(t.getFPS()),t.push(),t.fill(0,0,0,128),t.rect(e.x-5,e.y-e.fontSize,8.5*e.fontSize,5*e.gap+5),t.fill(t.p5play._statsColor),t.textAlign("left"),t.textSize(e.fontSize),e.font&&t.textFont(e.font);let i=e.x,s=e.y;t.text("sprites: "+t.p5play.spritesDrawn,i,s),t.text("display: "+Math.round(t.frameRate())+"hz",i,s+e.gap),t.text("fps avg: "+t.p5play._fpsAvg,i,s+2*e.gap),t.text("fps min: "+t.p5play._fpsMin,i,s+3*e.gap),t.text("fps max: "+t.p5play._fpsMax,i,s+4*e.gap),t.pop(),e.show=!1}t.world.autoStep&&t.world.timeScale>0&&t.world.step(),t.world.autoStep??=!0,t.allSprites._autoUpdate&&t.allSprites.update(),t.allSprites._autoUpdate??=!0;for(let e of t.allSprites)e.autoDraw??=!0,e.autoUpdate??=!0;for(let e in t.kb)"holdThreshold"!=e&&(t.kb[e]<0?t.kb[e]=0:t.kb[e]>0&&t.kb[e]++);for(let e=0;e0&&e[t]++,i?.hover&&(i[t]=e[t]),e._dragFrame[t]?(e.drag[t]++,i&&(i.drag[t]=e.drag[t]),e._dragFrame[t]=!1):e.drag[t]<0&&(e.drag[t]=0,i&&(i.drag[t]=0));if(t.world.mouseTracking&&t.mouse.isActive){let s=t.world.getMouseSprites();for(let t=0;t0?e.mouse.hover=-1:e.mouse.hover<0&&(e.mouse.hover=0)}e.left<=0&&e.center<=0&&e.right<=0&&(t.world.mouseSprite=null);let r=t.world.mouseSprite,o=e.drag.left>0||e.drag.center>0||e.drag.right>0;for(let e of t.world.mouseSprites)if(!s.includes(e)){let i=e.mouse;i.hover>0&&(i.hover=-1,i.left=i.center=i.right=0),o||e!=r||(t.world.mouseSprite=r=null)}r&&(s.includes(r)||s.push(r),i.x=r.x-e.x,i.y=r.y-e.y),t.world.mouseSprites=s}t.camera.off(),t._q5||(t.p5play._postDrawFrameTime=performance.now(),t.p5play._fps=Math.round(1e3/(t.p5play._postDrawFrameTime-t.p5play._preDrawFrameTime))||1),t.p5play._inPostDraw=!1})); +if("object"!=typeof planck){if("object"!=typeof process)throw"planck.js must be loaded before p5play";global.planck=require("./planck.min.js")}p5.prototype.registerMethod("init",(function(){const t=this,e=planck;if("object"!=typeof process&&0!=window._p5play_gtagged){let t=document.createElement("script");t.src="https://www.googletagmanager.com/gtag/js?id=G-EHXNCTSYLK",t.async=!0,document.head.append(t),window._p5play_gtagged=!0,t.onload=()=>{window.dataLayer??=[],window.gtag=function(){dataLayer.push(arguments)},gtag("js",new Date),gtag("config","G-EHXNCTSYLK"),gtag("event","p5play_v3_22")}}t.angleMode("degrees");const i=(i,s,r)=>new e.Vec2(i*r/t.world.meterSize,s*r/t.world.meterSize),s=(i,s,r)=>new e.Vec2(i/r*t.world.meterSize,s/r*t.world.meterSize),r=t=>Math.abs(t)<=e.Settings.linearSlop,o=(t,i)=>Math.abs(t-Math.round(t))<=(i||e.Settings.linearSlop)?Math.round(t):t,h=(e,i)=>{let s="degrees"==t._angleMode?360:t.TWO_PI,r=(e-i)%s,o=(s-Math.abs(r))*-Math.sign(r);return(Math.abs(r)-1){let e=navigator.userAgent.substring(t+10,t+12);this.os.platform="iOS",this.os.version=e}else{let t=navigator.userAgentData?.platform;!t&&navigator.platform&&(t=navigator.platform.slice(3),"Mac"==t?t="macOS":"Win"==t?t="Windows":"Lin"==t&&(t="Linux")),this.os.platform=t}}this.renderStats=!1,this._renderStats={x:10,y:20,font:"monospace"},this._fps=60,this._fpsArr=[60],this._collides={},this._colliding={},this._collided={},this._overlaps={},this._overlapping={},this._overlapped={}}onImageLoad(){}},this.p5play=new t.P5Play,delete t.P5Play;const a=console.log;this.log=console.log,this.Sprite=class{constructor(i,s,r,h,n){this._isSprite=!0,this.idNum;let a,u,c=[...arguments];if(void 0!==c[0]&&c[0]._isGroup&&(a=c[0],c=c.slice(1)),void 0!==c[0]&&("string"==typeof c[0]||c[0]instanceof t.SpriteAnimation||c[0]instanceof p5.Image)&&(u=c[0],c=c.slice(1)),1==c.length&&"number"==typeof c[0])throw new b("Sprite",0,[c[0]]);if(Array.isArray(c[0])){if(i=void 0,s=void 0,r=c[0],h=void 0,n=c[1],Array.isArray(n))throw new b("Sprite",1,[`[[${r}], [${h}]]`])}else i=c[0],s=c[1],r=c[2],h=c[3],n=c[4];"string"==typeof r&&(n=r,r=void 0),"string"==typeof h&&(!function(t){if("d"==t||"s"==t||"k"==t||"n"==t)return!0;let e=t.slice(0,2);return"dy"==e||"st"==e||"ki"==e||"no"==e}(h)?r=p(r,h):n=h,h=void 0),this.idNum=t.p5play.spritesCreated,this._uid=1e3+this.idNum,t.p5play.sprites[this._uid]=this,t.p5play.spritesCreated++,this.groups=[],this.animations=new t.SpriteAnimations,this.joints=[],this.joints.removeAll=()=>{for(;this.joints.length;)this.joints.at(-1).remove()},this.watch,this.mod={},this._removed=!1,this._life=2147483647,this._visible=!0,this._pixelPerfect=!1,this._aniChangeCount=0,this._draw=()=>this.__draw(),this._hasOverlap={},this._collisions={},this._overlappers={},a??=t.allSprites,this._tile="",this.tileSize=a.tileSize||1;let _=this;this._position={x:0,y:0},this._pos=t.createVector.call(t),Object.defineProperty(this._pos,"x",{get(){if(!_.body)return _._position.x;let e=_.body.getPosition().x/_.tileSize*t.world.meterSize;return t.p5play.friendlyRounding?o(e):e},set(i){if(_.body){let s=new e.Vec2(i*_.tileSize/t.world.meterSize,_.body.getPosition().y);_.body.setPosition(s)}_._position.x=i}}),Object.defineProperty(this._pos,"y",{get(){if(!_.body)return _._position.y;let e=_.body.getPosition().y/_.tileSize*t.world.meterSize;return t.p5play.friendlyRounding?o(e):e},set(i){if(_.body){let s=new e.Vec2(_.body.getPosition().x,i*_.tileSize/t.world.meterSize);_.body.setPosition(s)}_._position.y=i}}),this._canvasPos=t.createVector.call(t),Object.defineProperty(this._canvasPos,"x",{get(){let e=_._pos.x-t.camera.x;return"2d"==t.canvas.renderer&&(e+=t.canvas.hw/t.camera._zoom),e}}),Object.defineProperty(this._canvasPos,"y",{get(){let e=_._pos.y-t.camera.y;return"2d"==t.canvas.renderer&&(e+=t.canvas.hh/t.camera._zoom),e}}),this._velocity={x:0,y:0},this._direction=0,this._vel=t.createVector.call(t),Object.defineProperties(this._vel,{x:{get(){let e;return e=_.body?_.body.getLinearVelocity().x:_._velocity.x,e/=_.tileSize,t.p5play.friendlyRounding?o(e):e},set(t){t*=_.tileSize,_.body?_.body.setLinearVelocity(new e.Vec2(t,_.body.getLinearVelocity().y)):_._velocity.x=t,(t||this.y)&&(_._direction=this.heading())}},y:{get(){let e;return e=_.body?_.body.getLinearVelocity().y:_._velocity.y,e/=_.tileSize,t.p5play.friendlyRounding?o(e):e},set(t){t*=_.tileSize,_.body?_.body.setLinearVelocity(new e.Vec2(_.body.getLinearVelocity().x,t)):_._velocity.y=t,(t||this.x)&&(_._direction=this.heading())}}}),this._mirror={_x:1,_y:1,get x(){return this._x<0},set x(t){_.watch&&(_.mod[20]=!0),this._x=t?-1:1},get y(){return this._y<0},set y(t){_.watch&&(_.mod[20]=!0),this._y=t?-1:1}},this._heading="right",this._layer=a._layer,this._layer??=t.allSprites._getTopLayer()+1,a.dynamic&&(n??="dynamic"),a.kinematic&&(n??="kinematic"),a.static&&(n??="static"),n??=a.collider,n&&"string"==typeof n||(n="dynamic"),this.collider=n,i??=a.x,void 0===i&&(i="2d"==t.canvas?.renderer?t.canvas.hw/this.tileSize:0,r&&(this._vertexMode=!0)),s??=a.y,void 0===s&&(s="2d"==t.canvas?.renderer?t.canvas.hh/this.tileSize:0);let g=!1;if(void 0===r&&(r=a.w||a.width||a.d||a.diameter||a.v||a.vertices,h||a.d||a.diameter||(h=a.h||a.height,g=!0)),"function"==typeof i&&(i=i(a.length)),"function"==typeof s&&(s=s(a.length)),"function"==typeof r&&(r=r(a.length)),"function"==typeof h&&(h=h(a.length)),this.x=i,this.y=s,!a._isAllSpritesGroup&&!u){for(let t in a.animations){u=t;break}u||(u=a._img,"function"==typeof u&&(u=u(a.length)),u&&(this._img=!0))}for(let e=a;e;e=t.p5play.groups[e.parent])this.groups.push(e);if(this.groups.reverse(),u){let e=this.tileSize;this._img||u instanceof p5.Image?(this.image="string"!=typeof u?u:new t.EmojiImage(u,r),r||1==this._img.w&&1==this._img.h||(r=this._img.w/e,h??=this._img.h/e)):("string"==typeof u?this._changeAni(u):this._ani=u.clone(),r||1==this._ani.w&&1==this._ani.h||(r=this._ani.w/e,h??=this._ani.h/e))}if(this.groups=[],this.mouse=new t._SpriteMouse,this._rotation=0,this._rotationSpeed=0,this._bearing=0,this._scale=new l,Object.defineProperty(this._scale,"x",{get(){return this._x},set(t){if(t==this._x)return;_.watch&&(_.mod[26]=!0);let e=Math.abs(t/this._x);_._w*=e,_._hw*=e,_._resizeColliders({x:e,y:1}),this._x=t,this._avg=.5*(this._x+this._y)}}),Object.defineProperty(this._scale,"y",{get(){return this._y},set(t){if(t==this._y)return;_.watch&&(_.mod[26]=!0);let e=Math.abs(t/this._y);_._h&&(this._h*=e,this._hh*=e),_._resizeColliders({x:1,y:e}),this._y=t,this._avg=.5*(this._x+this._y)}}),this._offset={_x:0,_y:0,get x(){return this._x},set x(t){t!=this._x&&(_.watch&&(_.mod[21]=!0),_._offsetCenterBy(t-this._x,0))},get y(){return this._y},set y(t){t!=this._y&&(_.watch&&(_.mod[21]=!0),_._offsetCenterBy(0,t-this._y))}},this._massUndef=!0,void 0===r&&(this._dimensionsUndef=!0,this._widthUndef=!0,r=this.tileSize>1?1:50,void 0===h&&(this._heightUndef=!0)),g&&(h??=this.tileSize>1?1:50),this._shape=a.shape,3!=this.__collider)this._vertexMode?this.addCollider(r):this.addCollider(0,0,r,h),this.shape=this._shape;else{if(this.w=r,Array.isArray(r))throw new Error('Cannot set the collider type of a sprite with a polygon or chain shape to "none". To achieve the same effect, use .overlaps(allSprites) to have your sprite overlap with the allSprites group.');void 0!==r&&void 0===h?this.shape="circle":(this.shape="box",this.h=h)}this.prevPos={x:i,y:s},this.prevRotation=0,this._dest={x:i,y:s},this._destIdx=0,this._debug=!1,this.text,a._isAllSpritesGroup||t.allSprites.push(this),a.push(this);let f=a.vel.x||0,m=a.vel.y||0;"function"==typeof f&&(f=f(a.length-1)),"function"==typeof m&&(m=m(a.length-1)),this.vel.x=f,this.vel.y=m;let y=["ani","collider","x","y","w","h","d","diameter","dynamic","height","kinematic","static","vel","width"];for(let e of t.Sprite.propsAll){if(y.includes(e))continue;let i=a[e];void 0!==i&&("function"==typeof i&&d(i)&&(i=i(a.length-1)),"object"==typeof i?i instanceof p5.Color?this[e]=t.color(...i.levels):this[e]=Object.assign({},i):this[e]=i)}y=["add","animation","animations","autoCull","contains","GroupSprite","Group","idNum","length","mod","mouse","p","parent","Sprite","Subgroup","subgroups","velocity"];for(let e=0;e1?1:50,n??=h,d=i(h-.08,n-.08,this.tileSize)),"box"==l)u=e.Box(d.x/2,d.y/2,i(s,o,this.tileSize),0);else if("circle"==l)u=e.Circle(i(s,o,this.tileSize),d.x/2);else if(a){let _,g,f=[{x:0,y:0}],m={x:0,y:0},y={x:0,y:0},w={x:0,y:0},v=Array.isArray(a[0]);function x(){m.xw.x&&(w.x=m.x),m.y>w.y&&(w.y=m.y)}if(v){this._vertexMode&&(_=a[0][0],g=a[0][1],this.fixture&&this._relativeOrigin?(_=this.x-this._relativeOrigin.x,g=this.y-this._relativeOrigin.y,f.pop()):(this.x=_,this.y=g));for(let S=0;S0?1:-1;A=Math.abs(A);let k=0;for(let M=0;Me.Settings.maxPolygonVertices||"chain"==this._shape)&&(l="chain"),"polygon"==l?u=e.Polygon(f):"chain"==l&&(u=e.Chain(f,!1))}if(this.shape??=l,this.fixtureList){this._extents??={t:this.hh,b:this.hh,l:this._hw,r:this._hw};let G=this._extents,N=s-.5*h,E=s+.5*h,R=o-.5*n,U=o+.5*n;NG.r&&(G.r=E),RG.b&&(G.b=U),this._totalWidth=G.r-G.l,this._totalHeight=G.b-G.t;let V=Math.abs;this._largestExtent=Math.max(V(G.l),V(G.r),V(G.t),V(G.b))}else this._w=h,this._hw=.5*h,1!=this.__shape&&(this._h=n,this._hh=.5*n);return u}removeColliders(){this.body&&(this._removeContacts(0),this._removeFixtures(0))}removeSensors(){this.body&&(this._removeContacts(1),this._removeFixtures(1),this._hasSensors=!1)}_removeFixtures(e){let i;for(let s=this.fixtureList;s;s=s.getNext())if(void 0===e||s.m_isSensor==e){let e=s.m_next;s.destroyProxies(t.world.m_broadPhase),i?i.m_next=e:this.body.m_fixtureList=e}else i=s}_removeContacts(e){if(!this.body)return;let i=this.body.m_contactList;for(;i;){let s=i.contact;i=i.next,void 0!==e&&s.m_fixtureA.m_isSensor!=e||t.world.destroyContact(s)}}_offsetCenterBy(t,e){if(!t&&!e)return;if(this._offset._x+=t,this._offset._y+=e,!this.body)return;let s=i(t,e,this.tileSize);this.__offsetCenterBy(s.x,s.y)}__offsetCenterBy(t,e){for(let i=this.body.m_fixtureList;i;i=i.m_next){let s=i.m_shape;if("circle"!=s.m_type){let i=s.m_vertices;for(let s of i)s.x+=t,s.y+=e}else s.m_p.x+=t,s.m_p.y+=e}}_cloneBodyProps(){let t={},e=["bounciness","density","drag","friction","heading","isSuperFast","rotation","rotationDrag","rotationLock","rotationSpeed","scale","vel","x","y"];this._massUndef&&this._dimensionsUndef||e.push("mass");for(let i of e)"object"==typeof this[i]?t[i]=Object.assign({},this[i]):t[i]=this[i];return t}get animation(){return this._ani}set animation(t){this.changeAni(t)}get ani(){return this._ani}set ani(t){this.changeAni(t)}get anis(){return this.animations}get autoDraw(){return this._autoDraw}set autoDraw(t){this._autoDraw=t}get allowSleeping(){return this.body?.isSleepingAllowed()}set allowSleeping(t){this.watch&&(this.mod[5]=!0),this.body&&this.body.setSleepingAllowed(t)}get autoUpdate(){return this._autoUpdate}set autoUpdate(t){this._autoUpdate=t}get bounciness(){if(this.fixture)return this.fixture.getRestitution()}set bounciness(t){this.watch&&(this.mod[7]=!0);for(let e=this.fixtureList;e;e=e.getNext())e.setRestitution(t)}get collider(){return this._collider}set collider(e){if(e==this._collider)return;let i=(e=e.toLowerCase())[0];if("d"==i&&(e="dynamic"),"s"==i&&(e="static"),"k"==i&&(e="kinematic"),"n"==i&&(e="none"),e==this._collider)return;if("none"==e&&("chain"==this._shape||"polygon"==this._shape))return void console.error('Cannot set the collider type of a polygon or chain collider to "none". To achieve the same effect, use .overlaps(allSprites) to have your sprite overlap with the allSprites group.');if(this._removed)throw new Error("Cannot change the collider type of a sprite that was removed.");let s=this.__collider;this._collider=e,this.__collider=["d","s","k","n"].indexOf(i),this.watch&&(this.mod[8]=!0),void 0!==s&&(3!=this.__collider?(this.body&&this.body.setType(e),3==s&&(this.addCollider(),this.x=this._position.x,this.y=this._position.y,this.vel.x=this._velocity.x,this.vel.y=this._velocity.y,this.rotation=this._rotation,this.rotationSpeed=this._rotationSpeed)):(this.removeColliders(),this.fixture?.m_isSensor?this.body.m_gravityScale=0:(this._position.x=this.x,this._position.y=this.y,this._velocity.x=this.vel.x,this._velocity.y=this.vel.y,this._rotation=this.rotation,this._rotationSpeed=this.rotationSpeed,t.world.destroyBody(this.body),this.body=null)))}_parseColor(e){return e instanceof p5.Color?e:"object"!=typeof e?1==e.length?t.colorPal(e):t.color(e):t.color(...e.levels)}get color(){return this._color}set color(t){this.watch&&(this.mod[9]=!0),this._color=this._parseColor(t)}get colour(){return this._color}set colour(t){this.color=t}get fill(){return this._color}set fill(t){this.color=t}get fillColor(){return this._color}set fillColor(t){this.color=t}get stroke(){return this._stroke}set stroke(t){this.watch&&(this.mod[29]=!0),this._stroke=this._parseColor(t)}get strokeColor(){return this._stroke}set strokeColor(t){this.stroke=t}get strokeWeight(){return this._strokeWeight}set strokeWeight(t){this.watch&&(this.mod[30]=!0),this._strokeWeight=t}get textColor(){return this._textFill}set textColor(t){this.watch&&(this.mod[32]=!0),this._textFill=this._parseColor(t)}get textColour(){return this._textFill}set textColour(t){this.textColor=t}get textFill(){return this._textFill}set textFill(t){this.textColor=t}get textSize(){return this._textSize}set textSize(t){this.watch&&(this.mod[33]=!0),this._textSize=t}get textStroke(){return this._textStroke}set textStroke(t){this.watch&&(this.mod[34]=!0),this._textStroke=this._parseColor(t)}get textStrokeWeight(){return this._textStrokeWeight}set textStrokeWeight(t){this.watch&&(this.mod[35]=!0),this._textStrokeWeight=t}get tile(){return this._tile}set tile(t){this.watch&&(this.mod[36]=!0),this._tile=t}get tileSize(){return this._tileSize}set tileSize(t){this.watch&&(this.mod[37]=!0),this._tileSize=t}get bearing(){return this._bearing}set bearing(t){this.watch&&(this.mod[6]=!0),this._bearing=t}get debug(){return this._debug}set debug(t){this.watch&&(this.mod[10]=!0),this._debug=t}get density(){if(this.fixture)return this.fixture.getDensity()}set density(t){this.watch&&(this.mod[11]=!0);for(let e=this.fixtureList;e;e=e.getNext())e.setDensity(t)}_getDirectionAngle(e){e=e.toLowerCase().replaceAll(/[ _-]/g,"");let i={up:-90,down:90,left:180,right:0,upright:-45,rightup:-45,upleft:-135,leftup:-135,downright:45,rightdown:45,downleft:135,leftdown:135,forward:this.rotation,backward:this.rotation+180}[e];return"radians"==t._angleMode&&(i=t.radians(i)),i}get direction(){return 0!==this.vel.x||0!==this.vel.y?t.atan2(this.vel.y,this.vel.x):this._isTurtleSprite?this.rotation:this._direction}set direction(e){this.watch&&(this.mod[12]=!0),"string"==typeof e&&(this._heading=e,e=this._getDirectionAngle(e)),this._direction=e,this._isTurtleSprite&&(this.rotation=e);let i=this.speed;this.vel.x=t.cos(e)*i,this.vel.y=t.sin(e)*i}get drag(){return this.body?.getLinearDamping()}set drag(t){this.watch&&(this.mod[13]=!0),this.body&&this.body.setLinearDamping(t)}get draw(){return this._display}set draw(t){this._userDefinedDraw=!0,this._draw=t}get dynamic(){return this.body?.isDynamic()}set dynamic(t){this.collider=t?"dynamic":"kinematic"}get fixture(){return this.fixtureList}get fixtureList(){return this.body?this.body.m_fixtureList:null}get friction(){if(this.fixture)return this.fixture.getFriction()}set friction(t){this.watch&&(this.mod[14]=!0);for(let e=this.fixtureList;e;e=e.getNext())e.setFriction(t)}get heading(){return this._heading}set heading(t){this.direction=t}get img(){return this._img||this._ani?.frameImage}set img(t){this.image=t}get image(){return this._img||this._ani?.frameImage}set image(e){"string"==typeof e&&(e=e.includes(".")?t.loadImage(e):new t.EmojiImage(e,this.w)),this._img=this._extendImage(e)}_extendImage(t){return t.offset??={x:0,y:0},t._scale??={x:1,y:1},t.scale||Object.defineProperty(t,"scale",{get:()=>t._scale,set:e=>{"number"==typeof e&&(e={x:e,y:e}),t._scale=e}}),t}get isMoving(){return 0!=this.vel.x||0!=this.vel.y}get isSuperFast(){return this.body?.isBullet()}set isSuperFast(t){this.watch&&(this.mod[16]=!0),this.body&&this.body.setBullet(t)}get kinematic(){return this.body?.isKinematic()}set kinematic(t){this.collider=t?"kinematic":"dynamic"}get layer(){return this._layer}set layer(t){this.watch&&(this.mod[17]=!0),this._layer=t}get life(){return this._life}set life(t){this.watch&&(this.mod[18]=!0),this._life=t}get mass(){return this.body?.getMass()}set mass(t){if(!this.body)return;this.watch&&(this.mod[19]=!0);const i={I:0,center:new e.Vec2(this.body.getLocalCenter()),mass:0};this.body.getMassData(i),i.mass=t>0?t:1e-8,this.body.setMassData(i),delete this._massUndef}resetMass(){if(!this.body)return;let t=new e.Vec2(this.body.getLocalCenter());this.watch&&(this.mod[19]=!0),this.body.resetMassData(),this.body.setMassData({mass:this.body.getMass(),center:t,I:this.body.getInertia()})}resetCenterOfMass(){this.watch&&(this.mod[19]=!0),this.body.resetMassData();let{x:t,y:e}=this.body.getLocalCenter();if(0==t&&0==e)return;this.__offsetCenterBy(-t,-e),this.body.resetMassData();let i=this.body.getPosition();this.body.setPosition({x:i.x+t,y:i.y+e})}get mirror(){return this._mirror}set mirror(t){this.watch&&(this.mod[20]=!0),void 0!==t.x&&(this._mirror.x=t.x),void 0!==t.y&&(this._mirror.y=t.y)}get offset(){return this._offset}set offset(t){t.x??=this._offset._x,t.y??=this._offset._y,t.x==this._offset._x&&t.y==this._offset._y||(this.watch&&(this.mod[21]=!0),this._offsetCenterBy(t.x-this._offset._x,t.y-this._offset._y))}get opacity(){return this._opacity??1}set opacity(t){this.watch&&(this.mod[41]=!0),this._opacity=t}get previousPosition(){return this.prevPos}set previousPosition(t){this.prevPos=t}get previousRotation(){return this.prevRotation}set previousRotation(t){this.prevRotation=t}get pixelPerfect(){return this._pixelPerfect}set pixelPerfect(t){this.watch&&(this.mod[22]=!0),this._pixelPerfect=t}get removed(){return this._removed}set removed(t){t&&!this._removed&&(this.watch&&(this.mod[23]=!0),this._removed=!0,this._remove())}get rotation(){if(!this.body)return this._rotation||0;let i=this.body.getAngle();return"degrees"==t._angleMode&&(i=t.degrees(i)),t.p5play.friendlyRounding?o(i,e.Settings.angularSlop):i}set rotation(e){this.body?("degrees"==t._angleMode&&(e=t.radians(e%360)),this.body.setAngle(e),this.body.synchronizeTransform()):this._rotation=e}get rotationDrag(){return this.body?.getAngularDamping()}set rotationDrag(t){this.body&&(this.watch&&(this.mod[24]=!0),this.body.setAngularDamping(t))}get rotationLock(){return this.body?.isFixedRotation()}set rotationLock(t){if(!this.body)return;this.watch&&(this.mod[25]=!0);let e=this.mass;this.body.setFixedRotation(t),this.mass=e}get rotationSpeed(){if(this.body){let e=this.body.getAngularVelocity()/60;return"degrees"==t._angleMode?t.degrees(e):e}return this._rotationSpeed}set rotationSpeed(e){this.body?(e*=60,"degrees"==t._angleMode&&(e=t.radians(e)),this.body.setAngularVelocity(e)):this._rotationSpeed=e}get scale(){return this._scale}set scale(t){if(0==t&&(t=.01),"number"==typeof t?t={x:t,y:t}:(t.x??=this._scale._x,t.y??=this._scale._y),t.x==this._scale._x&&t.y==this._scale._y)return;this.watch&&(this.mod[26]=!0);let e={x:Math.abs(t.x/this._scale._x),y:Math.abs(t.y/this._scale._y)};this._w*=e.x,this._hw*=e.x,this._h&&(this._h*=e.y,this._hh*=e.y),this._resizeColliders(e),this._scale._x=t.x,this._scale._y=t.y,this._scale._avg=t.x}get sleeping(){if(this.body)return!this.body.isAwake()}set sleeping(t){this.body&&(this.watch&&(this.mod[28]=!0),this.body.setAwake(!t))}get speed(){return t.createVector(this.vel.x,this.vel.y).mag()}set speed(e){let i=this.direction;this.vel.x=t.cos(i)*e,this.vel.y=t.sin(i)*e}get static(){return this.body?.isStatic()}set static(t){this.collider=t?"static":"dynamic"}get tint(){return this._tint}set tint(t){this.watch&&(this.mod[42]=!0),this._tint=this._parseColor(t)}get tintColor(){return this._tint}set tintColor(t){this.tint=t}set vertices(t){if(3==this.__collider)throw new Error('Cannot set vertices of a sprite with collider type of "none".');this.watch&&(this.mod[27]=!0),this._removeFixtures(),this._originMode="start",this.addCollider(t),this._hasSensors&&this.addDefaultSensors()}get vertices(){return this._getVertices()}_getVertices(e){let i=this.fixture.getShape(),s=[...i.m_vertices];"polygon"==i.m_type&&s.unshift(s.at(-1));let r=this.x,h=this.y;for(let i=0;i=2)return void console.error('Cannot set the collider shape to chain or polygon if the sprite has a collider type of "none". To achieve the same effect, use .overlaps(allSprites) to have your sprite overlap with the allSprites group.');let s,r,o=this.__shape;if(this.__shape=i,this._shape=e,this.watch&&(this.mod[27]=!0),void 0===o)return;if(0==this.__shape?(this._h=this._w,this._hh=this._hw):(this._h=void 0,this._hh=void 0),1!=o&&1!=this.__shape?s=this._getVertices(!0):r=this._w,this._removeFixtures(),3!=this.__collider)if(s)this._originMode??="center",this.addCollider(s);else if(1==o){let t=this._w*Math.sin(Math.PI/12);this.addCollider(0,0,[t,-30,12])}else this.addCollider();this._hasSensors&&this.addDefaultSensors();let h=this._offset._x,n=this._offset._y;(h||n)&&(this._offset._x=0,this._offset._y=0,this._offsetCenterBy(h,n))}get update(){return this._update}set update(t){this._customUpdate=t}get vel(){return this._vel}set vel(t){this.vel.x=t.x,this.vel.y=t.y}get velocity(){return this._vel}set velocity(t){this.vel=t}get gravityScale(){return this.body?.getGravityScale()}set gravityScale(t){this.body&&(this.watch&&(this.mod[42]=!0),this.body.setGravityScale(t))}_update(){this._ani?.update&&this._ani.update();for(let t in this.mouse)-1==this.mouse[t]&&(this.mouse[t]=0);this._customUpdate&&this._customUpdate(),this.autoUpdate&&(this.autoUpdate=null)}_step(){this.life-=t.world.timeScale,2147483647!=this._life&&this._life<=0&&this.remove(),this.body||this._removed||(this.rotation+=this._rotationSpeed,this.x+=this.vel.x,this.y+=this.vel.y),this.watch&&(this.x!=this.prevX&&(this.mod[0]=this.mod[2]=!0),this.y!=this.prevY&&(this.mod[1]=this.mod[2]=!0),this.rotation!=this.prevRotation&&(this.mod[3]=this.mod[4]=!0)),(this.body||this._removed)&&this.__step()}__step(){let e,i=this;for(let s in n)for(let r in this[s]){if(r>=1e3){if(i._isGroup||i._uid>=r)continue;e=t.p5play.sprites[r]}else{if(i._isGroup&&i._uid>=r)continue;e=t.p5play.groups[r]}let o=i[s][r]+1;e&&0!=o&&-2!=o?(this[s][r]=o,e[s][i._uid]=o):(delete i[s][r],e&&delete e[s][i._uid])}}___step(){let e,i,s,r,o=this,h=!0;for(let a in n){for(let l in this[a]){if(l>=1e3){if(o._isGroup||o._uid>=l)continue;e=t.p5play.sprites[l]}else{if(o._isGroup&&o._uid>=l)continue;e=t.p5play.groups[l]}if(o._isGroup||e?._isGroup)continue;if(s=o._hasOverlap[e._uid]??e._hasOverlap[o._uid],h&&!1!==s||!h&&!0!==s)continue;let d=o[a][l];for(let s=0;s<3;s++){if(0==s&&1!=d&&-3!=d)continue;if(1==s&&-1==d)continue;if(2==s&&d>=1)continue;i=n[a][s];let h=t.p5play[i][o._uid];if(h){r=h[e._uid],r&&r.call(o,o,e,d);for(let t of e.groups)r=h[t._uid],r&&r.call(o,o,e,d)}let l=t.p5play[i][e._uid];if(l){r=l[o._uid],r&&r.call(e,e,o,d);for(let t of o.groups)r=l[t._uid],!r||h&&r==h[t._uid]||r.call(e,e,o,d)}}}h=!1}if(this._removed&&0==Object.keys(this._collisions).length&&0==Object.keys(this._overlappers).length){this._isSprite?delete t.p5play.sprites[this._uid]:t.p5play.targetVersion>=16&&delete t.p5play.groups[this._uid];for(let e in n)for(let i of n[e])delete t.p5play[i][this._uid]}}__draw(){if(!t.p5play.disableImages)if(this._ani)this._ani.draw(this._offset._x,this._offset._y,0,this._scale._x,this._scale._y);else if(this._img){let e=this._img,i=1!=this._scale._x||1!=this._scale._y||1!=e.scale.x||1!=e.scale.y;i&&(t.push(),t.scale(this._scale._x*e.scale.x,this._scale._y*e.scale.y)),t.image(e,this._offset._x+e.offset.x,this._offset._y+e.offset.y),i&&t.pop()}if(!this._ani&&!this._img||this.debug||t.p5play.disableImages)if(this.debug&&(t.noFill(),t.stroke(0,255,0),t.line(0,-2,0,2),t.line(-2,0,2,0)),3!=this.__collider){this.debug||0===this._strokeWeight?t.noStroke():2==this.__shape?t.stroke(this.stroke||this.color):this._stroke&&t.stroke(this._stroke);for(let e=this.fixtureList;e;e=e.getNext()){if(this.debug)e.m_isSensor?t.stroke(255,255,0):t.stroke(0,255,0);else if(e.m_isSensor)continue;this._drawFixture(e)}}else 0!==this._strokeWeight&&t.stroke(this._stroke||120),0==this.__shape?t.rect(this._offset._x,this._offset._y,this.w*this.tileSize,this.h*this.tileSize):1==this.__shape&&t.circle(this._offset._x,this._offset._y,this.d*this.tileSize);void 0!==this.text&&(t.textAlign(t.CENTER,t.CENTER),t.fill(this._textFill),this._textStrokeWeight&&t.strokeWeight(this._textStrokeWeight),this._textStroke?t.stroke(this._textStroke):t.noStroke(),t.textSize(this.textSize*this.tileSize),t.text(this.text,0,0))}_display(){let e,i=this.x*this.tileSize+t.world.origin.x,s=this.y*this.tileSize+t.world.origin.y;if(!this._userDefinedDraw){let e;if(e=this._totalWidth?Math.max(this._totalWidth,this._totalHeight):void 0!==this._h?Math.max(this._w,this._h):this._w,this.ani&&!t.p5play.disableImages&&(e=Math.max(e,this.ani.w,this.ani.h)),"chain"!=this.shape&&t.camera.isActive&&(i+et.camera.bound.max.x||s+et.camera.bound.max.y))return void(this._visible=null)}if(this._visible=!0,t.p5play.spritesDrawn++,this._pixelPerfect){let e,r;this.ani&&this.ani.length&&!t.p5play.disableImages?(e=this.ani[this.ani._frame].w,r=this.ani[this.ani._frame].h):(e=this._w,r=this._h),i=e%2==0?Math.round(i):Math.round(i-.5)+.5,s=r%2==0?Math.round(s):Math.round(s-.5)+.5}else i=o(i),s=o(s);for(let t of this.joints)t.visible?this._uid==t.spriteA._uid?(!t.spriteB._visible||this.layer<=t.spriteB.layer)&&t._display():(!t.spriteA._visible||this.layer{let s,r;do{if(await t.sleep(),c!=this._destIdx)return!1;let o=this.direction<0?this.direction+360:this.direction;if(u&&(o<=a||o>=l)||Math.abs(this.vel.x)<=d&&Math.abs(this.vel.y)<=d)return!1;e&&(s=this.vel.x>0?this._dest.x-this.x:this.x-this._dest.x),i&&(r=this.vel.y>0?this._dest.y-this.y:this.y-this._dest.y)}while(e&&s>p||i&&r>p);return this.x=this._dest.x,this.y=this._dest.y,this.vel.x=0,this.vel.y=0,!0})()}rotateTowards(t,e){if(1==this.__collider)return void new b(0);let i,s,r,o=arguments;"number"!=typeof o[0]?(i=o[0].x,s=o[0].y,e=o[1],r=o[2]):arguments.length>2&&(i=o[0],s=o[1],e=o[2],r=o[3]),void 0!==i?t=this.angleToFace(i,s,r):t-=this.rotation,e??=.1,this.rotationSpeed=t*e}angleTo(e,i){if("object"==typeof e){let s=e;if(s==t.mouse&&!t.mouse.isActive)return 0;if(void 0===s.x||void 0===s.y)return console.error("sprite.angleTo ERROR: rotation destination not defined, object given with no x or y properties"),0;i=s.y,e=s.x}return t.atan2(i-this.y,e-this.x)}rotationToFace(t,e,i){return"object"==typeof t&&(i=e,e=t.y,t=t.x),Math.abs(t-this.x)<.01&&Math.abs(e-this.y)<.01?0:this.angleTo(t,e)+(i||0)}angleToFace(t,e,i){let s=this.rotationToFace(t,e,i);return h(s,this.rotation)}rotateTo(e,i,s){if(1==this.__collider)return void new b(0);let r=arguments;if("number"!=typeof r[0]?e=this.rotationToFace(r[0].x,r[0].y,s):r.length>2&&(s=r[3],i=r[2],e=this.rotationToFace(r[0],r[1],s)),e==this.rotation)return;let o="degrees"==t._angleMode?360:t.TWO_PI;return(e=(e-this.rotation)%o)<0&&i>0&&(e+=o),e>0&&i<0&&(e-=o),i??=this.rotationSpeed||Math.sign(e),this.rotate(e,i)}rotateMinTo(t,e,i){if(1==this.__collider)return void new b(0);let s=arguments;return"number"!=typeof s[0]?t=this.rotationToFace(s[0].x,s[0].y,i):s.length>2&&(i=s[3],e=s[2],t=this.rotationToFace(s[0],s[1],i)),t!=this.rotation?(t=h(t,this.rotation),e??=this.rotationSpeed>.1?this.rotationSpeed:1,e=Math.abs(e)*Math.sign(t),this.rotate(t,e)):void 0}rotate(e,i){if(1==this.__collider)return void new b(0);if(isNaN(e))return void new b(1,[e]);if(0==e)return;i??=this.rotationSpeed||1;let s=e>0&&i>0;s||(e=-Math.abs(e),i=-Math.abs(i)),this.rotationSpeed=i;let r=Math.abs(i),o=this.rotation+e;this._rotateIdx??=0,this._rotateIdx++;let h=this._rotateIdx;return(async()=>{let e=.01;do{let n=Math.abs(o-this.rotation);if(r>n&&(this.rotationSpeed=n*Math.sign(i)),await t.sleep(),this._rotateIdx!=h)return!1;if(s&&this.rotationSpeed-.01)return!1}while((s&&o>this.rotation||!s&&o1)e=[...arguments];else if(e instanceof t.SpriteAnimation){if(e==this._ani)return;e=[e]}else if(!Array.isArray(e)){if(e==this._ani?.name)return;e=[e]}let i,s;this._aniChangeCount++;for(let r=0;r1&&("!"==o.name[0]&&(o.name=o.name.slice(1),o.start=-1,o.end=0),"<"!=o.name[0]&&">"!=o.name[0]||(o.name=o.name.slice(1),o.flipX=!0),"^"==o.name[0]&&(o.name=o.name.slice(1),o.flipY=!0),"**"==o.name&&(i=!0,e=e.slice(0,-1)),";;"==o.name&&(s=!0,e=e.slice(0,-1)))}let r=this._aniChangeCount;do{for(let t=0;t1&&(i.start=0),await this._playSequencedAni(i)}}while(i&&r==this._aniChangeCount);1!=e.length&&s&&this._ani.stop()}_playSequencedAni(t){return new Promise((e=>{let{name:i,start:s,end:r,flipX:o,flipY:h}=t;this._changeAni(i),o&&(this._ani.scale.x=-this._ani.scale.x),h&&(this._ani.scale.y=-this._ani.scale.y),s<0&&(s=this._ani.length+s),void 0!==s&&(this._ani._frame=s),void 0!==r?this._ani.goToFrame(r):this._ani._frame==this._ani.lastFrame&&e(),this._ani._onComplete=this._ani._onChange=()=>{o&&(this._ani.scale.x=-this._ani.scale.x),h&&(this._ani.scale.y=-this._ani.scale.y),this._ani._onComplete=this._ani._onChange=null,e()}}))}changeAnimation(){return this.changeAni(...arguments)}_changeAni(e){this._ani?._onChange&&this._ani._onChange(),this._ani?.onChange&&this._ani.onChange();let i=this.animations[e];if(!i)for(let t=this.groups.length-1;t>=0;t--){if(i=this.groups[t].animations[e],i){i=i.clone();break}}if(!i)throw t.noLoop(),new b("Sprite.changeAnimation",[e]);this._ani=i,this._ani.name=e,this.resetAnimationsOnChange&&(this._ani._frame=0)}remove(){this.removed=!0}_remove(){this.body&&t.world.destroyBody(this.body),this.body=null;for(let t of this.groups)t.remove(this)}toString(){return"s"+this.idNum}_setContactCB(e,i,s,r){let o;o=0==s?n._collisions[r]:n._overlappers[r];let h=t.p5play[o],a=h[this._uid]??={};a[e._uid]!=i&&(a[e._uid]=i,a=h[e._uid],a&&a[this._uid]&&(delete a[this._uid],0==Object.keys(a).length&&delete h[e._uid]))}_validateCollideParams(t,e){if(!t)throw new b("Sprite.collide",2);if(!t._isSprite&&!t._isGroup)throw new b("Sprite.collide",0,[t]);if(e&&"function"!=typeof e)throw new b("Sprite.collide",1,[e])}_ensureCollide(t,e,i){if(!1!==this._hasOverlap[t._uid]&&(this._hasOverlap[t._uid]=!1),!1!==t._hasOverlap[this._uid]&&(t._hasOverlap[this._uid]=!1,t._isGroup))for(let e of t)e._hasOverlap[this._uid]=!1,this._hasOverlap[e._uid]=!1}collide(t,e){return this.collides(t,e)}collides(t,e){return this._validateCollideParams(t,e),this._ensureCollide(t),e&&this._setContactCB(t,e,0,0),1==this._collisions[t._uid]||this._collisions[t._uid]<=-3}colliding(t,e){this._validateCollideParams(t,e),this._ensureCollide(t),e&&this._setContactCB(t,e,0,1);let i=this._collisions[t._uid];return i<=-3?1:i>0?i:0}collided(t,e){return this._validateCollideParams(t,e),this._ensureCollide(t),e&&this._setContactCB(t,e,0,2),this._collisions[t._uid]<=-1}_validateOverlapParams(t,e){if(!t)throw new b("Sprite.overlap",2);if(!t._isSprite&&!t._isGroup)throw new b("Sprite.overlap",0,[t]);if(e&&"function"!=typeof e)throw new b("Sprite.overlap",1,[e])}_ensureOverlap(t){if(this._hasSensors||this.addDefaultSensors(),!t._hasSensors)if(t._isSprite)t.addDefaultSensors();else{for(let e of t)e._hasSensors||e.addDefaultSensors();t._hasSensors=!0}if(this._hasOverlap[t._uid]||(this._removeContactsWith(t),this._hasOverlap[t._uid]=!0),!t._hasOverlap[this._uid]&&(t._removeContactsWith(this),t._hasOverlap[this._uid]=!0,t._isGroup))for(let e of t)e._hasOverlap[this._uid]=!0,this._hasOverlap[e._uid]=!0}overlap(t,e){return this.overlaps(t,e)}overlaps(t,e){return this._validateOverlapParams(t,e),this._ensureOverlap(t),e&&this._setContactCB(t,e,1,0),1==this._overlappers[t._uid]||this._overlappers[t._uid]<=-3}overlapping(t,e){this._validateOverlapParams(t,e),this._ensureOverlap(t),e&&this._setContactCB(t,e,1,1);let i=this._overlappers[t._uid];return i<=-3?1:i>0?i:0}overlapped(t,e){return this._validateOverlapParams(t,e),this._ensureOverlap(t),e&&this._setContactCB(t,e,1,2),this._overlappers[t._uid]<=-1}_removeContactsWith(t){if(t._isGroup)for(let e of t)this._removeContactsWith(e);else this.__removeContactsWith(t)}__removeContactsWith(e){if(this.body)for(let i=this.body.getContactList();i;i=i.next){let s=i.contact;s.m_fixtureA.m_body.sprite._uid!=e._uid&&s.m_fixtureB.m_body.sprite._uid!=e._uid||t.world.destroyContact(s)}}_sortFixtures(){let t,e,i=null,s=null;for(let r=this.fixtureList;r;r=r.getNext())r.m_isSensor?(s?s.m_next=r:s=r,e=r):(i?i.m_next=r:i=r,t=r);s&&(e.m_next=null),i&&(t.m_next=s),this.body.m_fixtureList=i||s}addDefaultSensors(){if(this._hasSensors)return;let t;if(this.body&&this.fixtureList){for(let e=this.fixtureList;e;e=e.getNext())e.m_isSensor||(t=e.m_shape,this.body.createFixture({shape:t,isSensor:!0}));this._sortFixtures()}else this.addSensor();this._hasSensors=!0}distanceTo(e){return t.dist(this.x,this.y,e.x,e.y)}},t.Sprite.propTypes={x:"Float64",y:"Float64",vel:"Vec2",rotation:"number",rotationSpeed:"number",allowSleeping:"boolean",bearing:"number",bounciness:"number",collider:"Uint8",color:"color",debug:"boolean",density:"number",direction:"number",drag:"number",friction:"number",h:"number",isSuperFast:"boolean",layer:"number",life:"Int32",mass:"number",mirror:"Vec2_boolean",offset:"Vec2",pixelPerfect:"boolean",removed:"boolean",rotationDrag:"number",rotationLock:"boolean",scale:"Vec2",shape:"Uint8",sleeping:"boolean",stroke:"color",strokeWeight:"number",text:"string",textColor:"color",textSize:"number",textStroke:"color",textStrokeWeight:"number",tile:"string",tileSize:"number",tint:"color",visible:"boolean",w:"number",opacity:"number",gravityScale:"number"},t.Sprite.props=Object.keys(t.Sprite.propTypes),t.Sprite.propsAll=t.Sprite.props.concat(["autoDraw","autoUpdate","d","diameter","dynamic","fill","height","heading","kinematic","resetAnimationsOnChange","speed","spriteSheet","static","width"]),t.Sprite.colliderTypes=["d","s","k","n"],t.Sprite.shapeTypes=["box","circle","chain","polygon"],t.Turtle=function(e){if(t.allSprites.tileSize>1)throw new Error("Turtle can't be used when allSprites.tileSize is greater than 1.");e??=25;let i=new t.Sprite(e,e,[[e,.4*e],[-e,.4*e],[0,.8*-e]]);i.color="green",i._isTurtleSprite=!0,i._prevPos={x:i.x,y:i.y};let s=i.move;return i.move=function(){return this._prevPos.x=this.x,this._prevPos.y=this.y,s.call(this,...arguments)},i},this.SpriteAnimation=class extends Array{constructor(){super();let e,i=[...arguments];if(this.name="default","object"==typeof i[0]&&(i[0]._isSprite||i[0]._isGroup)&&(e=i[0],i=i.slice(1),this._addedToSpriteOrGroup=!0),e??=t.allSprites,"string"!=typeof i[0]||1!=i[0].length&&i[0].includes(".")||(this.name=i[0],i=i.slice(1)),this._frame=0,this._cycles=0,this.targetFrame=-1,this.offset={x:e.anis.offset.x??0,y:e.anis.offset.y??0},this._frameDelay=e.anis.frameDelay||4,this.demoMode=e.anis.demoMode??!1,this.playing=!0,this.visible=!0,this.looping=e.anis.looping??!0,this.endOnFirstFrame=e.anis.endOnFirstFrame??!1,this.frameChanged=!1,this.onComplete=this.onChange=null,this._onComplete=this._onChange=null,this.rotation=e.anis.rotation??0,this._scale=new l,0!=i.length&&"number"!=typeof i[0]){if(e.animations[this.name]=this,e._ani=this,Array.isArray(i[0])&&"string"==typeof i[0][0]&&(i=[...i[0]]),2!=i.length||"string"!=typeof i[0]||"string"!=typeof i[1]&&"number"!=typeof i[1])if("string"==typeof i.at(-1)||i.at(-1)instanceof p5.Image)for(let s=0;s=3)throw new b("SpriteAnimation",1);o=i[0],r=i[1]}else r=i[0];let h=this;if(o instanceof p5.Image&&1!=o.width&&1!=o.height)this.spriteSheet=o,n();else{let a;a="string"==typeof o?o:o.url,t._incrementPreload(),this.spriteSheet=t.loadImage(a,(()=>{n(),t._decrementPreload()})),"string"==typeof o&&(e.spriteSheet=this.spriteSheet)}function n(){Array.isArray(r)&&(r=4==r.length?{pos:r.slice(0,2),size:r.slice(2)}:{pos:r});let{w:t,h:i,width:s,height:o,size:n,row:a,col:l,line:d,x:p,y:u,pos:c,frames:_,frameCount:g,frameDelay:f,frameSize:m,delay:y,rotation:w}=r;m??=n||e.anis.frameSize,y&&(h.frameDelay=y),f&&(h.frameDelay=f),w&&(h.rotation=w),_&&Array.isArray(_)?g=_.length:g??=_||1,t??=s||e.anis.w,i??=o||e.anis.h,p??=l||0,u??=d||a||0,c&&(p=c[0],u=c[1]),"number"==typeof m?t=i=m:m&&(t=m[0],i=m[1]);let v=e.tileSize;if(t&&i?(t*=v,i*=v):!e._dimensionsUndef&&e.w&&e.h?(t??=e.w*v,i??=e.h*v):1!=v?(t??=v,i??=v):g?(t??=h.spriteSheet.width/g,i??=h.spriteSheet.height):t=i=h.spriteSheet.width=h.spriteSheet.width&&(p=0,u+=i,u>=h.spriteSheet.height&&(u=0))}}}else{let d,p,u=i[0];isNaN(i[1])?d=i[1]:p=Number(i[1]);let c=u.lastIndexOf("."),_=0,g=0;for(let w=c-1;w>=0&&!isNaN(u.charAt(w));w--)_++;if(d)for(let v=d.length-5;v>=0&&!isNaN(d.charAt(v));v--)g++;let f,m=u.slice(c),y=u.slice(0,c-_);if(d&&(f=d.slice(0,c-g)),d&&y!=f)this.push(t.loadImage(u)),this.push(t.loadImage(d));else{let x,S=parseInt(u.slice(c-_,c),10);if(p??=parseInt(d.slice(c-g,c),10),p=this.length)throw new b("SpriteAnimation.frame",[t,this.length]);this._frame=t,this._cycles=0}get frameDelay(){return this._frameDelay}set frameDelay(t){t<=0&&(t=1),this._frameDelay=t}get scale(){return this._scale}set scale(t){"number"==typeof t&&(t={x:t,y:t}),this._scale._x=t.x,this._scale._y=t.y,this._scale._avg=t.x}clone(){this.length||console.error(`The animation named "${this.name}" must be loaded before it can be properly copied. Sprites need their own copy of a group's animation. Try loading the animation in the preload function and creating new group sprites in the setup function.`);let e=new t.SpriteAnimation;e.spriteSheet=this.spriteSheet;for(let t=0;tthis._frame&&-1!==this.targetFrame?this._frame++:this.targetFrame=this.lastFrame?this._frame=0:this._frame++:this._frame{this._onComplete=()=>{this._onComplete=null,t()}}))}pause(t){this.playing=!1,t&&(this._frame=t)}stop(t){this.playing=!1,t&&(this._frame=t)}rewind(){return this.looping=!1,this.goToFrame(0)}loop(){this.looping=!0,this.playing=!0}noLoop(){this.looping=!1}nextFrame(){this._frame0?this._frame=this._frame-1:this.looping&&(this._frame=this.length-1),this.targetFrame=-1,this.playing=!1,this._cycles=0}goToFrame(t){if(!(t<0||t>=this.length))return this.targetFrame=t,this._cycles=0,this.targetFrame!==this._frame&&(this.playing=!0),new Promise((t=>{this._onComplete=()=>{this._onComplete=null,t()}}))}get lastFrame(){return this.length-1}get frameImage(){let e=this[this._frame];if(e instanceof p5.Image)return e;let{x:i,y:s,w:r,h:o}=e,h=t.createImage(r,o);return h.copy(this.spriteSheet,this.offset.x,this.offset.y,r,o,i,s,r,o),h}get w(){return this.width}get width(){let t=this[this._frame];return t instanceof p5.Image?t.width:t?t.w:1}get h(){return this.height}get height(){let t=this[this._frame];return t instanceof p5.Image?t.height:t?t.h:1}},t.SpriteAnimation.props=["demoMode","endOnFirstFrame","frameDelay","frameSize","looping","offset","rotation","scale"],this.SpriteAnimations=class{#t={};constructor(){let e=this,i=[...t.SpriteAnimation.props],s=["offset","scale"];for(let t of i)Object.defineProperty(this,t,{get:()=>e.#t[t],set(i){e.#t[t]=i;for(let s in e){let r=e[s];r instanceof SpriteAnimation&&(r[t]=i)}}});for(let t of s){this.#t[t]={_x:0,_y:0};for(let i of["x","y"])Object.defineProperty(this.#t[t],i,{get:()=>e.#t[t]["_"+i],set(s){e.#t[t]["_"+i]=s;for(let r in e){let o=e[r];o instanceof SpriteAnimation&&(o[t][i]=s)}}})}}},this.Group=class extends Array{constructor(...e){let i;if(e[0]instanceof t.Group&&(i=e[0],e=e.slice(1)),super(...e),"number"==typeof e[0])return;for(let e of this)if(!(e instanceof t.Sprite))throw new Error("A group can only contain sprites");if(this._isGroup=!0,this.x,this.y,this.vel,this.rotation,this.rotationSpeed,this.autoDraw,this.allowSleeping,this.autoUpdate,this.bounciness,this.collider,this.color,this.debug,this.density,this.direction,this.drag,this.friction,this.h,this.isSuperFast,this.layer,this.life,this.mass,this.mirror,this.offset,this.pixelPerfect,this.removed,this.rotationDrag,this.rotationLock,this.scale,this.shape,this.sleeping,this.stroke,this.strokeWeight,this.text,this.textColor,this.tile,this.tileSize,this.visible,this.w,this.bearing,this.d,this.dynamic,this.heading,this.kinematic,this.resetAnimationsOnChange,this.speed,this.static,this.idNum,t.p5play.groupsCreated<999)this.idNum=t.p5play.groupsCreated;else{for(let e=1;et&&(t=e._layer);return t}get ani(){return this._ani}set ani(t){this.addAni(t);for(let e of this)e.changeAni(t)}get animation(){return this._ani}set animation(t){this.ani=t}get anis(){return this.animations}get img(){return this._img}set img(t){this.image=t}get image(){return this._img}set image(e){"function"!=typeof e?("string"==typeof e&&(e=e.includes(".")?t.loadImage(e):new t.EmojiImage(e,this.w||this.width||this.d||this.diameter)),this._img=t.Sprite.prototype._extendImage(e)):this._img=e}get amount(){return this.length}set amount(t){let e=t-this.length,i=e>0;e=Math.abs(e);for(let t=0;t0?i:0}collided(t,e){return this._validateCollideParams(t,e),this._ensureCollide(t),e&&this._setContactCB(t,e,0,2),this._collisions[t._uid]<=-1}_validateOverlapParams(t,e){if(e&&"function"!=typeof e)throw new b("Group.overlap",1,[e]);if(!t)throw new b("Group.overlap",2);if(!t._isGroup&&!t._isSprite)throw new b("Group.overlap",0,[t])}_ensureOverlap(t){if(!this._hasSensors){for(let t of this)t._hasSensors||t.addDefaultSensors();this._hasSensors=!0}if(!t._hasSensors)if(t._isSprite)t.addDefaultSensors();else{for(let e of t)e._hasSensors||e.addDefaultSensors();t._hasSensors=!0}if(1!=this._hasOverlap[t._uid]){this._removeContactsWith(t),this._hasOverlap[t._uid]=!0;for(let e of this)if(e._hasOverlap[t._uid]=!0,t._hasOverlap[e._uid]=!0,this._uid==t._uid)for(let i of t)e._hasOverlap[i._uid]=!0,i._hasOverlap[e._uid]=!0}if(1!=t._hasOverlap[this._uid]&&(t._removeContactsWith(this),t._hasOverlap[this._uid]=!0,t._isGroup))for(let e of t){e._hasOverlap[this._uid]=!0,this._hasOverlap[e._uid]=!0;for(let t of this)e._hasOverlap[t._uid]=!0,t._hasOverlap[e._uid]=!0}}overlap(t,e){return this.overlaps(t,e)}overlaps(t,e){return this._validateOverlapParams(t,e),this._ensureOverlap(t),e&&this._setContactCB(t,e,1,0),1==this._overlappers[t._uid]||this._overlappers[t._uid]<=-3}overlapping(t,e){this._validateOverlapParams(t,e),this._ensureOverlap(t),e&&this._setContactCB(t,e,1,1);let i=this._overlappers[t._uid];return i<=-3?1:i>0?i:0}overlapped(t,e){return this._validateOverlapParams(t,e),this._ensureOverlap(t),e&&this._setContactCB(t,e,1,2),this._overlappers[t._uid]<=-1}_removeContactsWith(t){for(let e of this)e._removeContactsWith(t)}applyForce(){for(let t of this)t.applyForce(...arguments)}applyForceScaled(){for(let t of this)t.applyForceScaled(...arguments)}attractTo(){for(let t of this)t.attractTo(...arguments)}applyTorque(){for(let t of this)t.applyTorque(...arguments)}move(t,e,i){let s=[];for(let r of this)s.push(r.move(t,e,i));return Promise.all(s)}moveTo(e,i,s){if("number"!=typeof e){let r=e;if(r==t.mouse&&!t.mouse.isActive)return;s=i,i=r.y,e=r.x}let r=this._resetCentroid(),o=[];for(let t of this){let h={x:t.x-r.x+e,y:t.y-r.y+i};o.push(t.moveTo(h.x,h.y,s))}return Promise.all(o)}moveTowards(e,i,s){if("number"!=typeof e){let r=e;if(r==t.mouse&&!t.mouse.isActive)return;s=i,i=r.y,e=r.x}if(void 0!==e||void 0!==i){this._resetCentroid();for(let t of this){void 0===t.distCentroid&&this._resetDistancesFromCentroid();let r={x:t.distCentroid.x+e,y:t.distCentroid.y+i};t.moveTowards(r.x,r.y,s)}}}moveAway(e,i,s){if("number"!=typeof e){let r=e;if(r==t.mouse&&!t.mouse.isActive)return;s=i,i=r.y,e=r.x}if(void 0!==e||void 0!==i){this._resetCentroid();for(let t of this){void 0===t.distCentroid&&this._resetDistancesFromCentroid();let r={x:t.distCentroid.x+e,y:t.distCentroid.y+i};t.moveAway(r.x,r.y,s)}}}push(...e){this.removed&&(console.warn("Adding a sprite to a group that was removed. Use `group.removeAll()` to remove all of a group's sprites without removing the group itself. Restoring the group in p5play's memory."),t.p5play.groups[this._uid]=this,this.removed=!1);for(let i of e){if(!(i instanceof t.Sprite))throw new Error("You can only add sprites to a group, not "+typeof i);if(i.removed){console.error("Can't add a removed sprite to a group");continue}let e;for(let s in this._hasOverlap){let r=this._hasOverlap[s];r&&!i._hasSensors&&i.addDefaultSensors(),e=s>=1e3?t.p5play.sprites[s]:t.p5play.groups[s],e&&!e.removed&&(r?e._ensureOverlap(i):e._ensureCollide(i))}for(let e in n){let s=n[e];for(let e of s){let s=t.p5play[e],r=s[this._uid];if(!r)continue;let o=s[i._uid]??={};for(let t in r)o[t]=r[t]}}super.push(i),this.parent&&t.p5play.groups[this.parent].push(i),i.groups.push(this)}return this.length}size(){return this.length}toString(){return"g"+this.idNum}cull(e,i,s,r,o){if(void 0===s){o=i,e=i=s=r=e}if(isNaN(e)||isNaN(i)||isNaN(s)||isNaN(r))throw new TypeError("The culling boundary must be defined with numbers");if(o&&"function"!=typeof o)throw new TypeError("The callback to group.cull must be a function");let h=t.camera.x-t.canvas.hw/t.camera.zoom,n=t.camera.y-t.canvas.hh/t.camera.zoom,a=-s+h,l=-e+n,d=t.width+r+h,p=t.height+i+n,u=0;for(let t=0;td||e.y>p)&&(u++,o?o(e,u):e.remove(),e.removed&&t--))}return u}remove(t){if(void 0===t)return this.removeAll(),void(this._isAllSpritesGroup||(this.removed=!0));let e;if(e="number"==typeof t?t>=0?t:this.length+t:this.indexOf(t),-1==e)return;let i=this[e];return this.splice(e,1),i}splice(e,i){let s=super.splice(e,i);if(!s)return;let r=[];for(let t of s){if(t.removed)continue;let e=this._uid;do{r.push(e);let i=t.groups.findIndex((t=>t._uid==e)),s=t.groups.splice(i,1);e=s[0].parent}while(e)}for(let e of r){let i=t.p5play.groups[e];for(let e in n)for(let s in i[e]){if(0==i[e][s])continue;let r;r=s>=1e3?t.p5play.sprites[s]:t.p5play.groups[s];let o=!1;for(let t of i)if(t[e][r._uid]>0){o=!0;break}o||(i[e][r._uid]=-2,r[e][i._uid]=-2)}}return s}pop(){return this.remove(this.length-1)}shift(){return this.remove(0)}unshift(){return console.error("unshift is not supported for groups"),this.length}removeAll(){for(;this.length>0;)this.at(-1).remove()}_step(){this.__step()}draw(){let e=[...this];e.sort(((t,e)=>t._layer-e._layer));for(let i=0;i2)return console.error("world.timeScale must be between 0 and 2");this._timeScale!=t&&(this._timeScale=t,this._updateTimeStep())}_updateTimeStep(){this._timeStep=1/(t._targetFrameRate||60)*this._timeScale}get velocityThreshold(){return e.Settings.velocityThreshold}set velocityThreshold(t){e.Settings.velocityThreshold=t}step(e,i,s){for(let e of t.allSprites)e.prevPos.x=e.x,e.prevPos.y=e.y,e.prevRotation=e.rotation;super.step(e||this._timeStep,i||this.velocityIterations,s||this.positionIterations),this.physicsTime+=e||this._timeStep;let r=Object.values(t.p5play.sprites),o=Object.values(t.p5play.groups);for(let t of r)t._step();for(let t of o)t._step();for(let t of r)t.___step();for(let t of o)t.___step();t.canvas.dispatchEvent&&t.canvas.dispatchEvent(this.steppedEvent),this.autoStep&&(this.autoStep=null)}get realTime(){return t.millis()/1e3}getSpritesAt(i,s,r,o){o??=!0;const h=new e.Vec2(i/t.world.meterSize,s/t.world.meterSize),n=new e.AABB;n.lowerBound=new e.Vec2(h.x-.001,h.y-.001),n.upperBound=new e.Vec2(h.x+.001,h.y+.001);let a=[];if(this.queryAABB(n,(t=>(t.getShape().testPoint(t.getBody().getTransform(),h)&&a.push(t),!0))),0==a.length)return[];r??=t.allSprites;let l=[];for(let t of a){const e=t.m_body.sprite;e._cameraActiveWhenDrawn==o&&(l.find((t=>t._uid==e._uid))||l.push(e))}return l.sort(((t,e)=>-1*(t._layer-e._layer))),l}getSpriteAt(t,e,i){return this.getSpritesAt(t,e,i)[0]}getMouseSprites(){let e=this.getSpritesAt(t.mouse.x,t.mouse.y);if(t.camera._wasOff){let i=this.getSpritesAt(t.mouse.canvasPos.x,t.mouse.canvasPos.y,t.allSprites,!1);i.length&&(e=[...i,...e])}return e}_beginContact(t){let e=t.m_fixtureA,i=t.m_fixtureB,s="_collisions";e.m_isSensor&&(s="_overlappers"),e=e.m_body.sprite,i=i.m_body.sprite,e[s][i._uid]=0,i[s][e._uid]=0;for(let t of i.groups)(!e[s][t._uid]||e[s][t._uid]<0)&&(e[s][t._uid]=0,t[s][e._uid]=0);for(let t of e.groups){(!i[s][t._uid]||i[s][t._uid]<0)&&(i[s][t._uid]=0,t[s][i._uid]=0);for(let e of i.groups)(!t[s][e._uid]||t[s][e._uid]<0)&&(t[s][e._uid]=0,e[s][t._uid]=0)}}_endContact(t){let e=t.m_fixtureA,i=t.m_fixtureB,s="_collisions";e.m_isSensor&&(s="_overlappers"),e=e.m_body.sprite,i=i.m_body.sprite,e[s][i._uid]=0!=e[s][i._uid]?-2:-4,i[s][e._uid]=0!=i[s][e._uid]?-2:-4;for(let t of i.groups){let i=!1;for(let r of t)if(r[s][e._uid]>=0){i=!0;break}i||(t[s][e._uid]=0!=t[s][e._uid]?-2:-4,e[s][t._uid]=0!=e[s][t._uid]?-2:-4)}for(let t of e.groups){let e=!1;for(let r of t)if(r[s][i._uid]>=0){e=!0;break}if(!e){t[s][i._uid]=0!=t[s][i._uid]?-2:-4,i[s][t._uid]=0!=i[s][t._uid]?-2:-4;for(let e of i.groups)t[s][e._uid]=0!=t[s][e._uid]?-2:-4,e[s][t._uid]=0!=e[s][t._uid]?-2:-4}}}_findContact(t,e,i){let s=e[t][i._uid];if(s)return s;for(let r of i.groups)if(s=e[t][r._uid],s)return s;for(let r of e.groups){if(s=r[t][i._uid],s)return s;for(let e of i.groups)if(r._uid==e._uid&&(s=r[t][e._uid],s))return s}return!1}get allowSleeping(){return this.getAllowSleeping()}set allowSleeping(t){this.setAllowSleeping(t)}rayCast(t,e,i){return this.rayCastAll(t,e,i,(()=>!0))[0]}rayCastAll(e,s,r,o){let h,n=t.allSprites.tileSize,a=i(e.x,e.y,n);if("number"==typeof arguments[1])h=i(e.x+r*t.cos(s),e.y+r*t.sin(s),n);else{let t=arguments[1];o??=arguments[2],h=i(t.x,t.y,n)}let l=[],d=1;super.rayCast(a,h,(function(t,e,i,s){let r=t.getBody().sprite,h=o&&o(r);return l.push({sprite:r,fraction:s}),h?(st.fraction-e.fraction));let p=[];for(let t of l)t.fraction<=d&&p.push(t.sprite);return p}},this.Camera=class{constructor(){this._pos=t.createVector.call(t),this.__pos={x:0,y:0,rounded:{}},this.isActive=!1,this.bound={min:{x:0,y:0},max:{x:0,y:0}},this._zoomIdx=-1,this._zoom=1,this._destIdx=0}get pos(){return this._pos}set pos(t){this.x=t.x,this.y=t.y}get position(){return this._pos}set position(t){this.x=t.x,this.y=t.y}_calcBoundsX(e){let i=t.canvas.hw/this._zoom;this.bound.min.x=e-i,this.bound.max.x=e+i}_calcBoundsY(e){let i=t.canvas.hh/this._zoom;this.bound.min.y=e-i,this.bound.max.y=e+i}get x(){return this._pos.x}set x(e){if(void 0===e||isNaN(e))return;this._pos.x=e;let i=-e;"2d"==t.canvas.renderer&&(i+=t.canvas.hw/this._zoom),this.__pos.x=i,t.allSprites.pixelPerfect&&(this.__pos.rounded.x=Math.round(i)),this._calcBoundsX(e)}get y(){return this._pos.y}set y(e){if(void 0===e||isNaN(e))return;this._pos.y=e;let i=-e;"2d"==t.canvas.renderer&&(i+=t.canvas.hh/this._zoom),this.__pos.y=i,t.allSprites.pixelPerfect&&(this.__pos.rounded.y=Math.round(i)),this._calcBoundsY(e)}moveTo(e,i,s){if(void 0===e)return;if(isNaN(e)&&(s=i,i=e.y,e=e.x),s??=1,s<=0)return console.warn("camera.moveTo: speed should be a positive number"),Promise.resolve(!1);let r=i-this.y,o=e-this.x,h=Math.sqrt(r*r+o*o),n=s/h,a=o*n,l=r*n;this._destIdx++;let d=this._destIdx,p=Math.ceil(h/s);return(async()=>{for(let e=0;e{for(let e=0;e0&&(e=e<.1?t.map(e,0,.1,30,4):e<.5?t.map(e,.1,.5,4,2.5):e<.8?t.map(e,.5,.8,2.5,1):e<.9?t.map(e,.8,.9,1,.5):t.map(e,.9,1,.5,.2)),this._springiness=e,"wheel"==this.type?this._j.setSpringFrequencyHz(e):this._j.setFrequency(e)}get damping(){return"wheel"!=this.type?this._j.getDampingRatio():this._j.getSpringDampingRatio()}set damping(t){"wheel"==this.type?this._j.setSpringDampingRatio(t):this._j.setDampingRatio(t)}get speed(){return this._j.getJointSpeed()}set speed(t){this._j.isMotorEnabled()||this._j.enableMotor(!0),this._j.setMotorSpeed(t)}get motorSpeed(){return this._j.getMotorSpeed()}get enableMotor(){return this._j.isMotorEnabled()}set enableMotor(t){this._j.enableMotor(t)}get maxPower(){return this._j.getMaxMotorTorque()}set maxPower(t){!this._j.isMotorEnabled()&&t&&this._j.enableMotor(!0),this._j.setMaxMotorTorque(t),t||this._j.enableMotor(!1)}get power(){return this._j.getMotorTorque()}get collideConnected(){return this._j.getCollideConnected()}set collideConnected(t){this._j.m_collideConnected=t}get reactionForce(){return this._j.getReactionForce(t.world._timeStep)}get reactionTorque(){return this._j.getReactionTorque(t.world._timeStep)}remove(){this._removed||(this.spriteA.joints.splice(this.spriteA.joints.indexOf(this),1),this.spriteB.joints.splice(this.spriteB.joints.indexOf(this),1),t.world.destroyJoint(this._j),this._removed=!0)}},this.GlueJoint=class extends t.Joint{constructor(t,e){super(...arguments,"glue")}},this.DistanceJoint=class extends t.Joint{constructor(t,i){super(...arguments,"distance");let s=e.DistanceJoint({},t.body,i.body,t.body.getWorldCenter(),i.body.getWorldCenter());this._createJoint(s)}_display(){let t,e;(this.offsetA.x||this.offsetA.y)&&(t=this.spriteA.body.getWorldPoint(this._j.m_localAnchorA),t=s(t.x,t.y,this.spriteA.tileSize)),(this.offsetB.x||this.offsetB.y)&&(e=this.spriteB.body.getWorldPoint(this._j.m_localAnchorB),e=s(e.x,e.y,this.spriteB.tileSize)),this._draw(t?t.x:this.spriteA.x,t?t.y:this.spriteA.y,e?e.x:this.spriteB.x,e?e.y:this.spriteB.y),this.visible=null}},this.WheelJoint=class extends t.Joint{constructor(i,s){super(...arguments,"wheel");let r=e.WheelJoint({maxMotorTorque:1e3,frequencyHz:4,dampingRatio:.7},i.body,s.body,s.body.getWorldCenter(),new e.Vec2(0,1));this._createJoint(r),this._angle="degrees"==t._angleMode?90:1.5707963267948966}_display(){let e,i,r=this.spriteA.x,o=this.spriteA.y;if(this.offsetB.x||this.offsetB.y){let t=this.spriteB.body.getWorldPoint(this._j.m_localAnchorB);t=s(t.x,t.y,this.spriteB.tileSize),e=t.x,i=t.y}else e=this.spriteB.x,i=this.spriteB.y;let h=t.tan(this.spriteA.rotation),n=t.tan(this._angle+this.spriteA.rotation),a=(i-o+h*r-n*e)/(h-n),l=h*(a-r)+o;this._draw(a,l,e,i),this.visible=null}get angle(){return this._angle}set angle(i){i!=this._angle&&(this._angle=i,this._j.m_localXAxisA=new e.Vec2(t.cos(i),t.sin(i)),this._j.m_localXAxisA.normalize(),this._j.m_localYAxisA=e.Vec2.crossNumVec2(1,this._j.m_localXAxisA))}},this.HingeJoint=class extends t.Joint{constructor(t,i){super(...arguments,"hinge");let s=e.RevoluteJoint({},t.body,i.body,t.body.getWorldCenter());this._createJoint(s)}_display(){const e=this.offsetA.x,i=this.offsetA.y,s=this.spriteA.rotation,r=e*t.cos(s)-i*t.sin(s),o=e*t.sin(s)+i*t.cos(s);this._draw(this.spriteA.x+r,this.spriteA.y+o),this.visible=null}get range(){return this.upperLimit-this.lowerLimit}set range(t){t/=2,this.upperLimit=t,this.lowerLimit=-t}get lowerLimit(){let e=this._j.getLowerLimit();return"radians"==t._angleMode?e:t.degrees(e)}set lowerLimit(e){this._j.isLimitEnabled()||this._j.enableLimit(!0),this.spriteA.body.setAwake(!0),this.spriteB.body.setAwake(!0),"degrees"==t._angleMode&&(e=t.radians(e)),this._j.m_lowerAngle=e}get upperLimit(){let e=this._j.getUpperLimit();return"radians"==t._angleMode?e:t.degrees(e)}set upperLimit(e){this._j.isLimitEnabled()||this._j.enableLimit(!0),this.spriteA.body.setAwake(!0),this.spriteB.body.setAwake(!0),"degrees"==t._angleMode&&(e=t.radians(e)),this._j.m_upperAngle=e}get angle(){let e=this._j.getJointAngle();return"radians"==t._angleMode?e:t.radians(e)}},t.RevoluteJoint=t.HingeJoint,this.SliderJoint=class extends t.Joint{constructor(t,i){super(...arguments,"slider");let s=e.PrismaticJoint({lowerTranslation:-1,upperTranslation:1,enableLimit:!0,maxMotorForce:50,motorSpeed:0,enableMotor:!0},t.body,i.body,t.body.getWorldCenter(),new e.Vec2(1,0));this._createJoint(s),this._angle=0}get angle(){return this._angle}set angle(i){i!=this._angle&&(this._angle=i,this._j.m_localXAxisA=new e.Vec2(t.cos(i),t.sin(i)),this._j.m_localXAxisA.normalize(),this._j.m_localYAxisA=e.Vec2.crossNumVec2(1,this._j.m_localXAxisA))}get range(){return this.upperLimit-this.lowerLimit}set range(t){t/=2,this.upperLimit=t,this.lowerLimit=-t}get lowerLimit(){return this._j.getLowerLimit()/this.spriteA.tileSize*t.world.meterSize}set lowerLimit(e){this._j.isLimitEnabled()||this._j.enableLimit(!0),e=e*this.spriteA.tileSize/t.world.meterSize,this._j.setLimits(e,this._j.getUpperLimit())}get upperLimit(){return this._j.getUpperLimit()/this.spriteA.tileSize*t.world.meterSize}set upperLimit(e){this._j.isLimitEnabled()||this._j.enableLimit(!0),e=e*this.spriteA.tileSize/t.world.meterSize,this._j.setLimits(this._j.getLowerLimit(),e)}},t.PrismaticJoint=t.SliderJoint,this.RopeJoint=class extends t.Joint{constructor(t,i){super(...arguments,"rope");let s=e.RopeJoint({maxLength:1},t.body,i.body,t.body.getWorldCenter());this._createJoint(s),this._j.m_localAnchorB.x=0,this._j.m_localAnchorB.y=0}get maxLength(){return e=this._j.getMaxLength(),i=this.spriteA.tileSize,e/i*t.world.meterSize;var e,i}set maxLength(e){var i,s;this._j.setMaxLength((i=e,s=this.spriteA.tileSize,i*s/t.world.meterSize))}};class l{constructor(){let t=this;Object.defineProperties(this,{x:{get:()=>t._x,set(e){e!=t._x&&(t._x=e,t._avg=.5*(t._x+t._y))},configurable:!0,enumerable:!0},y:{get:()=>t._y,set(e){e!=t._y&&(t._y=e,t._avg=.5*(t._x+t._y))},configurable:!0,enumerable:!0},_x:{value:1,enumerable:!1,writable:!0},_y:{value:1,enumerable:!1,writable:!0},_avg:{value:1,enumerable:!1,writable:!0}})}valueOf(){return this._avg}}!function(){let t=new Float32Array(1),e=new Int32Array(t.buffer)}();function d(t){return!/^(?:(?:\/\*[^(?:\*\/)]*\*\/\s*)|(?:\/\/[^\r\n]*))*\s*(?:(?:(?:async\s(?:(?:\/\*[^(?:\*\/)]*\*\/\s*)|(?:\/\/[^\r\n]*))*\s*)?function|class)(?:\s|(?:(?:\/\*[^(?:\*\/)]*\*\/\s*)|(?:\/\/[^\r\n]*))*)|(?:[_$\w][\w0-9_$]*\s*(?:\/\*[^(?:\*\/)]*\*\/\s*)*\s*\()|(?:\[\s*(?:\/\*[^(?:\*\/)]*\*\/\s*)*\s*(?:(?:['][^']+['])|(?:["][^"]+["]))\s*(?:\/\*[^(?:\*\/)]*\*\/\s*)*\s*\]\())/.test(t.toString())}function p(t,e){let i=t,s=e.toLowerCase();if("triangle"==s?i=[i,-120,3]:"square"==s?i=[i,-90,4]:"pentagon"==s?i=[i,-72,5]:"hexagon"==s?i=[i,-60,6]:"septagon"==s?i=[i,-51.4285714286,7]:"octagon"==s?i=[i,-45,8]:"enneagon"==s?i=[i,-40,9]:"decagon"==s?i=[i,-36,10]:"hendecagon"==s?i=[i,-32.7272727273,11]:"dodecagon"==s&&(i=[i,-30,12]),i==t)throw new Error("Invalid, not a regular polygon: "+e);return i}if(t.p5play.palettes=[{a:"aqua",b:"black",c:"crimson",d:"darkviolet",e:"peachpuff",f:"olive",g:"green",h:"hotpink",i:"indigo",j:"navy",k:"khaki",l:"lime",m:"magenta",n:"brown",o:"orange",p:"pink",q:"turquoise",r:"red",s:"skyblue",t:"tan",u:"blue",v:"violet",w:"white",x:"gold",y:"yellow",z:"gray"}],this.colorPal=(e,i)=>{if(e instanceof p5.Color)return e;"number"==typeof i&&(i=t.p5play.palettes[i]),i??=t.p5play.palettes[0];let s=i[e];return s?t.color(s):t.color(0,0,0,0)},this.EmojiImage=function(e,i){t.push(),t.textSize(i);let s=t.createGraphics(i,1.25*i);s.textSize(i),s.textAlign(t.CENTER),s.text(e,i/2,i);let r=s.drawingContext,o=s._pixelDensity||1,h=s.canvas.width,n=s.canvas.height,a=r.getImageData(0,0,h,n).data,l=h,d=0,p=n,u=0,c=3;for(let t=0;td&&(d=e),tu&&(u=t)),c+=4;return p=Math.floor(p/o),u=Math.floor(u/o),l=Math.floor(l/o),d=Math.floor(d/o),s=s.get(l,p,d-l+1,u-p+1),t.pop(),s.url=e,s},this.spriteArt=(e,i,s)=>{i??=1,"number"==typeof s&&(s=t.p5play.palettes[s]),s??=t.p5play.palettes[0];let r=e;"string"==typeof e&&(r=(e=(e=(e=e.trim()).replace(/\r*\n\t+/g,"\n")).replace(/\s+$/g,"")).split("\n"));let o=0;for(let t of r)t.length>o&&(o=t.length);let h=r.length,n=t.createImage(o*i,h*i);n.loadPixels();for(let t=0;tnew Promise(t?e=>{setTimeout(e,t)}:requestAnimationFrame),this.sleep=e=>e?t.delay(e):new Promise((e=>{if(t.canvas.dispatchEvent){t.canvas.addEventListener("p5play_worldStepped",(function i(){t.canvas.removeEventListener("p5play_worldStepped",i),e()}))}else setTimeout(e,1e3*t.world._timeStep)})),this.play=t=>{if(!t?.play)throw new Error("Tried to play your sound but it wasn't a sound object.");return new Promise((e=>{t.play(),t.onended((()=>e()))}))},window.location){let e=location.hostname;switch(e){case"":case"127.0.0.1":case"localhost":case"p5play.org":case"editor.p5js.org":case"codepen.io":case"codera.app":case"aug4th.com":case"cdpn.io":case"glitch.com":case"replit.com":case"stackblitz.com":case"jsfiddle.net":case"aijs.io":case"preview-aijs.web.app":case"quinton-ashley.github.io":break;default:if(/^[\d\.]+$/.test(e)||e.endsWith("stackblitz.io")||e.endsWith("glitch.me")||e.endsWith("replit.dev")||e.endsWith("codehs.com")||e.endsWith("openprocessing.org")||location.origin.endsWith("preview.p5js.org"))break;!async function(){if(document.getElementById("p5play-intro"))return;t._incrementPreload();let e=document.createElement("div");e.id="p5play-intro",e.style="position: absolute; width: 100%; height: 100%; top: 0; left: 0; z-index: 1000; background-color: black;";let i=document.createElement("img");i.style="position: absolute; top: 50%; left: 50%; width: 80vmin; height: 40vmin; margin-left: -40vmin; margin-top: -20vmin; z-index: 1001; opacity: 1; scale: 1; transition: scale 1.5s, opacity 0.4s ease-in-out;",i.onerror=()=>{i.style.imageRendering="pixelated",i.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAABACAYAAADS1n9/AAABbGlDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAACiRfZC/S0JhGIWfm4VgNkQNDg13igYr0SCXBjWQIkisQG26Xn+C2sfVCKMtWkPoP8igOWgoIgxaGhqCqCGitqamgpaSL+69hS51lvfhcDgcXujxaEKUeoFypWbEo2E1kUypzhcUFCxpelWEYrEFk39vlxT4uLezt+Nm12u7uRvciV6Wj88XNx88k/wvVyZb1YEvwKcLowaKF4ht1ITJW8CwkUimQGmYnLf5wOS0zSdWZjkeAeUaUPWClgHlFfCmu/x8F5dL6/rPMnO9O1tZWTJ7gBFmKVJFUEKjjkqMwB/5KSsfYQ1BHYMieQrUUAkhrIYsKnNU0JnAi4ofH3785p/tuo+7n/95O972M8y0pJRnHW++BUfT4DrteGNBGOyHq1OhGZplOYCeXA7eDmEgCUM34Fqt5gJ+e707DH1PUr6PgnMP2g0pP/elbDfB8QgXlW8Y/mq9pjC8gwAABSxJREFUeJztnb9y2zAMxulcpnbNntfJ3D5n97xO966Z3aNP9NHgBxAgQVmO8bvLNZZIiCI+gH8kpyl4bk7P3gErOJ/PZ0+zp9NpmZ9CAM54O7+wSgQhAEdWOb+wQgSvzZHAj5+/50x9/WkOeRMZwIkm+medXyAi8M4CL82R4KkIATjQRL8nJJN4XysEsAKv9L8DIYAnJyaBk8CUTDLA51/bbP7jHWSQRZPByADeTDp/tM4ozT4AVHSwO1kEMBMY/dTLFNcMcN5oSgTHYHBi2fPrS4qo98Mh/a+C8/ErdyJYw8cbb/bzH/ncGQY8aOYAnpThZ4XGerZdrn209fxIe6rVQw52Oif4NquAfF+d+Y6NSeej9C9F/714WAHkyP5uoxcSCBKSic5WMhwCciTlcnUaRSmVRlw5x0UiVx6VqW1Ru1zbaHl6TXS9Efae3GmuNzpXYDMA7VT6OxKE9nhPKNy1ZlHbEdL/qPNRdHsy2i5WAIk41yt6emM1Jw5OcL12eg4VR1rWmRCGAVEAGjhncseLQ7SOebZV6t4TxWEBcFHHOayO7PoHUcpy/y5FSP+jWJ06KoKRDAUngZxDUXrVlOsdR0jX8vjsxaqI1dilG0ciWdjgHcN4GqgERdcR1/VayjwgBFDzQG/yJEaASKgSIYBnAgg8BKAARRWKvkcjDwMhgAKIjkcACREJlgOuAu5K7Qgwaz0KeQaOOn9vTCsBwLwApMiZdOBROpnj3u2bdX5aPQfwaOBuDIr1HveYryldl30wBO4RZ4AS1aXCbFr2skezTa5b2+7Z7Z2nNjZKh3Jja3HGHtlAcnwyOj+/HIIFUACd0TizbhzTQU1ddAzYg+WYY5d0TM5dXql6A2VzO7n0jUS6kTtXuseVQ4Im01icXxgfApgOuvy8pevPjD3VuRrhRpu29trG2GI7eWPFkKCJerZdzH2UV8NUAsiqR8pnG5YdJjjNZA+8aYvqIq6dQqNfC9N5YofvDNuO3HbQ/tNG+dwVQOmwS8QAg/kY26lABF17Aqq65DgSlSkzMR2ZpM53hmsve32mvehLIvIcoFyIaUB9vhZB3bBmbJ6cLJkfrb4PRj+FmSAeCsbxiXF+0mSAG5WhDtjSfT32S3TtUb6wsMS6Qkd4TtKQoI62b0FTPkW3EQQ6G908KgcB5aA9BKir4WFf59q4ZNneF0eYZ/4SUxtB4lg88rVoLnqEa7CAOqz9J0Y9Caw/N44FnX0zYQPHRXsI4RqQ0Zk/B1iNUB5RYKohgN4svNG8GiApCpbr2QN2uHN08nmBGSK4ttyLkd1D1TBgxGUV4F1OOk/PSWUTENsRqJ3ovo1M5gHo+4A13/YPRd4sS2c7V/m1795WMJvZlNvIUv1RTtzXw2mqncXbnsSSqCJwIuCua3GetX4zBBj+ntDlBCeCYGNg2Vo7UXIeR6nv9fSPE0EIoAdwfs095xis85NeAC/SyWDSCQLXJ6cT9T2Ajo+MQOhkgWTMBMh55iecPSxDQHBLEwCG7WfJkd13CYS6mvpXrJPAoKURQdILATnSkrKbjTJLugc7piGAQWZEkDS7dMIj5utWulQf2SNIzk8hgD6zIoBQRy36n0U0k/sQgAIogjT/Z9saHO1pV3YhACUuImCcNWRPsGVZ1ocAjEAh9JwmOAsyaG9kPycEMAAUQWIcp3CWt71gB84SP34JJ7Gzm0I1A/a0hGomsTigF6VWZ3pEfQjAAY3jLM7yticRAnAEOW7GUd72ECEAZ2qneTjL294NKaX/gKttC9Kft4MAAAAASUVORK5CYII="};let s=window._p5play_intro_image;""==s||s?.includes("made_with_p5play")?((s.includes("bit.")||s.includes("pixel"))&&(i.style.imageRendering="pixelated"),i.src=s):i.src="https://p5play.org/assets/made_with_p5play.webp",await new Promise((t=>i.onload=t)),e.append(i),document.body.append(e),await t.delay(),i.offsetHeight,i.style.scale=1.2,await t.delay(1100),i.style.opacity=0,await t.delay(400),e.style.display="none",e.remove(),document.getElementById("p5play-intro")?.remove(),t._decrementPreload()}()}}let u=p5.disableFriendlyErrors;p5.disableFriendlyErrors=!0;const c=t.createCanvas;this.createCanvas=function(){let e,i,s,r=[...arguments];if("string"==typeof r[0])if(r[0].includes(":")){let t=r[0].split(":"),i=Number(t[0]),s=Number(t[1]),o=window.innerWidth,h=window.innerWidth*(s/i);h>window.innerHeight&&(o=window.innerHeight*(i/s),h=window.innerHeight),r[0]=Math.round(o),r.splice(1,0,Math.round(h)),e="fullscreen"}else r=[0,0,...r];if(r[0]||(r[0]=window.innerWidth,r[1]=window.innerHeight,e="fullscreen"),"string"==typeof r[2]){let t=r[2].toLowerCase().split(" ");"pixelated"==t[0]?(i="pixelated",t[1]?(e="centered",s=Number(t[1].slice(1))):e="fullscreen",r.splice(2,1)):"fullscreen"==t[0]&&(e="fullscreen",r.splice(2,1))}let o=c.call(t,...r);t.ctx=t.drawingContext;let h=o.canvas||o;return o.GL&&(h.renderer="webgl"),"webgpu"!=h.renderer&&(h.renderer="2d"),h.tabIndex=0,h.w=r[0],h.h=r[1],h.addEventListener&&(h.addEventListener("keydown",(function(t){" "!=t.key&&"/"!=t.key&&"ArrowUp"!=t.key&&"ArrowDown"!=t.key&&"ArrowLeft"!=t.key&&"ArrowRight"!=t.key||t.preventDefault()})),h.addEventListener("mouseover",(()=>{this.mouse.isOnCanvas=!0,this.mouse.isActive=!0})),h.addEventListener("mouseleave",(()=>{this.mouse.isOnCanvas=!1})),h.addEventListener("touchstart",(t=>t.preventDefault())),h.addEventListener("contextmenu",(t=>t.preventDefault()))),h.save??=t.saveCanvas.bind(t),h.resize??=t.resizeCanvas.bind(t),h.hw=.5*h.w,h.hh=.5*h.h,h.mouse={x:t.mouseX,y:t.mouseY},"2d"==h.renderer?(t.camera.x=t.camera.ogX=h.hw,t.camera.y=t.camera.ogY=h.hh):(t.camera.x=0,t.camera.y=0,"webgl"==h.renderer&&(t._textCache=!1),t.p5play._renderStats={x:10-h.hw,y:20-h.hh}),u||(p5.disableFriendlyErrors=!1),t.displayMode(e,i,s),o},this.Canvas=class{constructor(t,e,i,s){this.w,this.width,this.h,this.height,this.hw,this.hh,this.mouse}resize(){}save(){}},this.canvas=t.canvas,t.Canvas=function(){return t.createCanvas(...arguments).canvas};const _=t.resizeCanvas;this.resizeCanvas=(e,i)=>{e??=window.innerWidth,i??=window.innerHeight,_.call(t,e,i);let s=t.canvas;s.w=s.width/t.pixelDensity(),s.h=s.height/t.pixelDensity(),s.hw=.5*s.w,s.hh=.5*s.h,s.fullscreen&&(s.w/s.h>window.innerWidth/window.innerHeight?(s.style.width="100%!important",s.style.height="auto!important"):(s.style.width="auto!important",s.style.height="100%!important")),"2d"==s.renderer?(t.camera.x=s.hw,t.camera.y=s.hh):(t.camera.x=0,t.camera.y=0)};const g=t.frameRate;this.frameRate=function(e){let i=g.call(t,e);return e&&t.world._updateTimeStep(),i};const f=t.background;this.background=function(){let e=arguments;1==e.length&&1==e[0]?.length?f.call(t,t.colorPal(e[0])):f.call(t,...e)};const m=t.fill;this.fill=function(){let e=arguments;1==e.length&&1==e[0]?.length?m.call(t,t.colorPal(e[0])):m.call(t,...e)};const y=t.stroke;this.stroke=function(){let e=arguments;1==e.length&&1==e[0]?.length?y.call(t,t.colorPal(e[0])):y.call(t,...e)};const w=t.loadImage;this.loadImage=this.loadImg=function(){if(t.p5play.disableImages)return t._decrementPreload(),{w:16,width:16,h:16,height:16,pixels:[]};let e,i=arguments,s=i[0],r=t.p5play.images[s];if("function"==typeof i[i.length-1]&&(e=i[i.length-1]),r)return 1==r.width&&1==r.height||!r.pixels.length?e?(r.cbs.push(e),r.calls++):t._decrementPreload():(e&&e(),t._decrementPreload()),r;return r=w.call(t,s,(e=>{e.w||(Object.defineProperty(e,"w",{get:function(){return this.width}}),Object.defineProperty(e,"h",{get:function(){return this.height}}));for(let t of e.cbs)t(e);for(let i=1;i\nhtml, body {\n\tmargin: 0;\n\tpadding: 0;\n}\n.p5Canvas {\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.p5-pixelated {\n\timage-rendering: pixelated;\n\tfont-smooth: never;\n\t-webkit-font-smoothing: none;\n}\n.p5-centered,\n.p5-maxed,\n.p5-fullscreen {\n display: flex;\n\talign-items: center;\n\tjustify-content: center;\n}\nmain.p5-centered,\nmain.p5-maxed,\n.p5-fullscreen {\n\theight: 100vh;\n}\nmain {\n\toverscroll-behavior: none;\n}\n"),t._adjustDisplay=()=>{let e=t.canvas,i=e.style,s=e.parentElement;i&&s&&e.displayMode&&("pixelated"==e.renderQuality&&(e.classList.add("p5-pixelated"),t.pixelDensity(1),t.noSmooth&&t.noSmooth(),t.textFont&&t.textFont("monospace")),"normal"==e.displayMode?(s.classList.remove("p5-centered","p5-maxed","p5-fullscreen"),i.width=e.w*e.displayScale+"px",i.height=e.h*e.displayScale+"px"):(s.classList.add("p5-"+e.displayMode),s=s.getBoundingClientRect(),e.w/e.h>s.width/s.height?("centered"==e.displayMode?(i.width=e.w*e.displayScale+"px",i.maxWidth="100%"):i.width="100%",i.height="auto",i.maxHeight=""):(i.width="auto",i.maxWidth="","centered"==e.displayMode?(i.height=e.h*e.displayScale+"px",i.maxHeight="100%"):i.height="100%")))},t.displayMode=(e="normal",i="default",s=1)=>{let r=t.canvas;"string"==typeof s&&(s=parseFloat(s.slice(1))),Object.assign(r,{displayMode:e,renderQuality:i,displayScale:s}),t._adjustDisplay()});let x={generic:["Ah! I found an error","Oh no! Something went wrong","Oof! Something went wrong","Houston, we have a problem","Whoops, having trouble here"],Sprite:{constructor:{base:"Sorry I'm unable to make a new Sprite",0:"What is $0 for? If you're trying to specify the x position of the sprite, please specify the y position as well.",1:"If you're trying to specify points for a chain Sprite, please use an array of position arrays.\n$0",2:"Invalid input parameters: $0"},hw:{0:"I can't change the halfWidth of a Sprite directly, change the sprite's width instead."},hh:{1:"I can't change the halfHeight of a Sprite directly, change the sprite's height instead."},rotate:{0:"Can't use this function on a sprite with a static collider, try changing the sprite's collider type to kinematic.",1:'Can\'t use "$0" for the angle of rotation, it must be a number.'},rotateTo:{},rotateMinTo:{},rotateTowards:{},changeAnimation:'I can\'t find any animation named "$0".',collide:{0:"I can't make that sprite collide with $0. Sprites can only collide with another sprite or a group.",1:"The collision callback has to be a function.",2:"You're trying to check for an collision with a sprite or group that doesn't exist!"},overlap:{0:"I can't make that sprite overlap with $0. Sprites can only overlap with another sprite or a group.",1:"The overlap callback has to be a function.",2:"You're trying to check for an overlap with a sprite or group that doesn't exist!"}},SpriteAnimation:{constructor:{base:"Hey so, I tried to make a new SpriteAnimation but couldn't",1:"The name of the animation must be the first input parameter."},frame:"Index $0 out of bounds. That means there is no frame $0 in this animation. It only has $1 frames!"},Group:{constructor:{base:"Hmm awkward! Well it seems I can't make that new Group you wanted"}}};x.Group.collide=x.Sprite.collide,x.Group.overlap=x.Sprite.overlap,x.Sprite.rotateTo[0]=x.Sprite.rotateMinTo[0]=x.Sprite.rotateTowards[0]=x.Sprite.rotate[0];class b extends Error{constructor(t,e,i){super(),"string"!=typeof t&&(i=e,e=t,t=(t=this.stack.match(/\n\s*at ([^\(]*)/)[1]).slice(0,-1)),"number"!=typeof e&&(i=e,e=void 0),"new"==t.slice(0,3)&&(t=t.slice(4));let s=(t=t.split("."))[0];t=t[1]||"constructor";let r=this.stack.match(/\/([^p\/][^5][^\/:]*:[^\/:]+):/);r&&(r=r[1].split(":"),r=" in "+r[0]+" at line "+r[1]),r=" using "+s+"."+t+". ",i=i||[];let o,h=x[s][t];o=h.base?h.base+r:x.generic[Math.floor(Math.random()*x.generic.length)]+r,void 0!==e&&(h=h[e]),h&&(h=h.replace(/\$([0-9]+)/g,((t,e)=>i[e])),o+=h),p5._friendlyError(o,t)}}this.allSprites=new t.Group,this.world=new t.World,this.camera=new t.Camera,this.InputDevice=class{constructor(){this.holdThreshold=12,this._default=0}_ac(t){return t}presses(t){return t??=this._default,void 0===this[t]&&(t=this._ac(t)),1==this[t]||-3==this[t]}pressing(t){return t??=this._default,void 0===this[t]&&(t=this._ac(t)),-3==this[t]?1:this[t]>0?this[t]:0}pressed(t){return this.released(t)}holds(t){return t??=this._default,void 0===this[t]&&(t=this._ac(t)),this[t]==this.holdThreshold}holding(t){return t??=this._default,void 0===this[t]&&(t=this._ac(t)),this[t]>=this.holdThreshold?this[t]:0}held(t){return t??=this._default,void 0===this[t]&&(t=this._ac(t)),-2==this[t]}released(t){return t??=this._default,void 0===this[t]&&(t=this._ac(t)),this[t]<=-1}releases(t){return this.released(t)}},this._Mouse=class extends t.InputDevice{constructor(){super(),this._default="left";let e=this;this._pos=t.createVector.call(t),Object.defineProperty(this._pos,"x",{get:()=>e.x,set(t){e.x=t}}),Object.defineProperty(this._pos,"y",{get:()=>e.y,set(t){e.y=t}}),this.x=0,this.y=0,this.canvasPos={},this.left=0,this.center=0,this.right=0,this.drag={left:0,center:0,right:0},this._dragFrame={left:!1,center:!1,right:!1},this.isOnCanvas=!1,this.isActive=!1,this._visible=!0,this._cursor="default",this._ogX=0,this._ogY=0}_ac(t){return"left"==(t=t.toLowerCase()).slice(0,4)?t="left":"right"==t.slice(0,5)?t="right":"middle"==t.slice(0,6)&&(t="center"),t}_update(){t.mouse.canvasPos.x=t.mouseX,t.mouse.canvasPos.y=t.mouseY,t.camera.x==t.camera.ogX&&t.camera.y==t.camera.ogY&&1==t.camera.zoom?(this.x=t.mouseX,this.y=t.mouseY):"webgpu"!=t.canvas.renderer?(this.x=(t.mouseX-t.canvas.hw)/t.camera.zoom+t.camera.x,this.y=(t.mouseY-t.canvas.hh)/t.camera.zoom+t.camera.y):(this.x=t.mouseX/t.camera.zoom+t.camera.x,this.y=t.mouseY/t.camera.zoom+t.camera.y)}get pos(){return this._pos}get position(){return this._pos}get cursor(){return t.canvas.style.cursor}set cursor(e){e!=this._cursor&&(t.cursor(e),this._cursor=e)}get visible(){return this._visible}set visible(e){this._visible=e,t.canvas.style.cursor=e?"default":"none"}drags(t){return t??=this._default,1==this.drag[t]}dragging(t){return t??=this._default,this.drag[t]>0?this.drag[t]:0}dragged(t){return t??=this._default,this.drag[t]<=-1}},this.mouse=new t._Mouse,this._SpriteMouse=class extends t._Mouse{constructor(){super(),delete this.canvasPos,this.hover=0}hovers(){return 1==this.hover}hovering(){return this.hover>0?this.hover:0}hovered(){return this.hover<=-1}};const S=function(e){if(t.mouse.isActive=!0,t.mouse[e]++,t.world.mouseSprites.length){let i=t.world.mouseSprite?.mouse;i&&(i[e]=0,i.hover=0,i.drag[e]=0),ms=t.world.mouseSprites[0],t.world.mouseSprite=ms,i=ms.mouse,i[e]=1,i.hover<=0&&(i.hover=1)}},A=t._onmousedown;t._onmousedown=function(e){if(!t._setupDone)return;let i="left";1===e.button?i="center":2===e.button&&(i="right"),S.call(t,i),A.call(t,e)};const C=function(e){let i=t.mouse;i[e]>0&&(i._dragFrame[e]=!0)},k=t._onmousemove;t._onmousemove=function(e){if(!t._setupDone)return;let i="left";1===e.button?i="center":2===e.button&&(i="right"),C.call(t,i),k.call(t,e)};const M=function(e){let i=t.mouse;i[e]>=i.holdThreshold?i[e]=-2:i[e]>1?i[e]=-1:i[e]=-3,i.drag[e]>0&&(i.drag[e]=-1);let s=t.world.mouseSprite?.mouse;s&&(s.hover>1?(s[e]>=t.mouse.holdThreshold?s[e]=-2:s[e]>1?s[e]=-1:s[e]=-3,s.drag[e]>0&&(s.drag[e]=-1)):(s[e]=0,s.drag[e]=0))},z=t._onmouseup;if(t._onmouseup=function(e){if(!t._setupDone)return;let i="left";1===e.button?i="center":2===e.button&&(i="right"),M.call(t,i),z.call(t,e)},this._Touch=class extends t.InputDevice{constructor(e){super(),this.x,this.y,this.id=e.identifier,this._default="duration",this.holdThreshold=t.touches.holdThreshold,this.duration=1,this.drag=0,this._dragFrame=!1,this.canvasPos={},this._update(e)}_update(e){let i=t.canvas;const s=i.getBoundingClientRect(),r=i.scrollWidth/i.w||1,o=i.scrollHeight/i.h||1,h=this.canvasPos.x=(e.clientX-s.left)/r,n=this.canvasPos.y=(e.clientY-s.top)/o;t.camera.x==i.hw&&t.camera.y==i.hh&&1==t.camera.zoom?(this.x=h,this.y=n):(this.x=(h-i.hw)/t.camera.zoom+t.camera.x,this.y=(n-i.hh)/t.camera.zoom+t.camera.y),this.force=e.force}},this.touches=[],t.touches.holdThreshold=12,t._ontouchstart=function(e){if(t._setupDone){t.getAudioContext&&"suspended"==t.getAudioContext()?.state&&t.userStartAudio();for(let i of e.changedTouches)t.touches.push(new t._Touch(i)),1==t.touches.length&&(t.mouseX=t.touches[0].x,t.mouseY=t.touches[0].y,t.mouse._update(),t.world.mouseSprites=t.world.getMouseSprites(),t._onmousedown(e));t.touchStarted&&!t.touchStarted(e)&&e.preventDefault()}},t._ontouchmove=function(e){if(t._setupDone){for(let i of e.changedTouches){let s=t.touches.find((t=>t.id==i.identifier));s._update(i),s._dragFrame=!0,s.id==t.touches[0].id&&(t.mouseX=t.touches[0].x,t.mouseY=t.touches[0].y,t.mouse._update(),t._onmousemove(e))}t.touchMoved&&!t.touchMoved(e)&&e.preventDefault()}},t._ontouchend=function(e){if(t._setupDone){for(let i of e.changedTouches){let s=t.touches.find((t=>t.id==i.identifier));s._update(i),s.duration>=s.holdThreshold?s.duration=-2:s.duration>1?s.duration=-1:s.duration=-3,s.drag>0&&(s.drag=-1),s.id==t.touches[0].id&&(t.mouseX=t.touches[0].x,t.mouseY=t.touches[0].y,t.mouse._update(),t._onmouseup(e))}t.touchEnded&&!t.touchEnded(e)&&e.preventDefault()}},this._Keyboard=class extends t.InputDevice{constructor(){super(),this._default=" ",this.alt=0,this.arrowUp=0,this.arrowDown=0,this.arrowLeft=0,this.arrowRight=0,this.backspace=0,this.capsLock=0,this.control=0,this.enter=0,this.meta=0,this.shift=0,this.tab=0;let t=this._simpleKeyControls={arrowUp:"up",arrowDown:"down",arrowLeft:"left",arrowRight:"right"};t.w=t.W="up",t.s=t.S="down",t.a=t.A="left",t.d=t.D="right",t.i=t.I="up2",t.k=t.K="down2",t.j=t.J="left2",t.l=t.L="right2"}get visible(){return this._inp==document.activeElement}set visible(t){this._inp||(this._inp=Object.assign(document.createElement("input"),{type:"text",style:"position: fixed; height: 0; padding: 0; border: none; opacity: 0.0001; pointer-events: none;"}),document.body.appendChild(this._inp)),this._visible=t,t?this._inp.focus():this._inp.blur()}_ac(t){if(1!=t.length){if(!isNaN(t)){if(38==t)return"arrowUp";if(40==t)return"arrowDown";if(37==t)return"arrowLeft";if(39==t)return"arrowRight";if(t>=10)throw new Error("Use key names with the keyboard input functions, not keyCode numbers!");return t}t=t.replaceAll(/[ _-]/g,"")}if(1!=(t=t.toLowerCase()).length){if("arrowup"==t)return"arrowUp";if("arrowdown"==t)return"arrowDown";if("arrowleft"==t)return"arrowLeft";if("arrowright"==t)return"arrowRight";if("capslock"==t)return"capsLock"}return t}_pre(t){(!this[t]||this[t]<0)&&(this[t]=1)}_rel(t){this[t]>=this.holdThreshold?this[t]=-2:this[t]>1?this[t]=-1:this[t]=-3}get cmd(){return this.meta}get command(){return this.meta}get ctrl(){return this.control}get space(){return this[" "]}get spacebar(){return this[" "]}get opt(){return this.alt}get option(){return this.alt}get win(){return this.meta}get windows(){return this.meta}},this.kb=new t._Keyboard,this.keyboard=t.kb,"object"==typeof navigator&&navigator.keyboard){const e=navigator.keyboard;window==window.top?e.getLayoutMap().then((e=>{"w"!=e.get("KeyW")&&(t.p5play.standardizeKeyboard=!0)})):t.p5play.standardizeKeyboard=!0}else t.p5play.standardizeKeyboard=!0;function T(t){let e=t.code;return 4==e.length&&"Key"==e.slice(0,3)?e[3].toLowerCase():t.key}const j=t._onkeydown;t._onkeydown=function(t){let e=t.key;if(this.p5play.standardizeKeyboard&&(e=T(t)),e.length>1)e=e[0].toLowerCase()+e.slice(1);else{let t=e.toLowerCase(),i=e.toUpperCase();t!=i&&(e!=i?this.kb._pre(i):this.kb._pre(t))}this.kb._pre(e);let i=this.kb._simpleKeyControls[e];i&&this.kb._pre(i),j.call(this,t)};const O=t._onkeyup;t._onkeyup=function(t){let e=t.key;if(this.p5play.standardizeKeyboard&&(e=T(t)),e.length>1)e=e[0].toLowerCase()+e.slice(1);else{let t=e.toLowerCase(),i=e.toUpperCase();t!=i&&(e!=i?this.kb._rel(i):this.kb._rel(t))}this.kb._rel(e);let i=this.kb._simpleKeyControls[e];if(i&&this.kb._rel(i),t.shiftKey){let t=e.toLowerCase();this.kb[t]>0&&this.kb._rel(t)}O.call(this,t)},this.Contro=class extends t.InputDevice{constructor(t){super(),this._default="a",this.connected=!0,this.a=0,this.b=0,this.x=0,this.y=0,this.l=0,this.r=0,this.lt=0,this.rt=0,this.select=0,this.start=0,this.lsb=0,this.rsb=0,this.up=0,this.down=0,this.left=0,this.right=0,this.leftStick={x:0,y:0},this.rightStick={x:0,y:0},this.leftTrigger=0,this.rightTrigger=0,this.buttonMapping={a:0,b:1,x:2,y:3,l:4,r:5,lt:6,rt:7,select:8,start:9,lsb:10,rsb:11,up:12,down:13,left:14,right:15},this.axeMapping={leftStick:{x:0,y:1},rightStick:{x:2,y:3},leftTrigger:4,rightTrigger:5},this.isMock=!1,"string"!=typeof t?(this.gamepad=t,this.id=t.id):(this.gamepad={},this.id=t,this.isMock=!0),this._axeTriggers=this.gamepad.axes&&void 0!==this.gamepad.axes[this.axeMapping.leftTrigger],this.hasAnalogTriggers=this._axeTriggers||void 0,this.id.includes("GuliKit")&&(this.buttonMapping.a=1,this.buttonMapping.b=0,this.buttonMapping.x=3,this.buttonMapping.y=2)}_ac(t){return"lb"==(t=t.toLowerCase())?t="l":"rb"==t?t="r":"leftstickbutton"==t?t="lsb":"rightstickbutton"==t&&(t="rsb"),t}_update(){if(this.isMock)return;if(this.gamepad=navigator.getGamepads()[this.gamepad.index],!this.gamepad?.connected)return;let t=this.gamepad;for(let e in this.buttonMapping){let i=this.buttonMapping[e],s=t.buttons[i];s&&(s.pressed?this[e]++:this[e]=this[e]>0?-1:0)}return this.leftStick.x=t.axes[this.axeMapping.leftStick.x],this.leftStick.y=t.axes[this.axeMapping.leftStick.y],this.rightStick.x=t.axes[this.axeMapping.rightStick.x],this.rightStick.y=t.axes[this.axeMapping.rightStick.y],this._axeTriggers?(this.leftTrigger=t.axes[this.axeMapping.leftTrigger],this.rightTrigger=t.axes[this.axeMapping.rightTrigger]):(this.leftTrigger=t.buttons[this.buttonMapping.lt].value,this.rightTrigger=t.buttons[this.buttonMapping.rt].value,void 0===this.hasAnalogTriggers&&(this.leftTrigger||this.rightTrigger)&&(this.hasAnalogTriggers=!Number.isInteger(this.leftTrigger)||!Number.isInteger(this.rightTrigger))),!0}_reset(){for(let t in this.buttonMapping)this[t]=0;this.leftStick.x=0,this.leftStick.y=0,this.rightStick.x=0,this.rightStick.y=0,this.leftTrigger=0,this.rightTrigger=0}get cross(){return this.a}get circle(){return this.b}get square(){return this.x}get triangle(){return this.y}get ls(){return this.leftStick}get rs(){return this.rightStick}get lb(){return this.l}get rb(){return this.r}get l1(){return this.l}get r1(){return this.r}get zl(){return this.lt}get zr(){return this.rt}get l2(){return this.leftTrigger}get r2(){return this.rightTrigger}get leftStickButton(){return this.lsb}get rightStickButton(){return this.rsb}get l3(){return this.lsb}get r3(){return this.rsb}},this._Contros=class extends Array{constructor(){if(super(),window&&(window.addEventListener("gamepadconnected",(t=>{this._onConnect(t.gamepad)})),window.addEventListener("gamepaddisconnected",(t=>{this._onDisconnect(t.gamepad)}))),"object"!=typeof navigator||!navigator.getGamepads)return;let t=navigator.getGamepads();for(let e of t)e&&this._onConnect(e)}swap(e,i){let s=this[e];this[e]=this[i],this[i]=s,0!=e&&0!=i||(t.contro=this[0],!t._q5&&t._isGlobal&&(window.contro=this[0]))}remove(t){this[t]=null}onConnect(t){return!0}onDisconnect(t){return!1}_onConnect(e){if(e){for(let t=0;tt.p5play._fps,this.renderStats=(t,e)=>{console.error("p5play: renderStats() function is deprecated. Use `p5play.renderStats = true` instead.")}})),p5.prototype.registerMethod("pre",(function(){const t=this;t._q5||(t.p5play._preDrawFrameTime=performance.now()),t.p5play.spritesDrawn=0,t.mouse._update(),t.contros._update()})),p5.prototype.registerMethod("post",(function(){const t=this;if(t.p5play._inPostDraw=!0,t.allSprites.autoCull&&t.allSprites.cull(1e4),t.allSprites._autoDraw&&(t.camera.on(),t.allSprites.draw(),t.camera.off()),t.allSprites._autoDraw??=!0,t.p5play.renderStats){let e=t.p5play._renderStats;if(e.fontSize||(1==t.allSprites.tileSize||t.allSprites.tileSize>16?e.fontSize=16:e.fontSize=10,e.gap=1.25*e.fontSize),!t.p5play._fpsAvg||t.frameCount%20==0){let e=0,i=t.p5play._fpsArr.length;for(let s=0;s55?t.color(30,255,30):r>25?t.color(255,100,30):t.color(255,30,30),t.p5play._statsColor=s}t.p5play._fpsArr.push(t.getFPS()),t.push(),t.fill(0,0,0,128),t.rect(e.x-5,e.y-e.fontSize,8.5*e.fontSize,5*e.gap+5),t.fill(t.p5play._statsColor),t.textAlign("left"),t.textSize(e.fontSize),e.font&&t.textFont(e.font);let i=e.x,s=e.y;t.text("sprites: "+t.p5play.spritesDrawn,i,s),t.text("display: "+Math.round(t.frameRate())+"hz",i,s+e.gap),t.text("fps avg: "+t.p5play._fpsAvg,i,s+2*e.gap),t.text("fps min: "+t.p5play._fpsMin,i,s+3*e.gap),t.text("fps max: "+t.p5play._fpsMax,i,s+4*e.gap),t.pop(),e.show=!1}t.world.autoStep&&t.world.timeScale>0&&t.world.step(),t.world.autoStep??=!0,t.allSprites._autoUpdate&&t.allSprites.update(),t.allSprites._autoUpdate??=!0;for(let e of t.allSprites)e.autoDraw??=!0,e.autoUpdate??=!0;for(let e in t.kb)"holdThreshold"!=e&&(t.kb[e]<0?t.kb[e]=0:t.kb[e]>0&&t.kb[e]++);for(let e=0;e0&&e[t]++,i?.hover&&(i[t]=e[t]),e._dragFrame[t]?(e.drag[t]++,i&&(i.drag[t]=e.drag[t]),e._dragFrame[t]=!1):e.drag[t]<0&&(e.drag[t]=0,i&&(i.drag[t]=0));if(t.world.mouseTracking&&t.mouse.isActive){let s=t.world.getMouseSprites();for(let t=0;t0?e.mouse.hover=-1:e.mouse.hover<0&&(e.mouse.hover=0)}e.left<=0&&e.center<=0&&e.right<=0&&(t.world.mouseSprite=null);let r=t.world.mouseSprite,o=e.drag.left>0||e.drag.center>0||e.drag.right>0;for(let e of t.world.mouseSprites)if(!s.includes(e)){let i=e.mouse;i.hover>0&&(i.hover=-1,i.left=i.center=i.right=0),o||e!=r||(t.world.mouseSprite=r=null)}r&&(s.includes(r)||s.push(r),i.x=r.x-e.x,i.y=r.y-e.y),t.world.mouseSprites=s}t.camera.off(),t._q5||(t.p5play._postDrawFrameTime=performance.now(),t.p5play._fps=Math.round(1e3/(t.p5play._postDrawFrameTime-t.p5play._preDrawFrameTime))||1),t.p5play._inPostDraw=!1})); diff --git a/v3/q5.js b/v3/q5.js index 475955ea..ec96d2c5 100644 --- a/v3/q5.js +++ b/v3/q5.js @@ -1,6 +1,6 @@ /** * q5.js - * @version 2.8 + * @version 2.9 * @author quinton-ashley, Tezumie, and LingDong- * @license LGPL-3.0 * @class Q5 @@ -290,6 +290,13 @@ if (Q5._nodejs) global.p5 ??= global.Q5 = Q5; else 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); + } +} + if (typeof document == 'object') { document.addEventListener('DOMContentLoaded', () => { if (!Q5._hasGlobal) new Q5('auto'); @@ -486,6 +493,8 @@ Q5.modules.canvas = ($, q) => { c.h = h = Math.ceil(h); c.hw = w / 2; c.hh = h / 2; + + // changes the actual size of the canvas c.width = Math.ceil(w * $._pixelDensity); c.height = Math.ceil(h * $._pixelDensity); @@ -498,6 +507,17 @@ Q5.modules.canvas = ($, q) => { else $._adjustDisplay(); }; + $._setImageSize = (w, h) => { + q.width = c.w = w; + q.height = c.h = h; + c.hw = w / 2; + c.hh = h / 2; + + // changes the actual size of the canvas + c.width = Math.ceil(w * $._pixelDensity); + c.height = Math.ceil(h * $._pixelDensity); + }; + if ($._scope == 'image') return; if (c && $._scope != 'graphics') { @@ -552,6 +572,12 @@ Q5.modules.canvas = ($, q) => { return v; }; + $.defaultImageScale = (scale) => { + if (!scale) return $._defaultImageScale; + return ($._defaultImageScale = scale); + }; + $.defaultImageScale(0.5); + $.flexibleCanvas = (unit = 400) => { if (unit) { $._da = c.width / (unit * $._pixelDensity); @@ -705,6 +731,10 @@ Q5.renderers.q2d.canvas = ($, q) => { $.ctx.rotate(r); }; $.scale = (x, y) => { + if (x.x) { + y = x.y; + x = x.x; + } y ??= x; $.ctx.scale(x, y); }; @@ -1221,9 +1251,15 @@ Q5.renderers.q2d.image = ($, q) => { opt = typeof last == 'object' ? last : null; let g = $.createImage(1, 1, opt); + let pd = (g._pixelDensity = opt?.pixelDensity || 1); function loaded(img) { - g.resize(img.naturalWidth || img.width, img.naturalHeight || img.height); + g.canvas.defaultWidth = img.width * $._defaultImageScale; + g.canvas.defaultHeight = img.height * $._defaultImageScale; + g.naturalWidth = img.naturalWidth; + g.naturalHeight = img.naturalHeight; + g._setImageSize(Math.ceil(g.naturalWidth / pd), Math.ceil(g.naturalHeight / pd)); + g.ctx.drawImage(img, 0, 0); q._preloadCount--; if (cb) cb(g); @@ -1240,7 +1276,7 @@ Q5.renderers.q2d.image = ($, q) => { let img = new window.Image(); img.src = url; img.crossOrigin = 'Anonymous'; - img._pixelDensity = 1; + img._pixelDensity = pd; img.onload = () => loaded(img); img.onerror = (e) => { q._preloadCount--; @@ -1257,8 +1293,9 @@ Q5.renderers.q2d.image = ($, q) => { if (Q5._createNodeJSCanvas) { drawable = drawable.context.canvas; } - dw ??= img.width || img.videoWidth; - dh ??= img.height || img.videoHeight; + + dw ??= drawable.defaultWidth || drawable.width || img.videoWidth; + dh ??= drawable.defaultHeight || drawable.height || img.videoHeight; if ($._imageMode == 'center') { dx -= dw * 0.5; dy -= dh * 0.5; @@ -1319,15 +1356,16 @@ Q5.renderers.q2d.image = ($, q) => { if ($._scope == 'image') { $.resize = (w, h) => { - let o = new $._OffscreenCanvas($.canvas.width, $.canvas.height); + let c = $.canvas; + let o = new $._OffscreenCanvas(c.width, c.height); let tmpCtx = o.getContext('2d', { - colorSpace: $.canvas.colorSpace + colorSpace: c.colorSpace }); - tmpCtx.drawImage($.canvas, 0, 0); - $._setCanvasSize(w, h); + tmpCtx.drawImage(c, 0, 0); + $._setImageSize(w, h); - $.ctx.clearRect(0, 0, $.canvas.width, $.canvas.height); - $.ctx.drawImage(o, 0, 0, $.canvas.width, $.canvas.height); + $.ctx.clearRect(0, 0, c.width, c.height); + $.ctx.drawImage(o, 0, 0, c.width, c.height); }; } @@ -1724,8 +1762,9 @@ Q5.modules.ai = ($) => { } while (stackLines[idx].indexOf('q5') >= 0) idx++; - let parts = stackLines[idx].split(sep).at(-1); - parts = parts.split(':'); + 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[3] = parts[3].split(')')[0]; @@ -2088,7 +2127,7 @@ main { if ($.noSmooth) $.noSmooth(); if ($.textFont) $.textFont('monospace'); } - if (c.displayMode == 'normal') { + 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'; @@ -2113,7 +2152,7 @@ main { } }; - $.displayMode = (displayMode = 'normal', renderQuality = 'default', displayScale = 1) => { + $.displayMode = (displayMode = 'normal', renderQuality = 'smooth', displayScale = 1) => { if (typeof displayScale == 'string') { displayScale = parseFloat(displayScale.slice(1)); } @@ -3832,21 +3871,40 @@ fn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f { if ($._doStroke) { ci = $._strokeIndex; - // outer rectangle coordinates + // stroke weight adjustment let sw = $._strokeWeight / 2; - let to = t + sw, - bo = b - sw, - lo = l - sw, - ro = r + sw; - - // stroke is simply a bigger rectangle drawn first - addRect(lo, to, ro, to, ro, bo, lo, bo, ci, ti); - // inner rectangle coordinates - t -= sw; - b += sw; - l += sw; - r -= sw; + if ($._doFill) { + // existing behavior: draw stroke as one big rectangle + let to = t + sw, + bo = b - sw, + lo = l - sw, + ro = r + sw; + + // draw stroke rectangle + addRect(lo, to, ro, to, ro, bo, lo, bo, ci, ti); + + // adjust inner rectangle coordinates + t -= sw; + b += sw; + l += sw; + r -= sw; + } else { + // new behavior: draw stroke as four rectangles (sides) + 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); // top + addRect(lsw, bsw, rsw, bsw, rsw, bpsw, lsw, bpsw, ci, ti); // bottom + addRect(lsw, tsw, lpsw, tsw, lpsw, bsw, lsw, bsw, ci, ti); // left + addRect(rpsw, tsw, rsw, tsw, rsw, bsw, rpsw, bsw, ci, ti); // right + } } if ($._doFill) { @@ -4195,7 +4253,6 @@ fn fragmentMain(@location(0) texCoord: vec2f) -> @location(0) vec4f { { texture, colorSpace: $.canvas.colorSpace - // premultipliedAlpha: true }, textureSize ); @@ -4227,6 +4284,11 @@ fn fragmentMain(@location(0) texCoord: vec2f) -> @location(0) vec4f { const img = new Image(); img.crossOrigin = 'Anonymous'; img.onload = () => { + // calculate the default width and height that the image + // should be drawn at if the user doesn't specify a display size + img.defaultWidth = img.width * $._defaultImageScale; + img.defaultHeight = img.height * $._defaultImageScale; + $._createTexture(img); q._preloadCount--; }; @@ -4243,8 +4305,8 @@ fn fragmentMain(@location(0) texCoord: vec2f) -> @location(0) vec4f { if ($._matrixDirty) $._saveMatrix(); let ti = $._transformIndex; - w ??= img.width / $._pixelDensity; - h ??= img.height / $._pixelDensity; + w ??= img.defaultWidth; + h ??= img.defaultHeight; let [l, r, t, b] = $._calcBox(x, y, w, h, $._imageMode); diff --git a/v3/q5.min.js b/v3/q5.min.js index 89c9be11..b16727c2 100644 --- a/v3/q5.min.js +++ b/v3/q5.min.js @@ -1,8 +1,8 @@ /** * q5.js - * @version 2.8 + * @version 2.9 * @author quinton-ashley, Tezumie, and LingDong- * @license LGPL-3.0 * @class Q5 */ -function Q5(e,t,r){let a=this;a._q5=!0,a._parent=t,a._renderer=r||"q2d",a._preloadCount=0;let n,o="auto"==e;if(e??="global","auto"==e){if(!window.setup&&!window.draw)return;e="global"}a._scope=e,"global"==e&&(Q5._hasGlobal=a._isGlobal=!0,n=Q5._nodejs?global:window);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;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 l=0;a.millis=()=>performance.now()-l,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._draw=e=>{let t=e||performance.now();if(a._lastFrameTime??=t-a._targetFrameDuration,a._didResize&&(a.windowResized(),a._didResize=!1),a._loop)s=c(a._draw);else if(a.frameCount&&!a._redraw)return;if(s&&a.frameCount){if(t-a._lastFrameTime{a._loop=!1,s=null},a.loop=()=>{a._loop=!0,null==s&&a._draw()},a.isLooping=()=>a._loop,a.redraw=(e=1)=>{a._redraw=!0;for(let t=0;t{a.noLoop(),a.canvas.remove()},a.frameRate=e=>(e&&(a._targetFrameRate=e,a._targetFrameDuration=1e3/e),a._frameRate),a.getTargetFrameRate=()=>a._targetFrameRate||60,a.getFPS=()=>a._fps,a.Element=function(e){this.elt=e},a._elements=[],a.TWO_PI=a.TAU=2*Math.PI,a.log=a.print=console.log,a.describe=()=>{};for(let e in Q5.modules)Q5.modules[e](a,i);let d=Q5.renderers[a._renderer];for(let e in d)d[e](a,i);for(let e in Q5)"_"!=e[1]&&e[1]==e[1].toUpperCase()&&(a[e]=Q5[e]);if("graphics"==e)return;"global"==e&&(Object.assign(Q5,a),delete Q5.Q5);for(let e of Q5.methods.init)e.call(a);for(let[e,t]of Object.entries(Q5.prototype))"_"!=e[0]&&"function"==typeof a[e]&&(a[e]=t.bind(a));if("global"==e){let e=Object.getOwnPropertyNames(a);for(let t of e)"_"!=t[0]&&(n[t]=a[t])}"function"==typeof e&&e(a),Q5._instanceCount++;let c=window.requestAnimationFrame||function(e){const t=a._lastFrameTime+a._targetFrameDuration;return setTimeout((()=>{e(t)}),t-performance.now())},h=n||a;a._isTouchAware=h.touchStarted||h.touchMoved||h.mouseReleased,a._isGlobal&&(a.preload=h.preload,a.setup=h.setup,a.draw=h.draw),a.preload??=()=>{},a.setup??=()=>{},a.draw??=()=>{};let u=["mouseMoved","mousePressed","mouseReleased","mouseDragged","mouseClicked","keyPressed","keyReleased","keyTyped","touchStarted","touchMoved","touchEnded","windowResized"];for(let e of u)h[e]?a._isGlobal&&(a[e]=()=>{try{return h[e]()}catch(e){throw a._askAI&&a._askAI(e),e}}):a[e]=()=>{};async function p(){if(a._startDone=!0,a._preloadCount>0)return c(p);l=performance.now(),await a.setup(),a._setupDone=!0,a.frameCount||(null===a.ctx&&a.createCanvas(200,200),a.ctx&&a.resetMatrix(),c(a._draw))}function f(){try{a.preload(),a._startDone||p()}catch(e){throw a._askAI&&a._askAI(e),e}}o?f():setTimeout(f,32)}Q5.renderers={},Q5.modules={},Q5._nodejs="object"==typeof process,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._nodejs?global.p5??=global.Q5=Q5:"object"==typeof window?window.p5??=window.Q5=Q5:global.window=0,"object"==typeof document&&document.addEventListener("DOMContentLoaded",(()=>{Q5._hasGlobal||new Q5("auto")})),Q5.modules.canvas=(e,t)=>{e.CENTER="center",e.LEFT="left",e.RIGHT="right",e.TOP="top",e.BOTTOM="bottom",e.BASELINE="alphabetic",e.NORMAL="normal",e.ITALIC="italic",e.BOLD="bold",e.BOLDITALIC="italic bold",e.ROUND="round",e.SQUARE="butt",e.PROJECT="square",e.MITER="miter",e.BEVEL="bevel",e.CHORD=0,e.PIE=1,e.OPEN=2,e.RADIUS="radius",e.CORNER="corner",e.CORNERS="corners",e.CLOSE=1,e.LANDSCAPE="landscape",e.PORTRAIT="portrait",e.BLEND="source-over",e.REMOVE="destination-out",e.ADD="lighter",e.DARKEST="darken",e.LIGHTEST="lighten",e.DIFFERENCE="difference",e.SUBTRACT="subtract",e.EXCLUSION="exclusion",e.MULTIPLY="multiply",e.SCREEN="screen",e.REPLACE="copy",e.OVERLAY="overlay",e.HARD_LIGHT="hard-light",e.SOFT_LIGHT="soft-light",e.DODGE="color-dodge",e.BURN="color-burn",e.P2D="2d",e.WEBGL="webgl",e._OffscreenCanvas=window.OffscreenCanvas||function(){return document.createElement("canvas")},Q5._nodejs?Q5._createNodeJSCanvas&&(t.canvas=Q5._createNodeJSCanvas(100,100)):"image"!=e._scope&&"graphics"!=e._scope||(t.canvas=new e._OffscreenCanvas(100,100)),e.canvas||("object"==typeof document?(t.canvas=document.createElement("canvas"),e.canvas.id="q5Canvas"+Q5._instanceCount,e.canvas.classList.add("q5Canvas")):e.noCanvas());let r=e.canvas;if(r.width=e.width=100,r.height=e.height=100,e._pixelDensity=1,e.displayDensity=()=>window.devicePixelRatio||1,"image"!=e._scope&&(r.renderer=e._renderer,r[e._renderer]=!0,e._pixelDensity=Math.ceil(e.displayDensity())),e._adjustDisplay=()=>{r.style&&(r.style.width=r.w+"px",r.style.height=r.h+"px")},e.createCanvas=function(t,a,n){n??=arguments[3];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 i},e.createGraphics=function(t,r,a){let n=new Q5("graphics");return a??={},a.alpha??=!0,a.colorSpace??=e.canvas.colorSpace,n.createCanvas.call(e,t,r,a),n},e._save=async(e,t,r)=>{if(t=t||"untitled","jpg"==(r=r||"png")||"png"==r||"webp"==r)if(e instanceof OffscreenCanvas){const t=await e.convertToBlob({type:"image/"+r});e=await new Promise((e=>{const r=new FileReader;r.onloadend=()=>e(r.result),r.readAsDataURL(t)}))}else e=e.toDataURL("image/"+r);else{let t="text/plain";"json"==r&&("string"!=typeof e&&(e=JSON.stringify(e)),t="text/json"),e=new Blob([e],{type:t}),e=URL.createObjectURL(e)}let a=document.createElement("a");a.href=e,a.download=t+"."+r,a.click(),URL.revokeObjectURL(a.href)},e.save=(t,r,a)=>{if((!t||"string"==typeof t&&(!r||!a&&r.length<5))&&(a=r,r=t,t=e.canvas),a)return e._save(t,r,a);r?(r=r.split("."),e._save(t,r[0],r.at(-1))):e._save(t)},e._setCanvasSize=(a,n)=>{a??=window.innerWidth,n??=window.innerHeight,r.w=a=Math.ceil(a),r.h=n=Math.ceil(n),r.hw=a/2,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()},"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)},e.canvas.resize=e.resizeCanvas,e.canvas.save=e.saveCanvas=e.save,e.pixelDensity=t=>t&&t!=e._pixelDensity?(e._pixelDensity=t,e._setCanvasSize(r.w,r.h),t):e._pixelDensity,e.flexibleCanvas=(a=400)=>{a?(e._da=r.width/(a*e._pixelDensity),t.width=e._dau=a,t.height=r.h/r.w*a):e._da=0},e._styleNames=["_doStroke","_doFill","_strokeSet","_fillSet","_tint","_imageMode","_rectMode","_ellipseMode","_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.canvasOptions={alpha:!1,colorSpace:"display-p3"},window.matchMedia&&matchMedia("(dynamic-range: high) and (color-gamut: p3)").matches?Q5.supportsHDR=!0:Q5.canvasOptions.colorSpace="srgb",Q5.renderers.q2d={},Q5.renderers.q2d.canvas=(e,t)=>{let r=e.canvas;e.colorMode&&e.colorMode("rgb","integer"),e._createCanvas=function(a,n,o){return t.ctx=t.drawingContext=r.getContext("2d",o),"image"!=e._scope&&(e.ctx.fillStyle="white",e.ctx.strokeStyle="black",e.ctx.lineCap="round",e.ctx.lineJoin="miter",e.ctx.textAlign="left"),e.ctx.scale(e._pixelDensity,e._pixelDensity),e.ctx.save(),r},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&&(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._OffscreenCanvas(r.width,r.height),n.w=r.w,n.h=r.h,n.getContext("2d").drawImage(r,0,0)}e._setCanvasSize(t,a);for(let t in o)e.ctx[t]=o[t];e.scale(e._pixelDensity),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.noFill=()=>e._doFill=!1,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.noStroke=()=>e._doStroke=!1,e.opacity=t=>e.ctx.globalAlpha=t,e.translate=(t,r)=>{e._da&&(t*=e._da,r*=e._da),e.ctx.translate(t,r)},e.rotate=t=>{e._angleMode&&(t=e.radians(t)),e.ctx.rotate(t)},e.scale=(t,r)=>{r??=t,e.ctx.scale(t,r)},e.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.pushMatrix=()=>e.ctx.save(),e.popMatrix=()=>e.ctx.restore(),e.push=()=>{e.ctx.save(),e.pushStyles()},e.pop=()=>{e.ctx.restore(),e.popStyles()},e.createCapture=e=>{var t=document.createElement("video");return t.playsinline="playsinline",t.autoplay="autoplay",navigator.mediaDevices.getUserMedia(e).then((e=>{t.srcObject=e})),t.style.position="absolute",t.style.opacity=1e-5,t.style.zIndex=-1e3,document.body.append(t),t})},Q5.renderers.q2d.drawing=e=>{e._doStroke=!0,e._doFill=!0,e._strokeSet=!1,e._fillSet=!1,e._ellipseMode=e.CENTER,e._rectMode=e.CORNER,e._curveDetail=20,e._curveAlpha=0;let t=!0,r=[];function a(){e._doFill&&e.ctx.fill(),e._doStroke&&e.ctx.stroke()}function n(t,r,n,o,i,s,l,d){if(!e._doFill&&!e._doStroke)return;let c=e._angleMode,h=c?360:e.TAU;if((i%=h)<0&&(i+=h),(s%=h)<0&&(s+=h),0!=i||0!=s){if(i>s&&([i,s]=[s,i]),e.ctx.beginPath(),n==o)c&&(i=e.radians(i),s=e.radians(s)),e.ctx.arc(t,r,n/2,i,s);else{for(let a=0;ae.ctx.globalCompositeOperation=t,e.strokeCap=t=>e.ctx.lineCap=t,e.strokeJoin=t=>e.ctx.lineJoin=t,e.ellipseMode=t=>e._ellipseMode=t,e.rectMode=t=>e._rectMode=t,e.curveDetail=t=>e._curveDetail=t,e.curveAlpha=t=>e._curveAlpha=t,e.curveTightness=t=>e._curveAlpha=t,e.background=function(t){e.ctx.save(),e.ctx.resetTransform(),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.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())},e.arc=(t,r,a,o,i,s,l,d=25)=>{if(i==s)return e.ellipse(t,r,a,o);l??=e.PIE,e._ellipseMode==e.CENTER?n(t,r,a,o,i,s,l,d):e._ellipseMode==e.RADIUS?n(t,r,2*a,2*o,i,s,l,d):e._ellipseMode==e.CORNER?n(t+a/2,r+o/2,a,o,i,s,l,d):e._ellipseMode==e.CORNERS&&n((t+a)/2,(r+o)/2,a-t,o-r,i,s,l,d)},e.ellipse=(t,r,a,n)=>{n??=a,e._ellipseMode==e.CENTER?o(t,r,a,n):e._ellipseMode==e.RADIUS?o(t,r,2*a,2*n):e._ellipseMode==e.CORNER?o(t+a/2,r+n/2,a,n):e._ellipseMode==e.CORNERS&&o((t+a)/2,(r+n)/2,a-t,n-r)},e.circle=(t,r,n)=>{e._ellipseMode==e.CENTER?(e._da&&(t*=e._da,r*=e._da,n*=e._da),e.ctx.beginPath(),e.ctx.arc(t,r,n/2,0,e.TAU),a()):e.ellipse(t,r,n,n)},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,s,l,d)=>{e._rectMode==e.CENTER?i(t-a/2,r-n/2,a,n,o,s,l,d):e._rectMode==e.RADIUS?i(t-a,r-n,2*a,2*n,o,s,l,d):e._rectMode==e.CORNER?i(t,r,a,n,o,s,l,d):e._rectMode==e.CORNERS&&i(t,r,a-t,n-r,o,s,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=function(e,t,r,a,n,o,i,s,l,d){function c(e,t,r,a,n,o){let i=Math.pow(a-t,2)+Math.pow(n-r,2);return Math.pow(i,.5*o)+e}let h=[],u=c(0,e,t,r,a,d),p=c(u,r,a,n,o,d),f=c(p,n,o,i,s,d);for(let d=0;d0?(_[e]=1,_[e+1]=0):(_[e]=0,_[e+1]=1));let g=e*_[0]+r*_[1],x=t*_[0]+a*_[1],m=r*_[2]+n*_[3],v=a*_[2]+o*_[3],y=n*_[4]+i*_[5],w=o*_[4]+s*_[5],b=g*_[6]+m*_[7],S=x*_[6]+v*_[7],C=m*_[8]+y*_[9],M=v*_[8]+w*_[9],R=b*_[2]+C*_[3],I=S*_[2]+M*_[3];h.push([R,I])}return h}(...r.at(-4),...r.at(-3),...r.at(-2),...r.at(-1),e._curveDetail,e._curveAlpha);for(let r=0;r{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=`rgba(0, 0, 0, ${t/255})`,e.ctx.strokeStyle=`rgba(0, 0, 0, ${r/255})`},e.noErase=function(){e.ctx.globalCompositeOperation="source-over",e.ctx.restore()},e.inFill=(t,r)=>{const a=e._pixelDensity;return e.ctx.isPointInPath(t*a,r*a)},e.inStroke=(t,r)=>{const a=e._pixelDensity;return e.ctx.isPointInStroke(t*a,r*a)}},Q5.renderers.q2d.image=(e,t)=>{Q5.Image??=class{constructor(e,t,r){let a=this;a._scope="image",a.canvas=a.ctx=a.drawingContext=null,a.pixels=[],Q5.modules.canvas(a,a);let n=Q5.renderers.q2d;for(let e of["canvas","image","soft_filters"])n[e]&&n[e](a,a);a._pixelDensity=r.pixelDensity||1,a.createCanvas(e,t,r),delete a.createCanvas,a._loop=!1}get w(){return this.width}get h(){return this.height}},e.createImage=(t,r,a)=>(a??={},a.alpha??=!0,a.colorSpace??=e.canvas.colorSpace||Q5.canvasOptions.colorSpace,new Q5.Image(t,r,a)),e.loadImage=function(r,a,n){if(r.canvas)return r;if("gif"==r.slice(-3).toLowerCase())throw new Error("q5 doesn't support GIFs due to their impact on performance. Use a video or animation instead.");t._preloadCount++;let o=[...arguments].at(-1);n="object"==typeof o?o:null;let i=e.createImage(1,1,n);function s(e){i.resize(e.naturalWidth||e.width,e.naturalHeight||e.height),i.ctx.drawImage(e,0,0),t._preloadCount--,a&&a(i)}if(Q5._nodejs&&global.CairoCanvas)global.CairoCanvas.loadImage(r).then(s).catch((e=>{throw t._preloadCount--,e}));else{let e=new window.Image;e.src=r,e.crossOrigin="Anonymous",e._pixelDensity=1,e.onload=()=>s(e),e.onerror=e=>{throw t._preloadCount--,e}}return i},e.imageMode=t=>e._imageMode=t,e.image=(t,r,a,n,o,i=0,s=0,l,d)=>{if(!t)return;let c=t?.canvas||t;Q5._createNodeJSCanvas&&(c=c.context.canvas),n??=t.width||t.videoWidth,o??=t.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;l?l*=h:l=c.width||c.videoWidth,d?d*=h:d=c.height||c.videoHeight,e.ctx.drawImage(c,i*h,s*h,l,d,r,a,n,o),e._tint&&(e.ctx.globalCompositeOperation="multiply",e.ctx.fillStyle=e._tint.toString(),e.ctx.fillRect(r,a,n,o),e.ctx.globalCompositeOperation="source-over")},e._tint=null;let r=null;e._softFilter=()=>{throw new Error("Load q5-2d-soft-filters.js to use software filters.")},e.filter=(t,r)=>{if(!e.ctx.filter)return e._softFilter(t,r);if("string"==typeof t)f=t;else if(t==Q5.GRAY)f="saturate(0%)";else if(t==Q5.INVERT)f="invert(100%)";else if(t==Q5.BLUR){let t=Math.ceil(r*e._pixelDensity)||1;f=`blur(${t}px)`}else{if(t!=Q5.THRESHOLD)return e._softFilter(t,r);{r??=.5;let e=Math.floor(.5/Math.max(r,1e-5)*100);f=`saturate(0%) brightness(${e}%) contrast(1000000%)`}}e.ctx.filter=f,e.ctx.drawImage(e.canvas,0,0,e.canvas.w,e.canvas.h),e.ctx.filter="none"},"image"==e._scope&&(e.resize=(t,r)=>{let a=new e._OffscreenCanvas(e.canvas.width,e.canvas.height);a.getContext("2d",{colorSpace:e.canvas.colorSpace}).drawImage(e.canvas,0,0),e._setCanvasSize(t,r),e.ctx.clearRect(0,0,e.canvas.width,e.canvas.height),e.ctx.drawImage(a,0,0,e.canvas.width,e.canvas.height)}),e._getImageData=(t,r,a,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;ei&&(i=t),el&&(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.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.copy=()=>e.get(),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=(t||0)*o,r=(r||0)*o;let i=a=a||e.width,s=n=n||e.height;a*=o,n*=o;let l=e.createImage(a,n);return l.ctx.drawImage(e.canvas,t,r,a,n,0,0,a,n),l._pixelDensity=o,l.width=i,l.height=s,l},e.set=(t,r,a)=>{if(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{r=e._getImageData(0,0,e.canvas.width,e.canvas.height),t.pixels=r.data},e.updatePixels=()=>{null!=r&&e.ctx.putImageData(r,0,0)},e.smooth=()=>e.ctx.imageSmoothingEnabled=!0,e.noSmooth=()=>e.ctx.imageSmoothingEnabled=!1,"image"!=e._scope&&(e.tint=function(t){e._tint=t._q5Color?t:e.color(...arguments)},e.noTint=()=>e._tint=null)},Q5.THRESHOLD=1,Q5.GRAY=2,Q5.OPAQUE=3,Q5.INVERT=4,Q5.POSTERIZE=5,Q5.DILATE=6,Q5.ERODE=7,Q5.BLUR=8,Q5.renderers.q2d.text=(e,t)=>{e._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=(e,r)=>{t._preloadCount++;let a=e.split("/").pop().split(".")[0].replace(" ",""),n=new FontFace(a,`url(${e})`);return document.fonts.add(n),n.load().then((()=>{t._preloadCount--,r&&r(a)})),a},e.textFont=e=>{if(!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=>{if(a=!0,null==t||t==n)return n;e._da&&(t*=e._da),n=t,o=t-e._textSize,l=-1},e.textAlign=(t,r)=>{e.ctx.textAlign=e._textAlign=t,r&&(e.ctx.textBaseline=e._textBaseline=r==e.CENTER?"middle":r)},e.textWidth=t=>e.ctx.measureText(t).width,e.textAscent=t=>e.ctx.measureText(t).actualBoundingBoxAscent,e.textDescent=t=>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,img=e.text(t,0,0,r,a),h=!1,img);let _=[];e.text=(t,a,g,x,m)=>{if(void 0===t||!e._doFill&&!e._doStroke)return;t=t.toString(),e._da&&(a*=e._da,g*=e._da);let v,y,w,b,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>>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>x){let e=[];for(let t of _){let r=0;for(;r=t.length){e.push(t.slice(r));break}let n=t.lastIndexOf(" ",a);(-1===n||nm)break;if(_.length=0,e._fillSet||(S.fillStyle=b),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},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.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=o.split(":");let i=parseInt(o.at(-2));t&&i++,o[3]=o[3].split(")")[0];let s=o.slice(0,2).join(":"),l=s.split("/").at(-1);try{let r=(await(await fetch(s)).text()).split("\n"),a=r[i-1].trim(),n="",o=1;for(;n.length<1600&&(i-o>=0&&(n=r[i-o].trim()+"\n"+n),i+o10?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 "+l+" on line "+i+":\n\n"+a),console.warn("Ask AI ✨ "+d),t)return window.open(d,"_blank")}catch(e){}}},Q5.modules.color=(e,t)=>{e.RGB=e.RGBA=e._colorMode="rgb",e.OKLCH="oklch",e.colorMode=(r,a)=>{e._colorMode=r;let n="srgb"==e.canvas.colorSpace||"srgb"==r;if(a??=n?"integer":"float",e._colorFormat="float"==a||1==a?1:255,"oklch"==r)t.Color=Q5.ColorOKLCH;else{let r="srgb"==e.canvas.colorSpace;255==e._colorFormat?t.Color=r?Q5.ColorRGBA_8:Q5.ColorRGBA_P3_8:t.Color=r?Q5.ColorRGBA:Q5.ColorRGBA_P3,e._colorMode="rgb"}},e._namedColors={aqua:[0,255,255],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],crimson:[220,20,60],cyan:[0,255,255],darkviolet:[148,0,211],gold:[255,215,0],green:[0,128,0],gray:[128,128,128],grey:[128,128,128],hotpink:[255,105,180],indigo:[75,0,130],khaki:[240,230,140],lightgreen:[144,238,144],lime:[0,255,0],magenta:[255,0,255],navy:[0,0,128],orange:[255,165,0],olive:[128,128,0],peachpuff:[255,218,185],pink:[255,192,203],purple:[128,0,128],red:[255,0,0],skyblue:[135,206,235],tan:[210,180,140],turquoise:[64,224,208],transparent:[0,0,0,0],white:[255,255,255],violet:[238,130,238],yellow:[255,255,0]},e.color=(t,r,a,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])return console.error("q5 can't parse color: "+t+"\nOnly numeric input, hex, and common named colors are supported."),new o(0,0,0);[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?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=e=>e.l?e.l:100*(.2126*e.r+.7152*e.g+.0722*e.b)/255,e.hue=t=>{if(t.h)return t.h;let r=t.r,a=t.g,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("rgb"==e._colorMode)return new e.Color(e.constrain(e.lerp(t.r,r.r,a),0,255),e.constrain(e.lerp(t.g,r.g,a),0,255),e.constrain(e.lerp(t.b,r.b,a),0,255),e.constrain(e.lerp(t.a,r.a,a),0,255));{let 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.constrain(e.lerp(t.l,r.l,a),0,100),e.constrain(e.lerp(t.c,r.c,a),0,100),o,e.constrain(e.lerp(t.a,r.a,a),0,255))}}},Q5.Color=class{constructor(){this._q5Color=!0}},Q5.ColorOKLCH=class extends Q5.Color{constructor(e,t,r,a){super(),this.l=e,this.c=t,this.h=r,this.a=a??1}toString(){return`oklch(${this.l} ${this.c} ${this.h} / ${this.a})`}},Q5.ColorRGBA=class extends Q5.Color{constructor(e,t,r,a){super(),this.r=e,this.g=t,this.b=r,this.a=a??1}get levels(){return[this.r,this.g,this.b,this.a]}toString(){return`color(srgb ${this.r} ${this.g} ${this.b} / ${this.a})`}},Q5.ColorRGBA_P3=class extends Q5.ColorRGBA{toString(){return`color(display-p3 ${this.r} ${this.g} ${this.b} / ${this.a})`}},Q5.ColorRGBA_8=class extends Q5.ColorRGBA{constructor(e,t,r,a){super(e,t,r,a??255)}setRed(e){this.r=e}setGreen(e){this.g=e}setBlue(e){this.b=e}setAlpha(e){this.a=e}get levels(){return[this.r,this.g,this.b,this.a]}toString(){return`rgb(${this.r} ${this.g} ${this.b} / ${this.a/255})`}},Q5.ColorRGBA_P3_8=class extends Q5.ColorRGBA{constructor(e,t,r,a){super(e,t,r,a??255),this._edited=!0}get r(){return this._r}set r(e){this._r=e,this._edited=!0}get g(){return this._g}set g(e){this._g=e,this._edited=!0}get b(){return this._b}set b(e){this._b=e,this._edited=!0}get a(){return this._a}set a(e){this._a=e,this._edited=!0}toString(){if(this._edited){let e=(this._r/255).toFixed(3),t=(this._g/255).toFixed(3),r=(this._b/255).toFixed(3),a=(this._a/255).toFixed(3);this._css=`color(display-p3 ${e} ${t} ${r} / ${a})`,this._edited=!1}return this._css}},Q5.modules.display=e=>{if(!e.canvas||"graphics"==e._scope)return;let t=e.canvas;e.CENTERED="centered",e.FULLSCREEN="fullscreen",e.MAXED="maxed",e.PIXELATED="pixelated",0!=Q5._instanceCount||Q5._nodejs||document.head.insertAdjacentHTML("beforeend",""),e._adjustDisplay=()=>{let r=t.style,a=t.parentElement;r&&a&&t.displayMode&&("pixelated"==t.renderQuality&&(t.classList.add("q5-pixelated"),e.pixelDensity(1),e.noSmooth&&e.noSmooth(),e.textFont&&e.textFont("monospace")),"normal"==t.displayMode?(a.classList.remove("q5-centered","q5-maxed","q5-fullscreen"),r.width=t.w*t.displayScale+"px",r.height=t.h*t.displayScale+"px"):(a.classList.add("q5-"+t.displayMode),a=a.getBoundingClientRect(),t.w/t.h>a.width/a.height?("centered"==t.displayMode?(r.width=t.w*t.displayScale+"px",r.maxWidth="100%"):r.width="100%",r.height="auto",r.maxHeight=""):(r.width="auto",r.maxWidth="","centered"==t.displayMode?(r.height=t.h*t.displayScale+"px",r.maxHeight="100%"):r.height="100%")))},e.displayMode=(r="normal",a="default",n=1)=>{"string"==typeof n&&(n=parseFloat(n.slice(1))),Object.assign(t,{displayMode:r,renderQuality:a,displayScale:n}),e._adjustDisplay()},e.fullscreen=e=>{if(void 0===e)return document.fullscreenElement;e?document.body.requestFullscreen():document.body.exitFullscreen()}},Q5.modules.input=(e,t)=>{if("graphics"==e._scope)return;e.mouseX=0,e.mouseY=0,e.pmouseX=0,e.pmouseY=0,e.touches=[],e.mouseButton="",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=[e.LEFT,e.CENTER,e.RIGHT],n=e.canvas;function o(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._startAudio=()=>{e.getAudioContext&&"suspended"==e.getAudioContext()?.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}},e._onmousedown=r=>{e._startAudio(),e._updateMouse(r),t.mouseIsPressed=!0,t.mouseButton=a[r.button],e.mousePressed(r)},e._onmousemove=t=>{e._updateMouse(t),e.mouseIsPressed?e.mouseDragged(t):e.mouseMoved(t)},e._onmouseup=r=>{e._updateMouse(r),t.mouseIsPressed=!1,e.mouseReleased(r)},e._onclick=r=>{e._updateMouse(r),t.mouseIsPressed=!0,e.mouseClicked(r),t.mouseIsPressed=!1},e.cursor=(t,r,a)=>{let 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.requestPointerLock=document.body?.requestPointerLock,e.exitPointerLock=document.exitPointerLock,e._onkeydown=a=>{a.repeat||(e._startAudio(),t.keyIsPressed=!0,t.key=a.key,t.keyCode=a.keyCode,r[e.keyCode]=r[e.key.toLowerCase()]=!0,e.keyPressed(a),1==a.key.length&&e.keyTyped(a))},e._onkeyup=a=>{t.keyIsPressed=!1,t.key=a.key,t.keyCode=a.keyCode,r[e.keyCode]=r[e.key.toLowerCase()]=!1,e.keyReleased(a)},e.keyIsDown=e=>!!r["string"==typeof e?e.toLowerCase():e],e._ontouchstart=r=>{e._startAudio(),t.touches=[...r.touches].map(o),e._isTouchAware||(t.mouseX=e.touches[0].x,t.mouseY=e.touches[0].y,t.mouseIsPressed=!0,t.mouseButton=e.LEFT,e.mousePressed(r)||r.preventDefault()),e.touchStarted(r)||r.preventDefault()},e._ontouchmove=r=>{t.touches=[...r.touches].map(o),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(o),e._isTouchAware||e.touches.length||(t.mouseIsPressed=!1,e.mouseReleased(r)||r.preventDefault()),e.touchEnded(r)||r.preventDefault()},n&&(n.addEventListener("mousedown",(t=>e._onmousedown(t))),n.addEventListener("mouseup",(t=>e._onmouseup(t))),n.addEventListener("click",(t=>e._onclick(t))),n.addEventListener("touchstart",(t=>e._ontouchstart(t))),n.addEventListener("touchmove",(t=>e._ontouchmove(t))),n.addEventListener("touchcancel",(t=>e._ontouchend(t))),n.addEventListener("touchend",(t=>e._ontouchend(t)))),window){let t=window.addEventListener;t("mousemove",(t=>e._onmousemove(t)),!1),t("keydown",(t=>e._onkeydown(t)),!1),t("keyup",(t=>e._onkeyup(t)),!1)}},Q5.modules.math=(e,t)=>{e.RADIANS=0,e.DEGREES=1,e.PI=Math.PI,e.HALF_PI=Math.PI/2,e.QUARTER_PI=Math.PI/4,e.abs=Math.abs,e.ceil=Math.ceil,e.exp=Math.exp,e.floor=e.int=Math.floor,e.loge=Math.log,e.mag=Math.hypot,e.max=Math.max,e.min=Math.min,e.round=Math.round,e.pow=Math.pow,e.sqrt=Math.sqrt,e.SHR3=1,e.LCG=2;let r=0;e.angleMode=t=>{"radians"==t&&(t=0),r=e._angleMode=t};let a=e._DEGTORAD=Math.PI/180,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?ae*(1-r)+t*r,e.constrain=(e,t,r)=>Math.min(Math.max(e,t),r),e.dist=function(){let e=arguments;return 4==e.length?Math.hypot(e[0]-e[2],e[1]-e[3]):Math.hypot(e[0]-e[3],e[1]-e[4],e[2]-e[5])},e.norm=(t,r,a)=>e.map(t,r,a,0,1),e.sq=e=>e*e,e.fract=e=>e-Math.floor(e),e.sin=e=>Math.sin(r?e*a:e),e.cos=e=>Math.cos(r?e*a:e),e.tan=e=>Math.tan(r?e*a:e),e.asin=e=>{let t=Math.asin(e);return r?t*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())],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+n0?d+t:-d-t}if(s[e]+h()*(s[e-1]-s[e]){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])(r=c(),e=127&r,Math.abs(r)(t=c()>>>0){var e,t,r=2147483648,i=4294967296,c=3.442619855899,h=c,u=.00991256303526217,p=7.697117470131487,f=p,_=.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=_/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(_/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.Noise=Q5.PerlinNoise,e.noiseMode=e=>{t.Noise=Q5[e[0].toUpperCase()+e.slice(1)+"Noise"],l=null},e.noiseSeed=t=>{l=new e.Noise(t)},e.noise=(t=0,r=0,a=0)=>(l??=new e.Noise,l.noise(t,r,a)),e.noiseDetail=(t,r)=>{l??=new e.Noise,t>0&&(l.octaves=t),r>0&&(l.falloff=r)}},Q5.Noise=class{},Q5.PerlinNoise=class extends Q5.Noise{constructor(e){super(),this.grad3=[[1,1,0],[-1,1,0],[1,-1,0],[-1,-1,0],[1,0,1],[-1,0,1],[1,0,-1],[-1,0,-1],[0,1,1],[0,-1,1],[0,1,-1],[0,-1,-1]],this.octaves=1,this.falloff=.5,this.p=null==e?Array.from({length:256},(()=>Math.floor(256*Math.random()))):this.seedPermutation(e),this.p=this.p.concat(this.p)}seedPermutation(e){let t,r,a=[];for(let e=0;e<256;e++)a[e]=e;for(let 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{e.Sound=Q5.Sound,e.loadSound=(e,r)=>{t._preloadCount++,Q5.aud??=new window.AudioContext;let a=new Q5.Sound(e,r);return a.crossOrigin="Anonymous",a.addEventListener("canplaythrough",(()=>{t._preloadCount--,a.loaded=!0,r&&r(a)})),a},e.getAudioContext=()=>Q5.aud,e.userStartAudio=()=>Q5.aud.resume()},Q5.Sound=class extends Audio{constructor(e){super(e);let t=this;t.load(),t.panner=Q5.aud.createStereoPanner(),t.source=Q5.aud.createMediaElementSource(t),t.source.connect(t.panner),t.panner.connect(Q5.aud.destination),Object.defineProperty(t,"pan",{get:()=>t.panner.pan.value,set:e=>t.panner.pan.value=e})}setVolume(e){this.volume=e}setLoop(e){this.loop=e}setPan(e){this.pan=e}isLoaded(){return this.loaded}isPlaying(){return!this.paused}},Q5.modules.util=(e,t)=>{e._loadFile=(r,a,n)=>{t._preloadCount++;let o={};return fetch(r).then((e=>"json"==n?e.json():e.text())).then((r=>{t._preloadCount--,"csv"==n&&(r=e.CSV.parse(r)),Object.assign(o,r),a&&a(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"),e.CSV={},e.CSV.parse=(e,t=",",r="\n")=>{let a=[],n=e.split(r),o=n[0].split(t);for(let e=1;er[e]=JSON.parse(i[t]))),a.push(r)}return a},"object"==typeof localStorage&&(e.storeItem=localStorage.setItem,e.getItem=localStorage.getItem,e.removeItem=localStorage.removeItem,e.clearStorage=localStorage.clear),e.year=()=>(new Date).getFullYear(),e.day=()=>(new Date).getDay(),e.hour=()=>(new Date).getHours(),e.minute=()=>(new Date).getMinutes(),e.second=()=>(new Date).getSeconds()},Q5.modules.vector=e=>{e.createVector=(t,r,a)=>new Q5.Vector(t,r,a,e)},Q5.Vector=class{constructor(e,t,r,a){this.x=e||0,this.y=t||0,this.z=r||0,this._$=a||window,this._cn=null,this._cnsq=null}set(e,t,r){return this.x=e?.x||e||0,this.y=e?.y||t||0,this.z=e?.z||r||0,this}copy(){return new Q5.Vector(this.x,this.y,this.z)}_arg2v(e,t,r){return void 0!==e?.x?e:void 0!==t?{x:e,y:t,z:r||0}:{x:e,y:e,z:e}}_calcNorm(){this._cnsq=this.x*this.x+this.y*this.y+this.z*this.z,this._cn=Math.sqrt(this._cnsq)}add(){let e=this._arg2v(...arguments);return this.x+=e.x,this.y+=e.y,this.z+=e.z,this}rem(){let e=this._arg2v(...arguments);return this.x%=e.x,this.y%=e.y,this.z%=e.z,this}sub(){let e=this._arg2v(...arguments);return this.x-=e.x,this.y-=e.y,this.z-=e.z,this}mult(){let e=this._arg2v(...arguments);return this.x*=e.x,this.y*=e.y,this.z*=e.z,this}div(){let e=this._arg2v(...arguments);return e.x?this.x/=e.x:this.x=0,e.y?this.y/=e.y:this.y=0,e.z?this.z/=e.z:this.z=0,this}mag(){return this._calcNorm(),this._cn}magSq(){return this._calcNorm(),this._cnsq}dot(){let e=this._arg2v(...arguments);return this.x*e.x+this.y*e.y+this.z*e.z}dist(){let e=this._arg2v(...arguments),t=this.x-e.x,r=this.y-e.y,a=this.z-e.z;return Math.sqrt(t*t+r*r+a*a)}cross(){let e=this._arg2v(...arguments),t=this.y*e.z-this.z*e.y,r=this.z*e.x-this.x*e.z,a=this.x*e.y-this.y*e.x;return this.x=t,this.y=r,this.z=a,this}normalize(){this._calcNorm();let e=this._cn;return 0!=e&&(this.x/=e,this.y/=e,this.z/=e),this._cn=1,this._cnsq=1,this}limit(e){this._calcNorm();let t=this._cn;if(t>e){let r=e/t;this.x*=r,this.y*=r,this.z*=r,this._cn=e,this._cnsq=e*e}return this}setMag(e){this._calcNorm();let t=e/this._cn;return this.x*=t,this.y*=t,this.z*=t,this._cn=e,this._cnsq=e*e,this}heading(){return this._$.atan2(this.y,this.x)}setHeading(e){let t=this.mag();return this.x=t*this._$.cos(e),this.y=t*this._$.sin(e),this}rotate(e){let t=this._$.cos(e),r=this._$.sin(e),a=this.x*t-this.y*r,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(se.copy().add(t),Q5.Vector.cross=(e,t)=>e.copy().cross(t),Q5.Vector.dist=(e,t)=>Math.hypot(e.x-t.x,e.y-t.y,e.z-t.z),Q5.Vector.div=(e,t)=>e.copy().div(t),Q5.Vector.dot=(e,t)=>e.copy().dot(t),Q5.Vector.equals=(e,t,r)=>e.equals(t,r),Q5.Vector.lerp=(e,t,r)=>e.copy().lerp(t,r),Q5.Vector.slerp=(e,t,r)=>e.copy().slerp(t,r),Q5.Vector.limit=(e,t)=>e.copy().limit(t),Q5.Vector.heading=e=>this._$.atan2(e.y,e.x),Q5.Vector.magSq=e=>e.x*e.x+e.y*e.y+e.z*e.z,Q5.Vector.mag=e=>Math.sqrt(Q5.Vector.magSq(e)),Q5.Vector.mult=(e,t)=>e.copy().mult(t),Q5.Vector.normalize=e=>e.copy().normalize(),Q5.Vector.rem=(e,t)=>e.copy().rem(t),Q5.Vector.sub=(e,t)=>e.copy().sub(t);for(let e of["fromAngle","fromAngles","random2D","random3D"])Q5.Vector[e]=(t,r,a)=>(new Q5.Vector)[e](t,r,a);Q5.renderers.webgpu={},Q5.renderers.webgpu.canvas=(e,t)=>{let r=e.canvas;r.width=e.width=500,r.height=e.height=500,e.colorMode&&e.colorMode("rgb",1);let a,n,o,i=1,s=8;e._pipelineConfigs=[],e._pipelines=[];let l=e.drawStack=[],d=e.colorStack=new Float32Array(1e6);d.set([0,0,0,1,1,1,1,1]),e._transformLayout=Q5.device.createBindGroupLayout({label:"transformLayout",entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"uniform",hasDynamicOffset:!1}},{binding:1,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage",hasDynamicOffset:!1}}]}),o=Q5.device.createBindGroupLayout({label:"colorsLayout",entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage",hasDynamicOffset:!1}}]}),e.bindGroupLayouts=[e._transformLayout,o];let c=Q5.device.createBuffer({size:8,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),h=()=>{n=Q5.device.createTexture({size:[e.canvas.width,e.canvas.height],sampleCount:4,format:"bgra8unorm",usage:GPUTextureUsage.RENDER_ATTACHMENT}).createView()};e._createCanvas=(a,n,o)=>(t.ctx=t.drawingContext=r.getContext("webgpu"),o.format??=navigator.gpu.getPreferredCanvasFormat(),o.device??=Q5.device,e.ctx.configure(o),Q5.device.queue.writeBuffer(c,0,new Float32Array([e.canvas.hw,e.canvas.hh])),h(),r),e._resizeCanvas=(t,r)=>{e._setCanvasSize(t,r),h()},e.pixelDensity=t=>t&&t!=e._pixelDensity?(e._pixelDensity=t,e._setCanvasSize(r.w,r.h),h(),t):e._pixelDensity;let u=(t,r,a,n=1)=>{"string"==typeof t?t=e.color(t):null==a&&(n=r??1,r=a=t),t._q5Color&&(n=t.a,a=t.b,r=t.g,t=t.r);let o=d,l=s;o[l++]=t,o[l++]=r,o[l++]=a,o[l++]=n,s=l,i++};e._fillIndex=e._strokeIndex=0,e._doFill=e._doStroke=!0,e.fill=(t,r,a,n)=>{u(t,r,a,n),e._doFill=e._fillSet=!0,e._fillIndex=i},e.stroke=(t,r,a,n)=>{u(t,r,a,n),e._doStroke=e._strokeSet=!0,e._strokeIndex=i},e.noFill=()=>e._doFill=!1,e.noStroke=()=>e._doStroke=!1,e._strokeWeight=1,e.strokeWeight=t=>e._strokeWeight=Math.abs(t),e.resetMatrix=()=>{e._matrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],e._transformIndex=0},e.resetMatrix(),e._matrixDirty=!1;let p=[e._matrix.slice()];e._transformIndexStack=[],e.translate=(t,r,a)=>{(t||r||a)&&(e._matrix[12]+=t,e._matrix[13]-=r,e._matrix[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=e._matrix,o=n[0],i=n[1],s=n[4],l=n[5];o||i||s||l?(n[0]=o*r+s*a,n[1]=i*r+l*a,n[4]=s*r-o*a,n[5]=l*r-i*a):(n[0]=r,n[1]=a,n[4]=-a,n[5]=r),e._matrixDirty=!0},e.scale=(t=1,r,a=1)=>{r??=t;let n=e._matrix;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=e._matrix[0],n=e._matrix[1],o=e._matrix[4],i=e._matrix[5];e._matrix[0]=a+o*r,e._matrix[1]=n+i*r,e._matrixDirty=!0},e.shearY=t=>{if(!t)return;e._angleMode&&(t*=e._DEGTORAD);let r=Math.tan(t),a=e._matrix[0],n=e._matrix[1],o=e._matrix[4],i=e._matrix[5];e._matrix[4]=o+a*r,e._matrix[5]=i+n*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.");e._matrix=r.slice(),e._matrixDirty=!0},e._saveMatrix=()=>{p.push(e._matrix.slice()),e._transformIndex=p.length-1,e._matrixDirty=!1},e.pushMatrix=()=>{e._matrixDirty&&e._saveMatrix(),e._transformIndexStack.push(e._transformIndex)},e.popMatrix=()=>{if(!e._transformIndexStack.length)return console.warn("Matrix index stack is empty!");let t=e._transformIndexStack.pop();e._matrix=p[t].slice(),e._transformIndex=t,e._matrixDirty=!1},e.push=()=>{e.pushMatrix(),e.pushStyles()},e.pop=()=>{e.popMatrix(),e.popStyles()},e._calcBox=(e,t,r,a,n)=>{let o,i,s,l,d=r/2,c=a/2;return n&&"corner"!=n?"center"==n?(o=e-d,i=e+d,s=-(t-c),l=-(t+c)):(o=e,i=r,s=-t,l=-a):(o=e,i=e+r,s=-t,l=-(t+a)),[o,i,s,l]};let f=["zero","one","src-alpha","one-minus-src-alpha","dst","dst-alpha","one-minus-dst-alpha","one-minus-src"],_=["add","subtract","reverse-subtract","min","max"];const g={normal:[2,3,0,2,3,0],additive:[1,1,0,1,1,0]};e.blendConfigs={};for(const[t,r]of Object.entries(g))e.blendConfigs[t]={color:{srcFactor:f[r[0]],dstFactor:f[r[1]],operation:_[r[2]]},alpha:{srcFactor:f[r[3]],dstFactor:f[r[4]],operation:_[r[5]]}};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._beginRender=()=>{e.encoder=Q5.device.createCommandEncoder(),a=t.pass=e.encoder.beginRenderPass({label:"q5-webgpu",colorAttachments:[{view:n,resolveTarget:e.ctx.getCurrentTexture().createView(),loadOp:"clear",storeOp:"store"}]})},e._render=()=>{if(p.length>1||!e._transformBindGroup){let t=Q5.device.createBuffer({size:64*p.length,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});new Float32Array(t.getMappedRange()).set(p.flat()),t.unmap(),e._transformBindGroup=Q5.device.createBindGroup({layout:e._transformLayout,entries:[{binding:0,resource:{buffer:c}},{binding:1,resource:{buffer:t}}]})}a.setBindGroup(0,e._transformBindGroup);let t=Q5.device.createBuffer({size:4*s,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});new Float32Array(t.getMappedRange()).set(d.slice(0,s)),t.unmap(),e._colorsBindGroup=Q5.device.createBindGroup({layout:o,entries:[{binding:0,resource:{buffer:t}}]}),e.pass.setBindGroup(1,e._colorsBindGroup);for(let t of e._hooks.preRender)t();let r=0,n=0,i=0,h=-1;for(let t=0;t{a.end();let r=e.encoder.finish();Q5.device.queue.submit([r]),t.pass=e.encoder=null,e.drawStack.length=0,i=1,s=8,rotation=0,p.length=1,e._transformIndexStack.length=0}},Q5.initWebGPU=async()=>{if(!navigator.gpu)return console.warn("q5 WebGPU not supported on this browser!"),!1;if(!Q5.device){let e=await navigator.gpu.requestAdapter();if(!e)throw new Error("No appropriate GPUAdapter found.");Q5.device=await e.requestDevice()}return!0},Q5.webgpu=async function(e,t){if(e&&"global"!=e||(Q5._hasGlobal=!0),!await Q5.initWebGPU()){let r=new Q5(e,t);return r.colorMode("rgb",1),r._beginRender=()=>r.translate(r.canvas.hw,r.canvas.hh),r}return new Q5(e,t,"webgpu")},Q5.renderers.webgpu.drawing=(e,t)=>{let r,a=e.canvas,n=e.drawStack,o=new Float32Array(1e7),i=0,s=Q5.device.createShaderModule({label:"drawingVertexShader",code:"\nstruct VertexInput {\n\t@location(0) pos: vec2f,\n\t@location(1) colorIndex: f32,\n\t@location(2) transformIndex: f32\n}\nstruct VertexOutput {\n\t@builtin(position) position: vec4f,\n\t@location(0) color: vec4f\n}\nstruct Uniforms {\n\thalfWidth: f32,\n\thalfHeight: f32\n}\n\n@group(0) @binding(0) var uniforms: Uniforms;\n@group(0) @binding(1) var transforms: array>;\n\n@group(1) @binding(0) var colors : array;\n\n@vertex\nfn vertexMain(input: VertexInput) -> VertexOutput {\n\tvar vert = vec4f(input.pos, 0.0, 1.0);\n\tvert = transforms[i32(input.transformIndex)] * vert;\n\tvert.x /= uniforms.halfWidth;\n\tvert.y /= uniforms.halfHeight;\n\n\tvar output: VertexOutput;\n\toutput.position = vert;\n\toutput.color = colors[i32(input.colorIndex)];\n\treturn output;\n}\n"}),l=Q5.device.createShaderModule({label:"drawingFragmentShader",code:"\n@fragment\nfn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {\n\treturn color;\n}\n"}),d=Q5.device.createPipelineLayout({label:"drawingPipelineLayout",bindGroupLayouts:e.bindGroupLayouts});e._pipelineConfigs[0]={label:"drawingPipeline",layout:d,vertex:{module:s,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:l,entryPoint:"fragmentMain",targets:[{format:"bgra8unorm",blend:e.blendConfigs.normal}]},primitive:{topology:"triangle-strip",stripIndexFormat:"uint32"},multisample:{count:4}},e._pipelines[0]=Q5.device.createRenderPipeline(e._pipelineConfigs[0]);const c=(e,t,r,a)=>{let n=o,s=i;n[s++]=e,n[s++]=t,n[s++]=r,n[s++]=a,i=s},h=(e,t,r,a,s,l,d,c,h,u)=>{let p=o,f=i;p[f++]=e,p[f++]=t,p[f++]=h,p[f++]=u,p[f++]=r,p[f++]=a,p[f++]=h,p[f++]=u,p[f++]=d,p[f++]=c,p[f++]=h,p[f++]=u,p[f++]=s,p[f++]=l,p[f++]=h,p[f++]=u,i=f,n.push(0,4)},u=(t,r,a,s,l,d,c)=>{let h=0,u=e.TAU/l,p=o,f=i;for(let e=0;e<=l;e++){p[f++]=t,p[f++]=r,p[f++]=d,p[f++]=c;let e=t+a*Math.cos(h),n=r+s*Math.sin(h);p[f++]=e,p[f++]=n,p[f++]=d,p[f++]=c,h+=u}p[f++]=t,p[f++]=r,p[f++]=d,p[f++]=c,p[f++]=t+a,p[f++]=r,p[f++]=d,p[f++]=c,i=f,n.push(0,2*(l+1)+2)};e.rectMode=t=>e._rectMode=t,e.rect=(t,a,n,o)=>{let i,s,[l,d,c,u]=e._calcBox(t,a,n,o,e._rectMode);if(e._matrixDirty&&e._saveMatrix(),s=e._transformIndex,e._doStroke){i=e._strokeIndex;let t=e._strokeWeight/2,r=c+t,a=u-t,n=l-t,o=d+t;h(n,r,o,r,o,a,n,a,i,s),c-=t,u+=t,l+=t,d-=t}e._doFill&&(i=r??e._fillIndex,h(l,c,d,c,d,u,l,u,i,s))},e.square=(t,r,a)=>e.rect(t,r,a,a);let p;e.ellipseMode=t=>e._ellipseMode=t,e.ellipse=(t,a,n,o)=>{let i=(s=n==o?n:Math.max(n,o))<4?6:s<6?8:s<10?10:s<16?12:s<20?14:s<22?16:s<24?18:s<28?20:s<34?22:s<42?24:s<48?26:s<56?28:s<64?30:s<72?32:s<84?34:s<96?36:s<98?38:s<113?40:s<149?44:s<199?48:s<261?52:s<353?56:s<461?60:s<585?64:s<1200?70:s<1800?80:s<2400?90:100;var s;let l=Math.max(n,1)/2,d=n==o?l:Math.max(o,1)/2;e._matrixDirty&&e._saveMatrix();let c=e._transformIndex;if(e._doStroke){let r=e._strokeWeight/2;u(t,a,l+r,d+r,i,e._strokeIndex,c),l-=r,d-=r}e._doFill&&u(t,a,l,d,i,r??e._fillIndex,c)},e.circle=(t,r,a)=>e.ellipse(t,r,a,a),e.point=(t,a)=>{r=e._strokeIndex,e._doStroke=!1;let n=e._strokeWeight;n<2?(n=Math.round(n),e.rect(t,a,n,n)):e.ellipse(t,a,n,n),e._doStroke=!0,r=null},e.line=(t,a,n,o)=>{r=e._strokeIndex,e.push(),e._doStroke=!1,e.translate(t,-a),e.rotate(e.atan2(o-a,n-t));let i=Math.sqrt((n-t)**2+(o-a)**2),s=e._strokeWeight,l=s/2;e._rectMode="corner",s<4?e.rect(-l,-l,i+l,s):(e._ellipseMode="center",e.ellipse(0,0,s,s),e.ellipse(i,0,s,s),e.rect(0,-l,i,s)),e.pop(),r=null};let f=[];e.beginShape=()=>{p=0,f=[]},e.vertex=(t,r)=>{e._matrixDirty&&e._saveMatrix(),f.push(t,-r,e._fillIndex,e._transformIndex),p++},e.endShape=t=>{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){for(let e=1;e{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.background=(t,r,n,o)=>{if(e.push(),e.resetMatrix(),e._doStroke=!1,t.src){let r=e._imageMode;e._imageMode="corner",e.image(t,-a.hw,-a.hh,a.w,a.h),e._imageMode=r}else{let i=e._rectMode;e._rectMode="corner",e.fill(t,r,n,o),e.rect(-a.hw,-a.hh,a.w,a.h),e._rectMode=i}e.pop(),e._fillSet||(e._fillIndex=1)},e._hooks.preRender.push((()=>{e.pass.setPipeline(e._pipelines[0]);let t=Q5.device.createBuffer({size:4*i,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});new Float32Array(t.getMappedRange()).set(o.slice(0,i)),t.unmap(),e.pass.setVertexBuffer(0,t)})),e._hooks.postRender.push((()=>{i=0}))},Q5.renderers.webgpu.image=(e,t)=>{e._textureBindGroups=[];let r=[],a=Q5.device.createShaderModule({label:"imageVertexShader",code:"\nstruct VertexOutput {\n\t@builtin(position) position: vec4f,\n\t@location(0) texCoord: vec2f\n}\nstruct Uniforms {\n\thalfWidth: f32,\n\thalfHeight: f32\n}\n\n@group(0) @binding(0) var uniforms: Uniforms;\n@group(0) @binding(1) var transforms: array>;\n\n@vertex\nfn vertexMain(@location(0) pos: vec2f, @location(1) texCoord: vec2f, @location(2) transformIndex: f32) -> VertexOutput {\n\tvar vert = vec4f(pos, 0.0, 1.0);\n\tvert = transforms[i32(transformIndex)] * vert;\n\tvert.x /= uniforms.halfWidth;\n\tvert.y /= uniforms.halfHeight;\n\n\tvar output: VertexOutput;\n\toutput.position = vert;\n\toutput.texCoord = texCoord;\n\treturn output;\n}\n\t"}),n=Q5.device.createShaderModule({label:"imageFragmentShader",code:"\n@group(2) @binding(0) var samp: sampler;\n@group(2) @binding(1) var texture: texture_2d;\n\n@fragment\nfn fragmentMain(@location(0) texCoord: vec2f) -> @location(0) vec4f {\n\t// Sample the texture using the interpolated texture coordinate\n\treturn textureSample(texture, samp, texCoord);\n}\n\t"}),o=Q5.device.createBindGroupLayout({label:"textureLayout",entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,texture:{viewDimension:"2d",sampleType:"float"}}]});const i=Q5.device.createPipelineLayout({label:"imagePipelineLayout",bindGroupLayouts:[...e.bindGroupLayouts,o]});e._pipelineConfigs[1]={label:"imagePipeline",layout:i,vertex:{module:a,entryPoint:"vertexMain",buffers:[{arrayStride:0,attributes:[]},{arrayStride:20,attributes:[{shaderLocation:0,offset:0,format:"float32x2"},{shaderLocation:1,offset:8,format:"float32x2"},{shaderLocation:2,offset:16,format:"float32"}]}]},fragment:{module:n,entryPoint:"fragmentMain",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]);let s=Q5.device.createSampler({magFilter:"linear",minFilter:"linear"});e._textures=[];let l=0;e._createTexture=t=>{t.canvas&&(t=t.canvas);let r=[t.width,t.height,1],a=Q5.device.createTexture({size:r,format:"bgra8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT});Q5.device.queue.copyExternalImageToTexture({source:t},{texture:a,colorSpace:e.canvas.colorSpace},r),e._textures[l]=a,t.textureIndex=l;const n=Q5.device.createBindGroup({layout:o,entries:[{binding:0,resource:s},{binding:1,resource:a.createView()}]});e._textureBindGroups[l]=n,l=(l+1)%12e3,e._textures[l]&&(e._textures[l].destroy(),delete e._textures[l],delete e._textureBindGroups[l])},e.loadImage=e.loadTexture=r=>{t._preloadCount++;const a=new Image;return a.crossOrigin="Anonymous",a.onload=()=>{e._createTexture(a),t._preloadCount--},a.src=r,a},e.imageMode=t=>e._imageMode=t,e.image=(t,a,n,o,i)=>{if(t.canvas&&(t=t.canvas),null==t.textureIndex)return;e._matrixDirty&&e._saveMatrix();let s=e._transformIndex;o??=t.width/e._pixelDensity,i??=t.height/e._pixelDensity;let[l,d,c,h]=e._calcBox(a,n,o,i,e._imageMode);r.push(l,c,0,0,s,d,c,1,0,s,l,h,0,1,s,d,h,1,1,s),e.drawStack.push(1,t.textureIndex)},e._hooks.preRender.push((()=>{if(!e._textureBindGroups.length)return;e.pass.setPipeline(e._pipelines[1]);const t=Q5.device.createBuffer({size:4*r.length,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});new Float32Array(t.getMappedRange()).set(r),t.unmap(),e.pass.setVertexBuffer(1,t)})),e._hooks.postRender.push((()=>{r.length=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)=>{let r=Q5.device.createShaderModule({label:"MSDF text shader",code:"\n// Positions for simple quad geometry\nconst pos = array(vec2f(0, -1), vec2f(1, -1), vec2f(0, 0), vec2f(1, 0));\n\nstruct VertexInput {\n\t@builtin(vertex_index) vertex : u32,\n\t@builtin(instance_index) instance : u32\n}\nstruct VertexOutput {\n\t@builtin(position) position : vec4f,\n\t@location(0) texCoord : vec2f,\n\t@location(1) fillColor : vec4f\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\ttransformIndex: f32,\n\tfillIndex: f32,\n\tstrokeIndex: f32\n}\nstruct Uniforms {\n\thalfWidth: f32,\n\thalfHeight: f32\n}\n\n@group(0) @binding(0) var uniforms: Uniforms;\n@group(0) @binding(1) var transforms: array>;\n\n@group(1) @binding(0) var colors : array;\n\n@group(2) @binding(0) var fontTexture: texture_2d;\n@group(2) @binding(1) var fontSampler: sampler;\n@group(2) @binding(2) var fontChars: array;\n\n@group(3) @binding(0) var textChars: array;\n@group(3) @binding(1) var textMetadata: array;\n\n@vertex\nfn vertexMain(input : VertexInput) -> VertexOutput {\n\tlet char = textChars[input.instance];\n\n\tlet text = textMetadata[i32(char.w)];\n\n\tlet fontChar = fontChars[i32(char.z)];\n\n\tlet charPos = ((pos[input.vertex] * fontChar.size + char.xy + fontChar.offset) * text.scale) + text.pos;\n\n\tvar vert = vec4f(charPos, 0.0, 1.0);\n\tvert = transforms[i32(text.transformIndex)] * vert;\n\tvert.x /= uniforms.halfWidth;\n\tvert.y /= uniforms.halfHeight;\n\n\tvar output : VertexOutput;\n\toutput.position = vert;\n\toutput.texCoord = (pos[input.vertex] * vec2f(1, -1)) * fontChar.texExtent + fontChar.texOffset;\n\toutput.fillColor = colors[i32(text.fillIndex)];\n\treturn output;\n}\n\nfn sampleMsdf(texCoord: vec2f) -> f32 {\n\tlet c = textureSample(fontTexture, fontSampler, texCoord);\n\treturn max(min(c.r, c.g), min(max(c.r, c.g), c.b));\n}\n\n@fragment\nfn fragmentMain(input : VertexOutput) -> @location(0) vec4f {\n\t// pxRange (AKA distanceRange) comes from the msdfgen tool,\n\t// uses the default which is 4.\n\tlet pxRange = 4.0;\n\tlet sz = vec2f(textureDimensions(fontTexture, 0));\n\tlet dx = sz.x*length(vec2f(dpdxFine(input.texCoord.x), dpdyFine(input.texCoord.x)));\n\tlet dy = sz.y*length(vec2f(dpdxFine(input.texCoord.y), dpdyFine(input.texCoord.y)));\n\tlet toPixels = pxRange * inverseSqrt(dx * dx + dy * dy);\n\tlet sigDist = sampleMsdf(input.texCoord) - 0.5;\n\tlet pxDist = sigDist * toPixels;\n\tlet edgeWidth = 0.5;\n\tlet alpha = smoothstep(-edgeWidth, edgeWidth, pxDist);\n\tif (alpha < 0.001) {\n\t\tdiscard;\n\t}\n\treturn vec4f(input.fillColor.rgb, input.fillColor.a * alpha);\n}\n"}),a=Q5.device.createBindGroupLayout({label:"MSDF text group layout",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:"MSDF font group layout",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[2]={label:"msdf font pipeline",layout:i,vertex:{module:r,entryPoint:"vertexMain"},fragment:{module:r,entryPoint:"fragmentMain",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]);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={},d=e.createGraphics(1,1);d.colorMode(e.RGB,1),e.loadFont=(r,a)=>{if("json"!=r.slice(r.lastIndexOf(".")+1))return d.loadFont(r,a);let i=r.slice(r.lastIndexOf("/")+1,r.lastIndexOf("-"));return(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],_=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:_},f),"string"==typeof c.chars&&(c.chars=e.CSV.parse(c.chars," "),c.kernings=e.CSV.parse(c.kernings," "));let g=c.chars.length,x=Q5.device.createBuffer({size:32*g,usage:GPUBufferUsage.STORAGE,mappedAtCreation:!0}),m=new Float32Array(x.getMappedRange()),v=1/c.common.scaleW,y=1/c.common.scaleH,w={},b=0;for(let[e,t]of c.chars.entries())w[t.id]=t,w[t.id].charIndex=e,m[b]=t.x*v,m[b+1]=t.y*y,m[b+2]=t.width*v,m[b+3]=t.height*y,m[b+4]=t.width,m[b+5]=t.height,m[b+6]=t.xoffset,m[b+7]=-t.yoffset,b+=8;x.unmap();let S=Q5.device.createBindGroup({label:"msdf font bind group",layout:o,entries:[{binding:0,resource:_.createView()},{binding:1,resource:n},{binding:2,resource:{buffer:x}}]}),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,w,C),e._font.index=e._fonts.length,e._fonts.push(e._font),l[a]=e._font,t._preloadCount--,i&&i(a)})(r,i,a),i},e._textSize=18,e._textAlign="left",e._textBaseline="alphabetic";let c=!1,h=22.5,u=4.5,p=1.25;e.textFont=t=>{e._font=l[t]},e.textSize=t=>{e._textSize=t,c||(h=t*p,u=h-t)},e.textLeading=t=>{e._font.lineHeight=h=t,u=h-e._textSize,p=h/e._textSize,c=!0},e.textAlign=(t,r)=>{e._textAlign=t,r&&(e._textBaseline=r)},e._charStack=[],e._textStack=[];let f,_=(e,t,r)=>{let a=0,n=0,o=0,i=0,s=0,l=[],d=t.charCodeAt(0);for(let c=0;c{if(!e._font)return void(navigator.onLine&&!f&&(f=!0,e.loadFont("https://q5js.org/fonts/YaHei-msdf.json")));if(t.length>n){let e=[],r=0;for(;r=t.length){e.push(t.slice(r));break}let o=t.lastIndexOf(" ",a);(-1==o||o{let o=0;"center"==d?o=-.5*s.width- -.5*(s.width-s.lineWidths[a]):"right"==d&&(o=s.width-s.lineWidths[a]),l[p]=e+o,l[p+1]=t+r,l[p+2]=n.charIndex,l[p+3]=u,p+=4}))}else s=_(e._font,t,((e,t,r,a)=>{l[p]=e,l[p+1]=t,l[p+2]=a.charIndex,l[p+3]=u,p+=4})),"alphabetic"==c?a-=e._textSize:"center"==c?a-=.5*e._textSize:"bottom"==c&&(a-=h);e._charStack.push(l);let g=[];e._matrixDirty&&e._saveMatrix(),g[0]=r,g[1]=-a,g[2]=e._textSize/44,g[3]=e._transformIndex,g[4]=e._fillSet?e._fillIndex:0,g[5]=e._strokeIndex,e._textStack.push(g),e.drawStack.push(2,s.printedCharCount,e._font.index)},e.textWidth=t=>e._font?_(e._font,t).width:0,e.createTextImage=(t,r,a)=>{if(d.textSize(e._textSize),e._doFill){let t=4*e._fillIndex;d.fill(colorStack.slice(t,t+4))}if(e._doStroke){let t=4*e._strokeIndex;d.stroke(colorStack.slice(t,t+4))}let n=d.createTextImage(t,r,a);if(null==n.canvas.textureIndex)e._createTexture(n);else if(n.modified){let t=n.canvas,r=[t.width,t.height,1],a=e._textures[t.textureIndex];Q5.device.queue.copyExternalImageToTexture({source:t},{texture:a,colorSpace:e.canvas.colorSpace},r),n.modified=!1}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(!e._charStack.length)return;let t=0;for(let r of e._charStack)t+=4*r.length;let r=Q5.device.createBuffer({size:t,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});new Float32Array(r.getMappedRange()).set(e._charStack.flat()),r.unmap();let n=6*e._textStack.length*4,o=Q5.device.createBuffer({label:"textBuffer",size:n,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});new Float32Array(o.getMappedRange()).set(e._textStack.flat()),o.unmap(),e._textBindGroup=Q5.device.createBindGroup({label:"msdf text bind group",layout:a,entries:[{binding:0,resource:{buffer:r}},{binding:1,resource:{buffer:o}}]})})),e._hooks.postRender.push((()=>{e._charStack.length=0,e._textStack.length=0}))}; +function Q5(e,t,r){let a=this;a._q5=!0,a._parent=t,a._renderer=r||"q2d",a._preloadCount=0;let n,o="auto"==e;if(e??="global","auto"==e){if(!window.setup&&!window.draw)return;e="global"}a._scope=e,"global"==e&&(Q5._hasGlobal=a._isGlobal=!0,n=Q5._nodejs?global:window);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;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 l=0;a.millis=()=>performance.now()-l,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._draw=e=>{let t=e||performance.now();if(a._lastFrameTime??=t-a._targetFrameDuration,a._didResize&&(a.windowResized(),a._didResize=!1),a._loop)s=c(a._draw);else if(a.frameCount&&!a._redraw)return;if(s&&a.frameCount){if(t-a._lastFrameTime{a._loop=!1,s=null},a.loop=()=>{a._loop=!0,null==s&&a._draw()},a.isLooping=()=>a._loop,a.redraw=(e=1)=>{a._redraw=!0;for(let t=0;t{a.noLoop(),a.canvas.remove()},a.frameRate=e=>(e&&(a._targetFrameRate=e,a._targetFrameDuration=1e3/e),a._frameRate),a.getTargetFrameRate=()=>a._targetFrameRate||60,a.getFPS=()=>a._fps,a.Element=function(e){this.elt=e},a._elements=[],a.TWO_PI=a.TAU=2*Math.PI,a.log=a.print=console.log,a.describe=()=>{};for(let e in Q5.modules)Q5.modules[e](a,i);let d=Q5.renderers[a._renderer];for(let e in d)d[e](a,i);for(let e in Q5)"_"!=e[1]&&e[1]==e[1].toUpperCase()&&(a[e]=Q5[e]);if("graphics"==e)return;"global"==e&&(Object.assign(Q5,a),delete Q5.Q5);for(let e of Q5.methods.init)e.call(a);for(let[e,t]of Object.entries(Q5.prototype))"_"!=e[0]&&"function"==typeof a[e]&&(a[e]=t.bind(a));if("global"==e){let e=Object.getOwnPropertyNames(a);for(let t of e)"_"!=t[0]&&(n[t]=a[t])}"function"==typeof e&&e(a),Q5._instanceCount++;let c=window.requestAnimationFrame||function(e){const t=a._lastFrameTime+a._targetFrameDuration;return setTimeout((()=>{e(t)}),t-performance.now())},h=n||a;a._isTouchAware=h.touchStarted||h.touchMoved||h.mouseReleased,a._isGlobal&&(a.preload=h.preload,a.setup=h.setup,a.draw=h.draw),a.preload??=()=>{},a.setup??=()=>{},a.draw??=()=>{};let u=["mouseMoved","mousePressed","mouseReleased","mouseDragged","mouseClicked","keyPressed","keyReleased","keyTyped","touchStarted","touchMoved","touchEnded","windowResized"];for(let e of u)h[e]?a._isGlobal&&(a[e]=()=>{try{return h[e]()}catch(e){throw a._askAI&&a._askAI(e),e}}):a[e]=()=>{};async function p(){if(a._startDone=!0,a._preloadCount>0)return c(p);l=performance.now(),await a.setup(),a._setupDone=!0,a.frameCount||(null===a.ctx&&a.createCanvas(200,200),a.ctx&&a.resetMatrix(),c(a._draw))}function f(){try{a.preload(),a._startDone||p()}catch(e){throw a._askAI&&a._askAI(e),e}}o?f():setTimeout(f,32)}function createCanvas(e,t,r){if(!Q5._hasGlobal){(new Q5).createCanvas(e,t,r)}}Q5.renderers={},Q5.modules={},Q5._nodejs="object"==typeof process,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._nodejs?global.p5??=global.Q5=Q5:"object"==typeof window?window.p5??=window.Q5=Q5:global.window=0,"object"==typeof document&&document.addEventListener("DOMContentLoaded",(()=>{Q5._hasGlobal||new Q5("auto")})),Q5.modules.canvas=(e,t)=>{e.CENTER="center",e.LEFT="left",e.RIGHT="right",e.TOP="top",e.BOTTOM="bottom",e.BASELINE="alphabetic",e.NORMAL="normal",e.ITALIC="italic",e.BOLD="bold",e.BOLDITALIC="italic bold",e.ROUND="round",e.SQUARE="butt",e.PROJECT="square",e.MITER="miter",e.BEVEL="bevel",e.CHORD=0,e.PIE=1,e.OPEN=2,e.RADIUS="radius",e.CORNER="corner",e.CORNERS="corners",e.CLOSE=1,e.LANDSCAPE="landscape",e.PORTRAIT="portrait",e.BLEND="source-over",e.REMOVE="destination-out",e.ADD="lighter",e.DARKEST="darken",e.LIGHTEST="lighten",e.DIFFERENCE="difference",e.SUBTRACT="subtract",e.EXCLUSION="exclusion",e.MULTIPLY="multiply",e.SCREEN="screen",e.REPLACE="copy",e.OVERLAY="overlay",e.HARD_LIGHT="hard-light",e.SOFT_LIGHT="soft-light",e.DODGE="color-dodge",e.BURN="color-burn",e.P2D="2d",e.WEBGL="webgl",e._OffscreenCanvas=window.OffscreenCanvas||function(){return document.createElement("canvas")},Q5._nodejs?Q5._createNodeJSCanvas&&(t.canvas=Q5._createNodeJSCanvas(100,100)):"image"!=e._scope&&"graphics"!=e._scope||(t.canvas=new e._OffscreenCanvas(100,100)),e.canvas||("object"==typeof document?(t.canvas=document.createElement("canvas"),e.canvas.id="q5Canvas"+Q5._instanceCount,e.canvas.classList.add("q5Canvas")):e.noCanvas());let r=e.canvas;if(r.width=e.width=100,r.height=e.height=100,e._pixelDensity=1,e.displayDensity=()=>window.devicePixelRatio||1,"image"!=e._scope&&(r.renderer=e._renderer,r[e._renderer]=!0,e._pixelDensity=Math.ceil(e.displayDensity())),e._adjustDisplay=()=>{r.style&&(r.style.width=r.w+"px",r.style.height=r.h+"px")},e.createCanvas=function(t,a,n){n??=arguments[3];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 i},e.createGraphics=function(t,r,a){let n=new Q5("graphics");return a??={},a.alpha??=!0,a.colorSpace??=e.canvas.colorSpace,n.createCanvas.call(e,t,r,a),n},e._save=async(e,t,r)=>{if(t=t||"untitled","jpg"==(r=r||"png")||"png"==r||"webp"==r)if(e instanceof OffscreenCanvas){const t=await e.convertToBlob({type:"image/"+r});e=await new Promise((e=>{const r=new FileReader;r.onloadend=()=>e(r.result),r.readAsDataURL(t)}))}else e=e.toDataURL("image/"+r);else{let t="text/plain";"json"==r&&("string"!=typeof e&&(e=JSON.stringify(e)),t="text/json"),e=new Blob([e],{type:t}),e=URL.createObjectURL(e)}let a=document.createElement("a");a.href=e,a.download=t+"."+r,a.click(),URL.revokeObjectURL(a.href)},e.save=(t,r,a)=>{if((!t||"string"==typeof t&&(!r||!a&&r.length<5))&&(a=r,r=t,t=e.canvas),a)return e._save(t,r,a);r?(r=r.split("."),e._save(t,r[0],r.at(-1))):e._save(t)},e._setCanvasSize=(a,n)=>{a??=window.innerWidth,n??=window.innerHeight,r.w=a=Math.ceil(a),r.h=n=Math.ceil(n),r.hw=a/2,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,r.hw=a/2,r.hh=n/2,r.width=Math.ceil(a*e._pixelDensity),r.height=Math.ceil(n*e._pixelDensity)},"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)},e.canvas.resize=e.resizeCanvas,e.canvas.save=e.saveCanvas=e.save,e.pixelDensity=t=>t&&t!=e._pixelDensity?(e._pixelDensity=t,e._setCanvasSize(r.w,r.h),t):e._pixelDensity,e.defaultImageScale=t=>t?e._defaultImageScale=t:e._defaultImageScale,e.defaultImageScale(.5),e.flexibleCanvas=(a=400)=>{a?(e._da=r.width/(a*e._pixelDensity),t.width=e._dau=a,t.height=r.h/r.w*a):e._da=0},e._styleNames=["_doStroke","_doFill","_strokeSet","_fillSet","_tint","_imageMode","_rectMode","_ellipseMode","_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.canvasOptions={alpha:!1,colorSpace:"display-p3"},window.matchMedia&&matchMedia("(dynamic-range: high) and (color-gamut: p3)").matches?Q5.supportsHDR=!0:Q5.canvasOptions.colorSpace="srgb",Q5.renderers.q2d={},Q5.renderers.q2d.canvas=(e,t)=>{let r=e.canvas;e.colorMode&&e.colorMode("rgb","integer"),e._createCanvas=function(a,n,o){return t.ctx=t.drawingContext=r.getContext("2d",o),"image"!=e._scope&&(e.ctx.fillStyle="white",e.ctx.strokeStyle="black",e.ctx.lineCap="round",e.ctx.lineJoin="miter",e.ctx.textAlign="left"),e.ctx.scale(e._pixelDensity,e._pixelDensity),e.ctx.save(),r},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&&(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._OffscreenCanvas(r.width,r.height),n.w=r.w,n.h=r.h,n.getContext("2d").drawImage(r,0,0)}e._setCanvasSize(t,a);for(let t in o)e.ctx[t]=o[t];e.scale(e._pixelDensity),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.noFill=()=>e._doFill=!1,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.noStroke=()=>e._doStroke=!1,e.opacity=t=>e.ctx.globalAlpha=t,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.pushMatrix=()=>e.ctx.save(),e.popMatrix=()=>e.ctx.restore(),e.push=()=>{e.ctx.save(),e.pushStyles()},e.pop=()=>{e.ctx.restore(),e.popStyles()},e.createCapture=e=>{var t=document.createElement("video");return t.playsinline="playsinline",t.autoplay="autoplay",navigator.mediaDevices.getUserMedia(e).then((e=>{t.srcObject=e})),t.style.position="absolute",t.style.opacity=1e-5,t.style.zIndex=-1e3,document.body.append(t),t})},Q5.renderers.q2d.drawing=e=>{e._doStroke=!0,e._doFill=!0,e._strokeSet=!1,e._fillSet=!1,e._ellipseMode=e.CENTER,e._rectMode=e.CORNER,e._curveDetail=20,e._curveAlpha=0;let t=!0,r=[];function a(){e._doFill&&e.ctx.fill(),e._doStroke&&e.ctx.stroke()}function n(t,r,n,o,i,s,l,d){if(!e._doFill&&!e._doStroke)return;let c=e._angleMode,h=c?360:e.TAU;if((i%=h)<0&&(i+=h),(s%=h)<0&&(s+=h),0!=i||0!=s){if(i>s&&([i,s]=[s,i]),e.ctx.beginPath(),n==o)c&&(i=e.radians(i),s=e.radians(s)),e.ctx.arc(t,r,n/2,i,s);else{for(let a=0;ae.ctx.globalCompositeOperation=t,e.strokeCap=t=>e.ctx.lineCap=t,e.strokeJoin=t=>e.ctx.lineJoin=t,e.ellipseMode=t=>e._ellipseMode=t,e.rectMode=t=>e._rectMode=t,e.curveDetail=t=>e._curveDetail=t,e.curveAlpha=t=>e._curveAlpha=t,e.curveTightness=t=>e._curveAlpha=t,e.background=function(t){e.ctx.save(),e.ctx.resetTransform(),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.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())},e.arc=(t,r,a,o,i,s,l,d=25)=>{if(i==s)return e.ellipse(t,r,a,o);l??=e.PIE,e._ellipseMode==e.CENTER?n(t,r,a,o,i,s,l,d):e._ellipseMode==e.RADIUS?n(t,r,2*a,2*o,i,s,l,d):e._ellipseMode==e.CORNER?n(t+a/2,r+o/2,a,o,i,s,l,d):e._ellipseMode==e.CORNERS&&n((t+a)/2,(r+o)/2,a-t,o-r,i,s,l,d)},e.ellipse=(t,r,a,n)=>{n??=a,e._ellipseMode==e.CENTER?o(t,r,a,n):e._ellipseMode==e.RADIUS?o(t,r,2*a,2*n):e._ellipseMode==e.CORNER?o(t+a/2,r+n/2,a,n):e._ellipseMode==e.CORNERS&&o((t+a)/2,(r+n)/2,a-t,n-r)},e.circle=(t,r,n)=>{e._ellipseMode==e.CENTER?(e._da&&(t*=e._da,r*=e._da,n*=e._da),e.ctx.beginPath(),e.ctx.arc(t,r,n/2,0,e.TAU),a()):e.ellipse(t,r,n,n)},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,s,l,d)=>{e._rectMode==e.CENTER?i(t-a/2,r-n/2,a,n,o,s,l,d):e._rectMode==e.RADIUS?i(t-a,r-n,2*a,2*n,o,s,l,d):e._rectMode==e.CORNER?i(t,r,a,n,o,s,l,d):e._rectMode==e.CORNERS&&i(t,r,a-t,n-r,o,s,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=function(e,t,r,a,n,o,i,s,l,d){function c(e,t,r,a,n,o){let i=Math.pow(a-t,2)+Math.pow(n-r,2);return Math.pow(i,.5*o)+e}let h=[],u=c(0,e,t,r,a,d),p=c(u,r,a,n,o,d),f=c(p,n,o,i,s,d);for(let d=0;d0?(_[e]=1,_[e+1]=0):(_[e]=0,_[e+1]=1));let g=e*_[0]+r*_[1],x=t*_[0]+a*_[1],m=r*_[2]+n*_[3],v=a*_[2]+o*_[3],y=n*_[4]+i*_[5],w=o*_[4]+s*_[5],b=g*_[6]+m*_[7],S=x*_[6]+v*_[7],M=m*_[8]+y*_[9],C=v*_[8]+w*_[9],I=b*_[2]+M*_[3],R=S*_[2]+C*_[3];h.push([I,R])}return h}(...r.at(-4),...r.at(-3),...r.at(-2),...r.at(-1),e._curveDetail,e._curveAlpha);for(let r=0;r{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=`rgba(0, 0, 0, ${t/255})`,e.ctx.strokeStyle=`rgba(0, 0, 0, ${r/255})`},e.noErase=function(){e.ctx.globalCompositeOperation="source-over",e.ctx.restore()},e.inFill=(t,r)=>{const a=e._pixelDensity;return e.ctx.isPointInPath(t*a,r*a)},e.inStroke=(t,r)=>{const a=e._pixelDensity;return e.ctx.isPointInStroke(t*a,r*a)}},Q5.renderers.q2d.image=(e,t)=>{Q5.Image??=class{constructor(e,t,r){let a=this;a._scope="image",a.canvas=a.ctx=a.drawingContext=null,a.pixels=[],Q5.modules.canvas(a,a);let n=Q5.renderers.q2d;for(let e of["canvas","image","soft_filters"])n[e]&&n[e](a,a);a._pixelDensity=r.pixelDensity||1,a.createCanvas(e,t,r),delete a.createCanvas,a._loop=!1}get w(){return this.width}get h(){return this.height}},e.createImage=(t,r,a)=>(a??={},a.alpha??=!0,a.colorSpace??=e.canvas.colorSpace||Q5.canvasOptions.colorSpace,new Q5.Image(t,r,a)),e.loadImage=function(r,a,n){if(r.canvas)return r;if("gif"==r.slice(-3).toLowerCase())throw new Error("q5 doesn't support GIFs due to their impact on performance. Use a video or animation instead.");t._preloadCount++;let o=[...arguments].at(-1);n="object"==typeof o?o:null;let i=e.createImage(1,1,n),s=i._pixelDensity=n?.pixelDensity||1;function l(r){i.canvas.defaultWidth=r.width*e._defaultImageScale,i.canvas.defaultHeight=r.height*e._defaultImageScale,i.naturalWidth=r.naturalWidth,i.naturalHeight=r.naturalHeight,i._setImageSize(Math.ceil(i.naturalWidth/s),Math.ceil(i.naturalHeight/s)),i.ctx.drawImage(r,0,0),t._preloadCount--,a&&a(i)}if(Q5._nodejs&&global.CairoCanvas)global.CairoCanvas.loadImage(r).then(l).catch((e=>{throw t._preloadCount--,e}));else{let e=new window.Image;e.src=r,e.crossOrigin="Anonymous",e._pixelDensity=s,e.onload=()=>l(e),e.onerror=e=>{throw t._preloadCount--,e}}return 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;Q5._createNodeJSCanvas&&(c=c.context.canvas),n??=c.defaultWidth||c.width||t.videoWidth,o??=c.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;l?l*=h:l=c.width||c.videoWidth,d?d*=h:d=c.height||c.videoHeight,e.ctx.drawImage(c,i*h,s*h,l,d,r,a,n,o),e._tint&&(e.ctx.globalCompositeOperation="multiply",e.ctx.fillStyle=e._tint.toString(),e.ctx.fillRect(r,a,n,o),e.ctx.globalCompositeOperation="source-over")},e._tint=null;let r=null;e._softFilter=()=>{throw new Error("Load q5-2d-soft-filters.js to use software filters.")},e.filter=(t,r)=>{if(!e.ctx.filter)return e._softFilter(t,r);if("string"==typeof t)f=t;else if(t==Q5.GRAY)f="saturate(0%)";else if(t==Q5.INVERT)f="invert(100%)";else if(t==Q5.BLUR){let t=Math.ceil(r*e._pixelDensity)||1;f=`blur(${t}px)`}else{if(t!=Q5.THRESHOLD)return e._softFilter(t,r);{r??=.5;let e=Math.floor(.5/Math.max(r,1e-5)*100);f=`saturate(0%) brightness(${e}%) contrast(1000000%)`}}e.ctx.filter=f,e.ctx.drawImage(e.canvas,0,0,e.canvas.w,e.canvas.h),e.ctx.filter="none"},"image"==e._scope&&(e.resize=(t,r)=>{let a=e.canvas,n=new e._OffscreenCanvas(a.width,a.height);n.getContext("2d",{colorSpace:a.colorSpace}).drawImage(a,0,0),e._setImageSize(t,r),e.ctx.clearRect(0,0,a.width,a.height),e.ctx.drawImage(n,0,0,a.width,a.height)}),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;ei&&(i=t),el&&(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.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.copy=()=>e.get(),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=(t||0)*o,r=(r||0)*o;let i=a=a||e.width,s=n=n||e.height;a*=o,n*=o;let l=e.createImage(a,n);return l.ctx.drawImage(e.canvas,t,r,a,n,0,0,a,n),l._pixelDensity=o,l.width=i,l.height=s,l},e.set=(t,r,a)=>{if(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{r=e._getImageData(0,0,e.canvas.width,e.canvas.height),t.pixels=r.data},e.updatePixels=()=>{null!=r&&e.ctx.putImageData(r,0,0)},e.smooth=()=>e.ctx.imageSmoothingEnabled=!0,e.noSmooth=()=>e.ctx.imageSmoothingEnabled=!1,"image"!=e._scope&&(e.tint=function(t){e._tint=t._q5Color?t:e.color(...arguments)},e.noTint=()=>e._tint=null)},Q5.THRESHOLD=1,Q5.GRAY=2,Q5.OPAQUE=3,Q5.INVERT=4,Q5.POSTERIZE=5,Q5.DILATE=6,Q5.ERODE=7,Q5.BLUR=8,Q5.renderers.q2d.text=(e,t)=>{e._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=(e,r)=>{t._preloadCount++;let a=e.split("/").pop().split(".")[0].replace(" ",""),n=new FontFace(a,`url(${e})`);return document.fonts.add(n),n.load().then((()=>{t._preloadCount--,r&&r(a)})),a},e.textFont=e=>{if(!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=>{if(a=!0,null==t||t==n)return n;e._da&&(t*=e._da),n=t,o=t-e._textSize,l=-1},e.textAlign=(t,r)=>{e.ctx.textAlign=e._textAlign=t,r&&(e.ctx.textBaseline=e._textBaseline=r==e.CENTER?"middle":r)},e.textWidth=t=>e.ctx.measureText(t).width,e.textAscent=t=>e.ctx.measureText(t).actualBoundingBoxAscent,e.textDescent=t=>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,img=e.text(t,0,0,r,a),h=!1,img);let _=[];e.text=(t,a,g,x,m)=>{if(void 0===t||!e._doFill&&!e._doStroke)return;t=t.toString(),e._da&&(a*=e._da,g*=e._da);let v,y,w,b,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>>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>x){let e=[];for(let t of _){let r=0;for(;r=t.length){e.push(t.slice(r));break}let n=t.lastIndexOf(" ",a);(-1===n||nm)break;if(_.length=0,e._fillSet||(S.fillStyle=b),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},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.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[3]=i[3].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+o10?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.OKLCH="oklch",e.colorMode=(r,a)=>{e._colorMode=r;let n="srgb"==e.canvas.colorSpace||"srgb"==r;if(a??=n?"integer":"float",e._colorFormat="float"==a||1==a?1:255,"oklch"==r)t.Color=Q5.ColorOKLCH;else{let r="srgb"==e.canvas.colorSpace;255==e._colorFormat?t.Color=r?Q5.ColorRGBA_8:Q5.ColorRGBA_P3_8:t.Color=r?Q5.ColorRGBA:Q5.ColorRGBA_P3,e._colorMode="rgb"}},e._namedColors={aqua:[0,255,255],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],crimson:[220,20,60],cyan:[0,255,255],darkviolet:[148,0,211],gold:[255,215,0],green:[0,128,0],gray:[128,128,128],grey:[128,128,128],hotpink:[255,105,180],indigo:[75,0,130],khaki:[240,230,140],lightgreen:[144,238,144],lime:[0,255,0],magenta:[255,0,255],navy:[0,0,128],orange:[255,165,0],olive:[128,128,0],peachpuff:[255,218,185],pink:[255,192,203],purple:[128,0,128],red:[255,0,0],skyblue:[135,206,235],tan:[210,180,140],turquoise:[64,224,208],transparent:[0,0,0,0],white:[255,255,255],violet:[238,130,238],yellow:[255,255,0]},e.color=(t,r,a,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])return console.error("q5 can't parse color: "+t+"\nOnly numeric input, hex, and common named colors are supported."),new o(0,0,0);[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?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=e=>e.l?e.l:100*(.2126*e.r+.7152*e.g+.0722*e.b)/255,e.hue=t=>{if(t.h)return t.h;let r=t.r,a=t.g,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("rgb"==e._colorMode)return new e.Color(e.constrain(e.lerp(t.r,r.r,a),0,255),e.constrain(e.lerp(t.g,r.g,a),0,255),e.constrain(e.lerp(t.b,r.b,a),0,255),e.constrain(e.lerp(t.a,r.a,a),0,255));{let 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.constrain(e.lerp(t.l,r.l,a),0,100),e.constrain(e.lerp(t.c,r.c,a),0,100),o,e.constrain(e.lerp(t.a,r.a,a),0,255))}}},Q5.Color=class{constructor(){this._q5Color=!0}},Q5.ColorOKLCH=class extends Q5.Color{constructor(e,t,r,a){super(),this.l=e,this.c=t,this.h=r,this.a=a??1}toString(){return`oklch(${this.l} ${this.c} ${this.h} / ${this.a})`}},Q5.ColorRGBA=class extends Q5.Color{constructor(e,t,r,a){super(),this.r=e,this.g=t,this.b=r,this.a=a??1}get levels(){return[this.r,this.g,this.b,this.a]}toString(){return`color(srgb ${this.r} ${this.g} ${this.b} / ${this.a})`}},Q5.ColorRGBA_P3=class extends Q5.ColorRGBA{toString(){return`color(display-p3 ${this.r} ${this.g} ${this.b} / ${this.a})`}},Q5.ColorRGBA_8=class extends Q5.ColorRGBA{constructor(e,t,r,a){super(e,t,r,a??255)}setRed(e){this.r=e}setGreen(e){this.g=e}setBlue(e){this.b=e}setAlpha(e){this.a=e}get levels(){return[this.r,this.g,this.b,this.a]}toString(){return`rgb(${this.r} ${this.g} ${this.b} / ${this.a/255})`}},Q5.ColorRGBA_P3_8=class extends Q5.ColorRGBA{constructor(e,t,r,a){super(e,t,r,a??255),this._edited=!0}get r(){return this._r}set r(e){this._r=e,this._edited=!0}get g(){return this._g}set g(e){this._g=e,this._edited=!0}get b(){return this._b}set b(e){this._b=e,this._edited=!0}get a(){return this._a}set a(e){this._a=e,this._edited=!0}toString(){if(this._edited){let e=(this._r/255).toFixed(3),t=(this._g/255).toFixed(3),r=(this._b/255).toFixed(3),a=(this._a/255).toFixed(3);this._css=`color(display-p3 ${e} ${t} ${r} / ${a})`,this._edited=!1}return this._css}},Q5.modules.display=e=>{if(!e.canvas||"graphics"==e._scope)return;let t=e.canvas;e.CENTERED="centered",e.FULLSCREEN="fullscreen",e.MAXED="maxed",e.PIXELATED="pixelated",0!=Q5._instanceCount||Q5._nodejs||document.head.insertAdjacentHTML("beforeend",""),e._adjustDisplay=()=>{let r=t.style,a=t.parentElement;r&&a&&t.displayMode&&("pixelated"==t.renderQuality&&(t.classList.add("q5-pixelated"),e.pixelDensity(1),e.noSmooth&&e.noSmooth(),e.textFont&&e.textFont("monospace")),"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))),Object.assign(t,{displayMode:r,renderQuality:a,displayScale:n}),e._adjustDisplay()},e.fullscreen=e=>{if(void 0===e)return document.fullscreenElement;e?document.body.requestFullscreen():document.body.exitFullscreen()}},Q5.modules.input=(e,t)=>{if("graphics"==e._scope)return;e.mouseX=0,e.mouseY=0,e.pmouseX=0,e.pmouseY=0,e.touches=[],e.mouseButton="",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=[e.LEFT,e.CENTER,e.RIGHT],n=e.canvas;function o(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._startAudio=()=>{e.getAudioContext&&"suspended"==e.getAudioContext()?.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}},e._onmousedown=r=>{e._startAudio(),e._updateMouse(r),t.mouseIsPressed=!0,t.mouseButton=a[r.button],e.mousePressed(r)},e._onmousemove=t=>{e._updateMouse(t),e.mouseIsPressed?e.mouseDragged(t):e.mouseMoved(t)},e._onmouseup=r=>{e._updateMouse(r),t.mouseIsPressed=!1,e.mouseReleased(r)},e._onclick=r=>{e._updateMouse(r),t.mouseIsPressed=!0,e.mouseClicked(r),t.mouseIsPressed=!1},e.cursor=(t,r,a)=>{let 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.requestPointerLock=document.body?.requestPointerLock,e.exitPointerLock=document.exitPointerLock,e._onkeydown=a=>{a.repeat||(e._startAudio(),t.keyIsPressed=!0,t.key=a.key,t.keyCode=a.keyCode,r[e.keyCode]=r[e.key.toLowerCase()]=!0,e.keyPressed(a),1==a.key.length&&e.keyTyped(a))},e._onkeyup=a=>{t.keyIsPressed=!1,t.key=a.key,t.keyCode=a.keyCode,r[e.keyCode]=r[e.key.toLowerCase()]=!1,e.keyReleased(a)},e.keyIsDown=e=>!!r["string"==typeof e?e.toLowerCase():e],e._ontouchstart=r=>{e._startAudio(),t.touches=[...r.touches].map(o),e._isTouchAware||(t.mouseX=e.touches[0].x,t.mouseY=e.touches[0].y,t.mouseIsPressed=!0,t.mouseButton=e.LEFT,e.mousePressed(r)||r.preventDefault()),e.touchStarted(r)||r.preventDefault()},e._ontouchmove=r=>{t.touches=[...r.touches].map(o),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(o),e._isTouchAware||e.touches.length||(t.mouseIsPressed=!1,e.mouseReleased(r)||r.preventDefault()),e.touchEnded(r)||r.preventDefault()},n&&(n.addEventListener("mousedown",(t=>e._onmousedown(t))),n.addEventListener("mouseup",(t=>e._onmouseup(t))),n.addEventListener("click",(t=>e._onclick(t))),n.addEventListener("touchstart",(t=>e._ontouchstart(t))),n.addEventListener("touchmove",(t=>e._ontouchmove(t))),n.addEventListener("touchcancel",(t=>e._ontouchend(t))),n.addEventListener("touchend",(t=>e._ontouchend(t)))),window){let t=window.addEventListener;t("mousemove",(t=>e._onmousemove(t)),!1),t("keydown",(t=>e._onkeydown(t)),!1),t("keyup",(t=>e._onkeyup(t)),!1)}},Q5.modules.math=(e,t)=>{e.RADIANS=0,e.DEGREES=1,e.PI=Math.PI,e.HALF_PI=Math.PI/2,e.QUARTER_PI=Math.PI/4,e.abs=Math.abs,e.ceil=Math.ceil,e.exp=Math.exp,e.floor=e.int=Math.floor,e.loge=Math.log,e.mag=Math.hypot,e.max=Math.max,e.min=Math.min,e.round=Math.round,e.pow=Math.pow,e.sqrt=Math.sqrt,e.SHR3=1,e.LCG=2;let r=0;e.angleMode=t=>{"radians"==t&&(t=0),r=e._angleMode=t};let a=e._DEGTORAD=Math.PI/180,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?ae*(1-r)+t*r,e.constrain=(e,t,r)=>Math.min(Math.max(e,t),r),e.dist=function(){let e=arguments;return 4==e.length?Math.hypot(e[0]-e[2],e[1]-e[3]):Math.hypot(e[0]-e[3],e[1]-e[4],e[2]-e[5])},e.norm=(t,r,a)=>e.map(t,r,a,0,1),e.sq=e=>e*e,e.fract=e=>e-Math.floor(e),e.sin=e=>Math.sin(r?e*a:e),e.cos=e=>Math.cos(r?e*a:e),e.tan=e=>Math.tan(r?e*a:e),e.asin=e=>{let t=Math.asin(e);return r?t*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())],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+n0?d+t:-d-t}if(s[e]+h()*(s[e-1]-s[e]){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])(r=c(),e=127&r,Math.abs(r)(t=c()>>>0){var e,t,r=2147483648,i=4294967296,c=3.442619855899,h=c,u=.00991256303526217,p=7.697117470131487,f=p,_=.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=_/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(_/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.Noise=Q5.PerlinNoise,e.noiseMode=e=>{t.Noise=Q5[e[0].toUpperCase()+e.slice(1)+"Noise"],l=null},e.noiseSeed=t=>{l=new e.Noise(t)},e.noise=(t=0,r=0,a=0)=>(l??=new e.Noise,l.noise(t,r,a)),e.noiseDetail=(t,r)=>{l??=new e.Noise,t>0&&(l.octaves=t),r>0&&(l.falloff=r)}},Q5.Noise=class{},Q5.PerlinNoise=class extends Q5.Noise{constructor(e){super(),this.grad3=[[1,1,0],[-1,1,0],[1,-1,0],[-1,-1,0],[1,0,1],[-1,0,1],[1,0,-1],[-1,0,-1],[0,1,1],[0,-1,1],[0,1,-1],[0,-1,-1]],this.octaves=1,this.falloff=.5,this.p=null==e?Array.from({length:256},(()=>Math.floor(256*Math.random()))):this.seedPermutation(e),this.p=this.p.concat(this.p)}seedPermutation(e){let t,r,a=[];for(let e=0;e<256;e++)a[e]=e;for(let 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{e.Sound=Q5.Sound,e.loadSound=(e,r)=>{t._preloadCount++,Q5.aud??=new window.AudioContext;let a=new Q5.Sound(e,r);return a.crossOrigin="Anonymous",a.addEventListener("canplaythrough",(()=>{t._preloadCount--,a.loaded=!0,r&&r(a)})),a},e.getAudioContext=()=>Q5.aud,e.userStartAudio=()=>Q5.aud.resume()},Q5.Sound=class extends Audio{constructor(e){super(e);let t=this;t.load(),t.panner=Q5.aud.createStereoPanner(),t.source=Q5.aud.createMediaElementSource(t),t.source.connect(t.panner),t.panner.connect(Q5.aud.destination),Object.defineProperty(t,"pan",{get:()=>t.panner.pan.value,set:e=>t.panner.pan.value=e})}setVolume(e){this.volume=e}setLoop(e){this.loop=e}setPan(e){this.pan=e}isLoaded(){return this.loaded}isPlaying(){return!this.paused}},Q5.modules.util=(e,t)=>{e._loadFile=(r,a,n)=>{t._preloadCount++;let o={};return fetch(r).then((e=>"json"==n?e.json():e.text())).then((r=>{t._preloadCount--,"csv"==n&&(r=e.CSV.parse(r)),Object.assign(o,r),a&&a(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"),e.CSV={},e.CSV.parse=(e,t=",",r="\n")=>{let a=[],n=e.split(r),o=n[0].split(t);for(let e=1;er[e]=JSON.parse(i[t]))),a.push(r)}return a},"object"==typeof localStorage&&(e.storeItem=localStorage.setItem,e.getItem=localStorage.getItem,e.removeItem=localStorage.removeItem,e.clearStorage=localStorage.clear),e.year=()=>(new Date).getFullYear(),e.day=()=>(new Date).getDay(),e.hour=()=>(new Date).getHours(),e.minute=()=>(new Date).getMinutes(),e.second=()=>(new Date).getSeconds()},Q5.modules.vector=e=>{e.createVector=(t,r,a)=>new Q5.Vector(t,r,a,e)},Q5.Vector=class{constructor(e,t,r,a){this.x=e||0,this.y=t||0,this.z=r||0,this._$=a||window,this._cn=null,this._cnsq=null}set(e,t,r){return this.x=e?.x||e||0,this.y=e?.y||t||0,this.z=e?.z||r||0,this}copy(){return new Q5.Vector(this.x,this.y,this.z)}_arg2v(e,t,r){return void 0!==e?.x?e:void 0!==t?{x:e,y:t,z:r||0}:{x:e,y:e,z:e}}_calcNorm(){this._cnsq=this.x*this.x+this.y*this.y+this.z*this.z,this._cn=Math.sqrt(this._cnsq)}add(){let e=this._arg2v(...arguments);return this.x+=e.x,this.y+=e.y,this.z+=e.z,this}rem(){let e=this._arg2v(...arguments);return this.x%=e.x,this.y%=e.y,this.z%=e.z,this}sub(){let e=this._arg2v(...arguments);return this.x-=e.x,this.y-=e.y,this.z-=e.z,this}mult(){let e=this._arg2v(...arguments);return this.x*=e.x,this.y*=e.y,this.z*=e.z,this}div(){let e=this._arg2v(...arguments);return e.x?this.x/=e.x:this.x=0,e.y?this.y/=e.y:this.y=0,e.z?this.z/=e.z:this.z=0,this}mag(){return this._calcNorm(),this._cn}magSq(){return this._calcNorm(),this._cnsq}dot(){let e=this._arg2v(...arguments);return this.x*e.x+this.y*e.y+this.z*e.z}dist(){let e=this._arg2v(...arguments),t=this.x-e.x,r=this.y-e.y,a=this.z-e.z;return Math.sqrt(t*t+r*r+a*a)}cross(){let e=this._arg2v(...arguments),t=this.y*e.z-this.z*e.y,r=this.z*e.x-this.x*e.z,a=this.x*e.y-this.y*e.x;return this.x=t,this.y=r,this.z=a,this}normalize(){this._calcNorm();let e=this._cn;return 0!=e&&(this.x/=e,this.y/=e,this.z/=e),this._cn=1,this._cnsq=1,this}limit(e){this._calcNorm();let t=this._cn;if(t>e){let r=e/t;this.x*=r,this.y*=r,this.z*=r,this._cn=e,this._cnsq=e*e}return this}setMag(e){this._calcNorm();let t=e/this._cn;return this.x*=t,this.y*=t,this.z*=t,this._cn=e,this._cnsq=e*e,this}heading(){return this._$.atan2(this.y,this.x)}setHeading(e){let t=this.mag();return this.x=t*this._$.cos(e),this.y=t*this._$.sin(e),this}rotate(e){let t=this._$.cos(e),r=this._$.sin(e),a=this.x*t-this.y*r,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(se.copy().add(t),Q5.Vector.cross=(e,t)=>e.copy().cross(t),Q5.Vector.dist=(e,t)=>Math.hypot(e.x-t.x,e.y-t.y,e.z-t.z),Q5.Vector.div=(e,t)=>e.copy().div(t),Q5.Vector.dot=(e,t)=>e.copy().dot(t),Q5.Vector.equals=(e,t,r)=>e.equals(t,r),Q5.Vector.lerp=(e,t,r)=>e.copy().lerp(t,r),Q5.Vector.slerp=(e,t,r)=>e.copy().slerp(t,r),Q5.Vector.limit=(e,t)=>e.copy().limit(t),Q5.Vector.heading=e=>this._$.atan2(e.y,e.x),Q5.Vector.magSq=e=>e.x*e.x+e.y*e.y+e.z*e.z,Q5.Vector.mag=e=>Math.sqrt(Q5.Vector.magSq(e)),Q5.Vector.mult=(e,t)=>e.copy().mult(t),Q5.Vector.normalize=e=>e.copy().normalize(),Q5.Vector.rem=(e,t)=>e.copy().rem(t),Q5.Vector.sub=(e,t)=>e.copy().sub(t);for(let e of["fromAngle","fromAngles","random2D","random3D"])Q5.Vector[e]=(t,r,a)=>(new Q5.Vector)[e](t,r,a);Q5.renderers.webgpu={},Q5.renderers.webgpu.canvas=(e,t)=>{let r=e.canvas;r.width=e.width=500,r.height=e.height=500,e.colorMode&&e.colorMode("rgb",1);let a,n,o,i=1,s=8;e._pipelineConfigs=[],e._pipelines=[];let l=e.drawStack=[],d=e.colorStack=new Float32Array(1e6);d.set([0,0,0,1,1,1,1,1]),e._transformLayout=Q5.device.createBindGroupLayout({label:"transformLayout",entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"uniform",hasDynamicOffset:!1}},{binding:1,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage",hasDynamicOffset:!1}}]}),o=Q5.device.createBindGroupLayout({label:"colorsLayout",entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage",hasDynamicOffset:!1}}]}),e.bindGroupLayouts=[e._transformLayout,o];let c=Q5.device.createBuffer({size:8,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),h=()=>{n=Q5.device.createTexture({size:[e.canvas.width,e.canvas.height],sampleCount:4,format:"bgra8unorm",usage:GPUTextureUsage.RENDER_ATTACHMENT}).createView()};e._createCanvas=(a,n,o)=>(t.ctx=t.drawingContext=r.getContext("webgpu"),o.format??=navigator.gpu.getPreferredCanvasFormat(),o.device??=Q5.device,e.ctx.configure(o),Q5.device.queue.writeBuffer(c,0,new Float32Array([e.canvas.hw,e.canvas.hh])),h(),r),e._resizeCanvas=(t,r)=>{e._setCanvasSize(t,r),h()},e.pixelDensity=t=>t&&t!=e._pixelDensity?(e._pixelDensity=t,e._setCanvasSize(r.w,r.h),h(),t):e._pixelDensity;let u=(t,r,a,n=1)=>{"string"==typeof t?t=e.color(t):null==a&&(n=r??1,r=a=t),t._q5Color&&(n=t.a,a=t.b,r=t.g,t=t.r);let o=d,l=s;o[l++]=t,o[l++]=r,o[l++]=a,o[l++]=n,s=l,i++};e._fillIndex=e._strokeIndex=0,e._doFill=e._doStroke=!0,e.fill=(t,r,a,n)=>{u(t,r,a,n),e._doFill=e._fillSet=!0,e._fillIndex=i},e.stroke=(t,r,a,n)=>{u(t,r,a,n),e._doStroke=e._strokeSet=!0,e._strokeIndex=i},e.noFill=()=>e._doFill=!1,e.noStroke=()=>e._doStroke=!1,e._strokeWeight=1,e.strokeWeight=t=>e._strokeWeight=Math.abs(t),e.resetMatrix=()=>{e._matrix=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],e._transformIndex=0},e.resetMatrix(),e._matrixDirty=!1;let p=[e._matrix.slice()];e._transformIndexStack=[],e.translate=(t,r,a)=>{(t||r||a)&&(e._matrix[12]+=t,e._matrix[13]-=r,e._matrix[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=e._matrix,o=n[0],i=n[1],s=n[4],l=n[5];o||i||s||l?(n[0]=o*r+s*a,n[1]=i*r+l*a,n[4]=s*r-o*a,n[5]=l*r-i*a):(n[0]=r,n[1]=a,n[4]=-a,n[5]=r),e._matrixDirty=!0},e.scale=(t=1,r,a=1)=>{r??=t;let n=e._matrix;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=e._matrix[0],n=e._matrix[1],o=e._matrix[4],i=e._matrix[5];e._matrix[0]=a+o*r,e._matrix[1]=n+i*r,e._matrixDirty=!0},e.shearY=t=>{if(!t)return;e._angleMode&&(t*=e._DEGTORAD);let r=Math.tan(t),a=e._matrix[0],n=e._matrix[1],o=e._matrix[4],i=e._matrix[5];e._matrix[4]=o+a*r,e._matrix[5]=i+n*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.");e._matrix=r.slice(),e._matrixDirty=!0},e._saveMatrix=()=>{p.push(e._matrix.slice()),e._transformIndex=p.length-1,e._matrixDirty=!1},e.pushMatrix=()=>{e._matrixDirty&&e._saveMatrix(),e._transformIndexStack.push(e._transformIndex)},e.popMatrix=()=>{if(!e._transformIndexStack.length)return console.warn("Matrix index stack is empty!");let t=e._transformIndexStack.pop();e._matrix=p[t].slice(),e._transformIndex=t,e._matrixDirty=!1},e.push=()=>{e.pushMatrix(),e.pushStyles()},e.pop=()=>{e.popMatrix(),e.popStyles()},e._calcBox=(e,t,r,a,n)=>{let o,i,s,l,d=r/2,c=a/2;return n&&"corner"!=n?"center"==n?(o=e-d,i=e+d,s=-(t-c),l=-(t+c)):(o=e,i=r,s=-t,l=-a):(o=e,i=e+r,s=-t,l=-(t+a)),[o,i,s,l]};let f=["zero","one","src-alpha","one-minus-src-alpha","dst","dst-alpha","one-minus-dst-alpha","one-minus-src"],_=["add","subtract","reverse-subtract","min","max"];const g={normal:[2,3,0,2,3,0],additive:[1,1,0,1,1,0]};e.blendConfigs={};for(const[t,r]of Object.entries(g))e.blendConfigs[t]={color:{srcFactor:f[r[0]],dstFactor:f[r[1]],operation:_[r[2]]},alpha:{srcFactor:f[r[3]],dstFactor:f[r[4]],operation:_[r[5]]}};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._beginRender=()=>{e.encoder=Q5.device.createCommandEncoder(),a=t.pass=e.encoder.beginRenderPass({label:"q5-webgpu",colorAttachments:[{view:n,resolveTarget:e.ctx.getCurrentTexture().createView(),loadOp:"clear",storeOp:"store"}]})},e._render=()=>{if(p.length>1||!e._transformBindGroup){let t=Q5.device.createBuffer({size:64*p.length,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});new Float32Array(t.getMappedRange()).set(p.flat()),t.unmap(),e._transformBindGroup=Q5.device.createBindGroup({layout:e._transformLayout,entries:[{binding:0,resource:{buffer:c}},{binding:1,resource:{buffer:t}}]})}a.setBindGroup(0,e._transformBindGroup);let t=Q5.device.createBuffer({size:4*s,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});new Float32Array(t.getMappedRange()).set(d.slice(0,s)),t.unmap(),e._colorsBindGroup=Q5.device.createBindGroup({layout:o,entries:[{binding:0,resource:{buffer:t}}]}),e.pass.setBindGroup(1,e._colorsBindGroup);for(let t of e._hooks.preRender)t();let r=0,n=0,i=0,h=-1;for(let t=0;t{a.end();let r=e.encoder.finish();Q5.device.queue.submit([r]),t.pass=e.encoder=null,e.drawStack.length=0,i=1,s=8,rotation=0,p.length=1,e._transformIndexStack.length=0}},Q5.initWebGPU=async()=>{if(!navigator.gpu)return console.warn("q5 WebGPU not supported on this browser!"),!1;if(!Q5.device){let e=await navigator.gpu.requestAdapter();if(!e)throw new Error("No appropriate GPUAdapter found.");Q5.device=await e.requestDevice()}return!0},Q5.webgpu=async function(e,t){if(e&&"global"!=e||(Q5._hasGlobal=!0),!await Q5.initWebGPU()){let r=new Q5(e,t);return r.colorMode("rgb",1),r._beginRender=()=>r.translate(r.canvas.hw,r.canvas.hh),r}return new Q5(e,t,"webgpu")},Q5.renderers.webgpu.drawing=(e,t)=>{let r,a=e.canvas,n=e.drawStack,o=new Float32Array(1e7),i=0,s=Q5.device.createShaderModule({label:"drawingVertexShader",code:"\nstruct VertexInput {\n\t@location(0) pos: vec2f,\n\t@location(1) colorIndex: f32,\n\t@location(2) transformIndex: f32\n}\nstruct VertexOutput {\n\t@builtin(position) position: vec4f,\n\t@location(0) color: vec4f\n}\nstruct Uniforms {\n\thalfWidth: f32,\n\thalfHeight: f32\n}\n\n@group(0) @binding(0) var uniforms: Uniforms;\n@group(0) @binding(1) var transforms: array>;\n\n@group(1) @binding(0) var colors : array;\n\n@vertex\nfn vertexMain(input: VertexInput) -> VertexOutput {\n\tvar vert = vec4f(input.pos, 0.0, 1.0);\n\tvert = transforms[i32(input.transformIndex)] * vert;\n\tvert.x /= uniforms.halfWidth;\n\tvert.y /= uniforms.halfHeight;\n\n\tvar output: VertexOutput;\n\toutput.position = vert;\n\toutput.color = colors[i32(input.colorIndex)];\n\treturn output;\n}\n"}),l=Q5.device.createShaderModule({label:"drawingFragmentShader",code:"\n@fragment\nfn fragmentMain(@location(0) color: vec4f) -> @location(0) vec4f {\n\treturn color;\n}\n"}),d=Q5.device.createPipelineLayout({label:"drawingPipelineLayout",bindGroupLayouts:e.bindGroupLayouts});e._pipelineConfigs[0]={label:"drawingPipeline",layout:d,vertex:{module:s,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:l,entryPoint:"fragmentMain",targets:[{format:"bgra8unorm",blend:e.blendConfigs.normal}]},primitive:{topology:"triangle-strip",stripIndexFormat:"uint32"},multisample:{count:4}},e._pipelines[0]=Q5.device.createRenderPipeline(e._pipelineConfigs[0]);const c=(e,t,r,a)=>{let n=o,s=i;n[s++]=e,n[s++]=t,n[s++]=r,n[s++]=a,i=s},h=(e,t,r,a,s,l,d,c,h,u)=>{let p=o,f=i;p[f++]=e,p[f++]=t,p[f++]=h,p[f++]=u,p[f++]=r,p[f++]=a,p[f++]=h,p[f++]=u,p[f++]=d,p[f++]=c,p[f++]=h,p[f++]=u,p[f++]=s,p[f++]=l,p[f++]=h,p[f++]=u,i=f,n.push(0,4)},u=(t,r,a,s,l,d,c)=>{let h=0,u=e.TAU/l,p=o,f=i;for(let e=0;e<=l;e++){p[f++]=t,p[f++]=r,p[f++]=d,p[f++]=c;let e=t+a*Math.cos(h),n=r+s*Math.sin(h);p[f++]=e,p[f++]=n,p[f++]=d,p[f++]=c,h+=u}p[f++]=t,p[f++]=r,p[f++]=d,p[f++]=c,p[f++]=t+a,p[f++]=r,p[f++]=d,p[f++]=c,i=f,n.push(0,2*(l+1)+2)};e.rectMode=t=>e._rectMode=t,e.rect=(t,a,n,o)=>{let i,s,[l,d,c,u]=e._calcBox(t,a,n,o,e._rectMode);if(e._matrixDirty&&e._saveMatrix(),s=e._transformIndex,e._doStroke){i=e._strokeIndex;let t=e._strokeWeight/2;if(e._doFill){let e=c+t,r=u-t,a=l-t,n=d+t;h(a,e,n,e,n,r,a,r,i,s),c-=t,u+=t,l+=t,d-=t}else{let e=l-t,r=d+t,a=c+t,n=u-t,o=l+t,p=d-t,f=c-t,_=u+t;h(e,f,r,f,r,a,e,a,i,s),h(e,n,r,n,r,_,e,_,i,s),h(e,a,o,a,o,n,e,n,i,s),h(p,a,r,a,r,n,p,n,i,s)}}e._doFill&&(i=r??e._fillIndex,h(l,c,d,c,d,u,l,u,i,s))},e.square=(t,r,a)=>e.rect(t,r,a,a);let p;e.ellipseMode=t=>e._ellipseMode=t,e.ellipse=(t,a,n,o)=>{let i=(s=n==o?n:Math.max(n,o))<4?6:s<6?8:s<10?10:s<16?12:s<20?14:s<22?16:s<24?18:s<28?20:s<34?22:s<42?24:s<48?26:s<56?28:s<64?30:s<72?32:s<84?34:s<96?36:s<98?38:s<113?40:s<149?44:s<199?48:s<261?52:s<353?56:s<461?60:s<585?64:s<1200?70:s<1800?80:s<2400?90:100;var s;let l=Math.max(n,1)/2,d=n==o?l:Math.max(o,1)/2;e._matrixDirty&&e._saveMatrix();let c=e._transformIndex;if(e._doStroke){let r=e._strokeWeight/2;u(t,a,l+r,d+r,i,e._strokeIndex,c),l-=r,d-=r}e._doFill&&u(t,a,l,d,i,r??e._fillIndex,c)},e.circle=(t,r,a)=>e.ellipse(t,r,a,a),e.point=(t,a)=>{r=e._strokeIndex,e._doStroke=!1;let n=e._strokeWeight;n<2?(n=Math.round(n),e.rect(t,a,n,n)):e.ellipse(t,a,n,n),e._doStroke=!0,r=null},e.line=(t,a,n,o)=>{r=e._strokeIndex,e.push(),e._doStroke=!1,e.translate(t,-a),e.rotate(e.atan2(o-a,n-t));let i=Math.sqrt((n-t)**2+(o-a)**2),s=e._strokeWeight,l=s/2;e._rectMode="corner",s<4?e.rect(-l,-l,i+l,s):(e._ellipseMode="center",e.ellipse(0,0,s,s),e.ellipse(i,0,s,s),e.rect(0,-l,i,s)),e.pop(),r=null};let f=[];e.beginShape=()=>{p=0,f=[]},e.vertex=(t,r)=>{e._matrixDirty&&e._saveMatrix(),f.push(t,-r,e._fillIndex,e._transformIndex),p++},e.endShape=t=>{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){for(let e=1;e{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.background=(t,r,n,o)=>{if(e.push(),e.resetMatrix(),e._doStroke=!1,t.src){let r=e._imageMode;e._imageMode="corner",e.image(t,-a.hw,-a.hh,a.w,a.h),e._imageMode=r}else{let i=e._rectMode;e._rectMode="corner",e.fill(t,r,n,o),e.rect(-a.hw,-a.hh,a.w,a.h),e._rectMode=i}e.pop(),e._fillSet||(e._fillIndex=1)},e._hooks.preRender.push((()=>{e.pass.setPipeline(e._pipelines[0]);let t=Q5.device.createBuffer({size:4*i,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});new Float32Array(t.getMappedRange()).set(o.slice(0,i)),t.unmap(),e.pass.setVertexBuffer(0,t)})),e._hooks.postRender.push((()=>{i=0}))},Q5.renderers.webgpu.image=(e,t)=>{e._textureBindGroups=[];let r=[],a=Q5.device.createShaderModule({label:"imageVertexShader",code:"\nstruct VertexOutput {\n\t@builtin(position) position: vec4f,\n\t@location(0) texCoord: vec2f\n}\nstruct Uniforms {\n\thalfWidth: f32,\n\thalfHeight: f32\n}\n\n@group(0) @binding(0) var uniforms: Uniforms;\n@group(0) @binding(1) var transforms: array>;\n\n@vertex\nfn vertexMain(@location(0) pos: vec2f, @location(1) texCoord: vec2f, @location(2) transformIndex: f32) -> VertexOutput {\n\tvar vert = vec4f(pos, 0.0, 1.0);\n\tvert = transforms[i32(transformIndex)] * vert;\n\tvert.x /= uniforms.halfWidth;\n\tvert.y /= uniforms.halfHeight;\n\n\tvar output: VertexOutput;\n\toutput.position = vert;\n\toutput.texCoord = texCoord;\n\treturn output;\n}\n\t"}),n=Q5.device.createShaderModule({label:"imageFragmentShader",code:"\n@group(2) @binding(0) var samp: sampler;\n@group(2) @binding(1) var texture: texture_2d;\n\n@fragment\nfn fragmentMain(@location(0) texCoord: vec2f) -> @location(0) vec4f {\n\t// Sample the texture using the interpolated texture coordinate\n\treturn textureSample(texture, samp, texCoord);\n}\n\t"}),o=Q5.device.createBindGroupLayout({label:"textureLayout",entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,sampler:{type:"filtering"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,texture:{viewDimension:"2d",sampleType:"float"}}]});const i=Q5.device.createPipelineLayout({label:"imagePipelineLayout",bindGroupLayouts:[...e.bindGroupLayouts,o]});e._pipelineConfigs[1]={label:"imagePipeline",layout:i,vertex:{module:a,entryPoint:"vertexMain",buffers:[{arrayStride:0,attributes:[]},{arrayStride:20,attributes:[{shaderLocation:0,offset:0,format:"float32x2"},{shaderLocation:1,offset:8,format:"float32x2"},{shaderLocation:2,offset:16,format:"float32"}]}]},fragment:{module:n,entryPoint:"fragmentMain",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]);let s=Q5.device.createSampler({magFilter:"linear",minFilter:"linear"});e._textures=[];let l=0;e._createTexture=t=>{t.canvas&&(t=t.canvas);let r=[t.width,t.height,1],a=Q5.device.createTexture({size:r,format:"bgra8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT});Q5.device.queue.copyExternalImageToTexture({source:t},{texture:a,colorSpace:e.canvas.colorSpace},r),e._textures[l]=a,t.textureIndex=l;const n=Q5.device.createBindGroup({layout:o,entries:[{binding:0,resource:s},{binding:1,resource:a.createView()}]});e._textureBindGroups[l]=n,l=(l+1)%12e3,e._textures[l]&&(e._textures[l].destroy(),delete e._textures[l],delete e._textureBindGroups[l])},e.loadImage=e.loadTexture=r=>{t._preloadCount++;const a=new Image;return a.crossOrigin="Anonymous",a.onload=()=>{a.defaultWidth=a.width*e._defaultImageScale,a.defaultHeight=a.height*e._defaultImageScale,e._createTexture(a),t._preloadCount--},a.src=r,a},e.imageMode=t=>e._imageMode=t,e.image=(t,a,n,o,i)=>{if(t.canvas&&(t=t.canvas),null==t.textureIndex)return;e._matrixDirty&&e._saveMatrix();let s=e._transformIndex;o??=t.defaultWidth,i??=t.defaultHeight;let[l,d,c,h]=e._calcBox(a,n,o,i,e._imageMode);r.push(l,c,0,0,s,d,c,1,0,s,l,h,0,1,s,d,h,1,1,s),e.drawStack.push(1,t.textureIndex)},e._hooks.preRender.push((()=>{if(!e._textureBindGroups.length)return;e.pass.setPipeline(e._pipelines[1]);const t=Q5.device.createBuffer({size:4*r.length,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});new Float32Array(t.getMappedRange()).set(r),t.unmap(),e.pass.setVertexBuffer(1,t)})),e._hooks.postRender.push((()=>{r.length=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)=>{let r=Q5.device.createShaderModule({label:"MSDF text shader",code:"\n// Positions for simple quad geometry\nconst pos = array(vec2f(0, -1), vec2f(1, -1), vec2f(0, 0), vec2f(1, 0));\n\nstruct VertexInput {\n\t@builtin(vertex_index) vertex : u32,\n\t@builtin(instance_index) instance : u32\n}\nstruct VertexOutput {\n\t@builtin(position) position : vec4f,\n\t@location(0) texCoord : vec2f,\n\t@location(1) fillColor : vec4f\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\ttransformIndex: f32,\n\tfillIndex: f32,\n\tstrokeIndex: f32\n}\nstruct Uniforms {\n\thalfWidth: f32,\n\thalfHeight: f32\n}\n\n@group(0) @binding(0) var uniforms: Uniforms;\n@group(0) @binding(1) var transforms: array>;\n\n@group(1) @binding(0) var colors : array;\n\n@group(2) @binding(0) var fontTexture: texture_2d;\n@group(2) @binding(1) var fontSampler: sampler;\n@group(2) @binding(2) var fontChars: array;\n\n@group(3) @binding(0) var textChars: array;\n@group(3) @binding(1) var textMetadata: array;\n\n@vertex\nfn vertexMain(input : VertexInput) -> VertexOutput {\n\tlet char = textChars[input.instance];\n\n\tlet text = textMetadata[i32(char.w)];\n\n\tlet fontChar = fontChars[i32(char.z)];\n\n\tlet charPos = ((pos[input.vertex] * fontChar.size + char.xy + fontChar.offset) * text.scale) + text.pos;\n\n\tvar vert = vec4f(charPos, 0.0, 1.0);\n\tvert = transforms[i32(text.transformIndex)] * vert;\n\tvert.x /= uniforms.halfWidth;\n\tvert.y /= uniforms.halfHeight;\n\n\tvar output : VertexOutput;\n\toutput.position = vert;\n\toutput.texCoord = (pos[input.vertex] * vec2f(1, -1)) * fontChar.texExtent + fontChar.texOffset;\n\toutput.fillColor = colors[i32(text.fillIndex)];\n\treturn output;\n}\n\nfn sampleMsdf(texCoord: vec2f) -> f32 {\n\tlet c = textureSample(fontTexture, fontSampler, texCoord);\n\treturn max(min(c.r, c.g), min(max(c.r, c.g), c.b));\n}\n\n@fragment\nfn fragmentMain(input : VertexOutput) -> @location(0) vec4f {\n\t// pxRange (AKA distanceRange) comes from the msdfgen tool,\n\t// uses the default which is 4.\n\tlet pxRange = 4.0;\n\tlet sz = vec2f(textureDimensions(fontTexture, 0));\n\tlet dx = sz.x*length(vec2f(dpdxFine(input.texCoord.x), dpdyFine(input.texCoord.x)));\n\tlet dy = sz.y*length(vec2f(dpdxFine(input.texCoord.y), dpdyFine(input.texCoord.y)));\n\tlet toPixels = pxRange * inverseSqrt(dx * dx + dy * dy);\n\tlet sigDist = sampleMsdf(input.texCoord) - 0.5;\n\tlet pxDist = sigDist * toPixels;\n\tlet edgeWidth = 0.5;\n\tlet alpha = smoothstep(-edgeWidth, edgeWidth, pxDist);\n\tif (alpha < 0.001) {\n\t\tdiscard;\n\t}\n\treturn vec4f(input.fillColor.rgb, input.fillColor.a * alpha);\n}\n"}),a=Q5.device.createBindGroupLayout({label:"MSDF text group layout",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:"MSDF font group layout",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[2]={label:"msdf font pipeline",layout:i,vertex:{module:r,entryPoint:"vertexMain"},fragment:{module:r,entryPoint:"fragmentMain",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]);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={},d=e.createGraphics(1,1);d.colorMode(e.RGB,1),e.loadFont=(r,a)=>{if("json"!=r.slice(r.lastIndexOf(".")+1))return d.loadFont(r,a);let i=r.slice(r.lastIndexOf("/")+1,r.lastIndexOf("-"));return(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],_=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:_},f),"string"==typeof c.chars&&(c.chars=e.CSV.parse(c.chars," "),c.kernings=e.CSV.parse(c.kernings," "));let g=c.chars.length,x=Q5.device.createBuffer({size:32*g,usage:GPUBufferUsage.STORAGE,mappedAtCreation:!0}),m=new Float32Array(x.getMappedRange()),v=1/c.common.scaleW,y=1/c.common.scaleH,w={},b=0;for(let[e,t]of c.chars.entries())w[t.id]=t,w[t.id].charIndex=e,m[b]=t.x*v,m[b+1]=t.y*y,m[b+2]=t.width*v,m[b+3]=t.height*y,m[b+4]=t.width,m[b+5]=t.height,m[b+6]=t.xoffset,m[b+7]=-t.yoffset,b+=8;x.unmap();let S=Q5.device.createBindGroup({label:"msdf font bind group",layout:o,entries:[{binding:0,resource:_.createView()},{binding:1,resource:n},{binding:2,resource:{buffer:x}}]}),M=new Map;if(c.kernings)for(let e of c.kernings){let t=M.get(e.first);t||(t=new Map,M.set(e.first,t)),t.set(e.second,e.amount)}e._font=new s(S,c.common.lineHeight,w,M),e._font.index=e._fonts.length,e._fonts.push(e._font),l[a]=e._font,t._preloadCount--,i&&i(a)})(r,i,a),i},e._textSize=18,e._textAlign="left",e._textBaseline="alphabetic";let c=!1,h=22.5,u=4.5,p=1.25;e.textFont=t=>{e._font=l[t]},e.textSize=t=>{e._textSize=t,c||(h=t*p,u=h-t)},e.textLeading=t=>{e._font.lineHeight=h=t,u=h-e._textSize,p=h/e._textSize,c=!0},e.textAlign=(t,r)=>{e._textAlign=t,r&&(e._textBaseline=r)},e._charStack=[],e._textStack=[];let f,_=(e,t,r)=>{let a=0,n=0,o=0,i=0,s=0,l=[],d=t.charCodeAt(0);for(let c=0;c{if(!e._font)return void(navigator.onLine&&!f&&(f=!0,e.loadFont("https://q5js.org/fonts/YaHei-msdf.json")));if(t.length>n){let e=[],r=0;for(;r=t.length){e.push(t.slice(r));break}let o=t.lastIndexOf(" ",a);(-1==o||o{let o=0;"center"==d?o=-.5*s.width- -.5*(s.width-s.lineWidths[a]):"right"==d&&(o=s.width-s.lineWidths[a]),l[p]=e+o,l[p+1]=t+r,l[p+2]=n.charIndex,l[p+3]=u,p+=4}))}else s=_(e._font,t,((e,t,r,a)=>{l[p]=e,l[p+1]=t,l[p+2]=a.charIndex,l[p+3]=u,p+=4})),"alphabetic"==c?a-=e._textSize:"center"==c?a-=.5*e._textSize:"bottom"==c&&(a-=h);e._charStack.push(l);let g=[];e._matrixDirty&&e._saveMatrix(),g[0]=r,g[1]=-a,g[2]=e._textSize/44,g[3]=e._transformIndex,g[4]=e._fillSet?e._fillIndex:0,g[5]=e._strokeIndex,e._textStack.push(g),e.drawStack.push(2,s.printedCharCount,e._font.index)},e.textWidth=t=>e._font?_(e._font,t).width:0,e.createTextImage=(t,r,a)=>{if(d.textSize(e._textSize),e._doFill){let t=4*e._fillIndex;d.fill(colorStack.slice(t,t+4))}if(e._doStroke){let t=4*e._strokeIndex;d.stroke(colorStack.slice(t,t+4))}let n=d.createTextImage(t,r,a);if(null==n.canvas.textureIndex)e._createTexture(n);else if(n.modified){let t=n.canvas,r=[t.width,t.height,1],a=e._textures[t.textureIndex];Q5.device.queue.copyExternalImageToTexture({source:t},{texture:a,colorSpace:e.canvas.colorSpace},r),n.modified=!1}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(!e._charStack.length)return;let t=0;for(let r of e._charStack)t+=4*r.length;let r=Q5.device.createBuffer({size:t,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});new Float32Array(r.getMappedRange()).set(e._charStack.flat()),r.unmap();let n=6*e._textStack.length*4,o=Q5.device.createBuffer({label:"textBuffer",size:n,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST,mappedAtCreation:!0});new Float32Array(o.getMappedRange()).set(e._textStack.flat()),o.unmap(),e._textBindGroup=Q5.device.createBindGroup({label:"msdf text bind group",layout:a,entries:[{binding:0,resource:{buffer:r}},{binding:1,resource:{buffer:o}}]})})),e._hooks.postRender.push((()=>{e._charStack.length=0,e._textStack.length=0}))};