diff --git a/astro.config.mjs b/astro.config.mjs index 60ec9ac..412e959 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -12,7 +12,7 @@ const pwa = AstroPWA({ "favicon.svg", "p5-sandbox-icon-192x192.png", "p5-sandbox-icon-512x512.png", - "lib/p5.js", + // "lib/p5.js", "lib/p5.min.js", "lib/addons/p5.sound.js", "lib/addons/p5.sound.min.js", diff --git a/e2e/screenshots/basic-screenshot.png b/e2e/screenshots/basic-screenshot.png index 057cc0b..7b565ed 100644 Binary files a/e2e/screenshots/basic-screenshot.png and b/e2e/screenshots/basic-screenshot.png differ diff --git a/public/lib/p5.js b/public/lib/p5.js index 6c470be..56b282c 100644 --- a/public/lib/p5.js +++ b/public/lib/p5.js @@ -1,4 +1,4 @@ -/*! p5.js v1.9.0 November 28, 2023 */ +/*! p5.js v1.10.0 July 31, 2024 */ (function (f) { if (typeof exports === 'object' && typeof module !== 'undefined') { module.exports = f() @@ -317,7 +317,7 @@ 'params': [ { 'name': 'options', - 'description': '

An object containing clip settings.

\n', + 'description': '

an object containing clip settings.

\n', 'type': 'Object', 'optional': true } @@ -335,12 +335,12 @@ 'params': [ { 'name': 'callback', - 'description': '

A function that draws the mask shape.

\n', + 'description': '

a function that draws the mask shape.

\n', 'type': 'Function' }, { 'name': 'options', - 'description': '

An object containing clip settings.

\n', + 'description': '

an object containing clip settings.

\n', 'type': 'Object', 'optional': true } @@ -455,22 +455,26 @@ { 'name': 'r', 'description': '

normalized red value.

\n', - 'type': 'Number' + 'type': 'Number', + 'optional': true }, { 'name': 'g', 'description': '

normalized green value.

\n', - 'type': 'Number' + 'type': 'Number', + 'optional': true }, { 'name': 'b', 'description': '

normalized blue value.

\n', - 'type': 'Number' + 'type': 'Number', + 'optional': true }, { 'name': 'a', 'description': '

normalized alpha value.

\n', - 'type': 'Number' + 'type': 'Number', + 'optional': true } ], 'class': 'p5', @@ -1358,42 +1362,42 @@ 'params': [ { 'name': 'x1', - 'description': '

x-coordinate for the first anchor point

\n', + 'description': '

x-coordinate of the first anchor point.

\n', 'type': 'Number' }, { 'name': 'y1', - 'description': '

y-coordinate for the first anchor point

\n', + 'description': '

y-coordinate of the first anchor point.

\n', 'type': 'Number' }, { 'name': 'x2', - 'description': '

x-coordinate for the first control point

\n', + 'description': '

x-coordinate of the first control point.

\n', 'type': 'Number' }, { 'name': 'y2', - 'description': '

y-coordinate for the first control point

\n', + 'description': '

y-coordinate of the first control point.

\n', 'type': 'Number' }, { 'name': 'x3', - 'description': '

x-coordinate for the second control point

\n', + 'description': '

x-coordinate of the second control point.

\n', 'type': 'Number' }, { 'name': 'y3', - 'description': '

y-coordinate for the second control point

\n', + 'description': '

y-coordinate of the second control point.

\n', 'type': 'Number' }, { 'name': 'x4', - 'description': '

x-coordinate for the second anchor point

\n', + 'description': '

x-coordinate of the second anchor point.

\n', 'type': 'Number' }, { 'name': 'y4', - 'description': '

y-coordinate for the second anchor point

\n', + 'description': '

y-coordinate of the second anchor point.

\n', 'type': 'Number' } ], @@ -1413,7 +1417,7 @@ }, { 'name': 'z1', - 'description': '

z-coordinate for the first anchor point

\n', + 'description': '

z-coordinate of the first anchor point.

\n', 'type': 'Number' }, { @@ -1428,7 +1432,7 @@ }, { 'name': 'z2', - 'description': '

z-coordinate for the first control point

\n', + 'description': '

z-coordinate of the first control point.

\n', 'type': 'Number' }, { @@ -1443,7 +1447,7 @@ }, { 'name': 'z3', - 'description': '

z-coordinate for the second control point

\n', + 'description': '

z-coordinate of the second control point.

\n', 'type': 'Number' }, { @@ -1458,7 +1462,7 @@ }, { 'name': 'z4', - 'description': '

z-coordinate for the second anchor point

\n', + 'description': '

z-coordinate of the second anchor point.

\n', 'type': 'Number' } ], @@ -1471,7 +1475,7 @@ 'params': [ { 'name': 'detail', - 'description': '

resolution of the curves

\n', + 'description': '

number of segments to use. Defaults to 20.

\n', 'type': 'Number' } ], @@ -1483,27 +1487,27 @@ 'params': [ { 'name': 'a', - 'description': '

coordinate of first point on the curve

\n', + 'description': '

coordinate of first control point.

\n', 'type': 'Number' }, { 'name': 'b', - 'description': '

coordinate of first control point

\n', + 'description': '

coordinate of first anchor point.

\n', 'type': 'Number' }, { 'name': 'c', - 'description': '

coordinate of second control point

\n', + 'description': '

coordinate of second anchor point.

\n', 'type': 'Number' }, { 'name': 'd', - 'description': '

coordinate of second point on the curve

\n', + 'description': '

coordinate of second control point.

\n', 'type': 'Number' }, { 'name': 't', - 'description': '

value between 0 and 1

\n', + 'description': '

amount to interpolate between 0 and 1.

\n', 'type': 'Number' } ], @@ -1515,27 +1519,27 @@ 'params': [ { 'name': 'a', - 'description': '

coordinate of first point on the curve

\n', + 'description': '

coordinate of first anchor point.

\n', 'type': 'Number' }, { 'name': 'b', - 'description': '

coordinate of first control point

\n', + 'description': '

coordinate of first control point.

\n', 'type': 'Number' }, { 'name': 'c', - 'description': '

coordinate of second control point

\n', + 'description': '

coordinate of second control point.

\n', 'type': 'Number' }, { 'name': 'd', - 'description': '

coordinate of second point on the curve

\n', + 'description': '

coordinate of second anchor point.

\n', 'type': 'Number' }, { 'name': 't', - 'description': '

value between 0 and 1

\n', + 'description': '

amount to interpolate between 0 and 1.

\n', 'type': 'Number' } ], @@ -1551,42 +1555,42 @@ 'params': [ { 'name': 'x1', - 'description': '

x-coordinate for the beginning control point

\n', + 'description': '

x-coordinate of the first control point.

\n', 'type': 'Number' }, { 'name': 'y1', - 'description': '

y-coordinate for the beginning control point

\n', + 'description': '

y-coordinate of the first control point.

\n', 'type': 'Number' }, { 'name': 'x2', - 'description': '

x-coordinate for the first point

\n', + 'description': '

x-coordinate of the first anchor point.

\n', 'type': 'Number' }, { 'name': 'y2', - 'description': '

y-coordinate for the first point

\n', + 'description': '

y-coordinate of the first anchor point.

\n', 'type': 'Number' }, { 'name': 'x3', - 'description': '

x-coordinate for the second point

\n', + 'description': '

x-coordinate of the second anchor point.

\n', 'type': 'Number' }, { 'name': 'y3', - 'description': '

y-coordinate for the second point

\n', + 'description': '

y-coordinate of the second anchor point.

\n', 'type': 'Number' }, { 'name': 'x4', - 'description': '

x-coordinate for the ending control point

\n', + 'description': '

x-coordinate of the second control point.

\n', 'type': 'Number' }, { 'name': 'y4', - 'description': '

y-coordinate for the ending control point

\n', + 'description': '

y-coordinate of the second control point.

\n', 'type': 'Number' } ], @@ -1606,7 +1610,7 @@ }, { 'name': 'z1', - 'description': '

z-coordinate for the beginning control point

\n', + 'description': '

z-coordinate of the first control point.

\n', 'type': 'Number' }, { @@ -1621,7 +1625,7 @@ }, { 'name': 'z2', - 'description': '

z-coordinate for the first point

\n', + 'description': '

z-coordinate of the first anchor point.

\n', 'type': 'Number' }, { @@ -1636,7 +1640,7 @@ }, { 'name': 'z3', - 'description': '

z-coordinate for the second point

\n', + 'description': '

z-coordinate of the second anchor point.

\n', 'type': 'Number' }, { @@ -1651,7 +1655,7 @@ }, { 'name': 'z4', - 'description': '

z-coordinate for the ending control point

\n', + 'description': '

z-coordinate of the second control point.

\n', 'type': 'Number' } ], @@ -1664,7 +1668,7 @@ 'params': [ { 'name': 'resolution', - 'description': '

resolution of the curves

\n', + 'description': '

number of segments to use. Defaults to 20.

\n', 'type': 'Number' } ], @@ -1676,7 +1680,7 @@ 'params': [ { 'name': 'amount', - 'description': '

amount of deformation from the original vertices

\n', + 'description': '

amount of tightness.

\n', 'type': 'Number' } ], @@ -1688,27 +1692,27 @@ 'params': [ { 'name': 'a', - 'description': '

coordinate of first control point of the curve

\n', + 'description': '

coordinate of first anchor point.

\n', 'type': 'Number' }, { 'name': 'b', - 'description': '

coordinate of first point

\n', + 'description': '

coordinate of first control point.

\n', 'type': 'Number' }, { 'name': 'c', - 'description': '

coordinate of second point

\n', + 'description': '

coordinate of second control point.

\n', 'type': 'Number' }, { 'name': 'd', - 'description': '

coordinate of second control point

\n', + 'description': '

coordinate of second anchor point.

\n', 'type': 'Number' }, { 'name': 't', - 'description': '

value between 0 and 1

\n', + 'description': '

amount to interpolate between 0 and 1.

\n', 'type': 'Number' } ], @@ -1720,27 +1724,27 @@ 'params': [ { 'name': 'a', - 'description': '

coordinate of first control point

\n', + 'description': '

coordinate of first control point.

\n', 'type': 'Number' }, { 'name': 'b', - 'description': '

coordinate of first point on the curve

\n', + 'description': '

coordinate of first anchor point.

\n', 'type': 'Number' }, { 'name': 'c', - 'description': '

coordinate of second point on the curve

\n', + 'description': '

coordinate of second anchor point.

\n', 'type': 'Number' }, { 'name': 'd', - 'description': '

coordinate of second conrol point

\n', + 'description': '

coordinate of second control point.

\n', 'type': 'Number' }, { 'name': 't', - 'description': '

value between 0 and 1

\n', + 'description': '

amount to interpolate between 0 and 1.

\n', 'type': 'Number' } ], @@ -1757,7 +1761,7 @@ 'params': [ { 'name': 'kind', - 'description': '

either POINTS, LINES, TRIANGLES, TRIANGLE_FAN\n TRIANGLE_STRIP, QUADS, QUAD_STRIP or TESS

\n', + 'description': '

either POINTS, LINES, TRIANGLES, TRIANGLE_FAN\n TRIANGLE_STRIP, QUADS, QUAD_STRIP or TESS.

\n', 'type': 'Constant', 'optional': true } @@ -1774,32 +1778,32 @@ 'params': [ { 'name': 'x2', - 'description': '

x-coordinate for the first control point

\n', + 'description': '

x-coordinate of the first control point.

\n', 'type': 'Number' }, { 'name': 'y2', - 'description': '

y-coordinate for the first control point

\n', + 'description': '

y-coordinate of the first control point.

\n', 'type': 'Number' }, { 'name': 'x3', - 'description': '

x-coordinate for the second control point

\n', + 'description': '

x-coordinate of the second control point.

\n', 'type': 'Number' }, { 'name': 'y3', - 'description': '

y-coordinate for the second control point

\n', + 'description': '

y-coordinate of the second control point.

\n', 'type': 'Number' }, { 'name': 'x4', - 'description': '

x-coordinate for the anchor point

\n', + 'description': '

x-coordinate of the anchor point.

\n', 'type': 'Number' }, { 'name': 'y4', - 'description': '

y-coordinate for the anchor point

\n', + 'description': '

y-coordinate of the anchor point.

\n', 'type': 'Number' } ], @@ -1819,7 +1823,7 @@ }, { 'name': 'z2', - 'description': '

z-coordinate for the first control point (for WebGL mode)

\n', + 'description': '

z-coordinate of the first control point.

\n', 'type': 'Number' }, { @@ -1834,7 +1838,7 @@ }, { 'name': 'z3', - 'description': '

z-coordinate for the second control point (for WebGL mode)

\n', + 'description': '

z-coordinate of the second control point.

\n', 'type': 'Number' }, { @@ -1849,7 +1853,7 @@ }, { 'name': 'z4', - 'description': '

z-coordinate for the anchor point (for WebGL mode)

\n', + 'description': '

z-coordinate of the anchor point.

\n', 'type': 'Number' } ], @@ -1891,7 +1895,7 @@ }, { 'name': 'z', - 'description': '

z-coordinate of the vertex (for WebGL mode)

\n', + 'description': '

z-coordinate of the vertex.

\n', 'type': 'Number', 'optional': true } @@ -1933,22 +1937,22 @@ 'params': [ { 'name': 'cx', - 'description': '

x-coordinate for the control point

\n', + 'description': '

x-coordinate of the control point.

\n', 'type': 'Number' }, { 'name': 'cy', - 'description': '

y-coordinate for the control point

\n', + 'description': '

y-coordinate of the control point.

\n', 'type': 'Number' }, { 'name': 'x3', - 'description': '

x-coordinate for the anchor point

\n', + 'description': '

x-coordinate of the anchor point.

\n', 'type': 'Number' }, { 'name': 'y3', - 'description': '

y-coordinate for the anchor point

\n', + 'description': '

y-coordinate of the anchor point.

\n', 'type': 'Number' } ], @@ -1968,7 +1972,7 @@ }, { 'name': 'cz', - 'description': '

z-coordinate for the control point (for WebGL mode)

\n', + 'description': '

z-coordinate of the control point.

\n', 'type': 'Number' }, { @@ -1983,11 +1987,10 @@ }, { 'name': 'z3', - 'description': '

z-coordinate for the anchor point (for WebGL mode)

\n', + 'description': '

z-coordinate of the anchor point.

\n', 'type': 'Number' } - ], - 'chainable': 1 + ] } ] }, @@ -2000,12 +2003,12 @@ 'params': [ { 'name': 'x', - 'description': '

x-coordinate of the vertex

\n', + 'description': '

x-coordinate of the vertex.

\n', 'type': 'Number' }, { 'name': 'y', - 'description': '

y-coordinate of the vertex

\n', + 'description': '

y-coordinate of the vertex.

\n', 'type': 'Number' } ], @@ -2025,7 +2028,7 @@ }, { 'name': 'z', - 'description': '

z-coordinate of the vertex.\n Defaults to 0 if not specified.

\n', + 'description': '

z-coordinate of the vertex. Defaults to 0.

\n', 'type': 'Number', 'optional': true } @@ -2052,13 +2055,13 @@ }, { 'name': 'u', - 'description': '

the vertex\'s texture u-coordinate

\n', + 'description': '

u-coordinate of the vertex\'s texture. Defaults to 0.

\n', 'type': 'Number', 'optional': true }, { 'name': 'v', - 'description': '

the vertex\'s texture v-coordinate

\n', + 'description': '

v-coordinate of the vertex\'s texture. Defaults to 0.

\n', 'type': 'Number', 'optional': true } @@ -2076,8 +2079,8 @@ 'params': [ { 'name': 'vector', - 'description': '

A p5.Vector representing the vertex normal.

\n', - 'type': 'Vector' + 'description': '

vertex normal as a p5.Vector object.

\n', + 'type': 'p5.Vector' } ], 'chainable': 1 @@ -2086,17 +2089,17 @@ 'params': [ { 'name': 'x', - 'description': '

The x component of the vertex normal.

\n', + 'description': '

x-component of the vertex normal.

\n', 'type': 'Number' }, { 'name': 'y', - 'description': '

The y component of the vertex normal.

\n', + 'description': '

y-component of the vertex normal.

\n', 'type': 'Number' }, { 'name': 'z', - 'description': '

The z component of the vertex normal.

\n', + 'description': '

z-component of the vertex normal.

\n', 'type': 'Number' } ], @@ -2924,38 +2927,8 @@ 'class': 'p5', 'module': 'Foundation' }, - 'const': { - 'name': 'const', - 'class': 'p5', - 'module': 'Foundation' - }, - '===': { - 'name': '===', - 'class': 'p5', - 'module': 'Foundation' - }, - '>': { - 'name': '>', - 'class': 'p5', - 'module': 'Foundation' - }, - '>=': { - 'name': '>=', - 'class': 'p5', - 'module': 'Foundation' - }, - '<': { - 'name': '<', - 'class': 'p5', - 'module': 'Foundation' - }, - '<=': { - 'name': '<=', - 'class': 'p5', - 'module': 'Foundation' - }, - 'if-else': { - 'name': 'if-else', + 'if': { + 'name': 'if', 'class': 'p5', 'module': 'Foundation' }, @@ -2964,35 +2937,28 @@ 'class': 'p5', 'module': 'Foundation' }, - 'return': { - 'name': 'return', + 'Boolean': { + 'name': 'Boolean', 'class': 'p5', 'module': 'Foundation' }, - 'boolean': { - 'name': 'boolean', - 'params': [ - { - 'name': 'n', - 'description': '

value to parse

\n', - 'type': 'String|Boolean|Number|Array' - } - ], + 'String': { + 'name': 'String', 'class': 'p5', - 'module': 'Data' + 'module': 'Foundation' }, - 'string': { - 'name': 'string', + 'Number': { + 'name': 'Number', 'class': 'p5', 'module': 'Foundation' }, - 'number': { - 'name': 'number', + 'Object': { + 'name': 'Object', 'class': 'p5', 'module': 'Foundation' }, - 'object': { - 'name': 'object', + 'Array': { + 'name': 'Array', 'class': 'p5', 'module': 'Foundation' }, @@ -3011,6 +2977,11 @@ 'class': 'p5', 'module': 'Foundation' }, + 'console': { + 'name': 'console', + 'class': 'p5', + 'module': 'Foundation' + }, 'createCanvas': { 'name': 'createCanvas', 'class': 'p5', @@ -3019,24 +2990,26 @@ { 'params': [ { - 'name': 'w', - 'description': '

width of the canvas

\n', - 'type': 'Number' + 'name': 'width', + 'description': '

width of the canvas. Defaults to 100.

\n', + 'type': 'Number', + 'optional': true }, { - 'name': 'h', - 'description': '

height of the canvas

\n', - 'type': 'Number' + 'name': 'height', + 'description': '

height of the canvas. Defaults to 100.

\n', + 'type': 'Number', + 'optional': true }, { 'name': 'renderer', - 'description': '

either P2D or WEBGL

\n', + 'description': '

either P2D or WEBGL. Defaults to P2D.

\n', 'type': 'Constant', 'optional': true }, { 'name': 'canvas', - 'description': '

existing html canvas element

\n', + 'description': '

existing canvas element that should be used for the sketch.

\n', 'type': 'HTMLCanvasElement', 'optional': true } @@ -3045,14 +3018,16 @@ { 'params': [ { - 'name': 'w', + 'name': 'width', 'description': '', - 'type': 'Number' + 'type': 'Number', + 'optional': true }, { - 'name': 'h', + 'name': 'height', 'description': '', - 'type': 'Number' + 'type': 'Number', + 'optional': true }, { 'name': 'canvas', @@ -3068,18 +3043,18 @@ 'name': 'resizeCanvas', 'params': [ { - 'name': 'w', - 'description': '

width of the canvas

\n', + 'name': 'width', + 'description': '

width of the canvas.

\n', 'type': 'Number' }, { - 'name': 'h', - 'description': '

height of the canvas

\n', + 'name': 'height', + 'description': '

height of the canvas.

\n', 'type': 'Number' }, { 'name': 'noRedraw', - 'description': '

don\'t redraw the canvas immediately

\n', + 'description': '

whether to delay calling\n redraw(). Defaults\n to false.

\n', 'type': 'Boolean', 'optional': true } @@ -3100,24 +3075,24 @@ { 'params': [ { - 'name': 'w', - 'description': '

width of the offscreen graphics buffer

\n', + 'name': 'width', + 'description': '

width of the graphics buffer.

\n', 'type': 'Number' }, { - 'name': 'h', - 'description': '

height of the offscreen graphics buffer

\n', + 'name': 'height', + 'description': '

height of the graphics buffer.

\n', 'type': 'Number' }, { 'name': 'renderer', - 'description': '

either P2D or WEBGL\n undefined defaults to p2d

\n', + 'description': '

either P2D or WEBGL. Defaults to P2D.

\n', 'type': 'Constant', 'optional': true }, { 'name': 'canvas', - 'description': '

existing html canvas element

\n', + 'description': '

existing canvas element that should be\n used for the graphics buffer..

\n', 'type': 'HTMLCanvasElement', 'optional': true } @@ -3126,12 +3101,12 @@ { 'params': [ { - 'name': 'w', + 'name': 'width', 'description': '', 'type': 'Number' }, { - 'name': 'h', + 'name': 'height', 'description': '', 'type': 'Number' }, @@ -3150,7 +3125,7 @@ 'params': [ { 'name': 'options', - 'description': '

An optional object with configuration

\n', + 'description': '

configuration options.

\n', 'type': 'Object', 'optional': true } @@ -3158,12 +3133,25 @@ 'class': 'p5', 'module': 'Rendering' }, + 'clearDepth': { + 'name': 'clearDepth', + 'params': [ + { + 'name': 'depth', + 'description': '

amount of the depth buffer to clear between 0\n (none) and 1 (far clipping plane). Defaults to 1.

\n', + 'type': 'Number', + 'optional': true + } + ], + 'class': 'p5', + 'module': 'Rendering' + }, 'blendMode': { 'name': 'blendMode', 'params': [ { 'name': 'mode', - 'description': '

blend mode to set for canvas.\n either BLEND, DARKEST, LIGHTEST, DIFFERENCE, MULTIPLY,\n EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT,\n SOFT_LIGHT, DODGE, BURN, ADD, REMOVE or SUBTRACT

\n', + 'description': '

blend mode to set.\n either BLEND, DARKEST, LIGHTEST, DIFFERENCE, MULTIPLY,\n EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT,\n SOFT_LIGHT, DODGE, BURN, ADD, REMOVE or SUBTRACT

\n', 'type': 'Constant' } ], @@ -3205,7 +3193,7 @@ 'params': [ { 'name': 'n', - 'description': '

Redraw for n-times. The default value is 1.

\n', + 'description': '

number of times to run draw(). Defaults to 1.

\n', 'type': 'Integer', 'optional': true } @@ -3218,13 +3206,13 @@ 'params': [ { 'name': 'sketch', - 'description': '

a function containing a p5.js sketch

\n', + 'description': '

function containing the sketch.

\n', 'type': 'Object' }, { 'name': 'node', - 'description': '

ID or pointer to HTML DOM node to contain sketch in

\n', - 'type': 'String|Object' + 'description': '

ID or reference to the HTML element that will contain the sketch.

\n', + 'type': 'String|HTMLElement' } ], 'class': 'p5', @@ -3239,7 +3227,7 @@ 'params': [ { 'name': 'arr', - 'description': '

an array of numbers - should be 6 or 16 length (2×3 or 4×4 matrix values)

\n', + 'description': '

an array containing the elements of the transformation matrix. Its length should be either 6 (2D) or 16 (3D).

\n', 'type': 'Array' } ], @@ -3249,32 +3237,32 @@ 'params': [ { 'name': 'a', - 'description': '

numbers which define the 2×3 or 4×4 matrix to be multiplied

\n', + 'description': '

an element of the transformation matrix.

\n', 'type': 'Number' }, { 'name': 'b', - 'description': '

numbers which define the 2×3 or 4×4 matrix to be multiplied

\n', + 'description': '

an element of the transformation matrix.

\n', 'type': 'Number' }, { 'name': 'c', - 'description': '

numbers which define the 2×3 or 4×4 matrix to be multiplied

\n', + 'description': '

an element of the transformation matrix.

\n', 'type': 'Number' }, { 'name': 'd', - 'description': '

numbers which define the 2×3 or 4×4 matrix to be multiplied

\n', + 'description': '

an element of the transformation matrix.

\n', 'type': 'Number' }, { 'name': 'e', - 'description': '

numbers which define the 2×3 or 4×4 matrix to be multiplied

\n', + 'description': '

an element of the transformation matrix.

\n', 'type': 'Number' }, { 'name': 'f', - 'description': '

numbers which define the 2×3 or 4×4 matrix to be multiplied

\n', + 'description': '

an element of the transformation matrix.

\n', 'type': 'Number' } ], @@ -3314,52 +3302,52 @@ }, { 'name': 'g', - 'description': '

numbers which define the 4×4 matrix to be multiplied

\n', + 'description': '

an element of the transformation matrix.

\n', 'type': 'Number' }, { 'name': 'h', - 'description': '

numbers which define the 4×4 matrix to be multiplied

\n', + 'description': '

an element of the transformation matrix.

\n', 'type': 'Number' }, { 'name': 'i', - 'description': '

numbers which define the 4×4 matrix to be multiplied

\n', + 'description': '

an element of the transformation matrix.

\n', 'type': 'Number' }, { 'name': 'j', - 'description': '

numbers which define the 4×4 matrix to be multiplied

\n', + 'description': '

an element of the transformation matrix.

\n', 'type': 'Number' }, { 'name': 'k', - 'description': '

numbers which define the 4×4 matrix to be multiplied

\n', + 'description': '

an element of the transformation matrix.

\n', 'type': 'Number' }, { 'name': 'l', - 'description': '

numbers which define the 4×4 matrix to be multiplied

\n', + 'description': '

an element of the transformation matrix.

\n', 'type': 'Number' }, { 'name': 'm', - 'description': '

numbers which define the 4×4 matrix to be multiplied

\n', + 'description': '

an element of the transformation matrix.

\n', 'type': 'Number' }, { 'name': 'n', - 'description': '

numbers which define the 4×4 matrix to be multiplied

\n', + 'description': '

an element of the transformation matrix.

\n', 'type': 'Number' }, { 'name': 'o', - 'description': '

numbers which define the 4×4 matrix to be multiplied

\n', + 'description': '

an element of the transformation matrix.

\n', 'type': 'Number' }, { 'name': 'p', - 'description': '

numbers which define the 4×4 matrix to be multiplied

\n', + 'description': '

an element of the transformation matrix.

\n', 'type': 'Number' } ], @@ -3377,12 +3365,12 @@ 'params': [ { 'name': 'angle', - 'description': '

the angle of rotation, specified in radians\n or degrees, depending on current angleMode

\n', + 'description': '

angle of rotation in the current angleMode().

\n', 'type': 'Number' }, { 'name': 'axis', - 'description': '

(in 3d) the axis to rotate around

\n', + 'description': '

axis to rotate about in 3D.

\n', 'type': 'p5.Vector|Number[]', 'optional': true } @@ -3395,7 +3383,7 @@ 'params': [ { 'name': 'angle', - 'description': '

the angle of rotation, specified in radians\n or degrees, depending on current angleMode

\n', + 'description': '

angle of rotation in the current angleMode().

\n', 'type': 'Number' } ], @@ -3407,7 +3395,7 @@ 'params': [ { 'name': 'angle', - 'description': '

the angle of rotation, specified in radians\n or degrees, depending on current angleMode

\n', + 'description': '

angle of rotation in the current angleMode().

\n', 'type': 'Number' } ], @@ -3419,7 +3407,7 @@ 'params': [ { 'name': 'angle', - 'description': '

the angle of rotation, specified in radians\n or degrees, depending on current angleMode

\n', + 'description': '

angle of rotation in the current angleMode().

\n', 'type': 'Number' } ], @@ -3435,18 +3423,18 @@ 'params': [ { 'name': 's', - 'description': '

percent to scale the object, or percentage to\n scale the object in the x-axis if multiple arguments\n are given

\n', + 'description': '

amount to scale along the positive x-axis.

\n', 'type': 'Number|p5.Vector|Number[]' }, { 'name': 'y', - 'description': '

percent to scale the object in the y-axis

\n', + 'description': '

amount to scale along the positive y-axis. Defaults to s.

\n', 'type': 'Number', 'optional': true }, { 'name': 'z', - 'description': '

percent to scale the object in the z-axis (webgl only)

\n', + 'description': '

amount to scale along the positive z-axis. Defaults to y.

\n', 'type': 'Number', 'optional': true } @@ -3457,7 +3445,7 @@ 'params': [ { 'name': 'scales', - 'description': '

per-axis percents to scale the object

\n', + 'description': '

vector whose components should be used to scale.

\n', 'type': 'p5.Vector|Number[]' } ], @@ -3470,7 +3458,7 @@ 'params': [ { 'name': 'angle', - 'description': '

angle of shear specified in radians or degrees,\n depending on current angleMode

\n', + 'description': '

angle to shear by in the current angleMode().

\n', 'type': 'Number' } ], @@ -3482,7 +3470,7 @@ 'params': [ { 'name': 'angle', - 'description': '

angle of shear specified in radians or degrees,\n depending on current angleMode

\n', + 'description': '

angle to shear by in the current angleMode().

\n', 'type': 'Number' } ], @@ -3498,17 +3486,17 @@ 'params': [ { 'name': 'x', - 'description': '

left/right translation

\n', + 'description': '

amount to translate along the positive x-axis.

\n', 'type': 'Number' }, { 'name': 'y', - 'description': '

up/down translation

\n', + 'description': '

amount to translate along the positive y-axis.

\n', 'type': 'Number' }, { 'name': 'z', - 'description': '

forward/backward translation (WEBGL only)

\n', + 'description': '

amount to translate along the positive z-axis.

\n', 'type': 'Number', 'optional': true } @@ -3519,7 +3507,7 @@ 'params': [ { 'name': 'vector', - 'description': '

the vector to translate by

\n', + 'description': '

vector by which to translate.

\n', 'type': 'p5.Vector' } ], @@ -3532,13 +3520,13 @@ 'params': [ { 'name': 'key', - 'description': '', + 'description': '

name of the value.

\n', 'type': 'String' }, { 'name': 'value', - 'description': '', - 'type': 'String|Number|Object|Boolean|p5.Color|p5.Vector' + 'description': '

value to be stored.

\n', + 'type': 'String|Number|Boolean|Object|Array' } ], 'class': 'p5', @@ -3549,7 +3537,7 @@ 'params': [ { 'name': 'key', - 'description': '

name that you wish to use to store in local storage

\n', + 'description': '

name of the value.

\n', 'type': 'String' } ], @@ -3566,7 +3554,7 @@ 'params': [ { 'name': 'key', - 'description': '', + 'description': '

name of the value to remove.

\n', 'type': 'String' } ], @@ -4040,6 +4028,12 @@ 'type': 'String|Constant|Object', 'optional': true }, + { + 'name': 'flipped', + 'description': '

flip the capturing video and mirror the output with {flipped:true}. By\n default it is false.

\n', + 'type': 'Object', + 'optional': true + }, { 'name': 'callback', 'description': '

function to call once the stream\n has loaded.

\n', @@ -4197,7 +4191,7 @@ 'params': [ { 'name': 'event', - 'description': '

optional KeyboardEvent callback argument.

\n', + 'description': '

optional KeyboardEvent callback argument.

\n', 'type': 'KeyboardEvent', 'optional': true } @@ -4210,7 +4204,7 @@ 'params': [ { 'name': 'event', - 'description': '

optional KeyboardEvent callback argument.

\n', + 'description': '

optional KeyboardEvent callback argument.

\n', 'type': 'KeyboardEvent', 'optional': true } @@ -4223,7 +4217,7 @@ 'params': [ { 'name': 'event', - 'description': '

optional KeyboardEvent callback argument.

\n', + 'description': '

optional KeyboardEvent callback argument.

\n', 'type': 'KeyboardEvent', 'optional': true } @@ -4236,7 +4230,7 @@ 'params': [ { 'name': 'code', - 'description': '

The key to check for.

\n', + 'description': '

key to check.

\n', 'type': 'Number' } ], @@ -4308,7 +4302,7 @@ 'params': [ { 'name': 'event', - 'description': '

optional MouseEvent callback argument.

\n', + 'description': '

optional MouseEvent argument.

\n', 'type': 'MouseEvent', 'optional': true } @@ -4321,7 +4315,7 @@ 'params': [ { 'name': 'event', - 'description': '

optional MouseEvent callback argument.

\n', + 'description': '

optional MouseEvent argument.

\n', 'type': 'MouseEvent', 'optional': true } @@ -4334,7 +4328,7 @@ 'params': [ { 'name': 'event', - 'description': '

optional MouseEvent callback argument.

\n', + 'description': '

optional MouseEvent argument.

\n', 'type': 'MouseEvent', 'optional': true } @@ -4347,7 +4341,7 @@ 'params': [ { 'name': 'event', - 'description': '

optional MouseEvent callback argument.

\n', + 'description': '

optional MouseEvent argument.

\n', 'type': 'MouseEvent', 'optional': true } @@ -4360,7 +4354,7 @@ 'params': [ { 'name': 'event', - 'description': '

optional MouseEvent callback argument.

\n', + 'description': '

optional MouseEvent argument.

\n', 'type': 'MouseEvent', 'optional': true } @@ -4373,7 +4367,7 @@ 'params': [ { 'name': 'event', - 'description': '

optional MouseEvent callback argument.

\n', + 'description': '

optional MouseEvent argument.

\n', 'type': 'MouseEvent', 'optional': true } @@ -4386,7 +4380,7 @@ 'params': [ { 'name': 'event', - 'description': '

optional WheelEvent callback argument.

\n', + 'description': '

optional WheelEvent argument.

\n', 'type': 'WheelEvent', 'optional': true } @@ -4414,7 +4408,7 @@ 'params': [ { 'name': 'event', - 'description': '

optional TouchEvent callback argument.

\n', + 'description': '

optional TouchEvent argument.

\n', 'type': 'TouchEvent', 'optional': true } @@ -4427,7 +4421,7 @@ 'params': [ { 'name': 'event', - 'description': '

optional TouchEvent callback argument.

\n', + 'description': '

optional TouchEvent argument.

\n', 'type': 'TouchEvent', 'optional': true } @@ -4440,7 +4434,7 @@ 'params': [ { 'name': 'event', - 'description': '

optional TouchEvent callback argument.

\n', + 'description': '

optional TouchEvent argument.

\n', 'type': 'TouchEvent', 'optional': true } @@ -4474,7 +4468,7 @@ 'params': [ { 'name': 'selectedCanvas', - 'description': '

reference to a\n specific HTML5 canvas element.

\n', + 'description': '

reference to a\n specific HTML5 canvas element.

\n', 'type': 'p5.Framebuffer|p5.Element|HTMLCanvasElement' }, { @@ -4485,7 +4479,7 @@ }, { 'name': 'extension', - 'description': '

file extension, either \'jpg\' or \'png\'. Defaults to \'png\'.

\n', + 'description': '

file extension, either \'png\', \'webp\', or \'jpg\'. Defaults to \'png\'.

\n', 'type': 'String', 'optional': true } @@ -5163,107 +5157,45 @@ }, 'loadJSON': { 'name': 'loadJSON', - 'class': 'p5', - 'module': 'IO', - 'overloads': [ + 'params': [ { - 'params': [ - { - 'name': 'path', - 'description': '

name of the file or url to load

\n', - 'type': 'String' - }, - { - 'name': 'jsonpOptions', - 'description': '

options object for jsonp related settings

\n', - 'type': 'Object', - 'optional': true - }, - { - 'name': 'datatype', - 'description': '

"json" or "jsonp"

\n', - 'type': 'String', - 'optional': true - }, - { - 'name': 'callback', - 'description': '

function to be executed after\n loadJSON() completes, data is passed\n in as first argument

\n', - 'type': 'Function', - 'optional': true - }, - { - 'name': 'errorCallback', - 'description': '

function to be executed if\n there is an error, response is passed\n in as first argument

\n', - 'type': 'Function', - 'optional': true - } - ] + 'name': 'path', + 'description': '

path of the JSON file to be loaded.

\n', + 'type': 'String' }, { - 'params': [ - { - 'name': 'path', - 'description': '', - 'type': 'String' - }, - { - 'name': 'datatype', - 'description': '', - 'type': 'String' - }, - { - 'name': 'callback', - 'description': '', - 'type': 'Function', - 'optional': true - }, - { - 'name': 'errorCallback', - 'description': '', - 'type': 'Function', - 'optional': true - } - ] + 'name': 'successCallback', + 'description': '

function to call once the data is loaded. Will be passed the object.

\n', + 'type': 'Function', + 'optional': true }, { - 'params': [ - { - 'name': 'path', - 'description': '', - 'type': 'String' - }, - { - 'name': 'callback', - 'description': '', - 'type': 'Function' - }, - { - 'name': 'errorCallback', - 'description': '', - 'type': 'Function', - 'optional': true - } - ] + 'name': 'errorCallback', + 'description': '

function to call if the data fails to load. Will be passed an Error event object.

\n', + 'type': 'Function', + 'optional': true } - ] + ], + 'class': 'p5', + 'module': 'IO' }, 'loadStrings': { 'name': 'loadStrings', 'params': [ { - 'name': 'filename', - 'description': '

name of the file or url to load

\n', + 'name': 'path', + 'description': '

path of the text file to be loaded.

\n', 'type': 'String' }, { - 'name': 'callback', - 'description': '

function to be executed after loadStrings()\n completes, Array is passed in as first\n argument

\n', + 'name': 'successCallback', + 'description': '

function to call once the data is\n loaded. Will be passed the array.

\n', 'type': 'Function', 'optional': true }, { 'name': 'errorCallback', - 'description': '

function to be executed if\n there is an error, response is passed\n in as first argument

\n', + 'description': '

function to call if the data fails to\n load. Will be passed an Error event\n object.

\n', 'type': 'Function', 'optional': true } @@ -5311,19 +5243,19 @@ 'name': 'loadXML', 'params': [ { - 'name': 'filename', - 'description': '

name of the file or URL to load

\n', + 'name': 'path', + 'description': '

path of the XML file to be loaded.

\n', 'type': 'String' }, { - 'name': 'callback', - 'description': '

function to be executed after loadXML()\n completes, XML object is passed in as\n first argument

\n', + 'name': 'successCallback', + 'description': '

function to call once the data is\n loaded. Will be passed the\n p5.XML object.

\n', 'type': 'Function', 'optional': true }, { 'name': 'errorCallback', - 'description': '

function to be executed if\n there is an error, response is passed\n in as first argument

\n', + 'description': '

function to call if the data fails to\n load. Will be passed an Error event\n object.

\n', 'type': 'Function', 'optional': true } @@ -5604,12 +5536,12 @@ 'params': [ { 'name': 'name', - 'description': '

name of the file to be created

\n', + 'description': '

name of the file to create.

\n', 'type': 'String' }, { 'name': 'extension', - 'description': '', + 'description': '

format to use for the file.

\n', 'type': 'String', 'optional': true } @@ -5647,17 +5579,17 @@ 'params': [ { 'name': 'json', - 'description': '', + 'description': '

data to save.

\n', 'type': 'Array|Object' }, { 'name': 'filename', - 'description': '', + 'description': '

name of the file to be saved.

\n', 'type': 'String' }, { 'name': 'optimize', - 'description': '

If true, removes line breaks\n and spaces from the output\n file to optimize filesize\n (but not readability).

\n', + 'description': '

whether to trim unneeded whitespace. Defaults\n to true.

\n', 'type': 'Boolean', 'optional': true } @@ -5670,23 +5602,23 @@ 'params': [ { 'name': 'list', - 'description': '

string array to be written

\n', + 'description': '

data to save.

\n', 'type': 'String[]' }, { 'name': 'filename', - 'description': '

filename for output

\n', + 'description': '

name of file to be saved.

\n', 'type': 'String' }, { 'name': 'extension', - 'description': '

the filename\'s extension

\n', + 'description': '

format to use for the file.

\n', 'type': 'String', 'optional': true }, { 'name': 'isCRLF', - 'description': '

if true, change line-break to CRLF

\n', + 'description': '

whether to add \\r\\n to the end of each\n string. Defaults to false.

\n', 'type': 'Boolean', 'optional': true } @@ -5908,7 +5840,7 @@ 'params': [ { 'name': 'value', - 'description': '

the incoming value to be converted.

\n', + 'description': '

the value to be remapped.

\n', 'type': 'Number' }, { @@ -6425,7 +6357,7 @@ 'params': [ { 'name': 'size', - 'description': '

size of the letters in units of pixels

\n', + 'description': '

size of the letters in units of pixels.

\n', 'type': 'Number' } ], @@ -6446,7 +6378,7 @@ 'params': [ { 'name': 'style', - 'description': '

styling for text, either NORMAL,\n ITALIC, BOLD or BOLDITALIC

\n', + 'description': '

styling for text, either NORMAL,\n ITALIC, BOLD or BOLDITALIC.

\n', 'type': 'Constant' } ], @@ -6696,12 +6628,12 @@ 'params': [ { 'name': 'array', - 'description': '

Array to shuffle

\n', + 'description': '

array to shuffle.

\n', 'type': 'Array' }, { 'name': 'bool', - 'description': '

modify passed array

\n', + 'description': '

if true, shuffle the original array in place. Defaults to false.

\n', 'type': 'Boolean', 'optional': true } @@ -6774,15 +6706,28 @@ }, 'float': { 'name': 'float', - 'params': [ + 'class': 'p5', + 'module': 'Data', + 'overloads': [ { - 'name': 'str', - 'description': '

float string to parse

\n', - 'type': 'String' + 'params': [ + { + 'name': 'str', + 'description': '

string to convert.

\n', + 'type': 'String' + } + ] + }, + { + 'params': [ + { + 'name': 'ns', + 'description': '

array of strings to convert.

\n', + 'type': 'String[]' + } + ] } - ], - 'class': 'p5', - 'module': 'Data' + ] }, 'int': { 'name': 'int', @@ -6793,14 +6738,8 @@ 'params': [ { 'name': 'n', - 'description': '

value to parse

\n', + 'description': '

value to convert.

\n', 'type': 'String|Boolean|Number' - }, - { - 'name': 'radix', - 'description': '

the radix to convert to (default: 10)

\n', - 'type': 'Integer', - 'optional': true } ] }, @@ -6808,14 +6747,8 @@ 'params': [ { 'name': 'ns', - 'description': '

values to parse

\n', + 'description': '

values to convert.

\n', 'type': 'Array' - }, - { - 'name': 'radix', - 'description': '', - 'type': 'Integer', - 'optional': true } ] } @@ -6826,13 +6759,38 @@ 'params': [ { 'name': 'n', - 'description': '

value to parse

\n', - 'type': 'String|Boolean|Number|Array' + 'description': '

value to convert.

\n', + 'type': 'String|Boolean|Number' } ], 'class': 'p5', 'module': 'Data' }, + 'boolean': { + 'name': 'boolean', + 'class': 'p5', + 'module': 'Data', + 'overloads': [ + { + 'params': [ + { + 'name': 'n', + 'description': '

value to convert.

\n', + 'type': 'String|Boolean|Number' + } + ] + }, + { + 'params': [ + { + 'name': 'ns', + 'description': '

values to convert.

\n', + 'type': 'Array' + } + ] + } + ] + }, 'byte': { 'name': 'byte', 'class': 'p5', @@ -6842,7 +6800,7 @@ 'params': [ { 'name': 'n', - 'description': '

value to parse

\n', + 'description': '

value to convert.

\n', 'type': 'String|Boolean|Number' } ] @@ -6851,7 +6809,7 @@ 'params': [ { 'name': 'ns', - 'description': '

values to parse

\n', + 'description': '

values to convert.

\n', 'type': 'Array' } ] @@ -6867,7 +6825,7 @@ 'params': [ { 'name': 'n', - 'description': '

value to parse

\n', + 'description': '

value to convert.

\n', 'type': 'String|Number' } ] @@ -6876,7 +6834,7 @@ 'params': [ { 'name': 'ns', - 'description': '

values to parse

\n', + 'description': '

values to convert.

\n', 'type': 'Array' } ] @@ -6892,7 +6850,7 @@ 'params': [ { 'name': 'n', - 'description': '

value to parse

\n', + 'description': '

value to convert.

\n', 'type': 'String' } ] @@ -6901,8 +6859,8 @@ 'params': [ { 'name': 'ns', - 'description': '

values to parse

\n', - 'type': 'Array' + 'description': '

values to convert.

\n', + 'type': 'String[]' } ] } @@ -6917,12 +6875,12 @@ 'params': [ { 'name': 'n', - 'description': '

value to parse

\n', + 'description': '

value to convert.

\n', 'type': 'Number' }, { 'name': 'digits', - 'description': '', + 'description': '

number of digits to include.

\n', 'type': 'Number', 'optional': true } @@ -6932,7 +6890,7 @@ 'params': [ { 'name': 'ns', - 'description': '

array of values to parse

\n', + 'description': '

values to convert.

\n', 'type': 'Number[]' }, { @@ -6954,7 +6912,7 @@ 'params': [ { 'name': 'n', - 'description': '

value to parse

\n', + 'description': '

value to convert.

\n', 'type': 'String' } ] @@ -6963,8 +6921,8 @@ 'params': [ { 'name': 'ns', - 'description': '

values to parse

\n', - 'type': 'Array' + 'description': '

values to convert.

\n', + 'type': 'String[]' } ] } @@ -6975,12 +6933,12 @@ 'params': [ { 'name': 'list', - 'description': '

array of Strings to be joined

\n', + 'description': '

array of strings to combine.

\n', 'type': 'Array' }, { 'name': 'separator', - 'description': '

String to be placed between each item

\n', + 'description': '

character(s) to place between strings when they\'re combined.

\n', 'type': 'String' } ], @@ -6992,12 +6950,12 @@ 'params': [ { 'name': 'str', - 'description': '

the String to be searched

\n', + 'description': '

string to search.

\n', 'type': 'String' }, { 'name': 'regexp', - 'description': '

the regexp to be used for matching

\n', + 'description': '

regular expression to match.

\n', 'type': 'String' } ], @@ -7009,12 +6967,12 @@ 'params': [ { 'name': 'str', - 'description': '

the String to be searched

\n', + 'description': '

string to search.

\n', 'type': 'String' }, { 'name': 'regexp', - 'description': '

the regexp to be used for matching

\n', + 'description': '

regular expression to match.

\n', 'type': 'String' } ], @@ -7030,18 +6988,18 @@ 'params': [ { 'name': 'num', - 'description': '

the Number to format

\n', + 'description': '

number to format.

\n', 'type': 'Number|String' }, { 'name': 'left', - 'description': '

number of digits to the left of the\n decimal point

\n', + 'description': '

number of digits to include to the left of\n the decimal point.

\n', 'type': 'Integer|String', 'optional': true }, { 'name': 'right', - 'description': '

number of digits to the right of the\n decimal point

\n', + 'description': '

number of digits to include to the right\n of the decimal point.

\n', 'type': 'Integer|String', 'optional': true } @@ -7051,8 +7009,8 @@ 'params': [ { 'name': 'nums', - 'description': '

the Numbers to format

\n', - 'type': 'Array' + 'description': '

numbers to format.

\n', + 'type': 'Number[]' }, { 'name': 'left', @@ -7079,12 +7037,12 @@ 'params': [ { 'name': 'num', - 'description': '

the Number to format

\n', + 'description': '

number to format.

\n', 'type': 'Number|String' }, { 'name': 'right', - 'description': '

number of digits to the right of the\n decimal point

\n', + 'description': '

number of digits to include to the right\n of the decimal point.

\n', 'type': 'Integer|String', 'optional': true } @@ -7094,8 +7052,8 @@ 'params': [ { 'name': 'nums', - 'description': '

the Numbers to format

\n', - 'type': 'Array' + 'description': '

numbers to format.

\n', + 'type': 'Number[]' }, { 'name': 'right', @@ -7116,18 +7074,18 @@ 'params': [ { 'name': 'num', - 'description': '

the Number to format

\n', + 'description': '

number to format.

\n', 'type': 'Number' }, { 'name': 'left', - 'description': '

number of digits to the left of the decimal\n point

\n', + 'description': '

number of digits to include to the left of the\n decimal point.

\n', 'type': 'Integer', 'optional': true }, { 'name': 'right', - 'description': '

number of digits to the right of the\n decimal point

\n', + 'description': '

number of digits to include to the right of the\n decimal point.

\n', 'type': 'Integer', 'optional': true } @@ -7137,7 +7095,7 @@ 'params': [ { 'name': 'nums', - 'description': '

the Numbers to format

\n', + 'description': '

numbers to format.

\n', 'type': 'Number[]' }, { @@ -7165,18 +7123,18 @@ 'params': [ { 'name': 'num', - 'description': '

the Number to format

\n', + 'description': '

number to format.

\n', 'type': 'Number' }, { 'name': 'left', - 'description': '

number of digits to the left of the decimal\n point

\n', + 'description': '

number of digits to include to the left of the\n decimal point.

\n', 'type': 'Integer', 'optional': true }, { 'name': 'right', - 'description': '

number of digits to the right of the\n decimal point

\n', + 'description': '

number of digits to include to the right of the\n decimal point.

\n', 'type': 'Integer', 'optional': true } @@ -7186,7 +7144,7 @@ 'params': [ { 'name': 'nums', - 'description': '

the Numbers to format

\n', + 'description': '

numbers to format.

\n', 'type': 'Array' }, { @@ -7227,12 +7185,12 @@ 'params': [ { 'name': 'value', - 'description': '

the String to be split

\n', + 'description': '

string to split.

\n', 'type': 'String' }, { 'name': 'delim', - 'description': '

list of individual Strings that will be used as\n separators

\n', + 'description': '

character(s) to use for splitting the string.

\n', 'type': 'String', 'optional': true } @@ -7249,7 +7207,7 @@ 'params': [ { 'name': 'str', - 'description': '

a String to be trimmed

\n', + 'description': '

string to trim.

\n', 'type': 'String' } ] @@ -7258,8 +7216,8 @@ 'params': [ { 'name': 'strs', - 'description': '

an Array of Strings to be trimmed

\n', - 'type': 'Array' + 'description': '

strings to trim.

\n', + 'type': 'String[]' } ] } @@ -7315,7 +7273,7 @@ 'params': [ { 'name': 'callback', - 'description': '

A function that draws shapes.

\n', + 'description': '

function that draws the shape.

\n', 'type': 'Function' } ], @@ -7327,7 +7285,7 @@ 'params': [ { 'name': 'geometry', - 'description': '

The geometry whose resources should be freed

\n', + 'description': '

3D shape whose resources should be freed.

\n', 'type': 'p5.Geometry' } ], @@ -7339,25 +7297,25 @@ 'params': [ { 'name': 'width', - 'description': '

width of the plane

\n', + 'description': '

width of the plane.

\n', 'type': 'Number', 'optional': true }, { 'name': 'height', - 'description': '

height of the plane

\n', + 'description': '

height of the plane.

\n', 'type': 'Number', 'optional': true }, { 'name': 'detailX', - 'description': '

Optional number of triangle\n subdivisions in x-dimension

\n', + 'description': '

number of triangle subdivisions along the x-axis.

\n', 'type': 'Integer', 'optional': true }, { 'name': 'detailY', - 'description': '

Optional number of triangle\n subdivisions in y-dimension

\n', + 'description': '

number of triangle subdivisions along the y-axis.

\n', 'type': 'Integer', 'optional': true } @@ -7370,31 +7328,31 @@ 'params': [ { 'name': 'width', - 'description': '

width of the box

\n', + 'description': '

width of the box.

\n', 'type': 'Number', 'optional': true }, { 'name': 'height', - 'description': '

height of the box

\n', + 'description': '

height of the box.

\n', 'type': 'Number', 'optional': true }, { 'name': 'depth', - 'description': '

depth of the box

\n', + 'description': '

depth of the box.

\n', 'type': 'Number', 'optional': true }, { 'name': 'detailX', - 'description': '

Optional number of triangle\n subdivisions in x-dimension

\n', + 'description': '

number of triangle subdivisions along the x-axis.

\n', 'type': 'Integer', 'optional': true }, { 'name': 'detailY', - 'description': '

Optional number of triangle\n subdivisions in y-dimension

\n', + 'description': '

number of triangle subdivisions along the y-axis.

\n', 'type': 'Integer', 'optional': true } @@ -7407,19 +7365,19 @@ 'params': [ { 'name': 'radius', - 'description': '

radius of circle

\n', + 'description': '

radius of the sphere. Defaults to 50.

\n', 'type': 'Number', 'optional': true }, { 'name': 'detailX', - 'description': '

optional number of subdivisions in x-dimension

\n', + 'description': '

number of triangle subdivisions along the x-axis. Defaults to 24.

\n', 'type': 'Integer', 'optional': true }, { 'name': 'detailY', - 'description': '

optional number of subdivisions in y-dimension

\n', + 'description': '

number of triangle subdivisions along the y-axis. Defaults to 16.

\n', 'type': 'Integer', 'optional': true } @@ -7432,37 +7390,37 @@ 'params': [ { 'name': 'radius', - 'description': '

radius of the surface

\n', + 'description': '

radius of the cylinder. Defaults to 50.

\n', 'type': 'Number', 'optional': true }, { 'name': 'height', - 'description': '

height of the cylinder

\n', + 'description': '

height of the cylinder. Defaults to the value of radius.

\n', 'type': 'Number', 'optional': true }, { 'name': 'detailX', - 'description': '

number of subdivisions in x-dimension;\n default is 24

\n', + 'description': '

number of edges along the top and bottom. Defaults to 24.

\n', 'type': 'Integer', 'optional': true }, { 'name': 'detailY', - 'description': '

number of subdivisions in y-dimension;\n default is 1

\n', + 'description': '

number of triangle subdivisions along the y-axis. Defaults to 1.

\n', 'type': 'Integer', 'optional': true }, { 'name': 'bottomCap', - 'description': '

whether to draw the bottom of the cylinder

\n', + 'description': '

whether to draw the cylinder\'s bottom. Defaults to true.

\n', 'type': 'Boolean', 'optional': true }, { 'name': 'topCap', - 'description': '

whether to draw the top of the cylinder

\n', + 'description': '

whether to draw the cylinder\'s top. Defaults to true.

\n', 'type': 'Boolean', 'optional': true } @@ -7475,31 +7433,31 @@ 'params': [ { 'name': 'radius', - 'description': '

radius of the bottom surface

\n', + 'description': '

radius of the cone\'s base. Defaults to 50.

\n', 'type': 'Number', 'optional': true }, { 'name': 'height', - 'description': '

height of the cone

\n', + 'description': '

height of the cone. Defaults to the value of radius.

\n', 'type': 'Number', 'optional': true }, { 'name': 'detailX', - 'description': '

number of segments,\n the more segments the smoother geometry\n default is 24

\n', + 'description': '

number of edges used to draw the base. Defaults to 24.

\n', 'type': 'Integer', 'optional': true }, { 'name': 'detailY', - 'description': '

number of segments,\n the more segments the smoother geometry\n default is 1

\n', + 'description': '

number of triangle subdivisions along the y-axis. Defaults to 1.

\n', 'type': 'Integer', 'optional': true }, { 'name': 'cap', - 'description': '

whether to draw the base of the cone

\n', + 'description': '

whether to draw the cone\'s base. Defaults to true.

\n', 'type': 'Boolean', 'optional': true } @@ -7511,32 +7469,32 @@ 'name': 'ellipsoid', 'params': [ { - 'name': 'radiusx', - 'description': '

x-radius of ellipsoid

\n', + 'name': 'radiusX', + 'description': '

radius of the ellipsoid along the x-axis. Defaults to 50.

\n', 'type': 'Number', 'optional': true }, { - 'name': 'radiusy', - 'description': '

y-radius of ellipsoid

\n', + 'name': 'radiusY', + 'description': '

radius of the ellipsoid along the y-axis. Defaults to radiusX.

\n', 'type': 'Number', 'optional': true }, { - 'name': 'radiusz', - 'description': '

z-radius of ellipsoid

\n', + 'name': 'radiusZ', + 'description': '

radius of the ellipsoid along the z-axis. Defaults to radiusY.

\n', 'type': 'Number', 'optional': true }, { 'name': 'detailX', - 'description': '

number of segments,\n the more segments the smoother geometry\n default is 24. Avoid detail number above\n 150, it may crash the browser.

\n', + 'description': '

number of triangle subdivisions along the x-axis. Defaults to 24.

\n', 'type': 'Integer', 'optional': true }, { 'name': 'detailY', - 'description': '

number of segments,\n the more segments the smoother geometry\n default is 16. Avoid detail number above\n 150, it may crash the browser.

\n', + 'description': '

number of triangle subdivisions along the y-axis. Defaults to 16.

\n', 'type': 'Integer', 'optional': true } @@ -7549,25 +7507,25 @@ 'params': [ { 'name': 'radius', - 'description': '

radius of the whole ring

\n', + 'description': '

radius of the torus. Defaults to 50.

\n', 'type': 'Number', 'optional': true }, { 'name': 'tubeRadius', - 'description': '

radius of the tube

\n', + 'description': '

radius of the tube. Defaults to 10.

\n', 'type': 'Number', 'optional': true }, { 'name': 'detailX', - 'description': '

number of segments in x-dimension,\n the more segments the smoother geometry\n default is 24

\n', + 'description': '

number of edges that form the hole. Defaults to 24.

\n', 'type': 'Integer', 'optional': true }, { 'name': 'detailY', - 'description': '

number of segments in y-dimension,\n the more segments the smoother geometry\n default is 16

\n', + 'description': '

number of triangle subdivisions along the y-axis. Defaults to 16.

\n', 'type': 'Integer', 'optional': true } @@ -7580,25 +7538,25 @@ 'params': [ { 'name': 'sensitivityX', - 'description': '

sensitivity to mouse movement along X axis

\n', + 'description': '

sensitivity to movement along the x-axis. Defaults to 1.

\n', 'type': 'Number', 'optional': true }, { 'name': 'sensitivityY', - 'description': '

sensitivity to mouse movement along Y axis

\n', + 'description': '

sensitivity to movement along the y-axis. Defaults to 1.

\n', 'type': 'Number', 'optional': true }, { 'name': 'sensitivityZ', - 'description': '

sensitivity to scroll movement along Z axis

\n', + 'description': '

sensitivity to movement along the z-axis. Defaults to 1.

\n', 'type': 'Number', 'optional': true }, { 'name': 'options', - 'description': '

An optional object that can contain additional settings,\ndisableTouchActions - Boolean, default value is true.\nSetting this to true makes mobile interactions smoother by preventing\naccidental interactions with the page while orbiting. But if you\'re already\ndoing it via css or want the default touch actions, consider setting it to false.\nfreeRotation - Boolean, default value is false.\nBy default, horizontal movement of the mouse or touch pointer rotates the camera\naround the y-axis, and vertical movement rotates the camera around the x-axis.\nBut if setting this option to true, the camera always rotates in the direction\nthe pointer is moving. For zoom and move, the behavior is the same regardless of\ntrue/false.

\n', + 'description': '

object with two optional properties, disableTouchActions\n and freeRotation. Both are Booleans. disableTouchActions\n defaults to true and freeRotation defaults to false.

\n', 'type': 'Object', 'optional': true } @@ -7633,31 +7591,31 @@ }, { 'name': 'gridSize', - 'description': '

size of one side of the grid

\n', + 'description': '

side length of the grid.

\n', 'type': 'Number', 'optional': true }, { 'name': 'gridDivisions', - 'description': '

number of divisions in the grid

\n', + 'description': '

number of divisions in the grid.

\n', 'type': 'Number', 'optional': true }, { 'name': 'xOff', - 'description': '

X axis offset from origin (0,0,0)

\n', + 'description': '

offset from origin along the x-axis.

\n', 'type': 'Number', 'optional': true }, { 'name': 'yOff', - 'description': '

Y axis offset from origin (0,0,0)

\n', + 'description': '

offset from origin along the y-axis.

\n', 'type': 'Number', 'optional': true }, { 'name': 'zOff', - 'description': '

Z axis offset from origin (0,0,0)

\n', + 'description': '

offset from origin along the z-axis.

\n', 'type': 'Number', 'optional': true } @@ -7672,7 +7630,7 @@ }, { 'name': 'axesSize', - 'description': '

size of axes icon

\n', + 'description': '

length of axes icon markers.

\n', 'type': 'Number', 'optional': true }, @@ -7712,19 +7670,19 @@ }, { 'name': 'gridXOff', - 'description': '', + 'description': '

grid offset from the origin along the x-axis.

\n', 'type': 'Number', 'optional': true }, { 'name': 'gridYOff', - 'description': '', + 'description': '

grid offset from the origin along the y-axis.

\n', 'type': 'Number', 'optional': true }, { 'name': 'gridZOff', - 'description': '', + 'description': '

grid offset from the origin along the z-axis.

\n', 'type': 'Number', 'optional': true }, @@ -7736,19 +7694,19 @@ }, { 'name': 'axesXOff', - 'description': '', + 'description': '

axes icon offset from the origin along the x-axis.

\n', 'type': 'Number', 'optional': true }, { 'name': 'axesYOff', - 'description': '', + 'description': '

axes icon offset from the origin along the y-axis.

\n', 'type': 'Number', 'optional': true }, { 'name': 'axesZOff', - 'description': '', + 'description': '

axes icon offset from the origin along the z-axis.

\n', 'type': 'Number', 'optional': true } @@ -7770,22 +7728,22 @@ 'params': [ { 'name': 'v1', - 'description': '

red or hue value relative to\n the current color range

\n', + 'description': '

red or hue value in the current\n colorMode().

\n', 'type': 'Number' }, { 'name': 'v2', - 'description': '

green or saturation value\n relative to the current color range

\n', + 'description': '

green or saturation value in the current\n colorMode().

\n', 'type': 'Number' }, { 'name': 'v3', - 'description': '

blue or brightness value\n relative to the current color range

\n', + 'description': '

blue, brightness, or lightness value in the current\n colorMode().

\n', 'type': 'Number' }, { 'name': 'alpha', - 'description': '

alpha value relative to current\n color range (default is 0-255)

\n', + 'description': '

alpha (transparency) value in the current\n colorMode().

\n', 'type': 'Number', 'optional': true } @@ -7796,7 +7754,7 @@ 'params': [ { 'name': 'gray', - 'description': '

number specifying value between\n white and black

\n', + 'description': '

grayscale value between 0 and 255.

\n', 'type': 'Number' }, { @@ -7812,7 +7770,7 @@ 'params': [ { 'name': 'value', - 'description': '

a color string

\n', + 'description': '

color as a CSS string.

\n', 'type': 'String' } ], @@ -7822,7 +7780,7 @@ 'params': [ { 'name': 'values', - 'description': '

an array containing the red,green,blue &\n and alpha components of the color

\n', + 'description': '

color as an array of RGBA, HSBA, or HSLA\n values.

\n', 'type': 'Number[]' } ], @@ -7832,7 +7790,7 @@ 'params': [ { 'name': 'color', - 'description': '

color as a p5.Color

\n', + 'description': '

color as a p5.Color object.

\n', 'type': 'p5.Color' } ], @@ -7849,17 +7807,17 @@ 'params': [ { 'name': 'v1', - 'description': '

red or hue value relative to\n the current color range

\n', + 'description': '

red or hue value in the current\n colorMode().

\n', 'type': 'Number' }, { 'name': 'v2', - 'description': '

green or saturation value\n relative to the current color range

\n', + 'description': '

green or saturation value in the current\n colorMode().

\n', 'type': 'Number' }, { 'name': 'v3', - 'description': '

blue or brightness value\n relative to the current color range

\n', + 'description': '

blue, brightness, or lightness value in the current\n colorMode().

\n', 'type': 'Number' } ], @@ -7869,7 +7827,7 @@ 'params': [ { 'name': 'gray', - 'description': '

number specifying value between\n white and black

\n', + 'description': '

grayscale value between 0 and 255.

\n', 'type': 'Number' } ], @@ -7879,7 +7837,7 @@ 'params': [ { 'name': 'value', - 'description': '

color as a CSS string

\n', + 'description': '

color as a CSS string.

\n', 'type': 'String' } ], @@ -7889,7 +7847,7 @@ 'params': [ { 'name': 'values', - 'description': '

color as an array containing the\n red, green, and blue components

\n', + 'description': '

color as an array of RGBA, HSBA, or HSLA\n values.

\n', 'type': 'Number[]' } ], @@ -7899,7 +7857,7 @@ 'params': [ { 'name': 'color', - 'description': '

color as a p5.Color

\n', + 'description': '

color as a p5.Color object.

\n', 'type': 'p5.Color' } ], @@ -7916,32 +7874,32 @@ 'params': [ { 'name': 'v1', - 'description': '

red or hue value relative to the current\n color range

\n', + 'description': '

red or hue value in the current\n colorMode().

\n', 'type': 'Number' }, { 'name': 'v2', - 'description': '

green or saturation value relative to the\n current color range

\n', + 'description': '

green or saturation value in the current\n colorMode().

\n', 'type': 'Number' }, { 'name': 'v3', - 'description': '

blue or brightness value relative to the\n current color range

\n', + 'description': '

blue, brightness, or lightness value in the current\n colorMode().

\n', 'type': 'Number' }, { 'name': 'x', - 'description': '

x component of direction (inclusive range of -1 to 1)

\n', + 'description': '

x-component of the light\'s direction between -1 and 1.

\n', 'type': 'Number' }, { 'name': 'y', - 'description': '

y component of direction (inclusive range of -1 to 1)

\n', + 'description': '

y-component of the light\'s direction between -1 and 1.

\n', 'type': 'Number' }, { 'name': 'z', - 'description': '

z component of direction (inclusive range of -1 to 1)

\n', + 'description': '

z-component of the light\'s direction between -1 and 1.

\n', 'type': 'Number' } ], @@ -7966,7 +7924,7 @@ }, { 'name': 'direction', - 'description': '

direction of light as a\n p5.Vector

\n', + 'description': '

direction of the light as a\n p5.Vector object.

\n', 'type': 'p5.Vector' } ], @@ -7976,7 +7934,7 @@ 'params': [ { 'name': 'color', - 'description': '

color as a p5.Color,\n as an array, or as a CSS string

\n', + 'description': '

color as a p5.Color object,\n an array of color values, or as a CSS string.

\n', 'type': 'p5.Color|Number[]|String' }, { @@ -8023,32 +7981,32 @@ 'params': [ { 'name': 'v1', - 'description': '

red or hue value relative to the current\n color range

\n', + 'description': '

red or hue value in the current\n colorMode().

\n', 'type': 'Number' }, { 'name': 'v2', - 'description': '

green or saturation value relative to the\n current color range

\n', + 'description': '

green or saturation value in the current\n colorMode().

\n', 'type': 'Number' }, { 'name': 'v3', - 'description': '

blue or brightness value relative to the\n current color range

\n', + 'description': '

blue, brightness, or lightness value in the current\n colorMode().

\n', 'type': 'Number' }, { 'name': 'x', - 'description': '

x component of position

\n', + 'description': '

x-coordinate of the light.

\n', 'type': 'Number' }, { 'name': 'y', - 'description': '

y component of position

\n', + 'description': '

y-coordinate of the light.

\n', 'type': 'Number' }, { 'name': 'z', - 'description': '

z component of position

\n', + 'description': '

z-coordinate of the light.

\n', 'type': 'Number' } ], @@ -8073,7 +8031,7 @@ }, { 'name': 'position', - 'description': '

of light as a p5.Vector

\n', + 'description': '

position of the light as a\n p5.Vector object.

\n', 'type': 'p5.Vector' } ], @@ -8083,7 +8041,7 @@ 'params': [ { 'name': 'color', - 'description': '

color as a p5.Color,\n as an array, or as a CSS string

\n', + 'description': '

color as a p5.Color object,\n an array of color values, or a CSS string.

\n', 'type': 'p5.Color|Number[]|String' }, { @@ -8126,13 +8084,25 @@ 'params': [ { 'name': 'img', - 'description': '

image for the background

\n', + 'description': '

image to use as the light source.

\n', 'type': 'p5.image' } ], 'class': 'p5', 'module': '3D' }, + 'panorama': { + 'name': 'panorama', + 'params': [ + { + 'name': 'img', + 'description': '

360˚ image to use as the background.

\n', + 'type': 'p5.Image' + } + ], + 'class': 'p5', + 'module': '3D' + }, 'lights': { 'name': 'lights', 'class': 'p5', @@ -8143,17 +8113,17 @@ 'params': [ { 'name': 'constant', - 'description': '

CONSTANT value for determining falloff

\n', + 'description': '

constant value for calculating falloff.

\n', 'type': 'Number' }, { 'name': 'linear', - 'description': '

LINEAR value for determining falloff

\n', + 'description': '

linear value for calculating falloff.

\n', 'type': 'Number' }, { 'name': 'quadratic', - 'description': '

QUADRATIC value for determining falloff

\n', + 'description': '

quadratic value for calculating falloff.

\n', 'type': 'Number' } ], @@ -8169,58 +8139,58 @@ 'params': [ { 'name': 'v1', - 'description': '

red or hue value relative to the current color range

\n', + 'description': '

red or hue value in the current\n colorMode().

\n', 'type': 'Number' }, { 'name': 'v2', - 'description': '

green or saturation value relative to the current color range

\n', + 'description': '

green or saturation value in the current\n colorMode().

\n', 'type': 'Number' }, { 'name': 'v3', - 'description': '

blue or brightness value relative to the current color range

\n', + 'description': '

blue, brightness, or lightness value in the current\n colorMode().

\n', 'type': 'Number' }, { 'name': 'x', - 'description': '

x component of position

\n', + 'description': '

x-coordinate of the light.

\n', 'type': 'Number' }, { 'name': 'y', - 'description': '

y component of position

\n', + 'description': '

y-coordinate of the light.

\n', 'type': 'Number' }, { 'name': 'z', - 'description': '

z component of position

\n', + 'description': '

z-coordinate of the light.

\n', 'type': 'Number' }, { 'name': 'rx', - 'description': '

x component of light direction (inclusive range of -1 to 1)

\n', + 'description': '

x-component of light direction between -1 and 1.

\n', 'type': 'Number' }, { 'name': 'ry', - 'description': '

y component of light direction (inclusive range of -1 to 1)

\n', + 'description': '

y-component of light direction between -1 and 1.

\n', 'type': 'Number' }, { 'name': 'rz', - 'description': '

z component of light direction (inclusive range of -1 to 1)

\n', + 'description': '

z-component of light direction between -1 and 1.

\n', 'type': 'Number' }, { 'name': 'angle', - 'description': '

angle of cone. Defaults to PI/3

\n', + 'description': '

angle of the light cone. Defaults to PI / 3.

\n', 'type': 'Number', 'optional': true }, { 'name': 'concentration', - 'description': '

concentration of cone. Defaults to 100

\n', + 'description': '

concentration of the light. Defaults to 100.

\n', 'type': 'Number', 'optional': true } @@ -8231,17 +8201,17 @@ 'params': [ { 'name': 'color', - 'description': '

color as a p5.Color,\n as an array, or as a CSS string

\n', + 'description': '

color as a p5.Color object,\n an array of color values, or a CSS string.

\n', 'type': 'p5.Color|Number[]|String' }, { 'name': 'position', - 'description': '

position of light as a p5.Vector

\n', + 'description': '

position of the light as a p5.Vector object.

\n', 'type': 'p5.Vector' }, { 'name': 'direction', - 'description': '

direction of light as a p5.Vector

\n', + 'description': '

direction of light as a p5.Vector object.

\n', 'type': 'p5.Vector' }, { @@ -8550,29 +8520,29 @@ 'params': [ { 'name': 'path', - 'description': '

Path of the model to be loaded

\n', + 'description': '

path of the model to be loaded.

\n', 'type': 'String' }, { 'name': 'normalize', - 'description': '

If true, scale the model to a\n standardized size when loading

\n', + 'description': '

if true, scale the model to fit the canvas.

\n', 'type': 'Boolean' }, { 'name': 'successCallback', - 'description': '

Function to be called\n once the model is loaded. Will be passed\n the 3D model object.

\n', + 'description': '

function to call once the model is loaded. Will be passed\n the p5.Geometry object.

\n', 'type': 'function(p5.Geometry)', 'optional': true }, { 'name': 'failureCallback', - 'description': '

called with event error if\n the model fails to load.

\n', + 'description': '

function to call if the model fails to load. Will be passed an Error event object.

\n', 'type': 'Function(Event)', 'optional': true }, { 'name': 'fileType', - 'description': '

The file extension of the model\n (.stl, .obj).

\n', + 'description': '

model’s file extension. Either \'.obj\' or \'.stl\'.

\n', 'type': 'String', 'optional': true } @@ -8604,6 +8574,59 @@ 'optional': true } ] + }, + { + 'params': [ + { + 'name': 'path', + 'description': '', + 'type': 'String' + }, + { + 'name': 'options', + 'description': '

loading options.

\n', + 'type': 'Object', + 'optional': true, + 'props': [ + { + 'name': 'successCallback', + 'description': '', + 'type': 'function(p5.Geometry)', + 'optional': true + }, + { + 'name': 'failureCallback', + 'description': '', + 'type': 'Function(Event)', + 'optional': true + }, + { + 'name': 'fileType', + 'description': '', + 'type': 'String', + 'optional': true + }, + { + 'name': 'normalize', + 'description': '', + 'type': 'Boolean', + 'optional': true + }, + { + 'name': 'flipU', + 'description': '', + 'type': 'Boolean', + 'optional': true + }, + { + 'name': 'flipV', + 'description': '', + 'type': 'Boolean', + 'optional': true + } + ] + } + ] } ] }, @@ -8612,7 +8635,7 @@ 'params': [ { 'name': 'model', - 'description': '

Loaded 3d model to be rendered

\n', + 'description': '

3D shape to be drawn.

\n', 'type': 'p5.Geometry' } ], @@ -8624,23 +8647,23 @@ 'params': [ { 'name': 'vertFilename', - 'description': '

path to file containing vertex shader\nsource code

\n', + 'description': '

path of the vertex shader to be loaded.

\n', 'type': 'String' }, { 'name': 'fragFilename', - 'description': '

path to file containing fragment shader\nsource code

\n', + 'description': '

path of the fragment shader to be loaded.

\n', 'type': 'String' }, { - 'name': 'callback', - 'description': '

callback to be executed after loadShader\ncompletes. On success, the p5.Shader object is passed as the first argument.

\n', + 'name': 'successCallback', + 'description': '

function to call once the shader is loaded. Can be passed the\n p5.Shader object.

\n', 'type': 'Function', 'optional': true }, { - 'name': 'errorCallback', - 'description': '

callback to be executed when an error\noccurs inside loadShader. On error, the error is passed as the first\nargument.

\n', + 'name': 'failureCallback', + 'description': '

function to call if the shader fails to load. Can be passed an\n Error event object.

\n', 'type': 'Function', 'optional': true } @@ -8653,12 +8676,12 @@ 'params': [ { 'name': 'vertSrc', - 'description': '

source code for the vertex shader

\n', + 'description': '

source code for the vertex shader.

\n', 'type': 'String' }, { 'name': 'fragSrc', - 'description': '

source code for the fragment shader

\n', + 'description': '

source code for the fragment shader.

\n', 'type': 'String' } ], @@ -8670,7 +8693,7 @@ 'params': [ { 'name': 'fragSrc', - 'description': '

source code for the fragment shader

\n', + 'description': '

source code for the fragment shader.

\n', 'type': 'String' } ], @@ -8682,7 +8705,7 @@ 'params': [ { 'name': 's', - 'description': '

the p5.Shader object\nto use for rendering shapes.

\n', + 'description': '

p5.Shader object\n to apply.

\n', 'type': 'p5.Shader' } ], @@ -8699,7 +8722,7 @@ 'params': [ { 'name': 'tex', - 'description': '

image to use as texture

\n', + 'description': '

media to use as the texture.

\n', 'type': 'p5.Image|p5.MediaElement|p5.Graphics|p5.Texture|p5.Framebuffer|p5.FramebufferTexture' } ], @@ -8711,7 +8734,7 @@ 'params': [ { 'name': 'mode', - 'description': '

either IMAGE or NORMAL

\n', + 'description': '

either IMAGE or NORMAL.

\n', 'type': 'Constant' } ], @@ -8750,17 +8773,17 @@ 'params': [ { 'name': 'v1', - 'description': '

red or hue value relative to the current\n color range

\n', + 'description': '

red or hue value in the current\n colorMode().

\n', 'type': 'Number' }, { 'name': 'v2', - 'description': '

green or saturation value relative to the\n current color range

\n', + 'description': '

green or saturation value in the\n current colorMode().

\n', 'type': 'Number' }, { 'name': 'v3', - 'description': '

blue or brightness value relative to the\n current color range

\n', + 'description': '

blue, brightness, or lightness value in the\n current colorMode().

\n', 'type': 'Number' } ], @@ -8770,7 +8793,7 @@ 'params': [ { 'name': 'gray', - 'description': '

number specifying value between\n white and black

\n', + 'description': '

grayscale value between 0 (black) and 255 (white).

\n', 'type': 'Number' } ], @@ -8780,7 +8803,7 @@ 'params': [ { 'name': 'color', - 'description': '

color as a p5.Color,\n as an array, or as a CSS string

\n', + 'description': '

color as a p5.Color object,\n an array of color values, or a CSS string.

\n', 'type': 'p5.Color|Number[]|String' } ], @@ -8797,22 +8820,22 @@ 'params': [ { 'name': 'v1', - 'description': '

red or hue value relative to the current\n color range

\n', + 'description': '

red or hue value in the current\n colorMode().

\n', 'type': 'Number' }, { 'name': 'v2', - 'description': '

green or saturation value relative to the\n current color range

\n', + 'description': '

green or saturation value in the\n current colorMode().

\n', 'type': 'Number' }, { 'name': 'v3', - 'description': '

blue or brightness value relative to the\n current color range

\n', + 'description': '

blue, brightness, or lightness value in the\n current colorMode().

\n', 'type': 'Number' }, { 'name': 'alpha', - 'description': '

alpha value relative to current color\n range (default is 0-255)

\n', + 'description': '

alpha value in the current\n colorMode().

\n', 'type': 'Number', 'optional': true } @@ -8823,7 +8846,7 @@ 'params': [ { 'name': 'gray', - 'description': '

number specifying value between\n white and black

\n', + 'description': '

grayscale value between 0 (black) and 255 (white).

\n', 'type': 'Number' } ], @@ -8833,7 +8856,7 @@ 'params': [ { 'name': 'color', - 'description': '

color as a p5.Color,\n as an array, or as a CSS string

\n', + 'description': '

color as a p5.Color object,\n an array of color values, or a CSS string.

\n', 'type': 'p5.Color|Number[]|String' } ], @@ -8850,12 +8873,12 @@ 'params': [ { 'name': 'gray', - 'description': '

number specifying value between white and black.

\n', + 'description': '

grayscale value between 0 (black) and 255 (white).

\n', 'type': 'Number' }, { 'name': 'alpha', - 'description': '

alpha value relative to current color range\n (default is 0-255)

\n', + 'description': '

alpha value in the current current\n colorMode().

\n', 'type': 'Number', 'optional': true } @@ -8866,17 +8889,17 @@ 'params': [ { 'name': 'v1', - 'description': '

red or hue value relative to\n the current color range

\n', + 'description': '

red or hue value in\n the current colorMode().

\n', 'type': 'Number' }, { 'name': 'v2', - 'description': '

green or saturation value\n relative to the current color range

\n', + 'description': '

green or saturation value\n in the current colorMode().

\n', 'type': 'Number' }, { 'name': 'v3', - 'description': '

blue or brightness value\n relative to the current color range

\n', + 'description': '

blue, brightness, or lightness value\n in the current colorMode().

\n', 'type': 'Number' }, { @@ -8892,7 +8915,7 @@ 'params': [ { 'name': 'color', - 'description': '

color as a p5.Color,\n as an array, or as a CSS string

\n', + 'description': '

color as a p5.Color object,\n an array of color values, or a CSS string.

\n', 'type': 'p5.Color|Number[]|String' } ], @@ -8905,7 +8928,19 @@ 'params': [ { 'name': 'shine', - 'description': '

degree of shininess

\n', + 'description': '

amount of shine.

\n', + 'type': 'Number' + } + ], + 'class': 'p5', + 'module': '3D' + }, + 'metalness': { + 'name': 'metalness', + 'params': [ + { + 'name': 'metallic', + 'description': '

amount of metalness.

\n', 'type': 'Number' } ], @@ -8917,55 +8952,55 @@ 'params': [ { 'name': 'x', - 'description': '

camera position value on x axis

\n', + 'description': '

x-coordinate of the camera. Defaults to 0.

\n', 'type': 'Number', 'optional': true }, { 'name': 'y', - 'description': '

camera position value on y axis

\n', + 'description': '

y-coordinate of the camera. Defaults to 0.

\n', 'type': 'Number', 'optional': true }, { 'name': 'z', - 'description': '

camera position value on z axis

\n', + 'description': '

z-coordinate of the camera. Defaults to 800.

\n', 'type': 'Number', 'optional': true }, { 'name': 'centerX', - 'description': '

x coordinate representing center of the sketch

\n', + 'description': '

x-coordinate of the point the camera faces. Defaults to 0.

\n', 'type': 'Number', 'optional': true }, { 'name': 'centerY', - 'description': '

y coordinate representing center of the sketch

\n', + 'description': '

y-coordinate of the point the camera faces. Defaults to 0.

\n', 'type': 'Number', 'optional': true }, { 'name': 'centerZ', - 'description': '

z coordinate representing center of the sketch

\n', + 'description': '

z-coordinate of the point the camera faces. Defaults to 0.

\n', 'type': 'Number', 'optional': true }, { 'name': 'upX', - 'description': '

x component of direction \'up\' from camera

\n', + 'description': '

x-component of the camera’s "up" vector. Defaults to 0.

\n', 'type': 'Number', 'optional': true }, { 'name': 'upY', - 'description': '

y component of direction \'up\' from camera

\n', + 'description': '

y-component of the camera’s "up" vector. Defaults to 1.

\n', 'type': 'Number', 'optional': true }, { 'name': 'upZ', - 'description': '

z component of direction \'up\' from camera

\n', + 'description': '

z-component of the camera’s "up" vector. Defaults to 0.

\n', 'type': 'Number', 'optional': true } @@ -8978,25 +9013,25 @@ 'params': [ { 'name': 'fovy', - 'description': '

camera frustum vertical field of view,\n from bottom to top of view, in angleMode units

\n', + 'description': '

camera frustum vertical field of view. Defaults to\n 2 * atan(height / 2 / 800).

\n', 'type': 'Number', 'optional': true }, { 'name': 'aspect', - 'description': '

camera frustum aspect ratio

\n', + 'description': '

camera frustum aspect ratio. Defaults to\n width / height.

\n', 'type': 'Number', 'optional': true }, { 'name': 'near', - 'description': '

frustum near plane length

\n', + 'description': '

distance from the camera to the near clipping plane.\n Defaults to 0.1 * 800.

\n', 'type': 'Number', 'optional': true }, { 'name': 'far', - 'description': '

frustum far plane length

\n', + 'description': '

distance from the camera to the far clipping plane.\n Defaults to 10 * 800.

\n', 'type': 'Number', 'optional': true } @@ -9004,42 +9039,62 @@ 'class': 'p5', 'module': '3D' }, + 'linePerspective': { + 'name': 'linePerspective', + 'class': 'p5', + 'module': '3D', + 'overloads': [ + { + 'params': [ + { + 'name': 'enable', + 'description': '

whether to enable line perspective.

\n', + 'type': 'Boolean' + } + ] + }, + { + 'params': [ + ] + } + ] + }, 'ortho': { 'name': 'ortho', 'params': [ { 'name': 'left', - 'description': '

camera frustum left plane

\n', + 'description': '

x-coordinate of the frustum’s left plane. Defaults to -width / 2.

\n', 'type': 'Number', 'optional': true }, { 'name': 'right', - 'description': '

camera frustum right plane

\n', + 'description': '

x-coordinate of the frustum’s right plane. Defaults to width / 2.

\n', 'type': 'Number', 'optional': true }, { 'name': 'bottom', - 'description': '

camera frustum bottom plane

\n', + 'description': '

y-coordinate of the frustum’s bottom plane. Defaults to height / 2.

\n', 'type': 'Number', 'optional': true }, { 'name': 'top', - 'description': '

camera frustum top plane

\n', + 'description': '

y-coordinate of the frustum’s top plane. Defaults to -height / 2.

\n', 'type': 'Number', 'optional': true }, { 'name': 'near', - 'description': '

camera frustum near plane

\n', + 'description': '

z-coordinate of the frustum’s near plane. Defaults to 0.

\n', 'type': 'Number', 'optional': true }, { 'name': 'far', - 'description': '

camera frustum far plane

\n', + 'description': '

z-coordinate of the frustum’s far plane. Defaults to max(width, height) + 800.

\n', 'type': 'Number', 'optional': true } @@ -9052,37 +9107,37 @@ 'params': [ { 'name': 'left', - 'description': '

camera frustum left plane

\n', + 'description': '

x-coordinate of the frustum’s left plane. Defaults to -width / 20.

\n', 'type': 'Number', 'optional': true }, { 'name': 'right', - 'description': '

camera frustum right plane

\n', + 'description': '

x-coordinate of the frustum’s right plane. Defaults to width / 20.

\n', 'type': 'Number', 'optional': true }, { 'name': 'bottom', - 'description': '

camera frustum bottom plane

\n', + 'description': '

y-coordinate of the frustum’s bottom plane. Defaults to height / 20.

\n', 'type': 'Number', 'optional': true }, { 'name': 'top', - 'description': '

camera frustum top plane

\n', + 'description': '

y-coordinate of the frustum’s top plane. Defaults to -height / 20.

\n', 'type': 'Number', 'optional': true }, { 'name': 'near', - 'description': '

camera frustum near plane

\n', + 'description': '

z-coordinate of the frustum’s near plane. Defaults to 0.1 * 800.

\n', 'type': 'Number', 'optional': true }, { 'name': 'far', - 'description': '

camera frustum far plane

\n', + 'description': '

z-coordinate of the frustum’s far plane. Defaults to 10 * 800.

\n', 'type': 'Number', 'optional': true } @@ -9100,40 +9155,13 @@ 'params': [ { 'name': 'cam', - 'description': '

p5.Camera object

\n', + 'description': '

camera that should be made active.

\n', 'type': 'p5.Camera' } ], 'class': 'p5', 'module': '3D' }, - 'vertexNormal': { - 'name': 'vertexNormal', - 'params': [ - { - 'name': 'x', - 'description': '', - 'type': 'Number' - }, - { - 'name': 'y', - 'description': '', - 'type': 'Number' - }, - { - 'name': 'z', - 'description': '', - 'type': 'Number' - }, - { - 'name': 'v', - 'description': '', - 'type': 'Vector' - } - ], - 'class': 'p5', - 'module': 'Shape' - }, 'setAttributes': { 'name': 'setAttributes', 'class': 'p5', @@ -9657,7 +9685,7 @@ 'params': [ { 'name': 'class', - 'description': '

name of class to add

\n', + 'description': '

name of class to add.

\n', 'type': 'String' } ], @@ -9669,7 +9697,7 @@ 'params': [ { 'name': 'class', - 'description': '

name of class to remove

\n', + 'description': '

name of class to remove.

\n', 'type': 'String' } ], @@ -9681,7 +9709,7 @@ 'params': [ { 'name': 'c', - 'description': '

class name of class to check

\n', + 'description': '

name of class to check.

\n', 'type': 'String' } ], @@ -9693,7 +9721,7 @@ 'params': [ { 'name': 'c', - 'description': '

class name to toggle

\n', + 'description': '

class name to toggle.

\n', 'type': 'String' } ], @@ -9776,13 +9804,13 @@ 'params': [ { 'name': 'x', - 'description': '

x-position relative to upper left of window (optional)

\n', + 'description': '

x-position relative to top-left of window (optional)

\n', 'type': 'Number', 'optional': true }, { 'name': 'y', - 'description': '

y-position relative to upper left of window (optional)

\n', + 'description': '

y-position relative to top-left of window (optional)

\n', 'type': 'Number', 'optional': true }, @@ -9911,7 +9939,8 @@ { 'name': 'w', 'description': '

width of the element, either AUTO, or a number.

\n', - 'type': 'Number|Constant' + 'type': 'Number|Constant', + 'optional': true }, { 'name': 'h', @@ -9952,7 +9981,7 @@ 'params': [ { 'name': 'elmnt', - 'description': '

pass another p5.Element

\n', + 'description': '

another p5.Element.

\n', 'type': 'p5.Element', 'optional': true } @@ -9974,36 +10003,16 @@ }, 'createFramebuffer': { 'name': 'createFramebuffer', - 'class': 'p5.Graphics', - 'module': 'Rendering' - } - }, - 'JSON': { - 'stringify': { - 'name': 'stringify', - 'params': [ - { - 'name': 'object', - 'description': '

:Javascript object that you would like to convert to JSON

\n', - 'type': 'Object' - } - ], - 'class': 'JSON', - 'module': 'Foundation' - } - }, - 'console': { - 'log': { - 'name': 'log', 'params': [ { - 'name': 'message', - 'description': '

:Message that you would like to print to the console

\n', - 'type': 'String|Expression|Object' + 'name': 'options', + 'description': '

configuration options.

\n', + 'type': 'Object', + 'optional': true } ], - 'class': 'console', - 'module': 'Foundation' + 'class': 'p5.Graphics', + 'module': 'Rendering' } }, 'p5.TypedDict': { @@ -10907,8 +10916,8 @@ 'params': [ { 'name': 'data', - 'description': '

all data to be written by the PrintWriter

\n', - 'type': 'Array' + 'description': '

data to be written as a string, number,\n or array of strings and numbers.

\n', + 'type': 'String|Number|Array' } ], 'class': 'p5.PrintWriter', @@ -10919,8 +10928,8 @@ 'params': [ { 'name': 'data', - 'description': '

all data to be printed by the PrintWriter

\n', - 'type': 'Array' + 'description': '

data to be written as a string, number,\n or array of strings and numbers.

\n', + 'type': 'String|Number|Array' } ], 'class': 'p5.PrintWriter', @@ -11382,8 +11391,8 @@ 'name': 'setName', 'params': [ { - 'name': 'the', - 'description': '

new name of the node

\n', + 'name': 'name', + 'description': '

new tag name of the element.

\n', 'type': 'String' } ], @@ -11405,7 +11414,7 @@ 'params': [ { 'name': 'name', - 'description': '

element name

\n', + 'description': '

name of the elements to return.

\n', 'type': 'String', 'optional': true } @@ -11418,7 +11427,7 @@ 'params': [ { 'name': 'name', - 'description': '

element name or index

\n', + 'description': '

element name or index.

\n', 'type': 'String|Integer' } ], @@ -11429,8 +11438,8 @@ 'name': 'addChild', 'params': [ { - 'name': 'node', - 'description': '

a p5.XML Object which will be the child to be added

\n', + 'name': 'child', + 'description': '

child element to add.

\n', 'type': 'p5.XML' } ], @@ -11442,7 +11451,7 @@ 'params': [ { 'name': 'name', - 'description': '

element name or index

\n', + 'description': '

name or index of the child element to remove.

\n', 'type': 'String|Integer' } ], @@ -11463,8 +11472,8 @@ 'name': 'hasAttribute', 'params': [ { - 'name': 'the', - 'description': '

attribute to be checked

\n', + 'name': 'name', + 'description': '

name of the attribute to be checked.

\n', 'type': 'String' } ], @@ -11476,12 +11485,12 @@ 'params': [ { 'name': 'name', - 'description': '

the non-null full name of the attribute

\n', + 'description': '

name of the attribute to be checked.

\n', 'type': 'String' }, { 'name': 'defaultValue', - 'description': '

the default value of the attribute

\n', + 'description': '

value to return if the attribute doesn\'t exist.

\n', 'type': 'Number', 'optional': true } @@ -11494,12 +11503,12 @@ 'params': [ { 'name': 'name', - 'description': '

the non-null full name of the attribute

\n', + 'description': '

name of the attribute to be checked.

\n', 'type': 'String' }, { 'name': 'defaultValue', - 'description': '

the default value of the attribute

\n', + 'description': '

value to return if the attribute doesn\'t exist.

\n', 'type': 'Number', 'optional': true } @@ -11512,12 +11521,12 @@ 'params': [ { 'name': 'name', - 'description': '

the full name of the attribute

\n', + 'description': '

name of the attribute to be set.

\n', 'type': 'String' }, { 'name': 'value', - 'description': '

the value of the attribute

\n', + 'description': '

attribute\'s new value.

\n', 'type': 'Number|String|Boolean' } ], @@ -11529,7 +11538,7 @@ 'params': [ { 'name': 'defaultValue', - 'description': '

value returned if no content is found

\n', + 'description': '

value to return if the element has no\n content.

\n', 'type': 'String', 'optional': true } @@ -11541,8 +11550,8 @@ 'name': 'setContent', 'params': [ { - 'name': 'text', - 'description': '

the new content

\n', + 'name': 'content', + 'description': '

new content for the element.

\n', 'type': 'String' } ], @@ -12751,6 +12760,11 @@ 'name': 'random3D', 'class': 'p5.Vector', 'module': 'Math' + }, + 'clampToZero': { + 'name': 'clampToZero', + 'class': 'p5.Vector', + 'module': 'Math' } }, 'p5.Font': { @@ -12870,16 +12884,130 @@ }, 'perspective': { 'name': 'perspective', + 'params': [ + { + 'name': 'fovy', + 'description': '

camera frustum vertical field of view. Defaults to\n 2 * atan(height / 2 / 800).

\n', + 'type': 'Number', + 'optional': true + }, + { + 'name': 'aspect', + 'description': '

camera frustum aspect ratio. Defaults to\n width / height.

\n', + 'type': 'Number', + 'optional': true + }, + { + 'name': 'near', + 'description': '

distance from the camera to the near clipping plane.\n Defaults to 0.1 * 800.

\n', + 'type': 'Number', + 'optional': true + }, + { + 'name': 'far', + 'description': '

distance from the camera to the far clipping plane.\n Defaults to 10 * 800.

\n', + 'type': 'Number', + 'optional': true + } + ], 'class': 'p5.Camera', 'module': '3D' }, 'ortho': { 'name': 'ortho', + 'params': [ + { + 'name': 'left', + 'description': '

x-coordinate of the frustum’s left plane. Defaults to -width / 2.

\n', + 'type': 'Number', + 'optional': true + }, + { + 'name': 'right', + 'description': '

x-coordinate of the frustum’s right plane. Defaults to width / 2.

\n', + 'type': 'Number', + 'optional': true + }, + { + 'name': 'bottom', + 'description': '

y-coordinate of the frustum’s bottom plane. Defaults to height / 2.

\n', + 'type': 'Number', + 'optional': true + }, + { + 'name': 'top', + 'description': '

y-coordinate of the frustum’s top plane. Defaults to -height / 2.

\n', + 'type': 'Number', + 'optional': true + }, + { + 'name': 'near', + 'description': '

z-coordinate of the frustum’s near plane. Defaults to 0.

\n', + 'type': 'Number', + 'optional': true + }, + { + 'name': 'far', + 'description': '

z-coordinate of the frustum’s far plane. Defaults to max(width, height) + 800.

\n', + 'type': 'Number', + 'optional': true + } + ], 'class': 'p5.Camera', 'module': '3D' }, 'frustum': { 'name': 'frustum', + 'params': [ + { + 'name': 'left', + 'description': '

x-coordinate of the frustum’s left plane. Defaults to -width / 20.

\n', + 'type': 'Number', + 'optional': true + }, + { + 'name': 'right', + 'description': '

x-coordinate of the frustum’s right plane. Defaults to width / 20.

\n', + 'type': 'Number', + 'optional': true + }, + { + 'name': 'bottom', + 'description': '

y-coordinate of the frustum’s bottom plane. Defaults to height / 20.

\n', + 'type': 'Number', + 'optional': true + }, + { + 'name': 'top', + 'description': '

y-coordinate of the frustum’s top plane. Defaults to -height / 20.

\n', + 'type': 'Number', + 'optional': true + }, + { + 'name': 'near', + 'description': '

z-coordinate of the frustum’s near plane. Defaults to 0.1 * 800.

\n', + 'type': 'Number', + 'optional': true + }, + { + 'name': 'far', + 'description': '

z-coordinate of the frustum’s far plane. Defaults to 10 * 800.

\n', + 'type': 'Number', + 'optional': true + } + ], + 'class': 'p5.Camera', + 'module': '3D' + }, + 'roll': { + 'name': 'roll', + 'params': [ + { + 'name': 'angle', + 'description': '

amount to rotate camera in current\nangleMode units.

\n', + 'type': 'Number' + } + ], 'class': 'p5.Camera', 'module': '3D' }, @@ -12888,7 +13016,7 @@ 'params': [ { 'name': 'angle', - 'description': '

amount to rotate camera in current\nangleMode units.\nGreater than 0 values rotate counterclockwise (to the left).

\n', + 'description': '

amount to rotate in the current\n angleMode().

\n', 'type': 'Number' } ], @@ -12900,7 +13028,7 @@ 'params': [ { 'name': 'angle', - 'description': '

amount to rotate camera in current\nangleMode units.\nGreater than 0 values rotate counterclockwise (to the left).

\n', + 'description': '

amount to rotate in the current\n angleMode().

\n', 'type': 'Number' } ], @@ -12912,17 +13040,17 @@ 'params': [ { 'name': 'x', - 'description': '

x position of a point in world space

\n', + 'description': '

x-coordinate of the position where the camera should look in "world" space.

\n', 'type': 'Number' }, { 'name': 'y', - 'description': '

y position of a point in world space

\n', + 'description': '

y-coordinate of the position where the camera should look in "world" space.

\n', 'type': 'Number' }, { 'name': 'z', - 'description': '

z position of a point in world space

\n', + 'description': '

z-coordinate of the position where the camera should look in "world" space.

\n', 'type': 'Number' } ], @@ -12931,6 +13059,62 @@ }, 'camera': { 'name': 'camera', + 'params': [ + { + 'name': 'x', + 'description': '

x-coordinate of the camera. Defaults to 0.

\n', + 'type': 'Number', + 'optional': true + }, + { + 'name': 'y', + 'description': '

y-coordinate of the camera. Defaults to 0.

\n', + 'type': 'Number', + 'optional': true + }, + { + 'name': 'z', + 'description': '

z-coordinate of the camera. Defaults to 800.

\n', + 'type': 'Number', + 'optional': true + }, + { + 'name': 'centerX', + 'description': '

x-coordinate of the point the camera faces. Defaults to 0.

\n', + 'type': 'Number', + 'optional': true + }, + { + 'name': 'centerY', + 'description': '

y-coordinate of the point the camera faces. Defaults to 0.

\n', + 'type': 'Number', + 'optional': true + }, + { + 'name': 'centerZ', + 'description': '

z-coordinate of the point the camera faces. Defaults to 0.

\n', + 'type': 'Number', + 'optional': true + }, + { + 'name': 'upX', + 'description': '

x-component of the camera’s "up" vector. Defaults to 0.

\n', + 'type': 'Number', + 'optional': true + }, + { + 'name': 'upY', + 'description': '

x-component of the camera’s "up" vector. Defaults to 1.

\n', + 'type': 'Number', + 'optional': true + }, + { + 'name': 'upZ', + 'description': '

z-component of the camera’s "up" vector. Defaults to 0.

\n', + 'type': 'Number', + 'optional': true + } + ], 'class': 'p5.Camera', 'module': '3D' }, @@ -12939,17 +13123,17 @@ 'params': [ { 'name': 'x', - 'description': '

amount to move along camera\'s left-right axis

\n', + 'description': '

distance to move along the camera’s "local" x-axis.

\n', 'type': 'Number' }, { 'name': 'y', - 'description': '

amount to move along camera\'s up-down axis

\n', + 'description': '

distance to move along the camera’s "local" y-axis.

\n', 'type': 'Number' }, { 'name': 'z', - 'description': '

amount to move along camera\'s forward-backward axis

\n', + 'description': '

distance to move along the camera’s "local" z-axis.

\n', 'type': 'Number' } ], @@ -12961,17 +13145,17 @@ 'params': [ { 'name': 'x', - 'description': '

x position of a point in world space

\n', + 'description': '

x-coordinate in "world" space.

\n', 'type': 'Number' }, { 'name': 'y', - 'description': '

y position of a point in world space

\n', + 'description': '

y-coordinate in "world" space.

\n', 'type': 'Number' }, { 'name': 'z', - 'description': '

z position of a point in world space

\n', + 'description': '

z-coordinate in "world" space.

\n', 'type': 'Number' } ], @@ -12983,7 +13167,7 @@ 'params': [ { 'name': 'cam', - 'description': '

source camera

\n', + 'description': '

camera to copy.

\n', 'type': 'p5.Camera' } ], @@ -12995,17 +13179,17 @@ 'params': [ { 'name': 'cam0', - 'description': '

first p5.Camera

\n', + 'description': '

first camera.

\n', 'type': 'p5.Camera' }, { 'name': 'cam1', - 'description': '

second p5.Camera

\n', + 'description': '

second camera.

\n', 'type': 'p5.Camera' }, { 'name': 'amt', - 'description': '

amount to use for interpolation during slerp

\n', + 'description': '

amount of interpolation between 0.0 (cam0) and 1.0 (cam1).

\n', 'type': 'Number' } ], @@ -13024,12 +13208,12 @@ 'params': [ { 'name': 'width', - 'description': '', + 'description': '

width of the framebuffer.

\n', 'type': 'Number' }, { 'name': 'height', - 'description': '', + 'description': '

height of the framebuffer.

\n', 'type': 'Number' } ], @@ -13041,7 +13225,7 @@ 'params': [ { 'name': 'density', - 'description': '

A scaling factor for the number of pixels per\nside of the framebuffer

\n', + 'description': '

pixel density to set.

\n', 'type': 'Number', 'optional': true } @@ -13054,7 +13238,7 @@ 'params': [ { 'name': 'autoSized', - 'description': '

Whether or not the framebuffer should resize\nalong with the canvas it\'s attached to

\n', + 'description': '

whether to automatically resize the framebuffer to match the canvas.

\n', 'type': 'Boolean', 'optional': true } @@ -13087,13 +13271,18 @@ 'params': [ { 'name': 'callback', - 'description': '

A function to run that draws to the canvas. The\nfunction will immediately be run, but it will draw to the framebuffer\ninstead of the canvas.

\n', + 'description': '

function that draws to the framebuffer.

\n', 'type': 'Function' } ], 'class': 'p5.Framebuffer', 'module': 'Rendering' }, + 'loadPixels': { + 'name': 'loadPixels', + 'class': 'p5.Framebuffer', + 'module': 'Rendering' + }, 'get': { 'name': 'get', 'class': 'p5.Framebuffer', @@ -13103,22 +13292,22 @@ 'params': [ { 'name': 'x', - 'description': '

x-coordinate of the pixel

\n', + 'description': '

x-coordinate of the pixel. Defaults to 0.

\n', 'type': 'Number' }, { 'name': 'y', - 'description': '

y-coordinate of the pixel

\n', + 'description': '

y-coordinate of the pixel. Defaults to 0.

\n', 'type': 'Number' }, { 'name': 'w', - 'description': '

width of the section to be returned

\n', + 'description': '

width of the subsection to be returned.

\n', 'type': 'Number' }, { 'name': 'h', - 'description': '

height of the section to be returned

\n', + 'description': '

height of the subsection to be returned.

\n', 'type': 'Number' } ] @@ -13143,6 +13332,11 @@ } ] }, + 'updatePixels': { + 'name': 'updatePixels', + 'class': 'p5.Framebuffer', + 'module': 'Rendering' + }, 'color': { 'name': 'color', 'class': 'p5.Framebuffer', @@ -13155,28 +13349,63 @@ } }, 'p5.Geometry': { + 'vertices': { + 'name': 'vertices', + 'class': 'p5.Geometry', + 'module': 'Shape' + }, + 'vertexNormals': { + 'name': 'vertexNormals', + 'class': 'p5.Geometry', + 'module': 'Shape' + }, + 'faces': { + 'name': 'faces', + 'class': 'p5.Geometry', + 'module': 'Shape' + }, + 'uvs': { + 'name': 'uvs', + 'class': 'p5.Geometry', + 'module': 'Shape' + }, + 'calculateBoundingBox': { + 'name': 'calculateBoundingBox', + 'class': 'p5.Geometry', + 'module': 'Shape' + }, 'clearColors': { 'name': 'clearColors', 'class': 'p5.Geometry', 'module': 'Shape' }, - 'computeFaces': { - 'name': 'computeFaces', + 'saveObj': { + 'name': 'saveObj', + 'params': [ + { + 'name': 'fileName', + 'description': '

The name of the file to save the model as.\n If not specified, the default file name will be \'model.obj\'.

\n', + 'type': 'String', + 'optional': true, + 'optdefault': '\'model.obj\'' + } + ], 'class': 'p5.Geometry', 'module': 'Shape' }, - 'computeNormals': { - 'name': 'computeNormals', + 'saveStl': { + 'name': 'saveStl', 'params': [ { - 'name': 'shadingType', - 'description': '

shading type (FLAT for flat shading or SMOOTH for smooth shading) for buildGeometry() outputs. Defaults to FLAT.

\n', + 'name': 'fileName', + 'description': '

The name of the file to save the model as.\n If not specified, the default file name will be \'model.stl\'.

\n', 'type': 'String', - 'optional': true + 'optional': true, + 'optdefault': '\'model.stl\'' }, { 'name': 'options', - 'description': '

An optional object with configuration.

\n', + 'description': '

Optional settings. Options can include a boolean binary property, which\ncontrols whether or not a binary .stl file is saved. It defaults to false.

\n', 'type': 'Object', 'optional': true } @@ -13184,13 +13413,37 @@ 'class': 'p5.Geometry', 'module': 'Shape' }, - 'averageNormals': { - 'name': 'averageNormals', + 'flipU': { + 'name': 'flipU', + 'class': 'p5.Geometry', + 'module': 'Shape' + }, + 'flipV': { + 'name': 'flipV', 'class': 'p5.Geometry', 'module': 'Shape' }, - 'averagePoleNormals': { - 'name': 'averagePoleNormals', + 'computeFaces': { + 'name': 'computeFaces', + 'class': 'p5.Geometry', + 'module': 'Shape' + }, + 'computeNormals': { + 'name': 'computeNormals', + 'params': [ + { + 'name': 'shadingType', + 'description': '

shading type. either FLAT or SMOOTH. Defaults to FLAT.

\n', + 'type': 'String', + 'optional': true + }, + { + 'name': 'options', + 'description': '

shading options.

\n', + 'type': 'Object', + 'optional': true + } + ], 'class': 'p5.Geometry', 'module': 'Shape' }, @@ -13206,7 +13459,7 @@ 'params': [ { 'name': 'context', - 'description': '

The graphic or instance to copy this shader to.\nPass window if you need to copy to the main canvas.

\n', + 'description': '

WebGL context for the copied shader.

\n', 'type': 'p5|p5.Graphics' } ], @@ -13218,12 +13471,12 @@ 'params': [ { 'name': 'uniformName', - 'description': '

the name of the uniform.\nMust correspond to the name used in the vertex and fragment shaders

\n', + 'description': '

name of the uniform. Must match the name\n used in the vertex and fragment shaders.

\n', 'type': 'String' }, { 'name': 'data', - 'description': '

the data to associate with the uniform. The type can be\na boolean (true/false), a number, an array of numbers, or\nan image (p5.Image, p5.Graphics, p5.MediaElement, p5.Texture)

\n', + 'description': '

value to assign to the uniform. Must match the uniform’s data type.

\n', 'type': 'Boolean|Number|Number[]|p5.Image|p5.Graphics|p5.MediaElement|p5.Texture' } ], @@ -18066,7 +18319,7 @@ { 'base64-js': 20, 'buffer': 22, - 'ieee754': 268 + 'ieee754': 276 } ], 23: [ @@ -18092,7 +18345,7 @@ }; }, { - '../internals/is-object': 92 + '../internals/is-object': 93 } ], 25: [ @@ -18116,9 +18369,9 @@ }; }, { - '../internals/object-create': 108, - '../internals/object-define-property': 110, - '../internals/well-known-symbol': 166 + '../internals/object-create': 109, + '../internals/object-define-property': 111, + '../internals/well-known-symbol': 168 } ], 26: [ @@ -18132,7 +18385,7 @@ }; }, { - '../internals/string-multibyte': 141 + '../internals/string-multibyte': 143 } ], 27: [ @@ -18158,7 +18411,7 @@ }; }, { - '../internals/is-object': 92 + '../internals/is-object': 93 } ], 29: [ @@ -18321,15 +18574,15 @@ '../internals/classof': 47, '../internals/create-non-enumerable-property': 56, '../internals/descriptors': 61, - '../internals/global': 77, - '../internals/has': 78, - '../internals/is-object': 92, - '../internals/object-define-property': 110, - '../internals/object-get-prototype-of': 115, - '../internals/object-set-prototype-of': 119, - '../internals/redefine': 126, - '../internals/uid': 163, - '../internals/well-known-symbol': 166 + '../internals/global': 78, + '../internals/has': 79, + '../internals/is-object': 93, + '../internals/object-define-property': 111, + '../internals/object-get-prototype-of': 116, + '../internals/object-set-prototype-of': 120, + '../internals/redefine': 128, + '../internals/uid': 165, + '../internals/well-known-symbol': 168 } ], 31: [ @@ -18559,18 +18812,18 @@ '../internals/create-non-enumerable-property': 56, '../internals/descriptors': 61, '../internals/fails': 69, - '../internals/global': 77, - '../internals/ieee754': 83, - '../internals/internal-state': 88, - '../internals/object-define-property': 110, - '../internals/object-get-own-property-names': 113, - '../internals/object-get-prototype-of': 115, - '../internals/object-set-prototype-of': 119, - '../internals/redefine-all': 125, - '../internals/set-to-string-tag': 135, - '../internals/to-index': 151, - '../internals/to-integer': 153, - '../internals/to-length': 154 + '../internals/global': 78, + '../internals/ieee754': 84, + '../internals/internal-state': 89, + '../internals/object-define-property': 111, + '../internals/object-get-own-property-names': 114, + '../internals/object-get-prototype-of': 116, + '../internals/object-set-prototype-of': 120, + '../internals/redefine-all': 127, + '../internals/set-to-string-tag': 137, + '../internals/to-index': 153, + '../internals/to-integer': 155, + '../internals/to-length': 156 } ], 32: [ @@ -18606,9 +18859,9 @@ }; }, { - '../internals/to-absolute-index': 150, - '../internals/to-length': 154, - '../internals/to-object': 155 + '../internals/to-absolute-index': 152, + '../internals/to-length': 156, + '../internals/to-object': 157 } ], 33: [ @@ -18631,9 +18884,9 @@ }; }, { - '../internals/to-absolute-index': 150, - '../internals/to-length': 154, - '../internals/to-object': 155 + '../internals/to-absolute-index': 152, + '../internals/to-length': 156, + '../internals/to-object': 157 } ], 34: [ @@ -18712,11 +18965,11 @@ { '../internals/call-with-safe-iteration-closing': 44, '../internals/create-property': 58, - '../internals/function-bind-context': 72, - '../internals/get-iterator-method': 75, - '../internals/is-array-iterator-method': 89, - '../internals/to-length': 154, - '../internals/to-object': 155 + '../internals/function-bind-context': 73, + '../internals/get-iterator-method': 76, + '../internals/is-array-iterator-method': 90, + '../internals/to-length': 156, + '../internals/to-object': 157 } ], 36: [ @@ -18754,9 +19007,9 @@ }; }, { - '../internals/to-absolute-index': 150, - '../internals/to-indexed-object': 152, - '../internals/to-length': 154 + '../internals/to-absolute-index': 152, + '../internals/to-indexed-object': 154, + '../internals/to-length': 156 } ], 37: [ @@ -18836,10 +19089,10 @@ }, { '../internals/array-species-create': 43, - '../internals/function-bind-context': 72, - '../internals/indexed-object': 84, - '../internals/to-length': 154, - '../internals/to-object': 155 + '../internals/function-bind-context': 73, + '../internals/indexed-object': 85, + '../internals/to-length': 156, + '../internals/to-object': 157 } ], 38: [ @@ -18881,9 +19134,9 @@ { '../internals/array-method-is-strict': 40, '../internals/array-method-uses-to-length': 41, - '../internals/to-indexed-object': 152, - '../internals/to-integer': 153, - '../internals/to-length': 154 + '../internals/to-indexed-object': 154, + '../internals/to-integer': 155, + '../internals/to-length': 156 } ], 39: [ @@ -18913,7 +19166,7 @@ { '../internals/engine-v8-version': 66, '../internals/fails': 69, - '../internals/well-known-symbol': 166 + '../internals/well-known-symbol': 168 } ], 40: [ @@ -18972,7 +19225,7 @@ { '../internals/descriptors': 61, '../internals/fails': 69, - '../internals/has': 78 + '../internals/has': 79 } ], 42: [ @@ -19018,9 +19271,9 @@ }, { '../internals/a-function': 23, - '../internals/indexed-object': 84, - '../internals/to-length': 154, - '../internals/to-object': 155 + '../internals/indexed-object': 85, + '../internals/to-length': 156, + '../internals/to-object': 157 } ], 43: [ @@ -19046,9 +19299,9 @@ }; }, { - '../internals/is-array': 90, - '../internals/is-object': 92, - '../internals/well-known-symbol': 166 + '../internals/is-array': 91, + '../internals/is-object': 93, + '../internals/well-known-symbol': 168 } ], 44: [ @@ -19118,7 +19371,7 @@ }; }, { - '../internals/well-known-symbol': 166 + '../internals/well-known-symbol': 168 } ], 46: [ @@ -19162,8 +19415,8 @@ }, { '../internals/classof-raw': 46, - '../internals/to-string-tag-support': 159, - '../internals/well-known-symbol': 166 + '../internals/to-string-tag-support': 161, + '../internals/well-known-symbol': 168 } ], 48: [ @@ -19370,14 +19623,14 @@ '../internals/an-instance': 27, '../internals/define-iterator': 59, '../internals/descriptors': 61, - '../internals/function-bind-context': 72, - '../internals/internal-metadata': 87, - '../internals/internal-state': 88, - '../internals/iterate': 95, - '../internals/object-create': 108, - '../internals/object-define-property': 110, - '../internals/redefine-all': 125, - '../internals/set-species': 134 + '../internals/function-bind-context': 73, + '../internals/internal-metadata': 88, + '../internals/internal-state': 89, + '../internals/iterate': 96, + '../internals/object-create': 109, + '../internals/object-define-property': 111, + '../internals/redefine-all': 127, + '../internals/set-species': 136 } ], 49: [ @@ -19500,12 +19753,12 @@ '../internals/an-instance': 27, '../internals/an-object': 28, '../internals/array-iteration': 37, - '../internals/has': 78, - '../internals/internal-metadata': 87, - '../internals/internal-state': 88, - '../internals/is-object': 92, - '../internals/iterate': 95, - '../internals/redefine-all': 125 + '../internals/has': 79, + '../internals/internal-metadata': 88, + '../internals/internal-state': 89, + '../internals/is-object': 93, + '../internals/iterate': 96, + '../internals/redefine-all': 127 } ], 50: [ @@ -19616,14 +19869,14 @@ '../internals/check-correctness-of-iteration': 45, '../internals/export': 68, '../internals/fails': 69, - '../internals/global': 77, - '../internals/inherit-if-required': 85, - '../internals/internal-metadata': 87, - '../internals/is-forced': 91, - '../internals/is-object': 92, - '../internals/iterate': 95, - '../internals/redefine': 126, - '../internals/set-to-string-tag': 135 + '../internals/global': 78, + '../internals/inherit-if-required': 86, + '../internals/internal-metadata': 88, + '../internals/is-forced': 92, + '../internals/is-object': 93, + '../internals/iterate': 96, + '../internals/redefine': 128, + '../internals/set-to-string-tag': 137 } ], 51: [ @@ -19643,10 +19896,10 @@ }; }, { - '../internals/has': 78, - '../internals/object-define-property': 110, - '../internals/object-get-own-property-descriptor': 111, - '../internals/own-keys': 121 + '../internals/has': 79, + '../internals/object-define-property': 111, + '../internals/object-get-own-property-descriptor': 112, + '../internals/own-keys': 123 } ], 52: [ @@ -19668,7 +19921,7 @@ }; }, { - '../internals/well-known-symbol': 166 + '../internals/well-known-symbol': 168 } ], 53: [ @@ -19699,7 +19952,7 @@ }; }, { - '../internals/require-object-coercible': 131 + '../internals/require-object-coercible': 133 } ], 55: [ @@ -19725,10 +19978,10 @@ }, { '../internals/create-property-descriptor': 57, - '../internals/iterators': 97, - '../internals/iterators-core': 96, - '../internals/object-create': 108, - '../internals/set-to-string-tag': 135 + '../internals/iterators': 98, + '../internals/iterators-core': 97, + '../internals/object-create': 109, + '../internals/set-to-string-tag': 137 } ], 56: [ @@ -19747,7 +20000,7 @@ { '../internals/create-property-descriptor': 57, '../internals/descriptors': 61, - '../internals/object-define-property': 110 + '../internals/object-define-property': 111 } ], 57: [ @@ -19778,8 +20031,8 @@ }, { '../internals/create-property-descriptor': 57, - '../internals/object-define-property': 110, - '../internals/to-primitive': 158 + '../internals/object-define-property': 111, + '../internals/to-primitive': 160 } ], 59: [ @@ -19889,14 +20142,14 @@ '../internals/create-iterator-constructor': 55, '../internals/create-non-enumerable-property': 56, '../internals/export': 68, - '../internals/is-pure': 93, - '../internals/iterators': 97, - '../internals/iterators-core': 96, - '../internals/object-get-prototype-of': 115, - '../internals/object-set-prototype-of': 119, - '../internals/redefine': 126, - '../internals/set-to-string-tag': 135, - '../internals/well-known-symbol': 166 + '../internals/is-pure': 94, + '../internals/iterators': 98, + '../internals/iterators-core': 97, + '../internals/object-get-prototype-of': 116, + '../internals/object-set-prototype-of': 120, + '../internals/redefine': 128, + '../internals/set-to-string-tag': 137, + '../internals/well-known-symbol': 168 } ], 60: [ @@ -19914,10 +20167,10 @@ }; }, { - '../internals/has': 78, - '../internals/object-define-property': 110, - '../internals/path': 122, - '../internals/well-known-symbol-wrapped': 165 + '../internals/has': 79, + '../internals/object-define-property': 111, + '../internals/path': 124, + '../internals/well-known-symbol-wrapped': 167 } ], 61: [ @@ -19950,8 +20203,8 @@ }; }, { - '../internals/global': 77, - '../internals/is-object': 92 + '../internals/global': 78, + '../internals/is-object': 93 } ], 63: [ @@ -20010,7 +20263,7 @@ module.exports = getBuiltIn('navigator', 'userAgent') || ''; }, { - '../internals/get-built-in': 74 + '../internals/get-built-in': 75 } ], 66: [ @@ -20036,7 +20289,7 @@ }, { '../internals/engine-user-agent': 65, - '../internals/global': 77 + '../internals/global': 78 } ], 67: [ @@ -20121,11 +20374,11 @@ { '../internals/copy-constructor-properties': 51, '../internals/create-non-enumerable-property': 56, - '../internals/global': 77, - '../internals/is-forced': 91, - '../internals/object-get-own-property-descriptor': 111, - '../internals/redefine': 126, - '../internals/set-global': 133 + '../internals/global': 78, + '../internals/is-forced': 92, + '../internals/object-get-own-property-descriptor': 112, + '../internals/redefine': 128, + '../internals/set-global': 135 } ], 69: [ @@ -20274,13 +20527,49 @@ { '../internals/create-non-enumerable-property': 56, '../internals/fails': 69, - '../internals/redefine': 126, - '../internals/regexp-exec': 128, - '../internals/well-known-symbol': 166, - '../modules/es.regexp.exec': 205 + '../internals/redefine': 128, + '../internals/regexp-exec': 130, + '../internals/well-known-symbol': 168, + '../modules/es.regexp.exec': 213 } ], 71: [ + function (_dereq_, module, exports) { + 'use strict'; + var isArray = _dereq_('../internals/is-array'); + var toLength = _dereq_('../internals/to-length'); + var bind = _dereq_('../internals/function-bind-context'); + // `FlattenIntoArray` abstract operation + // https://tc39.github.io/proposal-flatMap/#sec-FlattenIntoArray + var flattenIntoArray = function (target, original, source, sourceLen, start, depth, mapper, thisArg) { + var targetIndex = start; + var sourceIndex = 0; + var mapFn = mapper ? bind(mapper, thisArg, 3) : false; + var element; + while (sourceIndex < sourceLen) { + if (sourceIndex in source) { + element = mapFn ? mapFn(source[sourceIndex], sourceIndex, original) : source[sourceIndex]; + if (depth > 0 && isArray(element)) { + targetIndex = flattenIntoArray(target, original, element, toLength(element.length), targetIndex, depth - 1) - 1; + } else { + if (targetIndex >= 9007199254740991) throw TypeError('Exceed the acceptable array length'); + target[targetIndex] = element; + } + targetIndex++; + } + sourceIndex++; + } + return targetIndex; + }; + module.exports = flattenIntoArray; + }, + { + '../internals/function-bind-context': 73, + '../internals/is-array': 91, + '../internals/to-length': 156 + } + ], + 72: [ function (_dereq_, module, exports) { var fails = _dereq_('../internals/fails'); module.exports = !fails(function () { @@ -20292,7 +20581,7 @@ '../internals/fails': 69 } ], - 72: [ + 73: [ function (_dereq_, module, exports) { var aFunction = _dereq_('../internals/a-function'); // optional / simple context binding @@ -20327,7 +20616,7 @@ '../internals/a-function': 23 } ], - 73: [ + 74: [ function (_dereq_, module, exports) { 'use strict'; var aFunction = _dereq_('../internals/a-function'); @@ -20361,10 +20650,10 @@ }, { '../internals/a-function': 23, - '../internals/is-object': 92 + '../internals/is-object': 93 } ], - 74: [ + 75: [ function (_dereq_, module, exports) { var path = _dereq_('../internals/path'); var global = _dereq_('../internals/global'); @@ -20376,11 +20665,11 @@ }; }, { - '../internals/global': 77, - '../internals/path': 122 + '../internals/global': 78, + '../internals/path': 124 } ], - 75: [ + 76: [ function (_dereq_, module, exports) { var classof = _dereq_('../internals/classof'); var Iterators = _dereq_('../internals/iterators'); @@ -20392,11 +20681,11 @@ }, { '../internals/classof': 47, - '../internals/iterators': 97, - '../internals/well-known-symbol': 166 + '../internals/iterators': 98, + '../internals/well-known-symbol': 168 } ], - 76: [ + 77: [ function (_dereq_, module, exports) { var anObject = _dereq_('../internals/an-object'); var getIteratorMethod = _dereq_('../internals/get-iterator-method'); @@ -20410,10 +20699,10 @@ }, { '../internals/an-object': 28, - '../internals/get-iterator-method': 75 + '../internals/get-iterator-method': 76 } ], - 77: [ + 78: [ function (_dereq_, module, exports) { (function (global) { var check = function (it) { @@ -20429,7 +20718,7 @@ { } ], - 78: [ + 79: [ function (_dereq_, module, exports) { var hasOwnProperty = { }.hasOwnProperty; @@ -20440,7 +20729,7 @@ { } ], - 79: [ + 80: [ function (_dereq_, module, exports) { module.exports = { }; @@ -20448,7 +20737,7 @@ { } ], - 80: [ + 81: [ function (_dereq_, module, exports) { var global = _dereq_('../internals/global'); module.exports = function (a, b) { @@ -20459,19 +20748,19 @@ }; }, { - '../internals/global': 77 + '../internals/global': 78 } ], - 81: [ + 82: [ function (_dereq_, module, exports) { var getBuiltIn = _dereq_('../internals/get-built-in'); module.exports = getBuiltIn('document', 'documentElement'); }, { - '../internals/get-built-in': 74 + '../internals/get-built-in': 75 } ], - 82: [ + 83: [ function (_dereq_, module, exports) { var DESCRIPTORS = _dereq_('../internals/descriptors'); var fails = _dereq_('../internals/fails'); @@ -20491,7 +20780,7 @@ '../internals/fails': 69 } ], - 83: [ + 84: [ function (_dereq_, module, exports) { // IEEE754 conversions based on https://github.com/feross/ieee754 // eslint-disable-next-line no-shadow-restricted-names @@ -20585,7 +20874,7 @@ { } ], - 84: [ + 85: [ function (_dereq_, module, exports) { var fails = _dereq_('../internals/fails'); var classof = _dereq_('../internals/classof-raw'); @@ -20605,7 +20894,7 @@ '../internals/fails': 69 } ], - 85: [ + 86: [ function (_dereq_, module, exports) { var isObject = _dereq_('../internals/is-object'); var setPrototypeOf = _dereq_('../internals/object-set-prototype-of'); @@ -20620,11 +20909,11 @@ }; }, { - '../internals/is-object': 92, - '../internals/object-set-prototype-of': 119 + '../internals/is-object': 93, + '../internals/object-set-prototype-of': 120 } ], - 86: [ + 87: [ function (_dereq_, module, exports) { var store = _dereq_('../internals/shared-store'); var functionToString = Function.toString; @@ -20637,10 +20926,10 @@ module.exports = store.inspectSource; }, { - '../internals/shared-store': 137 + '../internals/shared-store': 139 } ], - 87: [ + 88: [ function (_dereq_, module, exports) { var hiddenKeys = _dereq_('../internals/hidden-keys'); var isObject = _dereq_('../internals/is-object'); @@ -20704,15 +20993,15 @@ hiddenKeys[METADATA] = true; }, { - '../internals/freezing': 71, - '../internals/has': 78, - '../internals/hidden-keys': 79, - '../internals/is-object': 92, - '../internals/object-define-property': 110, - '../internals/uid': 163 + '../internals/freezing': 72, + '../internals/has': 79, + '../internals/hidden-keys': 80, + '../internals/is-object': 93, + '../internals/object-define-property': 111, + '../internals/uid': 165 } ], - 88: [ + 89: [ function (_dereq_, module, exports) { var NATIVE_WEAK_MAP = _dereq_('../internals/native-weak-map'); var global = _dereq_('../internals/global'); @@ -20779,15 +21068,15 @@ }, { '../internals/create-non-enumerable-property': 56, - '../internals/global': 77, - '../internals/has': 78, - '../internals/hidden-keys': 79, - '../internals/is-object': 92, - '../internals/native-weak-map': 103, - '../internals/shared-key': 136 + '../internals/global': 78, + '../internals/has': 79, + '../internals/hidden-keys': 80, + '../internals/is-object': 93, + '../internals/native-weak-map': 104, + '../internals/shared-key': 138 } ], - 89: [ + 90: [ function (_dereq_, module, exports) { var wellKnownSymbol = _dereq_('../internals/well-known-symbol'); var Iterators = _dereq_('../internals/iterators'); @@ -20799,11 +21088,11 @@ }; }, { - '../internals/iterators': 97, - '../internals/well-known-symbol': 166 + '../internals/iterators': 98, + '../internals/well-known-symbol': 168 } ], - 90: [ + 91: [ function (_dereq_, module, exports) { var classof = _dereq_('../internals/classof-raw'); // `IsArray` abstract operation @@ -20816,7 +21105,7 @@ '../internals/classof-raw': 46 } ], - 91: [ + 92: [ function (_dereq_, module, exports) { var fails = _dereq_('../internals/fails'); var replacement = /#|\.prototype\./; @@ -20837,7 +21126,7 @@ '../internals/fails': 69 } ], - 92: [ + 93: [ function (_dereq_, module, exports) { module.exports = function (it) { return typeof it === 'object' ? it !== null : typeof it === 'function'; @@ -20846,14 +21135,14 @@ { } ], - 93: [ + 94: [ function (_dereq_, module, exports) { module.exports = false; }, { } ], - 94: [ + 95: [ function (_dereq_, module, exports) { var isObject = _dereq_('../internals/is-object'); var classof = _dereq_('../internals/classof-raw'); @@ -20868,11 +21157,11 @@ }, { '../internals/classof-raw': 46, - '../internals/is-object': 92, - '../internals/well-known-symbol': 166 + '../internals/is-object': 93, + '../internals/well-known-symbol': 168 } ], - 95: [ + 96: [ function (_dereq_, module, exports) { var anObject = _dereq_('../internals/an-object'); var isArrayIteratorMethod = _dereq_('../internals/is-array-iterator-method'); @@ -20922,13 +21211,13 @@ { '../internals/an-object': 28, '../internals/call-with-safe-iteration-closing': 44, - '../internals/function-bind-context': 72, - '../internals/get-iterator-method': 75, - '../internals/is-array-iterator-method': 89, - '../internals/to-length': 154 + '../internals/function-bind-context': 73, + '../internals/get-iterator-method': 76, + '../internals/is-array-iterator-method': 90, + '../internals/to-length': 156 } ], - 96: [ + 97: [ function (_dereq_, module, exports) { 'use strict'; var getPrototypeOf = _dereq_('../internals/object-get-prototype-of'); @@ -20969,13 +21258,13 @@ }, { '../internals/create-non-enumerable-property': 56, - '../internals/has': 78, - '../internals/is-pure': 93, - '../internals/object-get-prototype-of': 115, - '../internals/well-known-symbol': 166 + '../internals/has': 79, + '../internals/is-pure': 94, + '../internals/object-get-prototype-of': 116, + '../internals/well-known-symbol': 168 } ], - 97: [ + 98: [ function (_dereq_, module, exports) { module.exports = { }; @@ -20983,7 +21272,7 @@ { } ], - 98: [ + 99: [ function (_dereq_, module, exports) { // `Math.sign` method implementation // https://tc39.github.io/ecma262/#sec-math.sign @@ -20995,7 +21284,7 @@ { } ], - 99: [ + 100: [ function (_dereq_, module, exports) { var global = _dereq_('../internals/global'); var getOwnPropertyDescriptor = _dereq_('../internals/object-get-own-property-descriptor').f; @@ -21089,21 +21378,21 @@ { '../internals/classof-raw': 46, '../internals/engine-is-ios': 64, - '../internals/global': 77, - '../internals/object-get-own-property-descriptor': 111, - '../internals/task': 148 + '../internals/global': 78, + '../internals/object-get-own-property-descriptor': 112, + '../internals/task': 150 } ], - 100: [ + 101: [ function (_dereq_, module, exports) { var global = _dereq_('../internals/global'); module.exports = global.Promise; }, { - '../internals/global': 77 + '../internals/global': 78 } ], - 101: [ + 102: [ function (_dereq_, module, exports) { var fails = _dereq_('../internals/fails'); module.exports = !!Object.getOwnPropertySymbols && !fails(function () { @@ -21116,7 +21405,7 @@ '../internals/fails': 69 } ], - 102: [ + 103: [ function (_dereq_, module, exports) { var fails = _dereq_('../internals/fails'); var wellKnownSymbol = _dereq_('../internals/well-known-symbol'); @@ -21141,11 +21430,11 @@ }, { '../internals/fails': 69, - '../internals/is-pure': 93, - '../internals/well-known-symbol': 166 + '../internals/is-pure': 94, + '../internals/well-known-symbol': 168 } ], - 103: [ + 104: [ function (_dereq_, module, exports) { var global = _dereq_('../internals/global'); var inspectSource = _dereq_('../internals/inspect-source'); @@ -21153,11 +21442,11 @@ module.exports = typeof WeakMap === 'function' && /native code/.test(inspectSource(WeakMap)); }, { - '../internals/global': 77, - '../internals/inspect-source': 86 + '../internals/global': 78, + '../internals/inspect-source': 87 } ], - 104: [ + 105: [ function (_dereq_, module, exports) { 'use strict'; var aFunction = _dereq_('../internals/a-function'); @@ -21181,7 +21470,7 @@ '../internals/a-function': 23 } ], - 105: [ + 106: [ function (_dereq_, module, exports) { var isRegExp = _dereq_('../internals/is-regexp'); module.exports = function (it) { @@ -21192,10 +21481,10 @@ }; }, { - '../internals/is-regexp': 94 + '../internals/is-regexp': 95 } ], - 106: [ + 107: [ function (_dereq_, module, exports) { var global = _dereq_('../internals/global'); var globalIsFinite = global.isFinite; @@ -21206,10 +21495,10 @@ }; }, { - '../internals/global': 77 + '../internals/global': 78 } ], - 107: [ + 108: [ function (_dereq_, module, exports) { 'use strict'; var DESCRIPTORS = _dereq_('../internals/descriptors'); @@ -21279,14 +21568,14 @@ { '../internals/descriptors': 61, '../internals/fails': 69, - '../internals/indexed-object': 84, - '../internals/object-get-own-property-symbols': 114, - '../internals/object-keys': 117, - '../internals/object-property-is-enumerable': 118, - '../internals/to-object': 155 + '../internals/indexed-object': 85, + '../internals/object-get-own-property-symbols': 115, + '../internals/object-keys': 118, + '../internals/object-property-is-enumerable': 119, + '../internals/to-object': 157 } ], - 108: [ + 109: [ function (_dereq_, module, exports) { var anObject = _dereq_('../internals/an-object'); var defineProperties = _dereq_('../internals/object-define-properties'); @@ -21365,13 +21654,13 @@ '../internals/an-object': 28, '../internals/document-create-element': 62, '../internals/enum-bug-keys': 67, - '../internals/hidden-keys': 79, - '../internals/html': 81, - '../internals/object-define-properties': 109, - '../internals/shared-key': 136 + '../internals/hidden-keys': 80, + '../internals/html': 82, + '../internals/object-define-properties': 110, + '../internals/shared-key': 138 } ], - 109: [ + 110: [ function (_dereq_, module, exports) { var DESCRIPTORS = _dereq_('../internals/descriptors'); var definePropertyModule = _dereq_('../internals/object-define-property'); @@ -21392,11 +21681,11 @@ { '../internals/an-object': 28, '../internals/descriptors': 61, - '../internals/object-define-property': 110, - '../internals/object-keys': 117 + '../internals/object-define-property': 111, + '../internals/object-keys': 118 } ], - 110: [ + 111: [ function (_dereq_, module, exports) { var DESCRIPTORS = _dereq_('../internals/descriptors'); var IE8_DOM_DEFINE = _dereq_('../internals/ie8-dom-define'); @@ -21421,11 +21710,11 @@ { '../internals/an-object': 28, '../internals/descriptors': 61, - '../internals/ie8-dom-define': 82, - '../internals/to-primitive': 158 + '../internals/ie8-dom-define': 83, + '../internals/to-primitive': 160 } ], - 111: [ + 112: [ function (_dereq_, module, exports) { var DESCRIPTORS = _dereq_('../internals/descriptors'); var propertyIsEnumerableModule = _dereq_('../internals/object-property-is-enumerable'); @@ -21450,14 +21739,14 @@ { '../internals/create-property-descriptor': 57, '../internals/descriptors': 61, - '../internals/has': 78, - '../internals/ie8-dom-define': 82, - '../internals/object-property-is-enumerable': 118, - '../internals/to-indexed-object': 152, - '../internals/to-primitive': 158 + '../internals/has': 79, + '../internals/ie8-dom-define': 83, + '../internals/object-property-is-enumerable': 119, + '../internals/to-indexed-object': 154, + '../internals/to-primitive': 160 } ], - 112: [ + 113: [ function (_dereq_, module, exports) { var toIndexedObject = _dereq_('../internals/to-indexed-object'); var nativeGetOwnPropertyNames = _dereq_('../internals/object-get-own-property-names').f; @@ -21478,11 +21767,11 @@ }; }, { - '../internals/object-get-own-property-names': 113, - '../internals/to-indexed-object': 152 + '../internals/object-get-own-property-names': 114, + '../internals/to-indexed-object': 154 } ], - 113: [ + 114: [ function (_dereq_, module, exports) { var internalObjectKeys = _dereq_('../internals/object-keys-internal'); var enumBugKeys = _dereq_('../internals/enum-bug-keys'); @@ -21495,17 +21784,17 @@ }, { '../internals/enum-bug-keys': 67, - '../internals/object-keys-internal': 116 + '../internals/object-keys-internal': 117 } ], - 114: [ + 115: [ function (_dereq_, module, exports) { exports.f = Object.getOwnPropertySymbols; }, { } ], - 115: [ + 116: [ function (_dereq_, module, exports) { var has = _dereq_('../internals/has'); var toObject = _dereq_('../internals/to-object'); @@ -21526,12 +21815,12 @@ }, { '../internals/correct-prototype-getter': 53, - '../internals/has': 78, - '../internals/shared-key': 136, - '../internals/to-object': 155 + '../internals/has': 79, + '../internals/shared-key': 138, + '../internals/to-object': 157 } ], - 116: [ + 117: [ function (_dereq_, module, exports) { var has = _dereq_('../internals/has'); var toIndexedObject = _dereq_('../internals/to-indexed-object'); @@ -21553,12 +21842,12 @@ }, { '../internals/array-includes': 36, - '../internals/has': 78, - '../internals/hidden-keys': 79, - '../internals/to-indexed-object': 152 + '../internals/has': 79, + '../internals/hidden-keys': 80, + '../internals/to-indexed-object': 154 } ], - 117: [ + 118: [ function (_dereq_, module, exports) { var internalObjectKeys = _dereq_('../internals/object-keys-internal'); var enumBugKeys = _dereq_('../internals/enum-bug-keys'); @@ -21570,10 +21859,10 @@ }, { '../internals/enum-bug-keys': 67, - '../internals/object-keys-internal': 116 + '../internals/object-keys-internal': 117 } ], - 118: [ + 119: [ function (_dereq_, module, exports) { 'use strict'; var nativePropertyIsEnumerable = { @@ -21594,7 +21883,7 @@ { } ], - 119: [ + 120: [ function (_dereq_, module, exports) { var anObject = _dereq_('../internals/an-object'); var aPossiblePrototype = _dereq_('../internals/a-possible-prototype'); @@ -21630,7 +21919,51 @@ '../internals/an-object': 28 } ], - 120: [ + 121: [ + function (_dereq_, module, exports) { + var DESCRIPTORS = _dereq_('../internals/descriptors'); + var objectKeys = _dereq_('../internals/object-keys'); + var toIndexedObject = _dereq_('../internals/to-indexed-object'); + var propertyIsEnumerable = _dereq_('../internals/object-property-is-enumerable').f; + // `Object.{ entries, values }` methods implementation + var createMethod = function (TO_ENTRIES) { + return function (it) { + var O = toIndexedObject(it); + var keys = objectKeys(O); + var length = keys.length; + var i = 0; + var result = [ + ]; + var key; + while (length > i) { + key = keys[i++]; + if (!DESCRIPTORS || propertyIsEnumerable.call(O, key)) { + result.push(TO_ENTRIES ? [ + key, + O[key] + ] : O[key]); + } + } + return result; + }; + }; + module.exports = { + // `Object.entries` method + // https://tc39.github.io/ecma262/#sec-object.entries + entries: createMethod(true), + // `Object.values` method + // https://tc39.github.io/ecma262/#sec-object.values + values: createMethod(false) + }; + }, + { + '../internals/descriptors': 61, + '../internals/object-keys': 118, + '../internals/object-property-is-enumerable': 119, + '../internals/to-indexed-object': 154 + } + ], + 122: [ function (_dereq_, module, exports) { 'use strict'; var TO_STRING_TAG_SUPPORT = _dereq_('../internals/to-string-tag-support'); @@ -21644,10 +21977,10 @@ }, { '../internals/classof': 47, - '../internals/to-string-tag-support': 159 + '../internals/to-string-tag-support': 161 } ], - 121: [ + 123: [ function (_dereq_, module, exports) { var getBuiltIn = _dereq_('../internals/get-built-in'); var getOwnPropertyNamesModule = _dereq_('../internals/object-get-own-property-names'); @@ -21662,21 +21995,21 @@ }, { '../internals/an-object': 28, - '../internals/get-built-in': 74, - '../internals/object-get-own-property-names': 113, - '../internals/object-get-own-property-symbols': 114 + '../internals/get-built-in': 75, + '../internals/object-get-own-property-names': 114, + '../internals/object-get-own-property-symbols': 115 } ], - 122: [ + 124: [ function (_dereq_, module, exports) { var global = _dereq_('../internals/global'); module.exports = global; }, { - '../internals/global': 77 + '../internals/global': 78 } ], - 123: [ + 125: [ function (_dereq_, module, exports) { module.exports = function (exec) { try { @@ -21695,7 +22028,7 @@ { } ], - 124: [ + 126: [ function (_dereq_, module, exports) { var anObject = _dereq_('../internals/an-object'); var isObject = _dereq_('../internals/is-object'); @@ -21711,11 +22044,11 @@ }, { '../internals/an-object': 28, - '../internals/is-object': 92, - '../internals/new-promise-capability': 104 + '../internals/is-object': 93, + '../internals/new-promise-capability': 105 } ], - 125: [ + 127: [ function (_dereq_, module, exports) { var redefine = _dereq_('../internals/redefine'); module.exports = function (target, src, options) { @@ -21724,10 +22057,10 @@ }; }, { - '../internals/redefine': 126 + '../internals/redefine': 128 } ], - 126: [ + 128: [ function (_dereq_, module, exports) { var global = _dereq_('../internals/global'); var createNonEnumerableProperty = _dereq_('../internals/create-non-enumerable-property'); @@ -21764,14 +22097,14 @@ }, { '../internals/create-non-enumerable-property': 56, - '../internals/global': 77, - '../internals/has': 78, - '../internals/inspect-source': 86, - '../internals/internal-state': 88, - '../internals/set-global': 133 + '../internals/global': 78, + '../internals/has': 79, + '../internals/inspect-source': 87, + '../internals/internal-state': 89, + '../internals/set-global': 135 } ], - 127: [ + 129: [ function (_dereq_, module, exports) { var classof = _dereq_('./classof-raw'); var regexpExec = _dereq_('./regexp-exec'); @@ -21794,10 +22127,10 @@ }, { './classof-raw': 46, - './regexp-exec': 128 + './regexp-exec': 130 } ], - 128: [ + 130: [ function (_dereq_, module, exports) { 'use strict'; var regexpFlags = _dereq_('./regexp-flags'); @@ -21877,11 +22210,11 @@ module.exports = patchedExec; }, { - './regexp-flags': 129, - './regexp-sticky-helpers': 130 + './regexp-flags': 131, + './regexp-sticky-helpers': 132 } ], - 129: [ + 131: [ function (_dereq_, module, exports) { 'use strict'; var anObject = _dereq_('../internals/an-object'); @@ -21903,7 +22236,7 @@ '../internals/an-object': 28 } ], - 130: [ + 132: [ function (_dereq_, module, exports) { 'use strict'; var fails = _dereq_('./fails'); @@ -21929,7 +22262,7 @@ './fails': 69 } ], - 131: [ + 133: [ function (_dereq_, module, exports) { // `RequireObjectCoercible` abstract operation // https://tc39.github.io/ecma262/#sec-requireobjectcoercible @@ -21941,7 +22274,7 @@ { } ], - 132: [ + 134: [ function (_dereq_, module, exports) { // `SameValue` abstract operation // https://tc39.github.io/ecma262/#sec-samevalue @@ -21953,7 +22286,7 @@ { } ], - 133: [ + 135: [ function (_dereq_, module, exports) { var global = _dereq_('../internals/global'); var createNonEnumerableProperty = _dereq_('../internals/create-non-enumerable-property'); @@ -21968,10 +22301,10 @@ }, { '../internals/create-non-enumerable-property': 56, - '../internals/global': 77 + '../internals/global': 78 } ], - 134: [ + 136: [ function (_dereq_, module, exports) { 'use strict'; var getBuiltIn = _dereq_('../internals/get-built-in'); @@ -21994,12 +22327,12 @@ }, { '../internals/descriptors': 61, - '../internals/get-built-in': 74, - '../internals/object-define-property': 110, - '../internals/well-known-symbol': 166 + '../internals/get-built-in': 75, + '../internals/object-define-property': 111, + '../internals/well-known-symbol': 168 } ], - 135: [ + 137: [ function (_dereq_, module, exports) { var defineProperty = _dereq_('../internals/object-define-property').f; var has = _dereq_('../internals/has'); @@ -22015,12 +22348,12 @@ }; }, { - '../internals/has': 78, - '../internals/object-define-property': 110, - '../internals/well-known-symbol': 166 + '../internals/has': 79, + '../internals/object-define-property': 111, + '../internals/well-known-symbol': 168 } ], - 136: [ + 138: [ function (_dereq_, module, exports) { var shared = _dereq_('../internals/shared'); var uid = _dereq_('../internals/uid'); @@ -22030,11 +22363,11 @@ }; }, { - '../internals/shared': 138, - '../internals/uid': 163 + '../internals/shared': 140, + '../internals/uid': 165 } ], - 137: [ + 139: [ function (_dereq_, module, exports) { var global = _dereq_('../internals/global'); var setGlobal = _dereq_('../internals/set-global'); @@ -22044,11 +22377,11 @@ module.exports = store; }, { - '../internals/global': 77, - '../internals/set-global': 133 + '../internals/global': 78, + '../internals/set-global': 135 } ], - 138: [ + 140: [ function (_dereq_, module, exports) { var IS_PURE = _dereq_('../internals/is-pure'); var store = _dereq_('../internals/shared-store'); @@ -22063,11 +22396,11 @@ }); }, { - '../internals/is-pure': 93, - '../internals/shared-store': 137 + '../internals/is-pure': 94, + '../internals/shared-store': 139 } ], - 139: [ + 141: [ function (_dereq_, module, exports) { var anObject = _dereq_('../internals/an-object'); var aFunction = _dereq_('../internals/a-function'); @@ -22084,10 +22417,10 @@ { '../internals/a-function': 23, '../internals/an-object': 28, - '../internals/well-known-symbol': 166 + '../internals/well-known-symbol': 168 } ], - 140: [ + 142: [ function (_dereq_, module, exports) { var fails = _dereq_('../internals/fails'); // check the existence of a method, lowercase @@ -22103,7 +22436,7 @@ '../internals/fails': 69 } ], - 141: [ + 143: [ function (_dereq_, module, exports) { var toInteger = _dereq_('../internals/to-integer'); var requireObjectCoercible = _dereq_('../internals/require-object-coercible'); @@ -22130,11 +22463,11 @@ }; }, { - '../internals/require-object-coercible': 131, - '../internals/to-integer': 153 + '../internals/require-object-coercible': 133, + '../internals/to-integer': 155 } ], - 142: [ + 144: [ function (_dereq_, module, exports) { // https://github.com/zloirock/core-js/issues/280 var userAgent = _dereq_('../internals/engine-user-agent'); @@ -22145,7 +22478,7 @@ '../internals/engine-user-agent': 65 } ], - 143: [ + 145: [ function (_dereq_, module, exports) { // https://github.com/tc39/proposal-string-pad-start-end var toLength = _dereq_('../internals/to-length'); @@ -22178,12 +22511,12 @@ }; }, { - '../internals/require-object-coercible': 131, - '../internals/string-repeat': 145, - '../internals/to-length': 154 + '../internals/require-object-coercible': 133, + '../internals/string-repeat': 147, + '../internals/to-length': 156 } ], - 144: [ + 146: [ function (_dereq_, module, exports) { 'use strict'; // based on https://github.com/bestiejs/punycode.js/blob/master/punycode.js @@ -22347,7 +22680,7 @@ { } ], - 145: [ + 147: [ function (_dereq_, module, exports) { 'use strict'; var toInteger = _dereq_('../internals/to-integer'); @@ -22364,11 +22697,11 @@ }; }, { - '../internals/require-object-coercible': 131, - '../internals/to-integer': 153 + '../internals/require-object-coercible': 133, + '../internals/to-integer': 155 } ], - 146: [ + 148: [ function (_dereq_, module, exports) { var fails = _dereq_('../internals/fails'); var whitespaces = _dereq_('../internals/whitespaces'); @@ -22383,10 +22716,10 @@ }, { '../internals/fails': 69, - '../internals/whitespaces': 167 + '../internals/whitespaces': 169 } ], - 147: [ + 149: [ function (_dereq_, module, exports) { var requireObjectCoercible = _dereq_('../internals/require-object-coercible'); var whitespaces = _dereq_('../internals/whitespaces'); @@ -22415,11 +22748,11 @@ }; }, { - '../internals/require-object-coercible': 131, - '../internals/whitespaces': 167 + '../internals/require-object-coercible': 133, + '../internals/whitespaces': 169 } ], - 148: [ + 150: [ function (_dereq_, module, exports) { var global = _dereq_('../internals/global'); var fails = _dereq_('../internals/fails'); @@ -22525,12 +22858,12 @@ '../internals/document-create-element': 62, '../internals/engine-is-ios': 64, '../internals/fails': 69, - '../internals/function-bind-context': 72, - '../internals/global': 77, - '../internals/html': 81 + '../internals/function-bind-context': 73, + '../internals/global': 78, + '../internals/html': 82 } ], - 149: [ + 151: [ function (_dereq_, module, exports) { var classof = _dereq_('../internals/classof-raw'); // `thisNumberValue` abstract operation @@ -22546,7 +22879,7 @@ '../internals/classof-raw': 46 } ], - 150: [ + 152: [ function (_dereq_, module, exports) { var toInteger = _dereq_('../internals/to-integer'); var max = Math.max; @@ -22560,10 +22893,10 @@ }; }, { - '../internals/to-integer': 153 + '../internals/to-integer': 155 } ], - 151: [ + 153: [ function (_dereq_, module, exports) { var toInteger = _dereq_('../internals/to-integer'); var toLength = _dereq_('../internals/to-length'); @@ -22578,11 +22911,11 @@ }; }, { - '../internals/to-integer': 153, - '../internals/to-length': 154 + '../internals/to-integer': 155, + '../internals/to-length': 156 } ], - 152: [ + 154: [ function (_dereq_, module, exports) { // toObject with fallback for non-array-like ES3 strings var IndexedObject = _dereq_('../internals/indexed-object'); @@ -22592,11 +22925,11 @@ }; }, { - '../internals/indexed-object': 84, - '../internals/require-object-coercible': 131 + '../internals/indexed-object': 85, + '../internals/require-object-coercible': 133 } ], - 153: [ + 155: [ function (_dereq_, module, exports) { var ceil = Math.ceil; var floor = Math.floor; @@ -22609,7 +22942,7 @@ { } ], - 154: [ + 156: [ function (_dereq_, module, exports) { var toInteger = _dereq_('../internals/to-integer'); var min = Math.min; @@ -22620,10 +22953,10 @@ }; }, { - '../internals/to-integer': 153 + '../internals/to-integer': 155 } ], - 155: [ + 157: [ function (_dereq_, module, exports) { var requireObjectCoercible = _dereq_('../internals/require-object-coercible'); // `ToObject` abstract operation @@ -22633,10 +22966,10 @@ }; }, { - '../internals/require-object-coercible': 131 + '../internals/require-object-coercible': 133 } ], - 156: [ + 158: [ function (_dereq_, module, exports) { var toPositiveInteger = _dereq_('../internals/to-positive-integer'); module.exports = function (it, BYTES) { @@ -22646,10 +22979,10 @@ }; }, { - '../internals/to-positive-integer': 157 + '../internals/to-positive-integer': 159 } ], - 157: [ + 159: [ function (_dereq_, module, exports) { var toInteger = _dereq_('../internals/to-integer'); module.exports = function (it) { @@ -22659,10 +22992,10 @@ }; }, { - '../internals/to-integer': 153 + '../internals/to-integer': 155 } ], - 158: [ + 160: [ function (_dereq_, module, exports) { var isObject = _dereq_('../internals/is-object'); // `ToPrimitive` abstract operation @@ -22680,10 +23013,10 @@ }; }, { - '../internals/is-object': 92 + '../internals/is-object': 93 } ], - 159: [ + 161: [ function (_dereq_, module, exports) { var wellKnownSymbol = _dereq_('../internals/well-known-symbol'); var TO_STRING_TAG = wellKnownSymbol('toStringTag'); @@ -22693,10 +23026,10 @@ module.exports = String(test) === '[object z]'; }, { - '../internals/well-known-symbol': 166 + '../internals/well-known-symbol': 168 } ], - 160: [ + 162: [ function (_dereq_, module, exports) { 'use strict'; var $ = _dereq_('../internals/export'); @@ -22912,26 +23245,26 @@ '../internals/create-property-descriptor': 57, '../internals/descriptors': 61, '../internals/export': 68, - '../internals/global': 77, - '../internals/has': 78, - '../internals/inherit-if-required': 85, - '../internals/internal-state': 88, - '../internals/is-object': 92, - '../internals/object-create': 108, - '../internals/object-define-property': 110, - '../internals/object-get-own-property-descriptor': 111, - '../internals/object-get-own-property-names': 113, - '../internals/object-set-prototype-of': 119, - '../internals/set-species': 134, - '../internals/to-index': 151, - '../internals/to-length': 154, - '../internals/to-offset': 156, - '../internals/to-primitive': 158, - '../internals/typed-array-constructors-require-wrappers': 161, - '../internals/typed-array-from': 162 + '../internals/global': 78, + '../internals/has': 79, + '../internals/inherit-if-required': 86, + '../internals/internal-state': 89, + '../internals/is-object': 93, + '../internals/object-create': 109, + '../internals/object-define-property': 111, + '../internals/object-get-own-property-descriptor': 112, + '../internals/object-get-own-property-names': 114, + '../internals/object-set-prototype-of': 120, + '../internals/set-species': 136, + '../internals/to-index': 153, + '../internals/to-length': 156, + '../internals/to-offset': 158, + '../internals/to-primitive': 160, + '../internals/typed-array-constructors-require-wrappers': 163, + '../internals/typed-array-from': 164 } ], - 161: [ + 163: [ function (_dereq_, module, exports) { /* eslint-disable no-new */ var global = _dereq_('../internals/global'); @@ -22958,10 +23291,10 @@ '../internals/array-buffer-view-core': 30, '../internals/check-correctness-of-iteration': 45, '../internals/fails': 69, - '../internals/global': 77 + '../internals/global': 78 } ], - 162: [ + 164: [ function (_dereq_, module, exports) { var toObject = _dereq_('../internals/to-object'); var toLength = _dereq_('../internals/to-length'); @@ -23003,14 +23336,14 @@ }, { '../internals/array-buffer-view-core': 30, - '../internals/function-bind-context': 72, - '../internals/get-iterator-method': 75, - '../internals/is-array-iterator-method': 89, - '../internals/to-length': 154, - '../internals/to-object': 155 + '../internals/function-bind-context': 73, + '../internals/get-iterator-method': 76, + '../internals/is-array-iterator-method': 90, + '../internals/to-length': 156, + '../internals/to-object': 157 } ], - 163: [ + 165: [ function (_dereq_, module, exports) { var id = 0; var postfix = Math.random(); @@ -23021,7 +23354,7 @@ { } ], - 164: [ + 166: [ function (_dereq_, module, exports) { var NATIVE_SYMBOL = _dereq_('../internals/native-symbol'); module.exports = NATIVE_SYMBOL // eslint-disable-next-line no-undef @@ -23029,19 +23362,19 @@ && typeof Symbol.iterator == 'symbol'; }, { - '../internals/native-symbol': 101 + '../internals/native-symbol': 102 } ], - 165: [ + 167: [ function (_dereq_, module, exports) { var wellKnownSymbol = _dereq_('../internals/well-known-symbol'); exports.f = wellKnownSymbol; }, { - '../internals/well-known-symbol': 166 + '../internals/well-known-symbol': 168 } ], - 166: [ + 168: [ function (_dereq_, module, exports) { var global = _dereq_('../internals/global'); var shared = _dereq_('../internals/shared'); @@ -23061,15 +23394,15 @@ }; }, { - '../internals/global': 77, - '../internals/has': 78, - '../internals/native-symbol': 101, - '../internals/shared': 138, - '../internals/uid': 163, - '../internals/use-symbol-as-uid': 164 + '../internals/global': 78, + '../internals/has': 79, + '../internals/native-symbol': 102, + '../internals/shared': 140, + '../internals/uid': 165, + '../internals/use-symbol-as-uid': 166 } ], - 167: [ + 169: [ function (_dereq_, module, exports) { // a string of all valid unicode whitespaces // eslint-disable-next-line max-len @@ -23078,7 +23411,7 @@ { } ], - 168: [ + 170: [ function (_dereq_, module, exports) { 'use strict'; var $ = _dereq_('../internals/export'); @@ -23101,11 +23434,11 @@ { '../internals/array-buffer': 31, '../internals/export': 68, - '../internals/global': 77, - '../internals/set-species': 134 + '../internals/global': 78, + '../internals/set-species': 136 } ], - 169: [ + 171: [ function (_dereq_, module, exports) { 'use strict'; var $ = _dereq_('../internals/export'); @@ -23179,14 +23512,14 @@ '../internals/engine-v8-version': 66, '../internals/export': 68, '../internals/fails': 69, - '../internals/is-array': 90, - '../internals/is-object': 92, - '../internals/to-length': 154, - '../internals/to-object': 155, - '../internals/well-known-symbol': 166 + '../internals/is-array': 91, + '../internals/is-object': 93, + '../internals/to-length': 156, + '../internals/to-object': 157, + '../internals/well-known-symbol': 168 } ], - 170: [ + 172: [ function (_dereq_, module, exports) { var $ = _dereq_('../internals/export'); var copyWithin = _dereq_('../internals/array-copy-within'); @@ -23208,7 +23541,7 @@ '../internals/export': 68 } ], - 171: [ + 173: [ function (_dereq_, module, exports) { 'use strict'; var $ = _dereq_('../internals/export'); @@ -23236,7 +23569,7 @@ '../internals/export': 68 } ], - 172: [ + 174: [ function (_dereq_, module, exports) { var $ = _dereq_('../internals/export'); var fill = _dereq_('../internals/array-fill'); @@ -23258,7 +23591,7 @@ '../internals/export': 68 } ], - 173: [ + 175: [ function (_dereq_, module, exports) { 'use strict'; var $ = _dereq_('../internals/export'); @@ -23288,7 +23621,7 @@ '../internals/export': 68 } ], - 174: [ + 176: [ function (_dereq_, module, exports) { 'use strict'; var $ = _dereq_('../internals/export'); @@ -23324,7 +23657,77 @@ '../internals/export': 68 } ], - 175: [ + 177: [ + function (_dereq_, module, exports) { + 'use strict'; + var $ = _dereq_('../internals/export'); + var flattenIntoArray = _dereq_('../internals/flatten-into-array'); + var toObject = _dereq_('../internals/to-object'); + var toLength = _dereq_('../internals/to-length'); + var aFunction = _dereq_('../internals/a-function'); + var arraySpeciesCreate = _dereq_('../internals/array-species-create'); + // `Array.prototype.flatMap` method + // https://github.com/tc39/proposal-flatMap + $({ + target: 'Array', + proto: true + }, { + flatMap: function flatMap(callbackfn /* , thisArg */ ) { + var O = toObject(this); + var sourceLen = toLength(O.length); + var A; + aFunction(callbackfn); + A = arraySpeciesCreate(O, 0); + A.length = flattenIntoArray(A, O, O, sourceLen, 0, 1, callbackfn, arguments.length > 1 ? arguments[1] : undefined); + return A; + } + }); + }, + { + '../internals/a-function': 23, + '../internals/array-species-create': 43, + '../internals/export': 68, + '../internals/flatten-into-array': 71, + '../internals/to-length': 156, + '../internals/to-object': 157 + } + ], + 178: [ + function (_dereq_, module, exports) { + 'use strict'; + var $ = _dereq_('../internals/export'); + var flattenIntoArray = _dereq_('../internals/flatten-into-array'); + var toObject = _dereq_('../internals/to-object'); + var toLength = _dereq_('../internals/to-length'); + var toInteger = _dereq_('../internals/to-integer'); + var arraySpeciesCreate = _dereq_('../internals/array-species-create'); + // `Array.prototype.flat` method + // https://github.com/tc39/proposal-flatMap + $({ + target: 'Array', + proto: true + }, { + flat: function flat( /* depthArg = 1 */ + ) { + var depthArg = arguments.length ? arguments[0] : undefined; + var O = toObject(this); + var sourceLen = toLength(O.length); + var A = arraySpeciesCreate(O, 0); + A.length = flattenIntoArray(A, O, O, sourceLen, 0, depthArg === undefined ? 1 : toInteger(depthArg)); + return A; + } + }); + }, + { + '../internals/array-species-create': 43, + '../internals/export': 68, + '../internals/flatten-into-array': 71, + '../internals/to-integer': 155, + '../internals/to-length': 156, + '../internals/to-object': 157 + } + ], + 179: [ function (_dereq_, module, exports) { 'use strict'; var $ = _dereq_('../internals/export'); @@ -23345,7 +23748,7 @@ '../internals/export': 68 } ], - 176: [ + 180: [ function (_dereq_, module, exports) { var $ = _dereq_('../internals/export'); var from = _dereq_('../internals/array-from'); @@ -23369,7 +23772,7 @@ '../internals/export': 68 } ], - 177: [ + 181: [ function (_dereq_, module, exports) { 'use strict'; var $ = _dereq_('../internals/export'); @@ -23401,7 +23804,7 @@ '../internals/export': 68 } ], - 178: [ + 182: [ function (_dereq_, module, exports) { 'use strict'; var $ = _dereq_('../internals/export'); @@ -23438,7 +23841,7 @@ '../internals/export': 68 } ], - 179: [ + 183: [ function (_dereq_, module, exports) { 'use strict'; var toIndexedObject = _dereq_('../internals/to-indexed-object'); @@ -23510,12 +23913,12 @@ { '../internals/add-to-unscopables': 25, '../internals/define-iterator': 59, - '../internals/internal-state': 88, - '../internals/iterators': 97, - '../internals/to-indexed-object': 152 + '../internals/internal-state': 89, + '../internals/iterators': 98, + '../internals/to-indexed-object': 154 } ], - 180: [ + 184: [ function (_dereq_, module, exports) { 'use strict'; var $ = _dereq_('../internals/export'); @@ -23541,11 +23944,11 @@ { '../internals/array-method-is-strict': 40, '../internals/export': 68, - '../internals/indexed-object': 84, - '../internals/to-indexed-object': 152 + '../internals/indexed-object': 85, + '../internals/to-indexed-object': 154 } ], - 181: [ + 185: [ function (_dereq_, module, exports) { var $ = _dereq_('../internals/export'); var lastIndexOf = _dereq_('../internals/array-last-index-of'); @@ -23564,7 +23967,7 @@ '../internals/export': 68 } ], - 182: [ + 186: [ function (_dereq_, module, exports) { 'use strict'; var $ = _dereq_('../internals/export'); @@ -23594,7 +23997,7 @@ '../internals/export': 68 } ], - 183: [ + 187: [ function (_dereq_, module, exports) { 'use strict'; var $ = _dereq_('../internals/export'); @@ -23659,15 +24062,15 @@ '../internals/array-method-uses-to-length': 41, '../internals/create-property': 58, '../internals/export': 68, - '../internals/is-array': 90, - '../internals/is-object': 92, - '../internals/to-absolute-index': 150, - '../internals/to-indexed-object': 152, - '../internals/to-length': 154, - '../internals/well-known-symbol': 166 + '../internals/is-array': 91, + '../internals/is-object': 93, + '../internals/to-absolute-index': 152, + '../internals/to-indexed-object': 154, + '../internals/to-length': 156, + '../internals/well-known-symbol': 168 } ], - 184: [ + 188: [ function (_dereq_, module, exports) { 'use strict'; var $ = _dereq_('../internals/export'); @@ -23695,7 +24098,7 @@ '../internals/export': 68 } ], - 185: [ + 189: [ function (_dereq_, module, exports) { 'use strict'; var $ = _dereq_('../internals/export'); @@ -23784,13 +24187,35 @@ '../internals/array-species-create': 43, '../internals/create-property': 58, '../internals/export': 68, - '../internals/to-absolute-index': 150, - '../internals/to-integer': 153, - '../internals/to-length': 154, - '../internals/to-object': 155 + '../internals/to-absolute-index': 152, + '../internals/to-integer': 155, + '../internals/to-length': 156, + '../internals/to-object': 157 } ], - 186: [ + 190: [ + function (_dereq_, module, exports) { + // this method was added to unscopables after implementation + // in popular engines, so it's moved to a separate module + var addToUnscopables = _dereq_('../internals/add-to-unscopables'); + addToUnscopables('flatMap'); + }, + { + '../internals/add-to-unscopables': 25 + } + ], + 191: [ + function (_dereq_, module, exports) { + // this method was added to unscopables after implementation + // in popular engines, so it's moved to a separate module + var addToUnscopables = _dereq_('../internals/add-to-unscopables'); + addToUnscopables('flat'); + }, + { + '../internals/add-to-unscopables': 25 + } + ], + 192: [ function (_dereq_, module, exports) { var DESCRIPTORS = _dereq_('../internals/descriptors'); var defineProperty = _dereq_('../internals/object-define-property').f; @@ -23815,10 +24240,10 @@ }, { '../internals/descriptors': 61, - '../internals/object-define-property': 110 + '../internals/object-define-property': 111 } ], - 187: [ + 193: [ function (_dereq_, module, exports) { 'use strict'; var collection = _dereq_('../internals/collection'); @@ -23836,7 +24261,7 @@ '../internals/collection-strong': 48 } ], - 188: [ + 194: [ function (_dereq_, module, exports) { var $ = _dereq_('../internals/export'); var $hypot = Math.hypot; @@ -23879,7 +24304,7 @@ '../internals/export': 68 } ], - 189: [ + 195: [ function (_dereq_, module, exports) { var $ = _dereq_('../internals/export'); var log = Math.log; @@ -23899,7 +24324,7 @@ '../internals/export': 68 } ], - 190: [ + 196: [ function (_dereq_, module, exports) { var $ = _dereq_('../internals/export'); var sign = _dereq_('../internals/math-sign'); @@ -23914,10 +24339,10 @@ }, { '../internals/export': 68, - '../internals/math-sign': 98 + '../internals/math-sign': 99 } ], - 191: [ + 197: [ function (_dereq_, module, exports) { 'use strict'; var DESCRIPTORS = _dereq_('../internals/descriptors'); @@ -24014,20 +24439,36 @@ '../internals/classof-raw': 46, '../internals/descriptors': 61, '../internals/fails': 69, - '../internals/global': 77, - '../internals/has': 78, - '../internals/inherit-if-required': 85, - '../internals/is-forced': 91, - '../internals/object-create': 108, - '../internals/object-define-property': 110, - '../internals/object-get-own-property-descriptor': 111, - '../internals/object-get-own-property-names': 113, - '../internals/redefine': 126, - '../internals/string-trim': 147, - '../internals/to-primitive': 158 + '../internals/global': 78, + '../internals/has': 79, + '../internals/inherit-if-required': 86, + '../internals/is-forced': 92, + '../internals/object-create': 109, + '../internals/object-define-property': 111, + '../internals/object-get-own-property-descriptor': 112, + '../internals/object-get-own-property-names': 114, + '../internals/redefine': 128, + '../internals/string-trim': 149, + '../internals/to-primitive': 160 } ], - 192: [ + 198: [ + function (_dereq_, module, exports) { + var $ = _dereq_('../internals/export'); + // `Number.EPSILON` constant + // https://tc39.github.io/ecma262/#sec-number.epsilon + $({ + target: 'Number', + stat: true + }, { + EPSILON: Math.pow(2, - 52) + }); + }, + { + '../internals/export': 68 + } + ], + 199: [ function (_dereq_, module, exports) { var $ = _dereq_('../internals/export'); var numberIsFinite = _dereq_('../internals/number-is-finite'); @@ -24042,10 +24483,10 @@ }, { '../internals/export': 68, - '../internals/number-is-finite': 106 + '../internals/number-is-finite': 107 } ], - 193: [ + 200: [ function (_dereq_, module, exports) { 'use strict'; var $ = _dereq_('../internals/export'); @@ -24179,12 +24620,12 @@ { '../internals/export': 68, '../internals/fails': 69, - '../internals/string-repeat': 145, - '../internals/this-number-value': 149, - '../internals/to-integer': 153 + '../internals/string-repeat': 147, + '../internals/this-number-value': 151, + '../internals/to-integer': 155 } ], - 194: [ + 201: [ function (_dereq_, module, exports) { var $ = _dereq_('../internals/export'); var assign = _dereq_('../internals/object-assign'); @@ -24200,10 +24641,30 @@ }, { '../internals/export': 68, - '../internals/object-assign': 107 + '../internals/object-assign': 108 } ], - 195: [ + 202: [ + function (_dereq_, module, exports) { + var $ = _dereq_('../internals/export'); + var $entries = _dereq_('../internals/object-to-array').entries; + // `Object.entries` method + // https://tc39.github.io/ecma262/#sec-object.entries + $({ + target: 'Object', + stat: true + }, { + entries: function entries(O) { + return $entries(O); + } + }); + }, + { + '../internals/export': 68, + '../internals/object-to-array': 121 + } + ], + 203: [ function (_dereq_, module, exports) { var $ = _dereq_('../internals/export'); var iterate = _dereq_('../internals/iterate'); @@ -24227,10 +24688,10 @@ { '../internals/create-property': 58, '../internals/export': 68, - '../internals/iterate': 95 + '../internals/iterate': 96 } ], - 196: [ + 204: [ function (_dereq_, module, exports) { var $ = _dereq_('../internals/export'); var fails = _dereq_('../internals/fails'); @@ -24258,11 +24719,11 @@ '../internals/descriptors': 61, '../internals/export': 68, '../internals/fails': 69, - '../internals/object-get-own-property-descriptor': 111, - '../internals/to-indexed-object': 152 + '../internals/object-get-own-property-descriptor': 112, + '../internals/to-indexed-object': 154 } ], - 197: [ + 205: [ function (_dereq_, module, exports) { var $ = _dereq_('../internals/export'); var fails = _dereq_('../internals/fails'); @@ -24283,10 +24744,10 @@ { '../internals/export': 68, '../internals/fails': 69, - '../internals/object-get-own-property-names-external': 112 + '../internals/object-get-own-property-names-external': 113 } ], - 198: [ + 206: [ function (_dereq_, module, exports) { var $ = _dereq_('../internals/export'); var fails = _dereq_('../internals/fails'); @@ -24313,11 +24774,11 @@ '../internals/correct-prototype-getter': 53, '../internals/export': 68, '../internals/fails': 69, - '../internals/object-get-prototype-of': 115, - '../internals/to-object': 155 + '../internals/object-get-prototype-of': 116, + '../internals/to-object': 157 } ], - 199: [ + 207: [ function (_dereq_, module, exports) { var $ = _dereq_('../internals/export'); var toObject = _dereq_('../internals/to-object'); @@ -24341,11 +24802,11 @@ { '../internals/export': 68, '../internals/fails': 69, - '../internals/object-keys': 117, - '../internals/to-object': 155 + '../internals/object-keys': 118, + '../internals/to-object': 157 } ], - 200: [ + 208: [ function (_dereq_, module, exports) { var TO_STRING_TAG_SUPPORT = _dereq_('../internals/to-string-tag-support'); var redefine = _dereq_('../internals/redefine'); @@ -24359,12 +24820,12 @@ } }, { - '../internals/object-to-string': 120, - '../internals/redefine': 126, - '../internals/to-string-tag-support': 159 + '../internals/object-to-string': 122, + '../internals/redefine': 128, + '../internals/to-string-tag-support': 161 } ], - 201: [ + 209: [ function (_dereq_, module, exports) { 'use strict'; var $ = _dereq_('../internals/export'); @@ -24769,30 +25230,30 @@ '../internals/classof-raw': 46, '../internals/engine-v8-version': 66, '../internals/export': 68, - '../internals/get-built-in': 74, - '../internals/global': 77, - '../internals/host-report-errors': 80, - '../internals/inspect-source': 86, - '../internals/internal-state': 88, - '../internals/is-forced': 91, - '../internals/is-object': 92, - '../internals/is-pure': 93, - '../internals/iterate': 95, - '../internals/microtask': 99, - '../internals/native-promise-constructor': 100, - '../internals/new-promise-capability': 104, - '../internals/perform': 123, - '../internals/promise-resolve': 124, - '../internals/redefine': 126, - '../internals/redefine-all': 125, - '../internals/set-species': 134, - '../internals/set-to-string-tag': 135, - '../internals/species-constructor': 139, - '../internals/task': 148, - '../internals/well-known-symbol': 166 + '../internals/get-built-in': 75, + '../internals/global': 78, + '../internals/host-report-errors': 81, + '../internals/inspect-source': 87, + '../internals/internal-state': 89, + '../internals/is-forced': 92, + '../internals/is-object': 93, + '../internals/is-pure': 94, + '../internals/iterate': 96, + '../internals/microtask': 100, + '../internals/native-promise-constructor': 101, + '../internals/new-promise-capability': 105, + '../internals/perform': 125, + '../internals/promise-resolve': 126, + '../internals/redefine': 128, + '../internals/redefine-all': 127, + '../internals/set-species': 136, + '../internals/set-to-string-tag': 137, + '../internals/species-constructor': 141, + '../internals/task': 150, + '../internals/well-known-symbol': 168 } ], - 202: [ + 210: [ function (_dereq_, module, exports) { var $ = _dereq_('../internals/export'); var getBuiltIn = _dereq_('../internals/get-built-in'); @@ -24864,13 +25325,13 @@ '../internals/an-object': 28, '../internals/export': 68, '../internals/fails': 69, - '../internals/function-bind': 73, - '../internals/get-built-in': 74, - '../internals/is-object': 92, - '../internals/object-create': 108 + '../internals/function-bind': 74, + '../internals/get-built-in': 75, + '../internals/is-object': 93, + '../internals/object-create': 109 } ], - 203: [ + 211: [ function (_dereq_, module, exports) { var $ = _dereq_('../internals/export'); var isObject = _dereq_('../internals/is-object'); @@ -24898,13 +25359,13 @@ { '../internals/an-object': 28, '../internals/export': 68, - '../internals/has': 78, - '../internals/is-object': 92, - '../internals/object-get-own-property-descriptor': 111, - '../internals/object-get-prototype-of': 115 + '../internals/has': 79, + '../internals/is-object': 93, + '../internals/object-get-own-property-descriptor': 112, + '../internals/object-get-prototype-of': 116 } ], - 204: [ + 212: [ function (_dereq_, module, exports) { var DESCRIPTORS = _dereq_('../internals/descriptors'); var global = _dereq_('../internals/global'); @@ -24984,21 +25445,21 @@ { '../internals/descriptors': 61, '../internals/fails': 69, - '../internals/global': 77, - '../internals/inherit-if-required': 85, - '../internals/internal-state': 88, - '../internals/is-forced': 91, - '../internals/is-regexp': 94, - '../internals/object-define-property': 110, - '../internals/object-get-own-property-names': 113, - '../internals/redefine': 126, - '../internals/regexp-flags': 129, - '../internals/regexp-sticky-helpers': 130, - '../internals/set-species': 134, - '../internals/well-known-symbol': 166 + '../internals/global': 78, + '../internals/inherit-if-required': 86, + '../internals/internal-state': 89, + '../internals/is-forced': 92, + '../internals/is-regexp': 95, + '../internals/object-define-property': 111, + '../internals/object-get-own-property-names': 114, + '../internals/redefine': 128, + '../internals/regexp-flags': 131, + '../internals/regexp-sticky-helpers': 132, + '../internals/set-species': 136, + '../internals/well-known-symbol': 168 } ], - 205: [ + 213: [ function (_dereq_, module, exports) { 'use strict'; var $ = _dereq_('../internals/export'); @@ -25013,10 +25474,10 @@ }, { '../internals/export': 68, - '../internals/regexp-exec': 128 + '../internals/regexp-exec': 130 } ], - 206: [ + 214: [ function (_dereq_, module, exports) { 'use strict'; var redefine = _dereq_('../internals/redefine'); @@ -25051,11 +25512,11 @@ { '../internals/an-object': 28, '../internals/fails': 69, - '../internals/redefine': 126, - '../internals/regexp-flags': 129 + '../internals/redefine': 128, + '../internals/regexp-flags': 131 } ], - 207: [ + 215: [ function (_dereq_, module, exports) { 'use strict'; var collection = _dereq_('../internals/collection'); @@ -25073,7 +25534,7 @@ '../internals/collection-strong': 48 } ], - 208: [ + 216: [ function (_dereq_, module, exports) { 'use strict'; var $ = _dereq_('../internals/export'); @@ -25112,14 +25573,14 @@ { '../internals/correct-is-regexp-logic': 52, '../internals/export': 68, - '../internals/is-pure': 93, - '../internals/not-a-regexp': 105, - '../internals/object-get-own-property-descriptor': 111, - '../internals/require-object-coercible': 131, - '../internals/to-length': 154 + '../internals/is-pure': 94, + '../internals/not-a-regexp': 106, + '../internals/object-get-own-property-descriptor': 112, + '../internals/require-object-coercible': 133, + '../internals/to-length': 156 } ], - 209: [ + 217: [ function (_dereq_, module, exports) { 'use strict'; var $ = _dereq_('../internals/export'); @@ -25141,11 +25602,11 @@ { '../internals/correct-is-regexp-logic': 52, '../internals/export': 68, - '../internals/not-a-regexp': 105, - '../internals/require-object-coercible': 131 + '../internals/not-a-regexp': 106, + '../internals/require-object-coercible': 133 } ], - 210: [ + 218: [ function (_dereq_, module, exports) { 'use strict'; var charAt = _dereq_('../internals/string-multibyte').charAt; @@ -25183,11 +25644,11 @@ }, { '../internals/define-iterator': 59, - '../internals/internal-state': 88, - '../internals/string-multibyte': 141 + '../internals/internal-state': 89, + '../internals/string-multibyte': 143 } ], - 211: [ + 219: [ function (_dereq_, module, exports) { 'use strict'; var fixRegExpWellKnownSymbolLogic = _dereq_('../internals/fix-regexp-well-known-symbol-logic'); @@ -25234,12 +25695,12 @@ '../internals/advance-string-index': 26, '../internals/an-object': 28, '../internals/fix-regexp-well-known-symbol-logic': 70, - '../internals/regexp-exec-abstract': 127, - '../internals/require-object-coercible': 131, - '../internals/to-length': 154 + '../internals/regexp-exec-abstract': 129, + '../internals/require-object-coercible': 133, + '../internals/to-length': 156 } ], - 212: [ + 220: [ function (_dereq_, module, exports) { 'use strict'; var $ = _dereq_('../internals/export'); @@ -25259,11 +25720,11 @@ }, { '../internals/export': 68, - '../internals/string-pad': 143, - '../internals/string-pad-webkit-bug': 142 + '../internals/string-pad': 145, + '../internals/string-pad-webkit-bug': 144 } ], - 213: [ + 221: [ function (_dereq_, module, exports) { var $ = _dereq_('../internals/export'); var repeat = _dereq_('../internals/string-repeat'); @@ -25278,10 +25739,10 @@ }, { '../internals/export': 68, - '../internals/string-repeat': 145 + '../internals/string-repeat': 147 } ], - 214: [ + 222: [ function (_dereq_, module, exports) { 'use strict'; var fixRegExpWellKnownSymbolLogic = _dereq_('../internals/fix-regexp-well-known-symbol-logic'); @@ -25414,14 +25875,14 @@ '../internals/advance-string-index': 26, '../internals/an-object': 28, '../internals/fix-regexp-well-known-symbol-logic': 70, - '../internals/regexp-exec-abstract': 127, - '../internals/require-object-coercible': 131, - '../internals/to-integer': 153, - '../internals/to-length': 154, - '../internals/to-object': 155 + '../internals/regexp-exec-abstract': 129, + '../internals/require-object-coercible': 133, + '../internals/to-integer': 155, + '../internals/to-length': 156, + '../internals/to-object': 157 } ], - 215: [ + 223: [ function (_dereq_, module, exports) { 'use strict'; var fixRegExpWellKnownSymbolLogic = _dereq_('../internals/fix-regexp-well-known-symbol-logic'); @@ -25457,12 +25918,12 @@ { '../internals/an-object': 28, '../internals/fix-regexp-well-known-symbol-logic': 70, - '../internals/regexp-exec-abstract': 127, - '../internals/require-object-coercible': 131, - '../internals/same-value': 132 + '../internals/regexp-exec-abstract': 129, + '../internals/require-object-coercible': 133, + '../internals/same-value': 134 } ], - 216: [ + 224: [ function (_dereq_, module, exports) { 'use strict'; var fixRegExpWellKnownSymbolLogic = _dereq_('../internals/fix-regexp-well-known-symbol-logic'); @@ -25589,15 +26050,15 @@ '../internals/an-object': 28, '../internals/fails': 69, '../internals/fix-regexp-well-known-symbol-logic': 70, - '../internals/is-regexp': 94, - '../internals/regexp-exec': 128, - '../internals/regexp-exec-abstract': 127, - '../internals/require-object-coercible': 131, - '../internals/species-constructor': 139, - '../internals/to-length': 154 + '../internals/is-regexp': 95, + '../internals/regexp-exec': 130, + '../internals/regexp-exec-abstract': 129, + '../internals/require-object-coercible': 133, + '../internals/species-constructor': 141, + '../internals/to-length': 156 } ], - 217: [ + 225: [ function (_dereq_, module, exports) { 'use strict'; var $ = _dereq_('../internals/export'); @@ -25634,14 +26095,14 @@ { '../internals/correct-is-regexp-logic': 52, '../internals/export': 68, - '../internals/is-pure': 93, - '../internals/not-a-regexp': 105, - '../internals/object-get-own-property-descriptor': 111, - '../internals/require-object-coercible': 131, - '../internals/to-length': 154 + '../internals/is-pure': 94, + '../internals/not-a-regexp': 106, + '../internals/object-get-own-property-descriptor': 112, + '../internals/require-object-coercible': 133, + '../internals/to-length': 156 } ], - 218: [ + 226: [ function (_dereq_, module, exports) { 'use strict'; var $ = _dereq_('../internals/export'); @@ -25662,10 +26123,10 @@ { '../internals/create-html': 54, '../internals/export': 68, - '../internals/string-html-forced': 140 + '../internals/string-html-forced': 142 } ], - 219: [ + 227: [ function (_dereq_, module, exports) { 'use strict'; var $ = _dereq_('../internals/export'); @@ -25685,11 +26146,11 @@ }, { '../internals/export': 68, - '../internals/string-trim': 147, - '../internals/string-trim-forced': 146 + '../internals/string-trim': 149, + '../internals/string-trim-forced': 148 } ], - 220: [ + 228: [ function (_dereq_, module, exports) { // `Symbol.prototype.description` getter // https://tc39.github.io/ecma262/#sec-symbol.prototype.description @@ -25742,13 +26203,13 @@ '../internals/copy-constructor-properties': 51, '../internals/descriptors': 61, '../internals/export': 68, - '../internals/global': 77, - '../internals/has': 78, - '../internals/is-object': 92, - '../internals/object-define-property': 110 + '../internals/global': 78, + '../internals/has': 79, + '../internals/is-object': 93, + '../internals/object-define-property': 111 } ], - 221: [ + 229: [ function (_dereq_, module, exports) { var defineWellKnownSymbol = _dereq_('../internals/define-well-known-symbol'); // `Symbol.iterator` well-known symbol @@ -25759,7 +26220,7 @@ '../internals/define-well-known-symbol': 60 } ], - 222: [ + 230: [ function (_dereq_, module, exports) { 'use strict'; var $ = _dereq_('../internals/export'); @@ -26108,37 +26569,37 @@ '../internals/descriptors': 61, '../internals/export': 68, '../internals/fails': 69, - '../internals/get-built-in': 74, - '../internals/global': 77, - '../internals/has': 78, - '../internals/hidden-keys': 79, - '../internals/internal-state': 88, - '../internals/is-array': 90, - '../internals/is-object': 92, - '../internals/is-pure': 93, - '../internals/native-symbol': 101, - '../internals/object-create': 108, - '../internals/object-define-property': 110, - '../internals/object-get-own-property-descriptor': 111, - '../internals/object-get-own-property-names': 113, - '../internals/object-get-own-property-names-external': 112, - '../internals/object-get-own-property-symbols': 114, - '../internals/object-keys': 117, - '../internals/object-property-is-enumerable': 118, - '../internals/redefine': 126, - '../internals/set-to-string-tag': 135, - '../internals/shared': 138, - '../internals/shared-key': 136, - '../internals/to-indexed-object': 152, - '../internals/to-object': 155, - '../internals/to-primitive': 158, - '../internals/uid': 163, - '../internals/use-symbol-as-uid': 164, - '../internals/well-known-symbol': 166, - '../internals/well-known-symbol-wrapped': 165 + '../internals/get-built-in': 75, + '../internals/global': 78, + '../internals/has': 79, + '../internals/hidden-keys': 80, + '../internals/internal-state': 89, + '../internals/is-array': 91, + '../internals/is-object': 93, + '../internals/is-pure': 94, + '../internals/native-symbol': 102, + '../internals/object-create': 109, + '../internals/object-define-property': 111, + '../internals/object-get-own-property-descriptor': 112, + '../internals/object-get-own-property-names': 114, + '../internals/object-get-own-property-names-external': 113, + '../internals/object-get-own-property-symbols': 115, + '../internals/object-keys': 118, + '../internals/object-property-is-enumerable': 119, + '../internals/redefine': 128, + '../internals/set-to-string-tag': 137, + '../internals/shared': 140, + '../internals/shared-key': 138, + '../internals/to-indexed-object': 154, + '../internals/to-object': 157, + '../internals/to-primitive': 160, + '../internals/uid': 165, + '../internals/use-symbol-as-uid': 166, + '../internals/well-known-symbol': 168, + '../internals/well-known-symbol-wrapped': 167 } ], - 223: [ + 231: [ function (_dereq_, module, exports) { 'use strict'; var ArrayBufferViewCore = _dereq_('../internals/array-buffer-view-core'); @@ -26156,7 +26617,7 @@ '../internals/array-copy-within': 32 } ], - 224: [ + 232: [ function (_dereq_, module, exports) { 'use strict'; var ArrayBufferViewCore = _dereq_('../internals/array-buffer-view-core'); @@ -26174,7 +26635,7 @@ '../internals/array-iteration': 37 } ], - 225: [ + 233: [ function (_dereq_, module, exports) { 'use strict'; var ArrayBufferViewCore = _dereq_('../internals/array-buffer-view-core'); @@ -26193,7 +26654,7 @@ '../internals/array-fill': 33 } ], - 226: [ + 234: [ function (_dereq_, module, exports) { 'use strict'; var ArrayBufferViewCore = _dereq_('../internals/array-buffer-view-core'); @@ -26217,10 +26678,10 @@ { '../internals/array-buffer-view-core': 30, '../internals/array-iteration': 37, - '../internals/species-constructor': 139 + '../internals/species-constructor': 141 } ], - 227: [ + 235: [ function (_dereq_, module, exports) { 'use strict'; var ArrayBufferViewCore = _dereq_('../internals/array-buffer-view-core'); @@ -26238,7 +26699,7 @@ '../internals/array-iteration': 37 } ], - 228: [ + 236: [ function (_dereq_, module, exports) { 'use strict'; var ArrayBufferViewCore = _dereq_('../internals/array-buffer-view-core'); @@ -26256,7 +26717,7 @@ '../internals/array-iteration': 37 } ], - 229: [ + 237: [ function (_dereq_, module, exports) { var createTypedArrayConstructor = _dereq_('../internals/typed-array-constructor'); // `Float32Array` constructor @@ -26268,10 +26729,10 @@ }); }, { - '../internals/typed-array-constructor': 160 + '../internals/typed-array-constructor': 162 } ], - 230: [ + 238: [ function (_dereq_, module, exports) { var createTypedArrayConstructor = _dereq_('../internals/typed-array-constructor'); // `Float64Array` constructor @@ -26283,10 +26744,10 @@ }); }, { - '../internals/typed-array-constructor': 160 + '../internals/typed-array-constructor': 162 } ], - 231: [ + 239: [ function (_dereq_, module, exports) { 'use strict'; var ArrayBufferViewCore = _dereq_('../internals/array-buffer-view-core'); @@ -26304,7 +26765,7 @@ '../internals/array-iteration': 37 } ], - 232: [ + 240: [ function (_dereq_, module, exports) { 'use strict'; var ArrayBufferViewCore = _dereq_('../internals/array-buffer-view-core'); @@ -26322,7 +26783,7 @@ '../internals/array-includes': 36 } ], - 233: [ + 241: [ function (_dereq_, module, exports) { 'use strict'; var ArrayBufferViewCore = _dereq_('../internals/array-buffer-view-core'); @@ -26340,7 +26801,7 @@ '../internals/array-includes': 36 } ], - 234: [ + 242: [ function (_dereq_, module, exports) { var createTypedArrayConstructor = _dereq_('../internals/typed-array-constructor'); // `Int16Array` constructor @@ -26352,10 +26813,10 @@ }); }, { - '../internals/typed-array-constructor': 160 + '../internals/typed-array-constructor': 162 } ], - 235: [ + 243: [ function (_dereq_, module, exports) { var createTypedArrayConstructor = _dereq_('../internals/typed-array-constructor'); // `Int32Array` constructor @@ -26367,10 +26828,10 @@ }); }, { - '../internals/typed-array-constructor': 160 + '../internals/typed-array-constructor': 162 } ], - 236: [ + 244: [ function (_dereq_, module, exports) { 'use strict'; var global = _dereq_('../internals/global'); @@ -26408,12 +26869,12 @@ }, { '../internals/array-buffer-view-core': 30, - '../internals/global': 77, - '../internals/well-known-symbol': 166, - '../modules/es.array.iterator': 179 + '../internals/global': 78, + '../internals/well-known-symbol': 168, + '../modules/es.array.iterator': 183 } ], - 237: [ + 245: [ function (_dereq_, module, exports) { 'use strict'; var ArrayBufferViewCore = _dereq_('../internals/array-buffer-view-core'); @@ -26432,7 +26893,7 @@ '../internals/array-buffer-view-core': 30 } ], - 238: [ + 246: [ function (_dereq_, module, exports) { 'use strict'; var ArrayBufferViewCore = _dereq_('../internals/array-buffer-view-core'); @@ -26451,7 +26912,7 @@ '../internals/array-last-index-of': 38 } ], - 239: [ + 247: [ function (_dereq_, module, exports) { 'use strict'; var ArrayBufferViewCore = _dereq_('../internals/array-buffer-view-core'); @@ -26471,10 +26932,10 @@ { '../internals/array-buffer-view-core': 30, '../internals/array-iteration': 37, - '../internals/species-constructor': 139 + '../internals/species-constructor': 141 } ], - 240: [ + 248: [ function (_dereq_, module, exports) { 'use strict'; var ArrayBufferViewCore = _dereq_('../internals/array-buffer-view-core'); @@ -26492,7 +26953,7 @@ '../internals/array-reduce': 42 } ], - 241: [ + 249: [ function (_dereq_, module, exports) { 'use strict'; var ArrayBufferViewCore = _dereq_('../internals/array-buffer-view-core'); @@ -26510,7 +26971,7 @@ '../internals/array-reduce': 42 } ], - 242: [ + 250: [ function (_dereq_, module, exports) { 'use strict'; var ArrayBufferViewCore = _dereq_('../internals/array-buffer-view-core'); @@ -26537,7 +26998,7 @@ '../internals/array-buffer-view-core': 30 } ], - 243: [ + 251: [ function (_dereq_, module, exports) { 'use strict'; var ArrayBufferViewCore = _dereq_('../internals/array-buffer-view-core'); @@ -26568,12 +27029,12 @@ { '../internals/array-buffer-view-core': 30, '../internals/fails': 69, - '../internals/to-length': 154, - '../internals/to-object': 155, - '../internals/to-offset': 156 + '../internals/to-length': 156, + '../internals/to-object': 157, + '../internals/to-offset': 158 } ], - 244: [ + 252: [ function (_dereq_, module, exports) { 'use strict'; var ArrayBufferViewCore = _dereq_('../internals/array-buffer-view-core'); @@ -26603,10 +27064,10 @@ { '../internals/array-buffer-view-core': 30, '../internals/fails': 69, - '../internals/species-constructor': 139 + '../internals/species-constructor': 141 } ], - 245: [ + 253: [ function (_dereq_, module, exports) { 'use strict'; var ArrayBufferViewCore = _dereq_('../internals/array-buffer-view-core'); @@ -26624,7 +27085,7 @@ '../internals/array-iteration': 37 } ], - 246: [ + 254: [ function (_dereq_, module, exports) { 'use strict'; var ArrayBufferViewCore = _dereq_('../internals/array-buffer-view-core'); @@ -26642,7 +27103,7 @@ '../internals/array-buffer-view-core': 30 } ], - 247: [ + 255: [ function (_dereq_, module, exports) { 'use strict'; var ArrayBufferViewCore = _dereq_('../internals/array-buffer-view-core'); @@ -26662,12 +27123,12 @@ }, { '../internals/array-buffer-view-core': 30, - '../internals/species-constructor': 139, - '../internals/to-absolute-index': 150, - '../internals/to-length': 154 + '../internals/species-constructor': 141, + '../internals/to-absolute-index': 152, + '../internals/to-length': 156 } ], - 248: [ + 256: [ function (_dereq_, module, exports) { 'use strict'; var global = _dereq_('../internals/global'); @@ -26701,10 +27162,10 @@ { '../internals/array-buffer-view-core': 30, '../internals/fails': 69, - '../internals/global': 77 + '../internals/global': 78 } ], - 249: [ + 257: [ function (_dereq_, module, exports) { 'use strict'; var exportTypedArrayMethod = _dereq_('../internals/array-buffer-view-core').exportTypedArrayMethod; @@ -26733,10 +27194,10 @@ { '../internals/array-buffer-view-core': 30, '../internals/fails': 69, - '../internals/global': 77 + '../internals/global': 78 } ], - 250: [ + 258: [ function (_dereq_, module, exports) { var createTypedArrayConstructor = _dereq_('../internals/typed-array-constructor'); // `Uint16Array` constructor @@ -26748,10 +27209,10 @@ }); }, { - '../internals/typed-array-constructor': 160 + '../internals/typed-array-constructor': 162 } ], - 251: [ + 259: [ function (_dereq_, module, exports) { var createTypedArrayConstructor = _dereq_('../internals/typed-array-constructor'); // `Uint32Array` constructor @@ -26763,10 +27224,10 @@ }); }, { - '../internals/typed-array-constructor': 160 + '../internals/typed-array-constructor': 162 } ], - 252: [ + 260: [ function (_dereq_, module, exports) { var createTypedArrayConstructor = _dereq_('../internals/typed-array-constructor'); // `Uint8Array` constructor @@ -26778,10 +27239,10 @@ }); }, { - '../internals/typed-array-constructor': 160 + '../internals/typed-array-constructor': 162 } ], - 253: [ + 261: [ function (_dereq_, module, exports) { var createTypedArrayConstructor = _dereq_('../internals/typed-array-constructor'); // `Uint8ClampedArray` constructor @@ -26793,10 +27254,10 @@ }, true); }, { - '../internals/typed-array-constructor': 160 + '../internals/typed-array-constructor': 162 } ], - 254: [ + 262: [ function (_dereq_, module, exports) { 'use strict'; var global = _dereq_('../internals/global'); @@ -26868,15 +27329,15 @@ { '../internals/collection': 50, '../internals/collection-weak': 49, - '../internals/global': 77, - '../internals/internal-metadata': 87, - '../internals/internal-state': 88, - '../internals/is-object': 92, - '../internals/native-weak-map': 103, - '../internals/redefine-all': 125 + '../internals/global': 78, + '../internals/internal-metadata': 88, + '../internals/internal-state': 89, + '../internals/is-object': 93, + '../internals/native-weak-map': 104, + '../internals/redefine-all': 127 } ], - 255: [ + 263: [ function (_dereq_, module, exports) { var global = _dereq_('../internals/global'); var DOMIterables = _dereq_('../internals/dom-iterables'); @@ -26897,10 +27358,10 @@ '../internals/array-for-each': 34, '../internals/create-non-enumerable-property': 56, '../internals/dom-iterables': 63, - '../internals/global': 77 + '../internals/global': 78 } ], - 256: [ + 264: [ function (_dereq_, module, exports) { var global = _dereq_('../internals/global'); var DOMIterables = _dereq_('../internals/dom-iterables'); @@ -26937,12 +27398,12 @@ { '../internals/create-non-enumerable-property': 56, '../internals/dom-iterables': 63, - '../internals/global': 77, - '../internals/well-known-symbol': 166, - '../modules/es.array.iterator': 179 + '../internals/global': 78, + '../internals/well-known-symbol': 168, + '../modules/es.array.iterator': 183 } ], - 257: [ + 265: [ function (_dereq_, module, exports) { 'use strict'; // TODO: in core-js@4, move /modules/ dependencies to public entries for better optimization by tools like `preset-env` @@ -27320,23 +27781,23 @@ '../internals/create-iterator-constructor': 55, '../internals/create-property-descriptor': 57, '../internals/export': 68, - '../internals/function-bind-context': 72, - '../internals/get-built-in': 74, - '../internals/get-iterator': 76, - '../internals/get-iterator-method': 75, - '../internals/has': 78, - '../internals/internal-state': 88, - '../internals/is-object': 92, - '../internals/native-url': 102, - '../internals/object-create': 108, - '../internals/redefine': 126, - '../internals/redefine-all': 125, - '../internals/set-to-string-tag': 135, - '../internals/well-known-symbol': 166, - '../modules/es.array.iterator': 179 + '../internals/function-bind-context': 73, + '../internals/get-built-in': 75, + '../internals/get-iterator': 77, + '../internals/get-iterator-method': 76, + '../internals/has': 79, + '../internals/internal-state': 89, + '../internals/is-object': 93, + '../internals/native-url': 103, + '../internals/object-create': 109, + '../internals/redefine': 128, + '../internals/redefine-all': 127, + '../internals/set-to-string-tag': 137, + '../internals/well-known-symbol': 168, + '../modules/es.array.iterator': 183 } ], - 258: [ + 266: [ function (_dereq_, module, exports) { 'use strict'; // TODO: in core-js@4, move /modules/ dependencies to public entries for better optimization by tools like `preset-env` @@ -28363,21 +28824,21 @@ '../internals/array-from': 35, '../internals/descriptors': 61, '../internals/export': 68, - '../internals/global': 77, - '../internals/has': 78, - '../internals/internal-state': 88, - '../internals/native-url': 102, - '../internals/object-assign': 107, - '../internals/object-define-properties': 109, - '../internals/redefine': 126, - '../internals/set-to-string-tag': 135, - '../internals/string-multibyte': 141, - '../internals/string-punycode-to-ascii': 144, - '../modules/es.string.iterator': 210, - '../modules/web.url-search-params': 257 + '../internals/global': 78, + '../internals/has': 79, + '../internals/internal-state': 89, + '../internals/native-url': 103, + '../internals/object-assign': 108, + '../internals/object-define-properties': 110, + '../internals/redefine': 128, + '../internals/set-to-string-tag': 137, + '../internals/string-multibyte': 143, + '../internals/string-punycode-to-ascii': 146, + '../modules/es.string.iterator': 218, + '../modules/web.url-search-params': 265 } ], - 259: [ + 267: [ function (_dereq_, module, exports) { // This file can be required in Browserify and Node.js for automatic polyfill // To use it: require('es6-promise/auto'); @@ -28385,10 +28846,10 @@ module.exports = _dereq_('./').polyfill(); }, { - './': 260 + './': 268 } ], - 260: [ + 268: [ function (_dereq_, module, exports) { (function (process, global) { /*! @@ -29450,10 +29911,10 @@ }) }, { - '_process': 273 + '_process': 281 } ], - 261: [ + 269: [ function (_dereq_, module, exports) { (function (global, factory) { if (typeof define === 'function' && define.amd) { @@ -29566,7 +30027,7 @@ { } ], - 262: [ + 270: [ function (_dereq_, module, exports) { /* FileSaver.js * A saveAs() FileSaver implementation. @@ -29743,7 +30204,7 @@ { } ], - 263: [ + 271: [ function (_dereq_, module, exports) { var __defProp = Object.defineProperty; var __markAsModule = target=>__defProp(target, '__esModule', { @@ -30577,7 +31038,7 @@ { } ], - 264: [ + 272: [ function (_dereq_, module, exports) { 'use strict'; function _interopDefault(ex) { @@ -30877,11 +31338,11 @@ module.exports = Browser; }, { - '@babel/runtime/helpers/classCallCheck': 265, - '@babel/runtime/helpers/createClass': 266 + '@babel/runtime/helpers/classCallCheck': 273, + '@babel/runtime/helpers/createClass': 274 } ], - 265: [ + 273: [ function (_dereq_, module, exports) { arguments[4][5][0].apply(exports, arguments) }, @@ -30889,7 +31350,7 @@ 'dup': 5 } ], - 266: [ + 274: [ function (_dereq_, module, exports) { arguments[4][6][0].apply(exports, arguments) }, @@ -30897,7 +31358,7 @@ 'dup': 6 } ], - 267: [ + 275: [ function (_dereq_, module, exports) { 'use strict'; function _interopDefault(ex) { @@ -33391,7 +33852,7 @@ '@babel/runtime/helpers/typeof': 19 } ], - 268: [ + 276: [ function (_dereq_, module, exports) { exports.read = function (buffer, offset, isLE, mLen, nBytes) { var e, @@ -33477,7 +33938,7 @@ { } ], - 269: [ + 277: [ function (_dereq_, module, exports) { /* @@ -34638,7 +35099,7 @@ { } ], - 270: [ + 278: [ function (_dereq_, module, exports) { // (c) Dean McNamee , 2013. // @@ -35387,7 +35848,7 @@ { } ], - 271: [ + 279: [ function (_dereq_, module, exports) { (function (Buffer) { /** @@ -49899,7 +50360,7 @@ 'fs': 21 } ], - 272: [ + 280: [ function (_dereq_, module, exports) { (function (process) { // .dirname, .basename, and .extname methods are extracted from Node.js v8.11.1, @@ -50166,10 +50627,10 @@ }).call(this, _dereq_('_process')) }, { - '_process': 273 + '_process': 281 } ], - 273: [ + 281: [ function (_dereq_, module, exports) { // shim for using process in browser var process = module.exports = { @@ -50353,7 +50814,7 @@ { } ], - 274: [ + 282: [ function (_dereq_, module, exports) { /** * Copyright (c) 2014-present, Facebook, Inc. @@ -50979,7 +51440,7 @@ { } ], - 275: [ + 283: [ function (_dereq_, module, exports) { (function (self) { 'use strict'; @@ -51422,7 +51883,7 @@ { } ], - 276: [ + 284: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.function.name'); @@ -52150,16 +52611,16 @@ exports.default = _default; }, { - '../color/color_conversion': 282, - '../core/main': 298, - 'core-js/modules/es.function.name': 186, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.regexp.exec': 205, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.string.split': 216 + '../color/color_conversion': 290, + '../core/main': 306, + 'core-js/modules/es.function.name': 192, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.regexp.exec': 213, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.string.split': 224 } ], - 277: [ + 285: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.array.concat'); @@ -52196,7 +52657,7 @@ var labelTableId = '_labelTable'; //Label Table var labelTableElId = '_lte_'; //Label Table Element /** - * Creates a screen reader-accessible description for the canvas. + * Creates a screen reader-accessible description of the canvas. * * The first parameter, `text`, is the description of the canvas. * @@ -52208,8 +52669,8 @@ * visible to screen readers. This is the default mode. * * Read - * How to label your p5.js code to - * learn more about making sketches accessible. + * Writing accessible canvas descriptions + * to learn more about making sketches accessible. * * @method describe * @param {String} text description of the canvas. @@ -52339,8 +52800,10 @@ } }; /** - * Creates a screen reader-accessible description for elements in the canvas. - * Elements are shapes or groups of shapes that create meaning together. + * Creates a screen reader-accessible description of elements in the canvas. + * + * Elements are shapes or groups of shapes that create meaning together. For + * example, a few overlapping circles could make an "eye" element. * * The first parameter, `name`, is the name of the element. * @@ -52356,8 +52819,8 @@ * mode. * * Read - * How to label your p5.js code to - * learn more about making sketches accessible. + * Writing accessible canvas descriptions + * to learn more about making sketches accessible. * * @method describeElement * @param {String} name name of the element. @@ -52593,7 +53056,7 @@ } else if (type === 'label') { //If display is LABEL creates a div adjacent to the canvas element with //a table, a row header cell with the name of the elements, - //and adds the description of the element in adjecent cell. + //and adds the description of the element in adjacent cell. //if there is no label description container if (!this.dummyDOM.querySelector('#'.concat(cnvId + labelContainer))) { //if there are no accessible outputs (see textOutput() and gridOutput()) @@ -52624,14 +53087,14 @@ exports.default = _default; }, { - '../core/main': 298, - 'core-js/modules/es.array.concat': 169, - 'core-js/modules/es.regexp.exec': 205, - 'core-js/modules/es.string.ends-with': 208, - 'core-js/modules/es.string.replace': 214 + '../core/main': 306, + 'core-js/modules/es.array.concat': 171, + 'core-js/modules/es.regexp.exec': 213, + 'core-js/modules/es.string.ends-with': 216, + 'core-js/modules/es.string.replace': 222 } ], - 278: [ + 286: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.array.concat'); @@ -52705,17 +53168,20 @@ fill = '').concat(ingredients[x][y].color, ' ').concat(x, ''); } else { fill = '').concat(ingredients[x][y].color, ' ').concat(x, ' midpoint'); - } //if empty cell of location of shape is undefined - - if (!cells[ingredients[x][y].loc.locY][ingredients[x][y].loc.locX]) { - //fill it with shape info - cells[ingredients[x][y].loc.locY][ingredients[x][y].loc.locX] = fill; - //if a shape is already in that location - } else { - //add it - cells[ingredients[x][y].loc.locY][ingredients[x][y].loc.locX] = cells[ingredients[x][y].loc.locY][ingredients[x][y].loc.locX] + ' ' + fill; + } // Check if shape is in canvas, skip if not + + if (ingredients[x][y].loc.locY < cells.length && ingredients[x][y].loc.locX < cells[ingredients[x][y].loc.locY].length) { + //if empty cell of location of shape is undefined + if (!cells[ingredients[x][y].loc.locY][ingredients[x][y].loc.locX]) { + //fill it with shape info + cells[ingredients[x][y].loc.locY][ingredients[x][y].loc.locX] = fill; + //if a shape is already in that location + } else { + //add it + cells[ingredients[x][y].loc.locY][ingredients[x][y].loc.locX] = cells[ingredients[x][y].loc.locY][ingredients[x][y].loc.locX] + ' ' + fill; + } + shapeNumber++; } - shapeNumber++; } } //make table based on array @@ -52784,14 +53250,14 @@ exports.default = _default; }, { - '../core/main': 298, - 'core-js/modules/es.array.concat': 169, - 'core-js/modules/es.array.from': 176, - 'core-js/modules/es.array.map': 182, - 'core-js/modules/es.string.iterator': 210 + '../core/main': 306, + 'core-js/modules/es.array.concat': 171, + 'core-js/modules/es.array.from': 180, + 'core-js/modules/es.array.map': 186, + 'core-js/modules/es.string.iterator': 218 } ], - 279: [ + 287: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -52845,12 +53311,11 @@ * @requires core */ /** - * Creates a screen reader-accessible description for shapes on the canvas. - * `textOutput()` adds a general description, list of shapes, and - * table of shapes to the web page. + * Creates a screen reader-accessible description of shapes on the canvas. * - * The general description includes the canvas size, canvas color, and number - * of shapes. For example, + * `textOutput()` adds a general description, list of shapes, and + * table of shapes to the web page. The general description includes the + * canvas size, canvas color, and number of shapes. For example, * `Your output is a, 100 by 100 pixels, gray canvas containing the following 2 shapes:`. * * A list of shapes follows the general description. The list describes the @@ -52872,8 +53337,8 @@ * mode. * * Read - * How to label your p5.js code to - * learn more about making sketches accessible. + * Writing accessible canvas descriptions + * to learn more about making sketches accessible. * * @method textOutput * @param {Constant} [display] either FALLBACK or LABEL. @@ -52979,12 +53444,11 @@ } }; /** - * Creates a screen reader-accessible description for shapes on the canvas. - * `gridOutput()` adds a general description, table of shapes, and list of - * shapes to the web page. + * Creates a screen reader-accessible description of shapes on the canvas. * - * The general description includes the canvas size, canvas color, and number of - * shapes. For example, + * `gridOutput()` adds a general description, table of shapes, and list of + * shapes to the web page. The general description includes the canvas size, + * canvas color, and number of shapes. For example, * `gray canvas, 100 by 100 pixels, contains 2 shapes: 1 circle 1 square`. * * `gridOutput()` uses its table of shapes as a grid. Each shape in the grid @@ -53007,8 +53471,8 @@ * mode. * * Read - * How to label your p5.js code to - * learn more about making sketches accessible. + * Writing accessible canvas descriptions + * to learn more about making sketches accessible. * * @method gridOutput * @param {Constant} [display] either FALLBACK or LABEL. @@ -53138,7 +53602,8 @@ fill: 'white', stroke: 'black' }, - pShapes: '' + pShapes: '', + pBackground: '' }; } //if there is no dummyDOM create it @@ -53215,7 +53680,7 @@ _main.default.prototype._updateAccsOutput = function () { var cnvId = this.canvas.id; //if the shapes are not the same as before - if (JSON.stringify(this.ingredients.shapes) !== this.ingredients.pShapes) { + if (JSON.stringify(this.ingredients.shapes) !== this.ingredients.pShapes || this.ingredients.colors.background !== this.ingredients.pBackground) { //save current shapes as string in pShapes this.ingredients.pShapes = JSON.stringify(this.ingredients.shapes); if (this._accessibleOutputs.text) { @@ -53237,6 +53702,7 @@ _main.default.prototype._accsBackground = function (args) { //save current shapes as string in pShapes this.ingredients.pShapes = JSON.stringify(this.ingredients.shapes); + this.ingredients.pBackground = this.ingredients.colors.background; //empty shapes JSON this.ingredients.shapes = { }; @@ -53357,8 +53823,8 @@ var _untransformedPositio = untransformedPosition.matrixTransform(currentTransform), transformedX = _untransformedPositio.x, transformedY = _untransformedPositio.y; - var canvasWidth = this.width, - canvasHeight = this.height; + var canvasWidth = this.width * this._pixelDensity; + var canvasHeight = this.height * this._pixelDensity; if (transformedX < 0.4 * canvasWidth) { if (transformedY < 0.4 * canvasHeight) { return 'top left'; @@ -53470,23 +53936,23 @@ exports.default = _default; }, { - '../core/main': 298, - 'core-js/modules/es.array.concat': 169, - 'core-js/modules/es.array.fill': 172, - 'core-js/modules/es.array.from': 176, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.map': 182, - 'core-js/modules/es.number.to-fixed': 193, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/main': 306, + 'core-js/modules/es.array.concat': 171, + 'core-js/modules/es.array.fill': 174, + 'core-js/modules/es.array.from': 180, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.map': 186, + 'core-js/modules/es.number.to-fixed': 200, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 280: [ + 288: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.array.concat'); @@ -53605,11 +54071,11 @@ exports.default = _default; }, { - '../core/main': 298, - 'core-js/modules/es.array.concat': 169 + '../core/main': 306, + 'core-js/modules/es.array.concat': 171 } ], - 281: [ + 289: [ function (_dereq_, module, exports) { 'use strict'; var _main = _interopRequireDefault(_dereq_('./core/main')); @@ -53682,6 +54148,7 @@ _dereq_('./webgl/p5.DataArray'); _dereq_('./webgl/p5.Geometry'); _dereq_('./webgl/p5.Matrix'); + _dereq_('./webgl/p5.Quat'); _dereq_('./webgl/p5.RendererGL.Immediate'); _dereq_('./webgl/p5.RendererGL'); _dereq_('./webgl/p5.RendererGL.Retained'); @@ -53713,88 +54180,89 @@ module.exports = _main.default; }, { - './accessibility/color_namer': 276, - './accessibility/describe': 277, - './accessibility/gridOutput': 278, - './accessibility/outputs': 279, - './accessibility/textOutput': 280, - './color/color_conversion': 282, - './color/creating_reading': 283, - './color/p5.Color': 284, - './color/setting': 285, - './core/constants': 286, - './core/environment': 287, - './core/friendly_errors/fes_core': 289, - './core/friendly_errors/file_errors': 290, - './core/friendly_errors/sketch_reader': 291, - './core/friendly_errors/stacktrace': 292, - './core/friendly_errors/validate_params': 293, - './core/helpers': 294, - './core/init': 295, - './core/legacy': 297, - './core/main': 298, - './core/p5.Element': 299, - './core/p5.Graphics': 300, - './core/p5.Renderer': 301, - './core/p5.Renderer2D': 302, - './core/preload': 303, - './core/rendering': 304, - './core/shape/2d_primitives': 305, - './core/shape/attributes': 306, - './core/shape/curves': 307, - './core/shape/vertex': 308, - './core/shim': 309, - './core/structure': 310, - './core/transform': 311, - './data/local_storage.js': 312, - './data/p5.TypedDict': 313, - './dom/dom': 314, - './events/acceleration': 315, - './events/keyboard': 316, - './events/mouse': 317, - './events/touch': 318, - './image/filters': 319, - './image/image': 320, - './image/loading_displaying': 321, - './image/p5.Image': 322, - './image/pixels': 323, - './io/files': 324, - './io/p5.Table': 325, - './io/p5.TableRow': 326, - './io/p5.XML': 327, - './math/calculation': 328, - './math/math': 329, - './math/noise': 330, - './math/p5.Vector': 331, - './math/random': 332, - './math/trigonometry': 333, - './typography/attributes': 334, - './typography/loading_displaying': 335, - './typography/p5.Font': 336, - './utilities/array_functions': 337, - './utilities/conversion': 338, - './utilities/string_functions': 339, - './utilities/time_date': 340, - './webgl/3d_primitives': 341, - './webgl/interaction': 343, - './webgl/light': 344, - './webgl/loading': 345, - './webgl/material': 346, - './webgl/p5.Camera': 347, - './webgl/p5.DataArray': 348, - './webgl/p5.Framebuffer': 349, - './webgl/p5.Geometry': 350, - './webgl/p5.Matrix': 351, - './webgl/p5.RenderBuffer': 352, - './webgl/p5.RendererGL': 355, - './webgl/p5.RendererGL.Immediate': 353, - './webgl/p5.RendererGL.Retained': 354, - './webgl/p5.Shader': 356, - './webgl/p5.Texture': 357, - './webgl/text': 358 + './accessibility/color_namer': 284, + './accessibility/describe': 285, + './accessibility/gridOutput': 286, + './accessibility/outputs': 287, + './accessibility/textOutput': 288, + './color/color_conversion': 290, + './color/creating_reading': 291, + './color/p5.Color': 292, + './color/setting': 293, + './core/constants': 294, + './core/environment': 295, + './core/friendly_errors/fes_core': 297, + './core/friendly_errors/file_errors': 298, + './core/friendly_errors/sketch_reader': 299, + './core/friendly_errors/stacktrace': 300, + './core/friendly_errors/validate_params': 301, + './core/helpers': 302, + './core/init': 303, + './core/legacy': 305, + './core/main': 306, + './core/p5.Element': 307, + './core/p5.Graphics': 308, + './core/p5.Renderer': 309, + './core/p5.Renderer2D': 310, + './core/preload': 311, + './core/rendering': 312, + './core/shape/2d_primitives': 313, + './core/shape/attributes': 314, + './core/shape/curves': 315, + './core/shape/vertex': 316, + './core/shim': 317, + './core/structure': 318, + './core/transform': 319, + './data/local_storage.js': 320, + './data/p5.TypedDict': 321, + './dom/dom': 322, + './events/acceleration': 323, + './events/keyboard': 324, + './events/mouse': 325, + './events/touch': 326, + './image/filters': 327, + './image/image': 328, + './image/loading_displaying': 329, + './image/p5.Image': 330, + './image/pixels': 331, + './io/files': 332, + './io/p5.Table': 333, + './io/p5.TableRow': 334, + './io/p5.XML': 335, + './math/calculation': 336, + './math/math': 337, + './math/noise': 338, + './math/p5.Vector': 339, + './math/random': 340, + './math/trigonometry': 341, + './typography/attributes': 342, + './typography/loading_displaying': 343, + './typography/p5.Font': 344, + './utilities/array_functions': 345, + './utilities/conversion': 346, + './utilities/string_functions': 347, + './utilities/time_date': 348, + './webgl/3d_primitives': 349, + './webgl/interaction': 351, + './webgl/light': 352, + './webgl/loading': 353, + './webgl/material': 354, + './webgl/p5.Camera': 355, + './webgl/p5.DataArray': 356, + './webgl/p5.Framebuffer': 357, + './webgl/p5.Geometry': 358, + './webgl/p5.Matrix': 359, + './webgl/p5.Quat': 360, + './webgl/p5.RenderBuffer': 361, + './webgl/p5.RendererGL': 364, + './webgl/p5.RendererGL.Immediate': 362, + './webgl/p5.RendererGL.Retained': 363, + './webgl/p5.Shader': 365, + './webgl/p5.Texture': 366, + './webgl/text': 367 } ], - 282: [ + 290: [ function (_dereq_, module, exports) { 'use strict'; Object.defineProperty(exports, '__esModule', { @@ -54085,10 +54553,10 @@ exports.default = _default; }, { - '../core/main': 298 + '../core/main': 306 } ], - 283: [ + 291: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -54190,9 +54658,11 @@ * @requires constants */ /** - * Extracts the alpha (transparency) value from a - * p5.Color object, array of color components, or - * CSS color string. + * Gets the alpha (transparency) value of a color. + * + * `alpha()` extracts the alpha value from a + * p5.Color object, an array of color components, or + * a CSS color string. * * @method alpha * @param {p5.Color|Number[]|String} color p5.Color object, array of @@ -54202,15 +54672,84 @@ * @example *
* - * noStroke(); - * const c = color(0, 126, 255, 102); - * fill(c); - * rect(15, 15, 35, 70); - * // Sets 'alphaValue' to 102. - * const alphaValue = alpha(c); - * fill(alphaValue); - * rect(50, 15, 35, 70); - * describe('Two rectangles. The left one is light blue and the right one is charcoal gray.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.Color object. + * let c = color(0, 126, 255, 102); + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'alphaValue' to 102. + * let alphaValue = alpha(c); + * + * // Draw the right rectangle. + * fill(alphaValue); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is light blue and the right one is charcoal gray.'); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a color array. + * let c = [0, 126, 255, 102]; + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'alphaValue' to 102. + * let alphaValue = alpha(c); + * + * // Draw the left rectangle. + * fill(alphaValue); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is light blue and the right one is charcoal gray.'); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a CSS color string. + * let c = 'rgba(0, 126, 255, 0.4)'; + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'alphaValue' to 102. + * let alphaValue = alpha(c); + * + * // Draw the right rectangle. + * fill(alphaValue); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is light blue and the right one is charcoal gray.'); + * } * *
*/ @@ -54220,36 +54759,150 @@ return this.color(c)._getAlpha(); }; /** - * Extracts the blue value from a p5.Color object, - * array of color components, or CSS color string. + * Gets the blue value of a color. + * + * `blue()` extracts the blue value from a + * p5.Color object, an array of color components, or + * a CSS color string. + * + * By default, `blue()` returns a color's blue value in the range 0 + * to 255. If the colorMode() is set to RGB, it + * returns the blue value in the given range. * * @method blue * @param {p5.Color|Number[]|String} color p5.Color object, array of * color components, or CSS color string. * @return {Number} the blue value. + * * @example *
* - * const c = color(175, 100, 220); - * fill(c); - * rect(15, 20, 35, 60); - * // Sets 'blueValue' to 220. - * const blueValue = blue(c); - * fill(0, 0, blueValue); - * rect(50, 20, 35, 60); - * describe('Two rectangles. The left one is light purple and the right one is royal blue.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.Color object using RGB values. + * let c = color(175, 100, 220); + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'blueValue' to 220. + * let blueValue = blue(c); + * + * // Draw the right rectangle. + * fill(0, 0, blueValue); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is light purple and the right one is royal blue.'); + * } * *
* + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a color array. + * let c = [175, 100, 220]; + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'blueValue' to 220. + * let blueValue = blue(c); + * + * // Draw the right rectangle. + * fill(0, 0, blueValue); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is light purple and the right one is royal blue.'); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a CSS color string. + * let c = 'rgb(175, 100, 220)'; + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'blueValue' to 220. + * let blueValue = blue(c); + * + * // Draw the right rectangle. + * fill(0, 0, blueValue); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is light purple and the right one is royal blue.'); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Use RGB color with values in the range 0-100. + * colorMode(RGB, 100); + * + * // Create a p5.Color object using RGB values. + * let c = color(69, 39, 86); + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'blueValue' to 86. + * let blueValue = blue(c); + * + * // Draw the right rectangle. + * fill(0, 0, blueValue); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is light purple and the right one is royal blue.'); + * } + * + *
*/ _main.default.prototype.blue = function (c) { _main.default._validateParameters('blue', arguments); return this.color(c)._getBlue(); }; /** - * Extracts the HSB brightness value from a - * p5.Color object, array of color components, or - * CSS color string. + * Gets the brightness value of a color. + * + * `brightness()` extracts the HSB brightness value from a + * p5.Color object, an array of color components, or + * a CSS color string. + * + * By default, `brightness()` returns a color's HSB brightness in the range 0 + * to 100. If the colorMode() is set to HSB, it + * returns the brightness value in the given range. * * @method brightness * @param {p5.Color|Number[]|String} color p5.Color object, array of @@ -54259,31 +54912,124 @@ * @example *
* - * noStroke(); - * colorMode(HSB, 255); - * const c = color(0, 126, 255); - * fill(c); - * rect(15, 20, 35, 60); - * // Sets 'brightValue' to 255. - * const brightValue = brightness(c); - * fill(brightValue); - * rect(50, 20, 35, 60); - * describe('Two rectangles. The left one is salmon pink and the right one is white.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Use HSB color. + * colorMode(HSB); + * + * // Create a p5.Color object. + * let c = color(0, 50, 100); + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'brightValue' to 100. + * let brightValue = brightness(c); + * + * // Draw the right rectangle. + * fill(brightValue); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is salmon pink and the right one is white.'); + * } * *
* + * @example *
* - * noStroke(); - * colorMode(HSB, 255); - * const c = color('hsb(60, 100%, 50%)'); - * fill(c); - * rect(15, 20, 35, 60); - * // Sets 'brightValue' to 127.5 (50% of 255) - * const brightValue = brightness(c); - * fill(brightValue); - * rect(50, 20, 35, 60); - * describe('Two rectangles. The left one is olive and the right one is gray.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Use HSB color. + * colorMode(HSB); + * + * // Create a color array. + * let c = [0, 50, 100]; + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'brightValue' to 100. + * let brightValue = brightness(c); + * + * // Draw the right rectangle. + * fill(brightValue); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is salmon pink and the right one is white.'); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Use HSB color. + * colorMode(HSB); + * + * // Create a CSS color string. + * let c = 'rgb(255, 128, 128)'; + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'brightValue' to 100. + * let brightValue = brightness(c); + * + * // Draw the right rectangle. + * fill(brightValue); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is salmon pink and the right one is white.'); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Use HSB color with values in the range 0-255. + * colorMode(HSB, 255); + * + * // Create a p5.Color object. + * let c = color(0, 127, 255); + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'brightValue' to 255. + * let brightValue = brightness(c); + * + * // Draw the right rectangle. + * fill(brightValue); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is salmon pink and the right one is white.'); + * } * *
*/ @@ -54292,10 +55038,12 @@ return this.color(c)._getBrightness(); }; /** - * Creates a p5.Color object. By default, the - * parameters are interpreted as RGB values. Calling `color(255, 204, 0)` will - * return a bright yellow color. The way these parameters are interpreted may - * be changed with the colorMode() function. + * Creates a p5.Color object. + * + * By default, the parameters are interpreted as RGB values. Calling + * `color(255, 204, 0)` will return a bright yellow color. The way these + * parameters are interpreted may be changed with the + * colorMode() function. * * The version of `color()` with one parameter interprets the value one of two * ways. If the parameter is a number, it's interpreted as a grayscale value. @@ -54320,116 +55068,225 @@ * @example *
* - * const c = color(255, 204, 0); - * fill(c); - * noStroke(); - * rect(30, 20, 55, 55); - * describe('A yellow rectangle on a gray canvas.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.Color object using RGB values. + * let c = color(255, 204, 0); + * + * // Draw the square. + * fill(c); + * noStroke(); + * square(30, 20, 55); + * + * describe('A yellow square on a gray canvas.'); + * } * *
* + * @example *
* - * // RGB values. - * let c = color(255, 204, 0); - * fill(c); - * noStroke(); - * circle(25, 25, 80); - * // A grayscale value. - * c = color(65); - * fill(c); - * circle(75, 75, 80); - * describe( - * 'Two ellipses. The circle in the top-left corner is yellow and the one at the bottom-right is gray.' - * ); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.Color object using RGB values. + * let c1 = color(255, 204, 0); + * + * // Draw the left circle. + * fill(c1); + * noStroke(); + * circle(25, 25, 80); + * + * // Create a p5.Color object using a grayscale value. + * let c2 = color(65); + * + * // Draw the right circle. + * fill(c2); + * circle(75, 75, 80); + * + * describe( + * 'Two circles on a gray canvas. The circle in the top-left corner is yellow and the one at the bottom-right is gray.' + * ); + * } * *
* + * @example *
* - * // A CSS named color. - * const c = color('magenta'); - * fill(c); - * noStroke(); - * square(20, 20, 60); - * describe('A magenta square on a gray canvas.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.Color object using a named color. + * let c = color('magenta'); + * + * // Draw the square. + * fill(c); + * noStroke(); + * square(20, 20, 60); + * + * describe('A magenta square on a gray canvas.'); + * } * *
* + * @example *
* - * // CSS hex color codes. - * noStroke(); - * let c = color('#0f0'); - * fill(c); - * rect(0, 10, 45, 80); - * c = color('#00ff00'); - * fill(c); - * rect(55, 10, 45, 80); - * describe('Two bright green rectangles on a gray canvas.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.Color object using a hex color code. + * let c1 = color('#0f0'); + * + * // Draw the left rectangle. + * fill(c1); + * noStroke(); + * rect(0, 10, 45, 80); + * + * // Create a p5.Color object using a hex color code. + * let c2 = color('#00ff00'); + * + * // Draw the right rectangle. + * fill(c2); + * rect(55, 10, 45, 80); + * + * describe('Two bright green rectangles on a gray canvas.'); + * } * *
* + * @example *
* - * // RGB and RGBA color strings. - * noStroke(); - * let c = color('rgb(0,0,255)'); - * fill(c); - * square(10, 10, 35); - * c = color('rgb(0%, 0%, 100%)'); - * fill(c); - * square(55, 10, 35); - * c = color('rgba(0, 0, 255, 1)'); - * fill(c); - * square(10, 55, 35); - * c = color('rgba(0%, 0%, 100%, 1)'); - * fill(c); - * square(55, 55, 35); - * describe('Four blue squares in corners of a gray canvas.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.Color object using a RGB color string. + * let c1 = color('rgb(0, 0, 255)'); + * + * // Draw the top-left square. + * fill(c1); + * square(10, 10, 35); + * + * // Create a p5.Color object using a RGB color string. + * let c2 = color('rgb(0%, 0%, 100%)'); + * + * // Draw the top-right square. + * fill(c2); + * square(55, 10, 35); + * + * // Create a p5.Color object using a RGBA color string. + * let c3 = color('rgba(0, 0, 255, 1)'); + * + * // Draw the bottom-left square. + * fill(c3); + * square(10, 55, 35); + * + * // Create a p5.Color object using a RGBA color string. + * let c4 = color('rgba(0%, 0%, 100%, 1)'); + * + * // Draw the bottom-right square. + * fill(c4); + * square(55, 55, 35); + * + * describe('Four blue squares in the corners of a gray canvas.'); + * } * *
* + * @example *
* - * // HSL and HSLA color strings. - * let c = color('hsl(160, 100%, 50%)'); - * noStroke(); - * fill(c); - * rect(0, 10, 45, 80); - * c = color('hsla(160, 100%, 50%, 0.5)'); - * fill(c); - * rect(55, 10, 45, 80); - * describe('Two sea green rectangles. A darker rectangle on the left and a brighter one on the right.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.Color object using a HSL color string. + * let c1 = color('hsl(160, 100%, 50%)'); + * + * // Draw the left rectangle. + * noStroke(); + * fill(c1); + * rect(0, 10, 45, 80); + * + * // Create a p5.Color object using a HSLA color string. + * let c2 = color('hsla(160, 100%, 50%, 0.5)'); + * + * // Draw the right rectangle. + * fill(c2); + * rect(55, 10, 45, 80); + * + * describe('Two sea green rectangles. A darker rectangle on the left and a brighter one on the right.'); + * } * *
* *
* - * // HSB and HSBA color strings. - * let c = color('hsb(160, 100%, 50%)'); - * noStroke(); - * fill(c); - * rect(0, 10, 45, 80); - * c = color('hsba(160, 100%, 50%, 0.5)'); - * fill(c); - * rect(55, 10, 45, 80); - * describe('Two green rectangles. A darker rectangle on the left and a brighter one on the right.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.Color object using a HSB color string. + * let c1 = color('hsb(160, 100%, 50%)'); + * + * // Draw the left rectangle. + * noStroke(); + * fill(c1); + * rect(0, 10, 45, 80); + * + * // Create a p5.Color object using a HSBA color string. + * let c2 = color('hsba(160, 100%, 50%, 0.5)'); + * + * // Draw the right rectangle. + * fill(c2); + * rect(55, 10, 45, 80); + * + * describe('Two green rectangles. A darker rectangle on the left and a brighter one on the right.'); + * } * *
* *
* - * // Changing color modes. - * noStroke(); - * let c = color(50, 55, 100); - * fill(c); - * rect(0, 10, 45, 80); - * colorMode(HSB, 100); - * c = color(50, 55, 100); - * fill(c); - * rect(55, 10, 45, 80); - * describe('Two blue rectangles. A darker rectangle on the left and a brighter one on the right.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.Color object using RGB values. + * let c1 = color(50, 55, 100); + * + * // Draw the left rectangle. + * fill(c1); + * rect(0, 10, 45, 80); + * + * // Switch the color mode to HSB. + * colorMode(HSB, 100); + * + * // Create a p5.Color object using HSB values. + * let c2 = color(50, 55, 100); + * + * // Draw the right rectangle. + * fill(c2); + * rect(55, 10, 45, 80); + * + * describe('Two blue rectangles. A darker rectangle on the left and a brighter one on the right.'); + * } * *
*/ @@ -54461,32 +55318,144 @@ * @return {p5.Color} */ _main.default.prototype.color = function () { - _main.default._validateParameters('color', arguments); - if (arguments[0] instanceof _main.default.Color) { - return arguments[0]; // Do nothing if argument is already a color object. + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; } - var args = arguments[0] instanceof Array ? arguments[0] : arguments; - return new _main.default.Color(this, args); + _main.default._validateParameters('color', args); + if (args[0] instanceof _main.default.Color) { + return args[0]; // Do nothing if argument is already a color object. + } + var arg = Array.isArray(args[0]) ? args[0] : args; + return new _main.default.Color(this, arg); }; /** - * Extracts the green value from a p5.Color object, - * array of color components, or CSS color string. + * Gets the green value of a color. + * + * `green()` extracts the green value from a + * p5.Color object, an array of color components, or + * a CSS color string. + * + * By default, `green()` returns a color's green value in the range 0 + * to 255. If the colorMode() is set to RGB, it + * returns the green value in the given range. * * @method green * @param {p5.Color|Number[]|String} color p5.Color object, array of * color components, or CSS color string. * @return {Number} the green value. + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.Color object. + * let c = color(175, 100, 220); + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'greenValue' to 100. + * let greenValue = green(c); + * + * // Draw the right rectangle. + * fill(0, greenValue, 0); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is light purple and the right one is dark green.'); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a color array. + * let c = [175, 100, 220]; + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'greenValue' to 100. + * let greenValue = green(c); + * + * // Draw the right rectangle. + * fill(0, greenValue, 0); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is light purple and the right one is dark green.'); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a CSS color string. + * let c = 'rgb(175, 100, 220)'; + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'greenValue' to 100. + * let greenValue = green(c); + * + * // Draw the right rectangle. + * fill(0, greenValue, 0); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is light purple and the right one is dark green.'); + * } + * + *
+ * * @example *
* - * const c = color(20, 75, 200); - * fill(c); - * rect(15, 20, 35, 60); - * // Sets 'greenValue' to 75. - * const greenValue = green(c); - * fill(0, greenValue, 0); - * rect(50, 20, 35, 60); - * describe('Two rectangles. The rectangle on the left is blue and the one on the right is green.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Use RGB color with values in the range 0-100. + * colorMode(RGB, 100); + * + * // Create a p5.Color object using RGB values. + * let c = color(69, 39, 86); + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'greenValue' to 39. + * let greenValue = green(c); + * + * // Draw the right rectangle. + * fill(0, greenValue, 0); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is light purple and the right one is dark green.'); + * } * *
*/ @@ -54495,48 +55464,132 @@ return this.color(c)._getGreen(); }; /** - * Extracts the hue value from a - * p5.Color object, array of color components, or - * CSS color string. + * Gets the hue value of a color. * - * Hue exists in both HSB and HSL. It describes a color's position on the - * color wheel. By default, this function returns the HSL-normalized hue. If - * the colorMode() is set to HSB, it returns the - * HSB-normalized hue. + * `hue()` extracts the hue value from a + * p5.Color object, an array of color components, or + * a CSS color string. + * + * Hue describes a color's position on the color wheel. By default, `hue()` + * returns a color's HSL hue in the range 0 to 360. If the + * colorMode() is set to HSB or HSL, it returns the hue + * value in the given mode. * * @method hue * @param {p5.Color|Number[]|String} color p5.Color object, array of * color components, or CSS color string. - * @return {Number} the hue + * @return {Number} the hue value. + * * @example *
* - * noStroke(); - * colorMode(HSB, 255); - * const c = color(0, 126, 255); - * fill(c); - * rect(15, 20, 35, 60); - * // Sets 'hueValue' to 0. - * const hueValue = hue(c); - * fill(hueValue); - * rect(50, 20, 35, 60); - * describe( - * 'Two rectangles. The rectangle on the left is salmon pink and the one on the right is black.' - * ); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Use HSL color. + * colorMode(HSL); + * + * // Create a p5.Color object. + * let c = color(0, 50, 100); + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 20, 35, 60); + * + * // Set 'hueValue' to 0. + * let hueValue = hue(c); + * + * // Draw the right rectangle. + * fill(hueValue); + * rect(50, 20, 35, 60); + * + * describe( + * 'Two rectangles. The rectangle on the left is salmon pink and the one on the right is black.' + * ); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Use HSL color. + * colorMode(HSL); + * + * // Create a color array. + * let c = [0, 50, 100]; + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 20, 35, 60); + * + * // Set 'hueValue' to 0. + * let hueValue = hue(c); + * + * // Draw the right rectangle. + * fill(hueValue); + * rect(50, 20, 35, 60); + * + * describe( + * 'Two rectangles. The rectangle on the left is salmon pink and the one on the right is black.' + * ); + * } * *
* + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Use HSL color. + * colorMode(HSL); + * + * // Create a CSS color string. + * let c = 'rgb(255, 128, 128)'; + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 20, 35, 60); + * + * // Set 'hueValue' to 0. + * let hueValue = hue(c); + * + * // Draw the right rectangle. + * fill(hueValue); + * rect(50, 20, 35, 60); + * + * describe( + * 'Two rectangles. The rectangle on the left is salmon pink and the one on the right is black.' + * ); + * } + * + *
*/ _main.default.prototype.hue = function (c) { _main.default._validateParameters('hue', arguments); return this.color(c)._getHue(); }; /** - * Blends two colors to find a third color between them. The `amt` parameter - * specifies the amount to interpolate between the two values. 0 is equal to - * the first color, 0.1 is very near the first color, 0.5 is halfway between - * the two colors, and so on. Negative numbers are set to 0. Numbers greater - * than 1 are set to 1. This differs from the behavior of + * Blends two colors to find a third color between them. + * + * The `amt` parameter specifies the amount to interpolate between the two + * values. 0 is equal to the first color, 0.1 is very near the first color, + * 0.5 is halfway between the two colors, and so on. Negative numbers are set + * to 0. Numbers greater than 1 are set to 1. This differs from the behavior of * lerp. It's necessary because numbers outside of the * interval [0, 1] will produce strange and unexpected colors. * @@ -54546,31 +55599,46 @@ * @method lerpColor * @param {p5.Color} c1 interpolate from this color. * @param {p5.Color} c2 interpolate to this color. - * @param {Number} amt number between 0 and 1. + * @param {Number} amt number between 0 and 1. * @return {p5.Color} interpolated color. * * @example *
* - * colorMode(RGB); - * stroke(255); - * background(51); - * const from = color(218, 165, 32); - * const to = color(72, 61, 139); - * colorMode(RGB); - * const interA = lerpColor(from, to, 0.33); - * const interB = lerpColor(from, to, 0.66); - * fill(from); - * rect(10, 20, 20, 60); - * fill(interA); - * rect(30, 20, 20, 60); - * fill(interB); - * rect(50, 20, 20, 60); - * fill(to); - * rect(70, 20, 20, 60); - * describe( - * 'Four rectangles with white edges. From left to right, the rectangles are tan, brown, brownish purple, and purple.' - * ); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create p5.Color objects to interpolate between. + * let from = color(218, 165, 32); + * let to = color(72, 61, 139); + * + * // Create intermediate colors. + * let interA = lerpColor(from, to, 0.33); + * let interB = lerpColor(from, to, 0.66); + * + * // Draw the left rectangle. + * noStroke(); + * fill(from); + * rect(10, 20, 20, 60); + * + * // Draw the left-center rectangle. + * fill(interA); + * rect(30, 20, 20, 60); + * + * // Draw the right-center rectangle. + * fill(interB); + * rect(50, 20, 20, 60); + * + * // Draw the right rectangle. + * fill(to); + * rect(70, 20, 20, 60); + * + * describe( + * 'Four rectangles. From left to right, the rectangles are tan, brown, brownish purple, and purple.' + * ); + * } * *
*/ @@ -54602,7 +55670,7 @@ fromArray = c1.hsla; toArray = c2.hsla; } else { - throw new Error(''.concat(mode, 'cannot be used for interpolation.')); + throw new Error(''.concat(mode, ' cannot be used for interpolation.')); } // Prevent extrapolation. amt = Math.max(Math.min(amt, 1), 0); @@ -54614,7 +55682,23 @@ }; } // Perform interpolation. - l0 = this.lerp(fromArray[0], toArray[0], amt); + if (mode === constants.RGB) { + l0 = this.lerp(fromArray[0], toArray[0], amt); + } // l0 (hue) has to wrap around (and it's between 0 and 1) + else { + // find shortest path in the color wheel + if (Math.abs(fromArray[0] - toArray[0]) > 0.5) { + if (fromArray[0] > toArray[0]) { + toArray[0] += 1; + } else { + fromArray[0] += 1; + } + } + l0 = this.lerp(fromArray[0], toArray[0], amt); + if (l0 >= 1) { + l0 -= 1; + } + } l1 = this.lerp(fromArray[1], toArray[1], amt); l2 = this.lerp(fromArray[2], toArray[2], amt); l3 = this.lerp(fromArray[3], toArray[3], amt); @@ -54626,28 +55710,142 @@ return this.color(l0, l1, l2, l3); }; /** - * Extracts the HSL lightness value from a - * p5.Color object, array of color components, or - * CSS color string. + * Gets the lightness value of a color. + * + * `lightness()` extracts the HSL lightness value from a + * p5.Color object, an array of color components, or + * a CSS color string. + * + * By default, `lightness()` returns a color's HSL lightness in the range 0 + * to 100. If the colorMode() is set to HSL, it + * returns the lightness value in the given range. * * @method lightness * @param {p5.Color|Number[]|String} color p5.Color object, array of * color components, or CSS color string. - * @return {Number} the lightness + * @return {Number} the lightness value. * * @example *
* - * noStroke(); - * colorMode(HSL); - * const c = color(156, 100, 50, 1); - * fill(c); - * rect(15, 20, 35, 60); - * // Sets 'lightValue' to 50. - * const lightValue = lightness(c); - * fill(lightValue); - * rect(50, 20, 35, 60); - * describe('Two rectangles. The rectangle on the left is light green and the one on the right is gray.'); + * function setup() { + * createCanvas(100, 100); + * + * background(50); + * + * // Use HSL color. + * colorMode(HSL); + * + * // Create a p5.Color object using HSL values. + * let c = color(0, 100, 75); + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'lightValue' to 75. + * let lightValue = lightness(c); + * + * // Draw the right rectangle. + * fill(lightValue); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is salmon pink and the right one is gray.'); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(50); + * + * // Use HSL color. + * colorMode(HSL); + * + * // Create a color array. + * let c = [0, 100, 75]; + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'lightValue' to 75. + * let lightValue = lightness(c); + * + * // Draw the right rectangle. + * fill(lightValue); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is salmon pink and the right one is gray.'); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(50); + * + * // Use HSL color. + * colorMode(HSL); + * + * // Create a CSS color string. + * let c = 'rgb(255, 128, 128)'; + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'lightValue' to 75. + * let lightValue = lightness(c); + * + * // Draw the right rectangle. + * fill(lightValue); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is salmon pink and the right one is gray.'); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(50); + * + * // Use HSL color with values in the range 0-255. + * colorMode(HSL, 255); + * + * // Create a p5.Color object using HSL values. + * let c = color(0, 255, 191.5); + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'lightValue' to 191.5. + * let lightValue = lightness(c); + * + * // Draw the right rectangle. + * fill(lightValue); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is salmon pink and the right one is gray.'); + * } * *
*/ @@ -54656,27 +55854,133 @@ return this.color(c)._getLightness(); }; /** - * Extracts the red value from a - * p5.Color object, array of color components, or - * CSS color string. + * Gets the red value of a color. + * + * `red()` extracts the red value from a + * p5.Color object, an array of color components, or + * a CSS color string. + * + * By default, `red()` returns a color's red value in the range 0 + * to 255. If the colorMode() is set to RGB, it + * returns the red value in the given range. * * @method red * @param {p5.Color|Number[]|String} color p5.Color object, array of * color components, or CSS color string. * @return {Number} the red value. + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.Color object. + * let c = color(175, 100, 220); + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'redValue' to 175. + * let redValue = red(c); + * + * // Draw the right rectangle. + * fill(redValue, 0, 0); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is light purple and the right one is red.'); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a color array. + * let c = [175, 100, 220]; + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'redValue' to 175. + * let redValue = red(c); + * + * // Draw the right rectangle. + * fill(redValue, 0, 0); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is light purple and the right one is red.'); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a CSS color string. + * let c = 'rgb(175, 100, 220)'; + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'redValue' to 175. + * let redValue = red(c); + * + * // Draw the right rectangle. + * fill(redValue, 0, 0); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is light purple and the right one is red.'); + * } + * + *
+ * * @example *
* - * const c = color(255, 204, 0); - * fill(c); - * rect(15, 20, 35, 60); - * // Sets 'redValue' to 255. - * const redValue = red(c); - * fill(redValue, 0, 0); - * rect(50, 20, 35, 60); - * describe( - * 'Two rectangles with black edges. The rectangle on the left is yellow and the one on the right is red.' - * ); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Use RGB color with values in the range 0-100. + * colorMode(RGB, 100); + * + * // Create a p5.Color object. + * let c = color(69, 39, 86); + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'redValue' to 69. + * let redValue = red(c); + * + * // Draw the right rectangle. + * fill(redValue, 0, 0); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is light purple and the right one is red.'); + * } * *
*/ @@ -54685,33 +55989,174 @@ return this.color(c)._getRed(); }; /** - * Extracts the saturation value from a - * p5.Color object, array of color components, or - * CSS color string. + * Gets the saturation value of a color. * - * Saturation is scaled differently in HSB and HSL. By default, this function - * returns the HSL saturation. If the colorMode() - * is set to HSB, it returns the HSB saturation. + * `saturation()` extracts the saturation value from a + * p5.Color object, an array of color components, or + * a CSS color string. + * + * Saturation is scaled differently in HSB and HSL. By default, `saturation()` + * returns a color's HSL saturation in the range 0 to 100. If the + * colorMode() is set to HSB or HSL, it returns the + * saturation value in the given mode. * * @method saturation * @param {p5.Color|Number[]|String} color p5.Color object, array of * color components, or CSS color string. * @return {Number} the saturation value + * * @example *
* - * noStroke(); - * colorMode(HSB, 255); - * const c = color(0, 126, 255); - * fill(c); - * rect(15, 20, 35, 60); - * // Sets 'satValue' to 126. - * const satValue = saturation(c); - * fill(satValue); - * rect(50, 20, 35, 60); - * describe( - * 'Two rectangles. The rectangle on the left is deep pink and the one on the right is gray.' - * ); + * function setup() { + * createCanvas(100, 100); + * + * background(50); + * + * // Use HSB color. + * colorMode(HSB); + * + * // Create a p5.Color object. + * let c = color(0, 50, 100); + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'satValue' to 50. + * let satValue = saturation(c); + * + * // Draw the right rectangle. + * fill(satValue); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is salmon pink and the right one is dark gray.'); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(50); + * + * // Use HSB color. + * colorMode(HSB); + * + * // Create a color array. + * let c = [0, 50, 100]; + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'satValue' to 100. + * let satValue = saturation(c); + * + * // Draw the right rectangle. + * fill(satValue); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is salmon pink and the right one is gray.'); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(50); + * + * // Use HSB color. + * colorMode(HSB); + * + * // Create a CSS color string. + * let c = 'rgb(255, 128, 128)'; + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'satValue' to 100. + * let satValue = saturation(c); + * + * // Draw the right rectangle. + * fill(satValue); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is salmon pink and the right one is gray.'); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(50); + * + * // Use HSL color. + * colorMode(HSL); + * + * // Create a p5.Color object. + * let c = color(0, 100, 75); + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'satValue' to 100. + * let satValue = saturation(c); + * + * // Draw the right rectangle. + * fill(satValue); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is salmon pink and the right one is white.'); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(50); + * + * // Use HSL color with values in the range 0-255. + * colorMode(HSL, 255); + * + * // Create a p5.Color object. + * let c = color(0, 255, 191.5); + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 15, 35, 70); + * + * // Set 'satValue' to 255. + * let satValue = saturation(c); + * + * // Draw the right rectangle. + * fill(satValue); + * rect(50, 15, 35, 70); + * + * describe('Two rectangles. The left one is salmon pink and the right one is white.'); + * } * *
*/ @@ -54723,25 +56168,25 @@ exports.default = _default; }, { - '../core/constants': 286, - '../core/friendly_errors/fes_core': 289, - '../core/friendly_errors/file_errors': 290, - '../core/friendly_errors/validate_params': 293, - '../core/main': 298, - './p5.Color': 284, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.map': 182, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/constants': 294, + '../core/friendly_errors/fes_core': 297, + '../core/friendly_errors/file_errors': 298, + '../core/friendly_errors/validate_params': 301, + '../core/main': 306, + './p5.Color': 292, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.map': 186, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 284: [ + 292: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -55128,7 +56573,9 @@ '\\)$'].join(WHITESPACE.source), 'i') }; /** - * A class to describe a color. Each `p5.Color` object stores the color mode + * A class to describe a color. + * + * Each `p5.Color` object stores the color mode * and level maxes that were active during its construction. These values are * used to interpret the arguments passed to the object's constructor. They * also determine output formatting such as when @@ -55142,8 +56589,8 @@ * When different color representations are calculated, the results are cached * for performance. These values are normalized, floating-point numbers. * - * color() is the recommended way to create an instance - * of this class. + * Note: color() is the recommended way to create an + * instance of this class. * * @class p5.Color * @constructor @@ -55169,8 +56616,15 @@ this._calculateLevels(); } /** - * Returns the color formatted as a string. Doing so can be useful for - * debugging, or for using p5.js with other libraries. + * Returns the color formatted as a `String`. + * + * Calling `myColor.toString()` can be useful for debugging, as in + * `print(myColor.toString())`. It's also helpful for using p5.js with other + * libraries. + * + * The parameter, `format`, is optional. If a format string is passed, as in + * `myColor.toString('#rrggbb')`, it will determine how the color string is + * formatted. By default, color strings are formatted as `'rgba(r, g, b, a)'`. * * @method toString * @param {String} [format] how the color string will be formatted. @@ -55181,26 +56635,25 @@ * 'rgb%' 'hsb%' 'hsl%' 'rgba%' 'hsba%' and 'hsla%' format as percentages. * @return {String} the formatted string. * - * @example *
* - * createCanvas(200, 100); - * stroke(255); - * const myColor = color(100, 100, 250); - * fill(myColor); - * rotate(HALF_PI); - * text(myColor.toString(), 0, -5); - * text(myColor.toString('#rrggbb'), 0, -30); - * text(myColor.toString('rgba%'), 0, -55); - * describe('Three text representation of a color written sideways.'); - * - *
+ * function setup() { + * createCanvas(100, 100); * - *
- * - * const myColor = color(100, 130, 250); - * text(myColor.toString('#rrggbb'), 25, 25); - * describe('A hexadecimal representation of a color.'); + * background(200); + * + * // Create a p5.Color object. + * let myColor = color('darkorchid'); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * + * // Display the text. + * text(myColor.toString('#rrggbb'), 50, 50); + * + * describe('The text "#9932cc" written in purple on a gray background.'); + * } * *
*/ @@ -55260,9 +56713,10 @@ return 'rgba('.concat(a[0], ',', a[1], ',', a[2], ',', alpha, ')'); } } /** - * Sets the red component of a color. The range depends on the - * colorMode(). In the default RGB mode it's - * between 0 and 255. + * Sets the red component of a color. + * + * The range depends on the colorMode(). In the + * default RGB mode it's between 0 and 255. * * @method setRed * @param {Number} red the new red value. @@ -55270,16 +56724,27 @@ * @example *
* - * let backgroundColor; - * * function setup() { - * backgroundColor = color(100, 50, 150); - * } + * createCanvas(100, 100); * - * function draw() { - * backgroundColor.setRed(128 + 128 * sin(millis() / 1000)); - * background(backgroundColor); - * describe('A canvas with a gradually changing background color.'); + * background(200); + * + * // Create a p5.Color object. + * let c = color(255, 128, 128); + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 20, 35, 60); + * + * // Change the red value. + * c.setRed(64); + * + * // Draw the right rectangle. + * fill(c); + * rect(50, 20, 35, 60); + * + * describe('Two rectangles. The left one is salmon pink and the right one is teal.'); * } * *
@@ -55292,9 +56757,10 @@ this._array[0] = new_red / this.maxes[constants.RGB][0]; this._calculateLevels(); } /** - * Sets the green component of a color. The range depends on the - * colorMode(). In the default RGB mode it's - * between 0 and 255. + * Sets the green component of a color. + * + * The range depends on the colorMode(). In the + * default RGB mode it's between 0 and 255. * * @method setGreen * @param {Number} green the new green value. @@ -55302,16 +56768,27 @@ * @example *
* - * let backgroundColor; - * * function setup() { - * backgroundColor = color(100, 50, 150); - * } + * createCanvas(100, 100); * - * function draw() { - * backgroundColor.setGreen(128 + 128 * sin(millis() / 1000)); - * background(backgroundColor); - * describe('A canvas with a gradually changing background color.'); + * background(200); + * + * // Create a p5.Color object. + * let c = color(255, 128, 128); + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 20, 35, 60); + * + * // Change the green value. + * c.setGreen(255); + * + * // Draw the right rectangle. + * fill(c); + * rect(50, 20, 35, 60); + * + * describe('Two rectangles. The left one is salmon pink and the right one is yellow.'); * } * *
@@ -55324,9 +56801,10 @@ this._array[1] = new_green / this.maxes[constants.RGB][1]; this._calculateLevels(); } /** - * Sets the blue component of a color. The range depends on the - * colorMode(). In the default RGB mode it's - * between 0 and 255. + * Sets the blue component of a color. + * + * The range depends on the colorMode(). In the + * default RGB mode it's between 0 and 255. * * @method setBlue * @param {Number} blue the new blue value. @@ -55334,16 +56812,27 @@ * @example *
* - * let backgroundColor; - * * function setup() { - * backgroundColor = color(100, 50, 150); - * } + * createCanvas(100, 100); * - * function draw() { - * backgroundColor.setBlue(128 + 128 * sin(millis() / 1000)); - * background(backgroundColor); - * describe('A canvas with a gradually changing background color.'); + * background(200); + * + * // Create a p5.Color object. + * let c = color(255, 128, 128); + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 20, 35, 60); + * + * // Change the blue value. + * c.setBlue(255); + * + * // Draw the right rectangle. + * fill(c); + * rect(50, 20, 35, 60); + * + * describe('Two rectangles. The left one is salmon pink and the right one is pale fuchsia.'); * } * *
@@ -55356,8 +56845,10 @@ this._array[2] = new_blue / this.maxes[constants.RGB][2]; this._calculateLevels(); } /** - * Sets the alpha (transparency) value of a color. The range depends on the - * colorMode(). In the default RGB mode it's + * Sets the alpha (transparency) value of a color. + * + * The range depends on the + * colorMode(). In the default RGB mode it's * between 0 and 255. * * @method setAlpha @@ -55366,16 +56857,27 @@ * @example *
* - * function draw() { - * clear(); + * function setup() { + * createCanvas(100, 100); + * * background(200); - * const squareColor = color(100, 50, 100); - * squareColor.setAlpha(128 + 128 * sin(millis() / 1000)); - * fill(squareColor); - * rect(13, 13, width - 26, height - 26); - * describe( - * 'A purple square with gradually changing opacity drawn on a gray background.' - * ); + * + * // Create a p5.Color object. + * let c = color(255, 128, 128); + * + * // Draw the left rectangle. + * noStroke(); + * fill(c); + * rect(15, 20, 35, 60); + * + * // Change the alpha value. + * c.setAlpha(128); + * + * // Draw the right rectangle. + * fill(c); + * rect(50, 20, 35, 60); + * + * describe('Two rectangles. The left one is salmon pink and the right one is faded pink.'); * } * *
@@ -55737,30 +57239,30 @@ exports.default = _default; }, { - '../core/constants': 286, - '../core/main': 298, - './color_conversion': 282, - 'core-js/modules/es.array.includes': 177, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.join': 180, - 'core-js/modules/es.array.map': 182, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.regexp.constructor': 204, - 'core-js/modules/es.regexp.exec': 205, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.string.includes': 209, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.string.trim': 219, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/constants': 294, + '../core/main': 306, + './color_conversion': 290, + 'core-js/modules/es.array.includes': 181, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.join': 184, + 'core-js/modules/es.array.map': 186, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.regexp.constructor': 212, + 'core-js/modules/es.regexp.exec': 213, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.string.includes': 217, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.string.trim': 227, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 285: [ + 293: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -55859,71 +57361,155 @@ * @requires constants */ /** - * Start defining a shape that will mask subsequent things drawn to the canvas. - * Only opaque regions of the mask shape will allow content to be drawn. - * Any shapes drawn between this and endClip() will - * contribute to the mask shape. + * Starts defining a shape that will mask any shapes drawn afterward. * - * The mask will apply to anything drawn after this call. To draw without a mask, contain - * the code to apply the mask and to draw the masked content between - * push() and pop(). + * Any shapes drawn between `beginClip()` and + * endClip() will add to the mask shape. The mask + * will apply to anything drawn after endClip(). * - * Alternatively, rather than drawing the mask between this and - * endClip(), draw the mask in a callback function - * passed to clip(). + * The parameter, `options`, is optional. If an object with an `invert` + * property is passed, as in `beginClip({ invert: true })`, it will be used to + * set the masking mode. `{ invert: true }` inverts the mask, creating holes + * in shapes that are masked. `invert` is `false` by default. * - * Options can include: - * - `invert`: A boolean specifying whether or not to mask the areas *not* filled by the mask shape. Defaults to false. + * Masks can be contained between the + * push() and pop() functions. + * Doing so allows unmasked shapes to be drawn after masked shapes. + * + * Masks can also be defined in a callback function that's passed to + * clip(). * * @method beginClip - * @param {Object} [options] An object containing clip settings. + * @param {Object} [options] an object containing clip settings. * * @example *
* - * noStroke(); + * function setup() { + * createCanvas(100, 100); * - * // Mask in some shapes - * push(); - * beginClip(); - * triangle(15, 37, 30, 13, 43, 37); - * circle(45, 45, 7); - * endClip(); + * background(200); * - * fill('red'); - * rect(5, 5, 45, 45); - * pop(); + * // Create a mask. + * beginClip(); + * triangle(15, 37, 30, 13, 43, 37); + * circle(45, 45, 7); + * endClip(); * - * translate(50, 50); + * // Draw a backing shape. + * square(5, 5, 45); * - * // Mask out the same shapes - * push(); - * beginClip({ invert: true }); - * triangle(15, 37, 30, 13, 43, 37); - * circle(45, 45, 7); - * endClip(); + * describe('A white triangle and circle on a gray background.'); + * } + * + *
* - * fill('red'); - * rect(5, 5, 45, 45); - * pop(); + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create an inverted mask. + * beginClip({ invert: true }); + * triangle(15, 37, 30, 13, 43, 37); + * circle(45, 45, 7); + * endClip(); + * + * // Draw a backing shape. + * square(5, 5, 45); + * + * describe('A white square at the top-left corner of a gray square. The white square has a triangle and a circle cut out of it.'); + * } * *
* - * @alt - * In the top left, a red triangle and circle. In the bottom right, a red - * square with a triangle and circle cut out of it. + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * noStroke(); + * + * // Draw a masked shape. + * push(); + * // Create a mask. + * beginClip(); + * triangle(15, 37, 30, 13, 43, 37); + * circle(45, 45, 7); + * endClip(); + * + * // Draw a backing shape. + * square(5, 5, 45); + * pop(); + * + * // Translate the origin to the center. + * translate(50, 50); + * + * // Draw an inverted masked shape. + * push(); + * // Create an inverted mask. + * beginClip({ invert: true }); + * triangle(15, 37, 30, 13, 43, 37); + * circle(45, 45, 7); + * endClip(); + * + * // Draw a backing shape. + * square(5, 5, 45); + * pop(); + * + * describe('In the top left, a white triangle and circle. In the bottom right, a white square with a triangle and circle cut out of it.'); + * } + * + *
* * @example *
* * function setup() { * createCanvas(100, 100, WEBGL); + * + * describe('A silhouette of a rotating torus colored fuchsia.'); * } * * function draw() { - * background(255); + * background(200); + * + * // Create a mask. + * beginClip(); + * push(); + * rotateX(frameCount * 0.01); + * rotateY(frameCount * 0.01); + * scale(0.5); + * torus(30, 15); + * pop(); + * endClip(); + * + * // Draw a backing shape. * noStroke(); + * fill('fuchsia'); + * plane(100); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); * + * describe('A silhouette of a rotating torus colored with a gradient from cyan to purple.'); + * } + * + * function draw() { + * background(200); + * + * // Create a mask. * beginClip(); * push(); * rotateX(frameCount * 0.01); @@ -55933,21 +57519,19 @@ * pop(); * endClip(); * + * // Draw a backing shape. + * noStroke(); * beginShape(QUAD_STRIP); * fill(0, 255, 255); - * vertex(-width/2, -height/2); - * vertex(width/2, -height/2); + * vertex(-width / 2, -height / 2); + * vertex(width / 2, -height / 2); * fill(100, 0, 100); - * vertex(-width/2, height/2); - * vertex(width/2, height/2); + * vertex(-width / 2, height / 2); + * vertex(width / 2, height / 2); * endShape(); * } * *
- * - * @alt - * A silhouette of a rotating torus colored with a gradient from - * cyan to purple */ _main.default.prototype.beginClip = function () { @@ -55956,104 +57540,221 @@ this._renderer.beginClip(options); }; /** - * Finishes defining a shape that will mask subsequent things drawn to the canvas. - * Only opaque regions of the mask shape will allow content to be drawn. - * Any shapes drawn between beginClip() and this - * will contribute to the mask shape. + * Ends defining a mask that was started with + * beginClip(). * * @method endClip + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a mask. + * beginClip(); + * triangle(15, 37, 30, 13, 43, 37); + * circle(45, 45, 7); + * endClip(); + * + * // Draw a backing shape. + * square(5, 5, 45); + * + * describe('A white triangle and circle on a gray background.'); + * } + * + *
*/ _main.default.prototype.endClip = function () { this._renderer.endClip(); }; /** - * Use the shape drawn by a callback function to mask subsequent things drawn to the canvas. - * Only opaque regions of the mask shape will allow content to be drawn. + * Defines a shape that will mask any shapes drawn afterward. * - * The mask will apply to anything drawn after this call. To draw without a mask, contain - * the code to apply the mask and to draw the masked content between - * push() and pop(). + * The first parameter, `callback`, is a function that defines the mask. + * Any shapes drawn in `callback` will add to the mask shape. The mask + * will apply to anything drawn after `clip()` is called. * - * Alternatively, rather than drawing the mask shape in a function, draw the - * shape between beginClip() and endClip(). + * The second parameter, `options`, is optional. If an object with an `invert` + * property is passed, as in `beginClip({ invert: true })`, it will be used to + * set the masking mode. `{ invert: true }` inverts the mask, creating holes + * in shapes that are masked. `invert` is `false` by default. * - * Options can include: - * - `invert`: A boolean specifying whether or not to mask the areas *not* filled by the mask shape. Defaults to false. + * Masks can be contained between the + * push() and pop() functions. + * Doing so allows unmasked shapes to be drawn after masked shapes. + * + * Masks can also be defined with beginClip() + * and endClip(). * * @method clip - * @param {Function} callback A function that draws the mask shape. - * @param {Object} [options] An object containing clip settings. + * @param {Function} callback a function that draws the mask shape. + * @param {Object} [options] an object containing clip settings. * * @example *
* - * noStroke(); + * function setup() { + * createCanvas(100, 100); * - * // Mask in some shapes - * push(); - * clip(() => { + * background(200); + * + * // Create a mask. + * clip(mask); + * + * // Draw a backing shape. + * square(5, 5, 45); + * + * describe('A white triangle and circle on a gray background.'); + * } + * + * // Declare a function that defines the mask. + * function mask() { * triangle(15, 37, 30, 13, 43, 37); * circle(45, 45, 7); - * }); + * } + * + *
* - * fill('red'); - * rect(5, 5, 45, 45); - * pop(); + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); * - * translate(50, 50); + * background(200); * - * // Mask out the same shapes - * push(); - * clip(() => { + * // Create an inverted mask. + * clip(mask, { invert: true }); + * + * // Draw a backing shape. + * square(5, 5, 45); + * + * describe('A white square at the top-left corner of a gray square. The white square has a triangle and a circle cut out of it.'); + * } + * + * // Declare a function that defines the mask. + * function mask() { * triangle(15, 37, 30, 13, 43, 37); * circle(45, 45, 7); - * }, { invert: true }); - * - * fill('red'); - * rect(5, 5, 45, 45); - * pop(); + * } * *
* - * @alt - * In the top left, a red triangle and circle. In the bottom right, a red - * square with a triangle and circle cut out of it. + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * noStroke(); + * + * // Draw a masked shape. + * push(); + * // Create a mask. + * clip(mask); + * + * // Draw a backing shape. + * square(5, 5, 45); + * pop(); + * + * // Translate the origin to the center. + * translate(50, 50); + * + * // Draw an inverted masked shape. + * push(); + * // Create an inverted mask. + * clip(mask, { invert: true }); + * + * // Draw a backing shape. + * square(5, 5, 45); + * pop(); + * + * describe('In the top left, a white triangle and circle. In the bottom right, a white square with a triangle and circle cut out of it.'); + * } + * + * // Declare a function that defines the mask. + * function mask() { + * triangle(15, 37, 30, 13, 43, 37); + * circle(45, 45, 7); + * } + * + *
* * @example *
* * function setup() { * createCanvas(100, 100, WEBGL); + * + * describe('A silhouette of a rotating torus colored fuchsia.'); * } * * function draw() { - * background(255); + * background(200); + * + * // Create a mask. + * clip(mask); + * + * // Draw a backing shape. * noStroke(); + * fill('fuchsia'); + * plane(100); + * } * - * clip(() => { - * push(); - * rotateX(frameCount * 0.01); - * rotateY(frameCount * 0.01); - * scale(0.5); - * torus(30, 15); - * pop(); - * }); + * // Declare a function that defines the mask. + * function mask() { + * push(); + * rotateX(frameCount * 0.01); + * rotateY(frameCount * 0.01); + * scale(0.5); + * torus(30, 15); + * pop(); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A silhouette of a rotating torus colored with a gradient from cyan to purple.'); + * } * + * function draw() { + * background(200); + * + * // Create a mask. + * clip(mask); + * + * // Draw a backing shape. + * noStroke(); * beginShape(QUAD_STRIP); * fill(0, 255, 255); - * vertex(-width/2, -height/2); - * vertex(width/2, -height/2); + * vertex(-width / 2, -height / 2); + * vertex(width / 2, -height / 2); * fill(100, 0, 100); - * vertex(-width/2, height/2); - * vertex(width/2, height/2); + * vertex(-width / 2, height / 2); + * vertex(width / 2, height / 2); * endShape(); * } + * + * // Declare a function that defines the mask. + * function mask() { + * push(); + * rotateX(frameCount * 0.01); + * rotateY(frameCount * 0.01); + * scale(0.5); + * torus(30, 15); + * pop(); + * } * *
- * - * @alt - * A silhouette of a rotating torus colored with a gradient from - * cyan to purple */ _main.default.prototype.clip = function (callback, options) { this._renderer.beginClip(options); @@ -56061,27 +57762,32 @@ this._renderer.endClip(options); }; /** - * Sets the color used for the background of the canvas. By default, the - * background is transparent. This function is typically used within - * draw() to clear the display window at the beginning - * of each frame. It can also be used inside setup() to - * set the background on the first frame of animation. + * Sets the color used for the background of the canvas. * - * The version of `background()` with one parameter interprets the value one of four - * ways. If the parameter is a number, it's interpreted as a grayscale value. - * If the parameter is a string, it's interpreted as a CSS color string. RGB, RGBA, - * HSL, HSLA, hex, and named color strings are supported. If the parameter is a - * p5.Color object, it will be used as the background color. - * If the parameter is a p5.Image object, it will be used as - * the background image. + * By default, the background is transparent. `background()` is typically used + * within draw() to clear the display window at the + * beginning of each frame. It can also be used inside + * setup() to set the background on the first frame + * of animation. * - * The version of `background()` with two parameters interprets the first one as a - * grayscale value. The second parameter sets the alpha (transparency) value. + * The version of `background()` with one parameter interprets the value one + * of four ways. If the parameter is a `Number`, it's interpreted as a grayscale + * value. If the parameter is a `String`, it's interpreted as a CSS color string. + * RGB, RGBA, HSL, HSLA, hex, and named color strings are supported. If the + * parameter is a p5.Color object, it will be used as + * the background color. If the parameter is a + * p5.Image object, it will be used as the background + * image. + * + * The version of `background()` with two parameters interprets the first one + * as a grayscale value. The second parameter sets the alpha (transparency) + * value. * - * The version of `background()` with three parameters interprets them as RGB, HSB, - * or HSL colors, depending on the current colorMode(). - * By default, colors are specified in RGB values. Calling background(255, 204, 0) - * sets the background a bright yellow color. + * The version of `background()` with three parameters interprets them as RGB, + * HSB, or HSL colors, depending on the current + * colorMode(). By default, colors are specified + * in RGB values. Calling `background(255, 204, 0)` sets the background a bright + * yellow color. * * @method background * @param {p5.Color} color any value created by the color() function @@ -56090,99 +57796,160 @@ * @example *
* - * // A grayscale integer value. - * background(51); - * describe('A canvas with a dark charcoal gray background.'); + * function setup() { + * createCanvas(100, 100); + * + * // A grayscale value. + * background(51); + * + * describe('A canvas with a dark charcoal gray background.'); + * } * *
* *
* - * // A grayscale integer value and an alpha value. - * background(51, 0.4); - * describe('A canvas with a transparent gray background.'); + * function setup() { + * createCanvas(100, 100); + * + * // A grayscale value and an alpha value. + * background(51, 0.4); + * describe('A canvas with a transparent gray background.'); + * } * *
* *
* - * // R, G & B integer values. - * background(255, 204, 0); - * describe('A canvas with a yellow background.'); + * function setup() { + * createCanvas(100, 100); + * + * // R, G & B values. + * background(255, 204, 0); + * + * describe('A canvas with a yellow background.'); + * } * *
* *
* - * // H, S & B integer values. - * colorMode(HSB); - * background(255, 204, 100); - * describe('A canvas with a royal blue background.'); + * function setup() { + * createCanvas(100, 100); + * + * // Use HSB color. + * colorMode(HSB); + * + * // H, S & B values. + * background(255, 204, 100); + * + * describe('A canvas with a royal blue background.'); + * } * *
* *
* - * // A CSS named color. - * background('red'); - * describe('A canvas with a red background.'); + * function setup() { + * createCanvas(100, 100); + * + * // A CSS named color. + * background('red'); + * + * describe('A canvas with a red background.'); + * } * *
* *
* - * // Three-digit hex RGB notation. - * background('#fae'); - * describe('A canvas with a pink background.'); + * function setup() { + * createCanvas(100, 100); + * + * // Three-digit hex RGB notation. + * background('#fae'); + * + * describe('A canvas with a pink background.'); + * } * *
* *
* - * // Six-digit hex RGB notation. - * background('#222222'); - * describe('A canvas with a black background.'); + * function setup() { + * createCanvas(100, 100); + * + * // Six-digit hex RGB notation. + * background('#222222'); + * + * describe('A canvas with a black background.'); + * } * *
* *
* - * // Integer RGB notation. - * background('rgb(0,255,0)'); - * describe('A canvas with a bright green background.'); + * function setup() { + * createCanvas(100, 100); + * + * // Integer RGB notation. + * background('rgb(0, 255, 0)'); + * + * describe('A canvas with a bright green background.'); + * } * *
* *
* - * // Integer RGBA notation. - * background('rgba(0,255,0, 0.25)'); - * describe('A canvas with a transparent green background.'); + * function setup() { + * createCanvas(100, 100); + * + * // Integer RGBA notation. + * background('rgba(0, 255, 0, 0.25)'); + * + * describe('A canvas with a transparent green background.'); + * } * *
* *
* - * // Percentage RGB notation. - * background('rgb(100%,0%,10%)'); - * describe('A canvas with a red background.'); + * function setup() { + * createCanvas(100, 100); + * + * // Percentage RGB notation. + * background('rgb(100%, 0%, 10%)'); + * + * describe('A canvas with a red background.'); + * } * *
* *
* - * // Percentage RGBA notation. - * background('rgba(100%,0%,100%,0.5)'); - * describe('A canvas with a transparent purple background.'); + * function setup() { + * createCanvas(100, 100); + * + * // Percentage RGBA notation. + * background('rgba(100%, 0%, 100%, 0.5)'); + * + * describe('A canvas with a transparent purple background.'); + * } * *
* *
* - * // A p5.Color object. - * let c = color(0, 0, 255); - * background(c); - * describe('A canvas with a blue background.'); + * function setup() { + * createCanvas(100, 100); + * + * // A p5.Color object. + * let c = color(0, 0, 255); + * background(c); + * + * describe('A canvas with a blue background.'); + * } * *
* @@ -56231,12 +57998,14 @@ return this; }; /** - * Clears the pixels on the canvas. This function makes every pixel 100% - * transparent. Calling `clear()` doesn't clear objects created by `createX()` - * functions such as createGraphics(), + * Clears the pixels on the canvas. + * + * `clear()` makes every pixel 100% transparent. Calling `clear()` doesn't + * clear objects created by `createX()` functions such as + * createGraphics(), * createVideo(), and * createImg(). These objects will remain - * unchanged after calling clear() and can be redrawn. + * unchanged after calling `clear()` and can be redrawn. * * In WebGL mode, this function can clear the screen to a specific color. It * interprets four numeric parameters as normalized RGBA color values. It also @@ -56248,15 +58017,21 @@ * @example *
* + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * describe('A gray square. White circles are drawn as the user moves the mouse. The circles disappear when the user presses the mouse.'); + * } + * * function draw() { * circle(mouseX, mouseY, 20); - * describe('A white circle is drawn at the mouse x- and y-coordinates.'); * } * * function mousePressed() { * clear(); - * background(128); - * describe('The canvas is cleared when the mouse is clicked.'); + * background(200); * } * *
@@ -56274,6 +58049,7 @@ * pg.noStroke(); * pg.circle(pg.width / 2, pg.height / 2, 15); * image(pg, 20, 20); + * * describe('A white circle drawn on a gray square. The square gets smaller when the mouse is pressed.'); * } * @@ -56284,10 +58060,10 @@ * * * - * @param {Number} r normalized red value. - * @param {Number} g normalized green value. - * @param {Number} b normalized blue value. - * @param {Number} a normalized alpha value. + * @param {Number} [r] normalized red value. + * @param {Number} [g] normalized green value. + * @param {Number} [b] normalized blue value. + * @param {Number} [a] normalized alpha value. */ _main.default.prototype.clear = function () { var _r = (arguments.length <= 0 ? undefined : arguments[0]) || 0; @@ -56298,19 +58074,21 @@ return this; }; /** - * Changes the way p5.js interprets color data. By default, the numeric - * parameters for fill(), + * Changes the way color values are interpreted. + * + * By default, the `Number` parameters for fill(), * stroke(), * background(), and * color() are defined by values between 0 and 255 * using the RGB color model. This is equivalent to calling * `colorMode(RGB, 255)`. Pure red is `color(255, 0, 0)` in this model. * - * Calling `colorMode(RGB, 100)` sets colors to be interpreted as RGB color - * values between 0 and 100. Pure red is `color(100, 0, 0)` in this model. + * Calling `colorMode(RGB, 100)` sets colors to use RGB color values + * between 0 and 100. Pure red is `color(100, 0, 0)` in this model. * * Calling `colorMode(HSB)` or `colorMode(HSL)` changes to HSB or HSL system - * instead of RGB. + * instead of RGB. Pure red is `color(0, 100, 100)` in HSB and + * `color(0, 100, 50)` in HSL. * * p5.Color objects remember the mode that they were * created in. Changing modes doesn't affect their appearance. @@ -56325,63 +58103,179 @@ * @example *
* - * noStroke(); - * colorMode(RGB, 100); - * for (let i = 0; i < 100; i += 1) { - * for (let j = 0; j < 100; j += 1) { - * stroke(i, j, 0); - * point(i, j); - * } + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Fill with pure red. + * fill(255, 0, 0); + * + * circle(50, 50, 25); + * + * describe('A gray square with a red circle at its center.'); * } - * describe( - * 'A diagonal green to red gradient from bottom-left to top-right with shading transitioning to black at top-left corner.' - * ); * *
* + * @example *
* - * noStroke(); - * colorMode(HSB, 100); - * for (let i = 0; i < 100; i++) { - * for (let j = 0; j < 100; j++) { - * stroke(i, j, 100); - * point(i, j); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Use RGB color with values in the range 0-100. + * colorMode(RGB, 100); + * + * // Fill with pure red. + * fill(100, 0, 0); + * + * circle(50, 50, 25); + * + * describe('A gray square with a red circle at its center.'); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Use HSB color. + * colorMode(HSB); + * + * // Fill with pure red. + * fill(0, 100, 100); + * + * circle(50, 50, 25); + * + * describe('A gray square with a red circle at its center.'); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Use HSL color. + * colorMode(HSL); + * + * // Fill with pure red. + * fill(0, 100, 50); + * + * circle(50, 50, 25); + * + * describe('A gray square with a red circle at its center.'); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * // Use RGB color with values in the range 0-100. + * colorMode(RGB, 100); + * + * for (let x = 0; x < 100; x += 1) { + * for (let y = 0; y < 100; y += 1) { + * stroke(x, y, 0); + * point(x, y); + * } * } + * + * describe( + * 'A diagonal green to red gradient from bottom-left to top-right with shading transitioning to black at top-left corner.' + * ); * } - * describe('A rainbow gradient from left-to-right. Brightness transitions to white at the top.'); * *
* *
* - * colorMode(RGB, 255); - * let myColor = color(180, 175, 230); - * background(myColor); - * colorMode(RGB, 1); - * let redValue = red(myColor); - * let greenValue = green(myColor); - * let blueValue = blue(myColor); - * text(`Red: ${redValue}`, 10, 10, 80, 80); - * text(`Green: ${greenValue}`, 10, 40, 80, 80); - * text(`Blue: ${blueValue}`, 10, 70, 80, 80); - * describe('A purple canvas with the red, green, and blue decimal values of the color written on it.'); + * function setup() { + * createCanvas(100, 100); + * + * // Use HSB color with values in the range 0-100. + * colorMode(HSB, 100); + * + * for (let x = 0; x < 100; x += 1) { + * for (let y = 0; y < 100; y += 1) { + * stroke(x, y, 100); + * point(x, y); + * } + * } + * + * describe('A rainbow gradient from left-to-right. Brightness transitions to white at the top.'); + * } * *
* *
* - * noFill(); - * colorMode(RGB, 255, 255, 255, 1); - * background(255); - * strokeWeight(4); - * stroke(255, 0, 10, 0.3); - * circle(40, 40, 50); - * circle(50, 60, 50); - * describe('Two overlapping translucent pink circle outlines.'); + * function setup() { + * createCanvas(100, 100); + * + * // Create a p5.Color object. + * let myColor = color(180, 175, 230); + * background(myColor); + * + * // Use RGB color with values in the range 0-1. + * colorMode(RGB, 1); + * + * // Get the red, green, and blue color components. + * let redValue = red(myColor); + * let greenValue = green(myColor); + * let blueValue = blue(myColor); + * + * // Round the color components for display. + * redValue = round(redValue, 2); + * greenValue = round(greenValue, 2); + * blueValue = round(blueValue, 2); + * + * // Display the color components. + * text(`Red: ${redValue}`, 10, 10, 80, 80); + * text(`Green: ${greenValue}`, 10, 40, 80, 80); + * text(`Blue: ${blueValue}`, 10, 70, 80, 80); + * + * describe('A purple canvas with the red, green, and blue decimal values of the color written on it.'); + * } * *
* + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(255); + * + * // Use RGB color with alpha values in the range 0-1. + * colorMode(RGB, 255, 255, 255, 1); + * + * noFill(); + * strokeWeight(4); + * stroke(255, 0, 10, 0.3); + * circle(40, 40, 50); + * circle(50, 60, 50); + * + * describe('Two overlapping translucent pink circle outlines.'); + * } + * + *
*/ /** * @method colorMode @@ -56421,13 +58315,14 @@ return this; }; /** - * Sets the color used to fill shapes. Calling `fill(255, 165, 0)` or - * `fill('orange')` means all shapes drawn after the fill command will be - * filled with the color orange. + * Sets the color used to fill shapes. + * + * Calling `fill(255, 165, 0)` or `fill('orange')` means all shapes drawn + * after the fill command will be filled with the color orange. * * The version of `fill()` with one parameter interprets the value one of - * three ways. If the parameter is a number, it's interpreted as a grayscale - * value. If the parameter is a string, it's interpreted as a CSS color + * three ways. If the parameter is a `Number`, it's interpreted as a grayscale + * value. If the parameter is a `String`, it's interpreted as a CSS color * string. A p5.Color object can also be provided to * set the fill color. * @@ -56445,102 +58340,181 @@ * @example *
* - * // Grayscale integer value. - * fill(51); - * square(20, 20, 60); - * describe('A dark charcoal gray square with a black outline.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // A grayscale value. + * fill(51); + * square(20, 20, 60); + * + * describe('A dark charcoal gray square with a black outline.'); + * } * *
* *
* - * // R, G & B integer values. - * fill(255, 204, 0); - * square(20, 20, 60); - * describe('A yellow square with a black outline.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // R, G & B values. + * fill(255, 204, 0); + * square(20, 20, 60); + * + * describe('A yellow square with a black outline.'); + * } * *
* *
* - * // H, S & B integer values. - * colorMode(HSB); - * fill(255, 204, 100); - * square(20, 20, 60); - * describe('A royal blue square with a black outline.'); + * function setup() { + * createCanvas(100, 100); + * + * background(100); + * + * // Use HSB color. + * colorMode(HSB); + * + * // H, S & B values. + * fill(255, 204, 100); + * square(20, 20, 60); + * + * describe('A royal blue square with a black outline.'); + * } * *
* *
* - * // A CSS named color. - * fill('red'); - * square(20, 20, 60); - * describe('A red square with a black outline.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // A CSS named color. + * fill('red'); + * square(20, 20, 60); + * + * describe('A red square with a black outline.'); + * } * *
* *
* - * // Three-digit hex RGB notation. - * fill('#fae'); - * square(20, 20, 60); - * describe('A pink square with a black outline.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Three-digit hex RGB notation. + * fill('#fae'); + * square(20, 20, 60); + * + * describe('A pink square with a black outline.'); + * } * *
* *
* - * // Six-digit hex RGB notation. - * fill('#A251FA'); - * square(20, 20, 60); - * describe('A purple square with a black outline.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Six-digit hex RGB notation. + * fill('#A251FA'); + * square(20, 20, 60); + * + * describe('A purple square with a black outline.'); + * } * *
* *
* - * // Integer RGB notation. - * fill('rgb(0,255,0)'); - * square(20, 20, 60); - * describe('A bright green square with a black outline.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Integer RGB notation. + * fill('rgb(0, 255, 0)'); + * square(20, 20, 60); + * + * describe('A bright green square with a black outline.'); + * } * *
* *
* - * // Integer RGBA notation. - * fill('rgba(0,255,0, 0.25)'); - * square(20, 20, 60); - * describe('A soft green rectange with a black outline.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Integer RGBA notation. + * fill('rgba(0, 255, 0, 0.25)'); + * square(20, 20, 60); + * + * describe('A soft green rectange with a black outline.'); + * } * *
* *
* - * // Percentage RGB notation. - * fill('rgb(100%,0%,10%)'); - * square(20, 20, 60); - * describe('A red square with a black outline.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Percentage RGB notation. + * fill('rgb(100%, 0%, 10%)'); + * square(20, 20, 60); + * + * describe('A red square with a black outline.'); + * } * *
* *
* - * // Percentage RGBA notation. - * fill('rgba(100%,0%,100%,0.5)'); - * square(20, 20, 60); - * describe('A dark fuchsia square with a black outline.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Percentage RGBA notation. + * fill('rgba(100%, 0%, 100%, 0.5)'); + * square(20, 20, 60); + * + * describe('A dark fuchsia square with a black outline.'); + * } * *
* *
* - * // p5.Color object. - * let c = color(0, 0, 255); - * fill(c); - * square(20, 20, 60); - * describe('A blue square with a black outline.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // A p5.Color object. + * let c = color(0, 0, 255); + * fill(c); + * square(20, 20, 60); + * + * describe('A blue square with a black outline.'); + * } * *
*/ @@ -56574,21 +58548,32 @@ return this; }; /** - * Disables setting the interior color of shapes. This is the same as making - * the fill completely transparent. If both - * noStroke() and - * noFill() are called, nothing will be drawn to the - * screen. + * Disables setting the fill color for shapes. + * + * Calling `noFill()` is the same as making the fill completely transparent, + * as in `fill(0, 0)`. If both noStroke() and + * `noFill()` are called, nothing will be drawn to the screen. * * @method noFill * @chainable + * * @example *
* - * square(32, 10, 35); - * noFill(); - * square(32, 55, 35); - * describe('A white square on top of an empty square. Both squares have black outlines.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Draw the top square. + * square(32, 10, 35); + * + * // Draw the bottom square. + * noFill(); + * square(32, 55, 35); + * + * describe('A white square on above an empty square. Both squares have black outlines.'); + * } * *
* @@ -56596,16 +58581,23 @@ * * function setup() { * createCanvas(100, 100, WEBGL); + * + * describe('A purple cube wireframe spinning on a black canvas.'); * } * * function draw() { * background(0); + * + * // Style the box. * noFill(); * stroke(100, 100, 240); + * + * // Rotate the coordinates. * rotateX(frameCount * 0.01); * rotateY(frameCount * 0.01); - * box(45, 45, 45); - * describe('A purple cube wireframe spinning on a black canvas.'); + * + * // Draw the box. + * box(45); * } * * @@ -56615,8 +58607,10 @@ return this; }; /** - * Disables drawing the stroke (outline). If both - * noStroke() and + * Disables drawing points, lines, and the outlines of shapes. + * + * Calling `noStroke()` is the same as making the stroke completely transparent, + * as in `stroke(0, 0)`. If both `noStroke()` and * noFill() are called, nothing will be drawn to the * screen. * @@ -56625,9 +58619,16 @@ * @example *
* - * noStroke(); - * square(20, 20, 60); - * describe('A white square with no outline.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * noStroke(); + * square(20, 20, 60); + * + * describe('A white square with no outline.'); + * } * *
* @@ -56635,16 +58636,23 @@ * * function setup() { * createCanvas(100, 100, WEBGL); + * + * describe('A pink cube with no edge outlines spinning on a black canvas.'); * } * * function draw() { * background(0); + * + * // Style the box. * noStroke(); * fill(240, 150, 150); + * + * // Rotate the coordinates. * rotateX(frameCount * 0.01); * rotateY(frameCount * 0.01); - * box(45, 45, 45); - * describe('A pink cube with no edge outlines spinning on a black canvas.'); + * + * // Draw the box. + * box(45); * } * * @@ -56654,15 +58662,16 @@ return this; }; /** - * Sets the color used to draw lines and borders around shapes. Calling - * `stroke(255, 165, 0)` or `stroke('orange')` means all shapes drawn after - * the `stroke()` command will be filled with the color orange. The way these - * parameters are interpreted may be changed with the + * Sets the color used to draw points, lines, and the outlines of shapes. + * + * Calling `stroke(255, 165, 0)` or `stroke('orange')` means all shapes drawn + * after calling `stroke()` will be filled with the color orange. The way + * these parameters are interpreted may be changed with the * colorMode() function. * * The version of `stroke()` with one parameter interprets the value one of - * three ways. If the parameter is a number, it's interpreted as a grayscale - * value. If the parameter is a string, it's interpreted as a CSS color + * three ways. If the parameter is a `Number`, it's interpreted as a grayscale + * value. If the parameter is a `String`, it's interpreted as a CSS color * string. A p5.Color object can also be provided to * set the stroke color. * @@ -56686,112 +58695,191 @@ * @example *
* - * // Grayscale integer value. - * strokeWeight(4); - * stroke(51); - * rect(20, 20, 60, 60); - * describe('A white rectangle with a dark charcoal gray outline.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // A grayscale value. + * strokeWeight(4); + * stroke(51); + * square(20, 20, 60); + * + * describe('A white square with a dark charcoal gray outline.'); + * } * *
* *
* - * // R, G & B integer values. - * stroke(255, 204, 0); - * strokeWeight(4); - * rect(20, 20, 60, 60); - * describe('A white rectangle with a yellow outline.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // R, G & B values. + * stroke(255, 204, 0); + * strokeWeight(4); + * square(20, 20, 60); + * + * describe('A white square with a yellow outline.'); + * } * *
* *
* - * // H, S & B integer values. - * colorMode(HSB); - * strokeWeight(4); - * stroke(255, 204, 100); - * rect(20, 20, 60, 60); - * describe('A white rectangle with a royal blue outline.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Use HSB color. + * colorMode(HSB); + * + * // H, S & B values. + * strokeWeight(4); + * stroke(255, 204, 100); + * square(20, 20, 60); + * + * describe('A white square with a royal blue outline.'); + * } * *
* *
* - * // A CSS named color. - * stroke('red'); - * strokeWeight(4); - * rect(20, 20, 60, 60); - * describe('A white rectangle with a red outline.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // A CSS named color. + * stroke('red'); + * strokeWeight(4); + * square(20, 20, 60); + * + * describe('A white square with a red outline.'); + * } * *
* *
* - * // Three-digit hex RGB notation. - * stroke('#fae'); - * strokeWeight(4); - * rect(20, 20, 60, 60); - * describe('A white rectangle with a pink outline.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Three-digit hex RGB notation. + * stroke('#fae'); + * strokeWeight(4); + * square(20, 20, 60); + * + * describe('A white square with a pink outline.'); + * } * *
* *
* - * // Six-digit hex RGB notation. - * stroke('#222222'); - * strokeWeight(4); - * rect(20, 20, 60, 60); - * describe('A white rectangle with a black outline.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Six-digit hex RGB notation. + * stroke('#222222'); + * strokeWeight(4); + * square(20, 20, 60); + * + * describe('A white square with a black outline.'); + * } * *
* *
* - * // Integer RGB notation. - * stroke('rgb(0,255,0)'); - * strokeWeight(4); - * rect(20, 20, 60, 60); - * describe('A whiite rectangle with a bright green outline.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Integer RGB notation. + * stroke('rgb(0, 255, 0)'); + * strokeWeight(4); + * square(20, 20, 60); + * + * describe('A whiite square with a bright green outline.'); + * } * *
* *
* - * // Integer RGBA notation. - * stroke('rgba(0,255,0,0.25)'); - * strokeWeight(4); - * rect(20, 20, 60, 60); - * describe('A white rectangle with a soft green outline.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Integer RGBA notation. + * stroke('rgba(0, 255, 0, 0.25)'); + * strokeWeight(4); + * square(20, 20, 60); + * + * describe('A white square with a soft green outline.'); + * } * *
* *
* - * // Percentage RGB notation. - * stroke('rgb(100%,0%,10%)'); - * strokeWeight(4); - * rect(20, 20, 60, 60); - * describe('A white rectangle with a red outline.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Percentage RGB notation. + * stroke('rgb(100%, 0%, 10%)'); + * strokeWeight(4); + * square(20, 20, 60); + * + * describe('A white square with a red outline.'); + * } * *
* *
* - * // Percentage RGBA notation. - * stroke('rgba(100%,0%,100%,0.5)'); - * strokeWeight(4); - * rect(20, 20, 60, 60); - * describe('A white rectangle with a dark fuchsia outline.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Percentage RGBA notation. + * stroke('rgba(100%, 0%, 100%, 0.5)'); + * strokeWeight(4); + * square(20, 20, 60); + * + * describe('A white square with a dark fuchsia outline.'); + * } * *
* *
* - * // p5.Color object. - * stroke(color(0, 0, 255)); - * strokeWeight(4); - * rect(20, 20, 60, 60); - * describe('A white rectangle with a blue outline.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // A p5.Color object. + * stroke(color(0, 0, 255)); + * strokeWeight(4); + * square(20, 20, 60); + * + * describe('A white square with a blue outline.'); + * } * *
*/ @@ -56825,10 +58913,12 @@ return this; }; /** - * All drawing that follows erase() will subtract - * from the canvas, revealing the web page underneath. The erased areas will - * become transparent, allowing the content behind the canvas to show through. - * The fill(), stroke(), and + * Starts using shapes to erase parts of the canvas. + * + * All drawing that follows `erase()` will subtract from the canvas, revealing + * the web page underneath. The erased areas will become transparent, allowing + * the content behind the canvas to show through. The + * fill(), stroke(), and * blendMode() have no effect once `erase()` is * called. * @@ -56857,45 +58947,49 @@ * Defaults to 255, which is full strength. * * @chainable + * * @example *
* - * background(100, 100, 250); - * fill(250, 100, 100); - * square(20, 20, 60); - * erase(); - * circle(25, 30, 30); - * noErase(); - * describe('A purple canvas with a pink square in the middle. A circle is erased from the top-left, leaving a white hole.'); - * - *
+ * function setup() { + * createCanvas(100, 100); * - *
- * - * let p = createP('I am a DOM element'); - * p.style('font-size', '12px'); - * p.style('width', '65px'); - * p.style('text-align', 'center'); - * p.position(18, 26); + * background(100, 100, 250); + * + * // Draw a pink square. + * fill(250, 100, 100); + * square(20, 20, 60); * - * background(100, 170, 210); - * erase(200, 100); - * circle(50, 50, 77); - * noErase(); - * describe('A blue canvas with a circular hole in the center that reveals the message "I am a DOM element".'); + * // Erase a circular area. + * erase(); + * circle(25, 30, 30); + * noErase(); + * + * describe('A purple canvas with a pink square in the middle. A circle is erased from the top-left, leaving a hole.'); + * } * *
* + * @example *
* - * background(150, 250, 150); - * fill(100, 100, 250); - * square(20, 20, 60); - * strokeWeight(5); - * erase(150, 255); - * triangle(50, 10, 70, 50, 90, 10); - * noErase(); - * describe('A mint green canvas with a purple square in the center. A triangle in the top-right corner partially erases its interior and a fully erases its outline.'); + * function setup() { + * createCanvas(100, 100); + * + * background(100, 100, 250); + * + * // Draw a pink square. + * fill(250, 100, 100); + * square(20, 20, 60); + * + * // Erase a circular area. + * strokeWeight(5); + * erase(150, 255); + * circle(25, 30, 30); + * noErase(); + * + * describe('A purple canvas with a pink square in the middle. A circle at the top-left partially erases its interior and a fully erases its outline.'); + * } * *
*/ @@ -56907,6 +59001,7 @@ }; /** * Ends erasing that was started with erase(). + * * The fill(), stroke(), and * blendMode() settings will return to what they * were prior to calling erase(). @@ -56916,15 +59011,26 @@ * @example *
* - * background(235, 145, 15); - * noStroke(); - * fill(30, 45, 220); - * rect(30, 10, 10, 80); - * erase(); - * circle(50, 50, 60); - * noErase(); - * rect(70, 10, 10, 80); - * describe('An orange canvas with two tall blue rectangles. A circular hole in the center erases the rectangle on the left but not the one on the right.'); + * function setup() { + * createCanvas(100, 100); + * + * background(235, 145, 15); + * + * // Draw the left rectangle. + * noStroke(); + * fill(30, 45, 220); + * rect(30, 10, 10, 80); + * + * // Erase a circle. + * erase(); + * circle(50, 50, 60); + * noErase(); + * + * // Draw the right rectangle. + * rect(70, 10, 10, 80); + * + * describe('An orange canvas with two tall blue rectangles. A circular hole in the center erases the rectangle on the left but not the one on the right.'); + * } * *
*/ @@ -56936,22 +59042,22 @@ exports.default = _default; }, { - '../core/constants': 286, - '../core/main': 298, - './p5.Color': 284, - 'core-js/modules/es.array.fill': 172, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/constants': 294, + '../core/main': 306, + './p5.Color': 292, + 'core-js/modules/es.array.fill': 174, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 286: [ + 294: [ function (_dereq_, module, exports) { 'use strict'; Object.defineProperty(exports, '__esModule', { @@ -56970,7 +59076,7 @@ * @property {String} VERSION * @final */ - var VERSION = '1.9.0'; + var VERSION = '1.10.0'; // GRAPHICS RENDERER /** * The default, two-dimensional renderer. @@ -57049,127 +59155,546 @@ var WAIT = 'wait'; // TRIGONOMETRY /** - * HALF_PI is a mathematical constant with the value - * 1.57079632679489661923. It is half the ratio of the - * circumference of a circle to its diameter. It is useful in - * combination with the trigonometric functions sin() and cos(). + * A `Number` constant that's approximately 1.5708. + * + * `HALF_PI` is half the value of the mathematical constant π. It's useful for + * many tasks that involve rotation and oscillation. For example, calling + * `rotate(HALF_PI)` rotates the coordinate system `HALF_PI` radians, which is + * a quarter turn (90˚). + * + * Note: `TWO_PI` radians equals 360˚, `PI` radians equals 180˚, `HALF_PI` + * radians equals 90˚, and `QUARTER_PI` radians equals 45˚. * * @property {Number} HALF_PI * @final * * @example - *
- * arc(50, 50, 80, 80, 0, HALF_PI); - *
+ *
+ * + * function setup() { + * createCanvas(100, 100); * - * @alt - * 80×80 white quarter-circle with curve toward bottom right of canvas. + * background(200); + * + * // Draw an arc from 0 to HALF_PI. + * arc(50, 50, 80, 80, 0, HALF_PI); + * + * describe('The bottom-right quarter of a circle drawn in white on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Translate the origin to the center. + * translate(50, 50); + * + * // Draw a line. + * line(0, 0, 40, 0); + * + * // Rotate a quarter turn. + * rotate(HALF_PI); + * + * // Draw the same line, rotated. + * line(0, 0, 40, 0); + * + * describe('Two black lines on a gray background. One line extends from the center to the right. The other line extends from the center to the bottom.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A red circle and a blue circle oscillate from left to right on a gray background. The red circle appears to chase the blue circle.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Translate the origin to the center. + * translate(50, 50); + * + * // Calculate the x-coordinates. + * let x1 = 40 * sin(frameCount * 0.05); + * let x2 = 40 * sin(frameCount * 0.05 + HALF_PI); + * + * // Style the oscillators. + * noStroke(); + * + * // Draw the red oscillator. + * fill(255, 0, 0); + * circle(x1, 0, 20); + * + * // Draw the blue oscillator. + * fill(0, 0, 255); + * circle(x2, 0, 20); + * } + * + *
*/ exports.WAIT = WAIT; var HALF_PI = _PI / 2; /** - * PI is a mathematical constant with the value - * 3.14159265358979323846. It is the ratio of the circumference - * of a circle to its diameter. It is useful in combination with - * the trigonometric functions sin() and cos(). + * A `Number` constant that's approximately 3.1416. + * + * `PI` is the mathematical constant π. It's useful for many tasks that + * involve rotation and oscillation. For example, calling `rotate(PI)` rotates + * the coordinate system `PI` radians, which is a half turn (180˚). + * + * Note: `TWO_PI` radians equals 360˚, `PI` radians equals 180˚, `HALF_PI` + * radians equals 90˚, and `QUARTER_PI` radians equals 45˚. * * @property {Number} PI * @final * * @example - *
- * arc(50, 50, 80, 80, 0, PI); - *
+ *
+ * + * function setup() { + * createCanvas(100, 100); * - * @alt - * white half-circle with curve toward bottom of canvas. - */ - exports.HALF_PI = HALF_PI; - var PI = _PI; - /** - * QUARTER_PI is a mathematical constant with the value 0.7853982. - * It is one quarter the ratio of the circumference of a circle to - * its diameter. It is useful in combination with the trigonometric - * functions sin() and cos(). + * background(200); * - * @property {Number} QUARTER_PI - * @final + * // Draw an arc from 0 to PI. + * arc(50, 50, 80, 80, 0, PI); * - * @example - *
- * arc(50, 50, 80, 80, 0, QUARTER_PI); - *
+ * describe('The bottom half of a circle drawn in white on a gray background.'); + * } + *
+ *
* - * @alt - * white eighth-circle rotated about 40 degrees with curve bottom right canvas. - */ - exports.PI = PI; - var QUARTER_PI = _PI / 4; - /** - * TAU is an alias for TWO_PI, a mathematical constant with the - * value 6.28318530717958647693. It is twice the ratio of the - * circumference of a circle to its diameter. It is useful in - * combination with the trigonometric functions sin() and cos(). + *
+ * + * function setup() { + * createCanvas(100, 100); * - * @property {Number} TAU - * @final + * background(200); * - * @example - *
- * arc(50, 50, 80, 80, 0, TAU); - *
+ * // Translate the origin to the center. + * translate(50, 50); * - * @alt - * 80×80 white ellipse shape in center of canvas. - */ - exports.QUARTER_PI = QUARTER_PI; - var TAU = _PI * 2; - /** - * TWO_PI is a mathematical constant with the value - * 6.28318530717958647693. It is twice the ratio of the - * circumference of a circle to its diameter. It is useful in - * combination with the trigonometric functions sin() and cos(). + * // Draw a line. + * line(0, 0, 40, 0); * - * @property {Number} TWO_PI - * @final + * // Rotate a half turn. + * rotate(PI); * - * @example - *
- * arc(50, 50, 80, 80, 0, TWO_PI); - *
+ * // Draw the same line, rotated. + * line(0, 0, 40, 0); * - * @alt - * 80×80 white ellipse shape in center of canvas. - */ - exports.TAU = TAU; - var TWO_PI = _PI * 2; - /** - * Constant to be used with the angleMode() function, to set the mode in - * which p5.js interprets and calculates angles (either DEGREES or RADIANS). - * @property {String} DEGREES - * @final + * describe('A horizontal black line on a gray background.'); + * } + *
+ *
* - * @example - *
+ *
+ * * function setup() { - * angleMode(DEGREES); + * createCanvas(100, 100); + * + * describe( + * 'A red circle and a blue circle oscillate from left to right on a gray background. The circles drift apart, then meet in the middle, over and over again.' + * ); * } - *
+ * + * function draw() { + * background(200); + * + * // Translate the origin to the center. + * translate(50, 50); + * + * // Calculate the x-coordinates. + * let x1 = 40 * sin(frameCount * 0.05); + * let x2 = 40 * sin(frameCount * 0.05 + PI); + * + * // Style the oscillators. + * noStroke(); + * + * // Draw the red oscillator. + * fill(255, 0, 0); + * circle(x1, 0, 20); + * + * // Draw the blue oscillator. + * fill(0, 0, 255); + * circle(x2, 0, 20); + * } + *
+ *
*/ - exports.TWO_PI = TWO_PI; - var DEGREES = 'degrees'; + exports.HALF_PI = HALF_PI; + var PI = _PI; /** - * Constant to be used with the angleMode() function, to set the mode - * in which p5.js interprets and calculates angles (either RADIANS or DEGREES). - * @property {String} RADIANS + * A `Number` constant that's approximately 0.7854. + * + * `QUARTER_PI` is one-fourth the value of the mathematical constant π. It's + * useful for many tasks that involve rotation and oscillation. For example, + * calling `rotate(QUARTER_PI)` rotates the coordinate system `QUARTER_PI` + * radians, which is an eighth of a turn (45˚). + * + * Note: `TWO_PI` radians equals 360˚, `PI` radians equals 180˚, `HALF_PI` + * radians equals 90˚, and `QUARTER_PI` radians equals 45˚. + * + * @property {Number} QUARTER_PI * @final * * @example - *
+ *
+ * * function setup() { - * angleMode(RADIANS); + * createCanvas(100, 100); + * + * background(200); + * + * // Draw an arc from 0 to QUARTER_PI. + * arc(50, 50, 80, 80, 0, QUARTER_PI); + * + * describe('A one-eighth slice of a circle drawn in white on a gray background.'); * } - *
+ *
+ *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Translate the origin to the center. + * translate(50, 50); + * + * // Draw a line. + * line(0, 0, 40, 0); + * + * // Rotate an eighth turn. + * rotate(QUARTER_PI); + * + * // Draw the same line, rotated. + * line(0, 0, 40, 0); + * + * describe('Two black lines that form a "V" opening towards the bottom-right corner of a gray square.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A red circle and a blue circle oscillate from left to right on a gray background. The red circle appears to chase the blue circle.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Translate the origin to the center. + * translate(50, 50); + * + * // Calculate the x-coordinates. + * let x1 = 40 * sin(frameCount * 0.05); + * let x2 = 40 * sin(frameCount * 0.05 + QUARTER_PI); + * + * // Style the oscillators. + * noStroke(); + * + * // Draw the red oscillator. + * fill(255, 0, 0); + * circle(x1, 0, 20); + * + * // Draw the blue oscillator. + * fill(0, 0, 255); + * circle(x2, 0, 20); + * } + * + *
+ */ + exports.PI = PI; + var QUARTER_PI = _PI / 4; + /** + * A `Number` constant that's approximately 6.2382. + * + * `TAU` is twice the value of the mathematical constant π. It's useful for + * many tasks that involve rotation and oscillation. For example, calling + * `rotate(TAU)` rotates the coordinate system `TAU` radians, which is one + * full turn (360˚). `TAU` and `TWO_PI` are equal. + * + * Note: `TAU` radians equals 360˚, `PI` radians equals 180˚, `HALF_PI` + * radians equals 90˚, and `QUARTER_PI` radians equals 45˚. + * + * @property {Number} TAU + * @final + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Draw an arc from 0 to TAU. + * arc(50, 50, 80, 80, 0, TAU); + * + * describe('A white circle drawn on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Translate the origin to the center. + * translate(50, 50); + * + * // Draw a line. + * line(0, 0, 40, 0); + * + * // Rotate a full turn. + * rotate(TAU); + * + * // Style the second line. + * strokeWeight(5); + * + * // Draw the same line, shorter and rotated. + * line(0, 0, 20, 0); + * + * describe( + * 'Two horizontal black lines on a gray background. A thick line extends from the center toward the right. A thin line extends from the end of the thick line.' + * ); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A red circle with a blue center oscillates from left to right on a gray background.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Translate the origin to the center. + * translate(50, 50); + * + * // Calculate the x-coordinates. + * let x1 = 40 * sin(frameCount * 0.05); + * let x2 = 40 * sin(frameCount * 0.05 + TAU); + * + * // Style the oscillators. + * noStroke(); + * + * // Draw the red oscillator. + * fill(255, 0, 0); + * circle(x1, 0, 20); + * + * // Draw the blue oscillator, smaller. + * fill(0, 0, 255); + * circle(x2, 0, 10); + * } + * + *
+ */ + exports.QUARTER_PI = QUARTER_PI; + var TAU = _PI * 2; + /** + * A `Number` constant that's approximately 6.2382. + * + * `TWO_PI` is twice the value of the mathematical constant π. It's useful for + * many tasks that involve rotation and oscillation. For example, calling + * `rotate(TWO_PI)` rotates the coordinate system `TWO_PI` radians, which is + * one full turn (360˚). `TWO_PI` and `TAU` are equal. + * + * Note: `TWO_PI` radians equals 360˚, `PI` radians equals 180˚, `HALF_PI` + * radians equals 90˚, and `QUARTER_PI` radians equals 45˚. + * + * @property {Number} TWO_PI + * @final + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Draw an arc from 0 to TWO_PI. + * arc(50, 50, 80, 80, 0, TWO_PI); + * + * describe('A white circle drawn on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Translate the origin to the center. + * translate(50, 50); + * + * // Draw a line. + * line(0, 0, 40, 0); + * + * // Rotate a full turn. + * rotate(TWO_PI); + * + * // Style the second line. + * strokeWeight(5); + * + * // Draw the same line, shorter and rotated. + * line(0, 0, 20, 0); + * + * describe( + * 'Two horizontal black lines on a gray background. A thick line extends from the center toward the right. A thin line extends from the end of the thick line.' + * ); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A red circle with a blue center oscillates from left to right on a gray background.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Translate the origin to the center. + * translate(50, 50); + * + * // Calculate the x-coordinates. + * let x1 = 40 * sin(frameCount * 0.05); + * let x2 = 40 * sin(frameCount * 0.05 + TWO_PI); + * + * // Style the oscillators. + * noStroke(); + * + * // Draw the red oscillator. + * fill(255, 0, 0); + * circle(x1, 0, 20); + * + * // Draw the blue oscillator, smaller. + * fill(0, 0, 255); + * circle(x2, 0, 10); + * } + * + *
+ */ + exports.TAU = TAU; + var TWO_PI = _PI * 2; + /** + * A `String` constant that's used to set the + * angleMode(). + * + * By default, functions such as rotate() and + * sin() expect angles measured in units of radians. + * Calling `angleMode(DEGREES)` ensures that angles are measured in units of + * degrees. + * + * Note: `TWO_PI` radians equals 360˚. + * + * @property {String} DEGREES + * @final + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Draw a red arc from 0 to HALF_PI radians. + * fill(255, 0, 0); + * arc(50, 50, 80, 80, 0, HALF_PI); + * + * // Use degrees. + * angleMode(DEGREES); + * + * // Draw a blue arc from 90˚ to 180˚. + * fill(0, 0, 255); + * arc(50, 50, 80, 80, 90, 180); + * + * describe('The bottom half of a circle drawn on a gray background. The bottom-right quarter is red. The bottom-left quarter is blue.'); + * } + * + *
+ */ + exports.TWO_PI = TWO_PI; + var DEGREES = 'degrees'; + /** + * A `String` constant that's used to set the + * angleMode(). + * + * By default, functions such as rotate() and + * sin() expect angles measured in units of radians. + * Calling `angleMode(RADIANS)` ensures that angles are measured in units of + * radians. Doing so can be useful if the + * angleMode() has been set to + * DEGREES. + * + * Note: `TWO_PI` radians equals 360˚. + * + * @property {String} RADIANS + * @final + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Use degrees. + * angleMode(DEGREES); + * + * // Draw a red arc from 0˚ to 90˚. + * fill(255, 0, 0); + * arc(50, 50, 80, 80, 0, 90); + * + * // Use radians. + * angleMode(RADIANS); + * + * // Draw a blue arc from HALF_PI to PI. + * fill(0, 0, 255); + * arc(50, 50, 80, 80, HALF_PI, PI); + * + * describe('The bottom half of a circle drawn on a gray background. The bottom-right quarter is red. The bottom-left quarter is blue.'); + * } + * + *
*/ exports.DEGREES = DEGREES; var RADIANS = 'radians'; @@ -57862,7 +60387,7 @@ { } ], - 287: [ + 295: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -58030,7 +60555,8 @@ } }; /** - * Tracks the number of frames drawn since the sketch started. + * A `Number` variable that tracks the number of frames drawn since the sketch + * started. * * `frameCount`'s value is 0 inside setup(). It * increments by 1 each time the code in draw() @@ -58042,6 +60568,8 @@ *
* * function setup() { + * createCanvas(100, 100); + * * background(200); * * // Display the value of @@ -58058,11 +60586,15 @@ *
* * function setup() { + * createCanvas(100, 100); + * * // Set the frameRate to 30. * frameRate(30); * * textSize(30); * textAlign(CENTER, CENTER); + * + * describe('A number written in black in the middle of a gray square. Its value increases rapidly.'); * } * * function draw() { @@ -58071,16 +60603,17 @@ * // Display the value of * // frameCount. * text(frameCount, 50, 50); - * - * describe('A number written in black in the middle of a gray square. Its value increases rapidly.'); * } * *
*/ _main.default.prototype.frameCount = 0; /** - * Tracks the amount of time, in milliseconds, it took for - * draw to draw the previous frame. `deltaTime` is + * A `Number` variable that tracks the number of milliseconds it took to draw + * the last frame. + * + * `deltaTime` contains the amount of time it took + * draw() to execute during the previous frame. It's * useful for simulating physics. * * @property {Integer} deltaTime @@ -58092,8 +60625,12 @@ * let speed = 0.05; * * function setup() { + * createCanvas(100, 100); + * * // Set the frameRate to 30. * frameRate(30); + * + * describe('A white circle moves from left to right on a gray background. It reappears on the left side when it reaches the right side.'); * } * * function draw() { @@ -58115,16 +60652,16 @@ * // Use x to set the circle's * // position. * circle(x, 50, 20); - * - * describe('A white circle moves from left to right on a gray background. It reappears on the left side when it reaches the right side.'); * } *
*
*/ _main.default.prototype.deltaTime = 0; /** - * Tracks whether the browser window is focused and can receive user input. - * `focused` is `true` if the window if focused and `false` if not. + * A `Boolean` variable that's `true` if the browser is focused and `false` if + * not. + * + * Note: The browser window can only receive input if it's focused. * * @property {Boolean} focused * @readOnly @@ -58134,6 +60671,12 @@ * // Open this example in two separate browser * // windows placed side-by-side to demonstrate. * + * function setup() { + * createCanvas(100, 100); + * + * describe('A square changes color from green to red when the browser window is out of focus.'); + * } + * * function draw() { * // Change the background color * // when the browser window @@ -58143,8 +60686,6 @@ * } else { * background(255, 0, 0); * } - * - * describe('A square changes color from green to red when the browser window is out of focus.'); * } * * @@ -58159,7 +60700,7 @@ * strings: `'help'`, `'wait'`, `'crosshair'`, `'not-allowed'`, `'zoom-in'`, * and `'grab'`. If the path to an image is passed, as in * `cursor('assets/target.png')`, then the image will be used as the cursor. - * Images must be in .cur, .gif, .jpg, .jpeg, or .png format. + * Images must be in .cur, .gif, .jpg, .jpeg, or .png format and should be at most 32 by 32 pixels large. * * The parameters `x` and `y` are optional. If an image is used for the * cursor, `x` and `y` set the location pointed to within the image. They are @@ -58175,19 +60716,29 @@ * @example *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('A gray square. The cursor appears as crosshairs.'); + * } + * * function draw() { * background(200); * * // Set the cursor to crosshairs: + * cursor(CROSS); - * - * describe('A gray square. The cursor appears as crosshairs.'); * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('A gray square divided into quadrants. The cursor image changes when the mouse moves to each quadrant.'); + * } + * * function draw() { * background(200); * @@ -58205,14 +60756,18 @@ * } else { * cursor('grab'); * } - * - * describe('A gray square divided into quadrants. The cursor image changes when the mouse moves to each quadrant.'); * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('An image of three purple curves follows the mouse. The image shifts when the mouse is pressed.'); + * } + * * function draw() { * background(200); * @@ -58223,8 +60778,6 @@ * } else { * cursor('https://avatars0.githubusercontent.com/u/1617169?s=16'); * } - * - * describe('An image of three purple curves follows the mouse. The image shifts when the mouse is pressed.'); * } * *
@@ -58274,6 +60827,12 @@ * @example *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('A white circle on a gray background. The circle moves from left to right in a loop. It slows down when the mouse is pressed.'); + * } + * * function draw() { * background(200); * @@ -58292,14 +60851,18 @@ * // Use x to set the circle's * // position. * circle(x, 50, 20); - * - * describe('A white circle on a gray background. The circle moves from left to right in a loop. It slows down when the mouse is pressed.'); * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('A number written in black on a gray background. The number decreases when the mouse is pressed.'); + * } + * * function draw() { * background(200); * @@ -58315,8 +60878,6 @@ * // and display it. * let fps = frameRate(); * text(fps, 50, 50); - * - * describe('A number written in black written on a gray background. The number decreases when the mouse is pressed.'); * } * *
@@ -58362,14 +60923,22 @@ return this.frameRate(fps); }; /** - * Returns the target frame rate. The value is either the system frame rate or - * the last value passed to frameRate(). + * Returns the target frame rate. + * + * The value is either the system frame rate or the last value passed to + * frameRate(). * * @method getTargetFrameRate * @return {Number} _targetFrameRate * @example *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('The number 20 written in black on a gray background.'); + * } + * * function draw() { * background(200); * @@ -58380,8 +60949,6 @@ * // display it. * let fps = getTargetFrameRate(); * text(fps, 43, 54); - * - * describe('The number 20 written in black on a gray background.'); * } * *
@@ -58415,8 +60982,9 @@ this._curElement.elt.style.cursor = 'none'; }; /** - * A string variable with the WebGL version in use. Its value equals one of - * the followin string constants: + * A `String` variable with the WebGL version in use. + * + * `webglVersion`'s value equals one of the following string constants: * * - `WEBGL2` whose value is `'webgl2'`, * - `WEBGL` whose value is `'webgl'`, or @@ -58495,9 +61063,10 @@ */ _main.default.prototype.webglVersion = C.P2D; /** - * A numeric variable that stores the width of the screen display. Its value + * A `Number` variable that stores the width of the screen display. + * + * `displayWidth` is useful for running full-screen programs. Its value * depends on the current pixelDensity(). - * `displayWidth` is useful for running full-screen programs. * * Note: The actual screen width can be computed as * `displayWidth * pixelDensity()`. @@ -58524,9 +61093,10 @@ */ _main.default.prototype.displayWidth = screen.width; /** - * A numeric variable that stores the height of the screen display. Its value + * A `Number` variable that stores the height of the screen display. + * + * `displayHeight` is useful for running full-screen programs. Its value * depends on the current pixelDensity(). - * `displayHeight` is useful for running full-screen programs. * * Note: The actual screen height can be computed as * `displayHeight * pixelDensity()`. @@ -58553,9 +61123,10 @@ */ _main.default.prototype.displayHeight = screen.height; /** - * A numeric variable that stores the width of the browser's - * layout viewport. - * This viewport is the area within the browser that's available for drawing. + * A `Number` variable that stores the width of the browser's viewport. + * + * The layout viewport + * is the area within the browser that's available for drawing. * * @property {Number} windowWidth * @readOnly @@ -58577,11 +61148,12 @@ * @alt * This example does not render anything. */ - _main.default.prototype.windowWidth = getWindowWidth(); + _main.default.prototype.windowWidth = 0; /** - * A numeric variable that stores the height of the browser's - * layout viewport. - * This viewport is the area within the browser that's available for drawing. + * A `Number` variable that stores the height of the browser's viewport. + * + * The layout viewport + * is the area within the browser that's available for drawing. * * @property {Number} windowHeight * @readOnly @@ -58603,13 +61175,16 @@ * @alt * This example does not render anything. */ - _main.default.prototype.windowHeight = getWindowHeight(); + _main.default.prototype.windowHeight = 0; /** - * The code in `windowResized()` is called once each time the browser window - * is resized. It's a good place to resize the canvas or make other + * A function that's called when the browser window is resized. + * + * Code placed in the body of `windowResized()` will run when the + * browser window's size changes. It's a good place to call + * resizeCanvas() or make other * adjustments to accommodate the new window size. * - * The `event` parameter is optional. If added to the function definition, it + * The `event` parameter is optional. If added to the function declaration, it * can be used for debugging or other purposes. * * @method windowResized @@ -58619,12 +61194,15 @@ * * function setup() { * createCanvas(windowWidth, windowHeight); + * + * describe('A gray canvas with a white circle at its center. The canvas takes up the entire browser window. It changes size to match the browser window.'); * } * * function draw() { * background(200); * - * describe('A gray canvas that takes up the entire browser window. It changes size to match the browser window.'); + * // Draw a circle at the center. + * circle(width / 2, height / 2, 50); * } * * // Resize the canvas when the @@ -58680,10 +61258,19 @@ function getWindowHeight() { return window.innerHeight || document.documentElement && document.documentElement.clientHeight || document.body && document.body.clientHeight || 0; } /** - * A numeric variable that stores the width of the drawing canvas. Its - * default value is 100. + * Called upon each p5 instantiation instead of module import due to the + * possibility of the window being resized when no sketch is active. + */ + + _main.default.prototype._updateWindowSize = function () { + this._setProperty('windowWidth', getWindowWidth()); + this._setProperty('windowHeight', getWindowHeight()); + }; + /** + * A `Number` variable that stores the width of the canvas in pixels. * - * Calling createCanvas() or + * `width`'s default value is 100. Calling + * createCanvas() or * resizeCanvas() changes the value of * `width`. Calling noCanvas() sets its value to * 0. @@ -58737,7 +61324,7 @@ * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { * resizeCanvas(50, 100); * background(200); - * text(width, 42, 27); + * text(width, 21, 54); * } * } * @@ -58746,13 +61333,12 @@ * @property {Number} width * @readOnly */ - _main.default.prototype.width = 0; /** - * A numeric variable that stores the height of the drawing canvas. Its - * default value is 100. + * A `Number` variable that stores the height of the canvas in pixels. * - * Calling createCanvas() or + * `height`'s default value is 100. Calling + * createCanvas() or * resizeCanvas() changes the value of * `height`. Calling noCanvas() sets its value to * 0. @@ -58779,7 +61365,7 @@ * background(200); * * // Display the canvas' height. - * text(height, 21, 54); + * text(height, 42, 27); * * describe('The number 50 written in black on a gray rectangle.'); * } @@ -58866,10 +61452,16 @@ } }; /** - * Sets the pixel scaling for high pixel density displays. + * Sets the pixel density or returns the current density. + * + * Computer displays are grids of little lights called pixels. A + * display's pixel density describes how many pixels it packs into an + * area. Displays with smaller pixels have a higher pixel density and create + * sharper images. * - * By default, the pixel density is set to match display density. Calling - * `pixelDensity(1)` turn this off. + * `pixelDensity()` sets the pixel scaling for high pixel density displays. + * By default, the pixel density is set to match the display's density. + * Calling `pixelDensity(1)` turn this off. * * Calling `pixelDensity()` without an argument returns the current pixel * density. @@ -58922,7 +61514,7 @@ var returnValue; if (typeof val === 'number') { if (val !== this._pixelDensity) { - this._pixelDensity = val; + this._pixelDensity = this._maxAllowedPixelDimensions = val; } returnValue = this; this.resizeCanvas(this.width, this.height, true); // as a side effect, it will clear the canvas @@ -58999,7 +61591,7 @@ } /** * Returns the sketch's current * URL - * as a string. + * as a `String`. * * @method getURL * @return {String} url @@ -59027,7 +61619,7 @@ /** * Returns the current * URL - * path as an array of strings. + * path as an `Array` of `String`s. * * For example, consider a sketch hosted at the URL * `https://example.com/sketchbook`. Calling `getURLPath()` returns @@ -59062,7 +61654,7 @@ /** * Returns the current * URL parameters - * in an Object. + * in an `Object`. * * For example, calling `getURLParams()` in a sketch hosted at the URL * `http://p5js.org?year=2014&month=May&day=15` returns @@ -59112,27 +61704,27 @@ exports.default = _default; }, { - './constants': 286, - './main': 298, - 'core-js/modules/es.array.concat': 169, - 'core-js/modules/es.array.filter': 173, - 'core-js/modules/es.array.includes': 177, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.regexp.exec': 205, - 'core-js/modules/es.string.includes': 209, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.string.search': 215, - 'core-js/modules/es.string.split': 216, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256 + './constants': 294, + './main': 306, + 'core-js/modules/es.array.concat': 171, + 'core-js/modules/es.array.filter': 175, + 'core-js/modules/es.array.includes': 181, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.regexp.exec': 213, + 'core-js/modules/es.string.includes': 217, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.string.search': 223, + 'core-js/modules/es.string.split': 224, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 288: [ + 296: [ function (_dereq_, module, exports) { 'use strict'; Object.defineProperty(exports, '__esModule', { @@ -59272,7 +61864,7 @@ { } ], - 289: [ + 297: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -60357,40 +62949,40 @@ exports.default = _default; }, { - '../constants': 286, - '../internationalization': 296, - '../main': 298, - './browser_errors': 288, - 'core-js/modules/es.array.concat': 169, - 'core-js/modules/es.array.filter': 173, - 'core-js/modules/es.array.for-each': 175, - 'core-js/modules/es.array.includes': 177, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.join': 180, - 'core-js/modules/es.array.map': 182, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.array.some': 184, - 'core-js/modules/es.function.name': 186, - 'core-js/modules/es.object.assign': 194, - 'core-js/modules/es.object.get-own-property-names': 197, - 'core-js/modules/es.object.keys': 199, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.regexp.constructor': 204, - 'core-js/modules/es.regexp.exec': 205, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.string.match': 211, - 'core-js/modules/es.string.replace': 214, - 'core-js/modules/es.string.split': 216, - 'core-js/modules/es.string.starts-with': 217, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/web.dom-collections.for-each': 255, - 'core-js/modules/web.dom-collections.iterator': 256 + '../constants': 294, + '../internationalization': 304, + '../main': 306, + './browser_errors': 296, + 'core-js/modules/es.array.concat': 171, + 'core-js/modules/es.array.filter': 175, + 'core-js/modules/es.array.for-each': 179, + 'core-js/modules/es.array.includes': 181, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.join': 184, + 'core-js/modules/es.array.map': 186, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.array.some': 188, + 'core-js/modules/es.function.name': 192, + 'core-js/modules/es.object.assign': 201, + 'core-js/modules/es.object.get-own-property-names': 205, + 'core-js/modules/es.object.keys': 207, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.regexp.constructor': 212, + 'core-js/modules/es.regexp.exec': 213, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.string.match': 219, + 'core-js/modules/es.string.replace': 222, + 'core-js/modules/es.string.split': 224, + 'core-js/modules/es.string.starts-with': 225, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/web.dom-collections.for-each': 263, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 290: [ + 298: [ function (_dereq_, module, exports) { 'use strict'; Object.defineProperty(exports, '__esModule', { @@ -60503,11 +63095,11 @@ exports.default = _default; }, { - '../internationalization': 296, - '../main': 298 + '../internationalization': 304, + '../main': 306 } ], - 291: [ + 299: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -61005,38 +63597,38 @@ exports.default = _default; }, { - '../constants': 286, - '../internationalization': 296, - '../main': 298, - 'core-js/modules/es.array.filter': 173, - 'core-js/modules/es.array.for-each': 175, - 'core-js/modules/es.array.from': 176, - 'core-js/modules/es.array.includes': 177, - 'core-js/modules/es.array.index-of': 178, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.join': 180, - 'core-js/modules/es.array.map': 182, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.keys': 199, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.regexp.constructor': 204, - 'core-js/modules/es.regexp.exec': 205, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.string.includes': 209, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.string.match': 211, - 'core-js/modules/es.string.split': 216, - 'core-js/modules/es.string.trim': 219, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.for-each': 255, - 'core-js/modules/web.dom-collections.iterator': 256 + '../constants': 294, + '../internationalization': 304, + '../main': 306, + 'core-js/modules/es.array.filter': 175, + 'core-js/modules/es.array.for-each': 179, + 'core-js/modules/es.array.from': 180, + 'core-js/modules/es.array.includes': 181, + 'core-js/modules/es.array.index-of': 182, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.join': 184, + 'core-js/modules/es.array.map': 186, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.keys': 207, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.regexp.constructor': 212, + 'core-js/modules/es.regexp.exec': 213, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.string.includes': 217, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.string.match': 219, + 'core-js/modules/es.string.split': 224, + 'core-js/modules/es.string.trim': 227, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.for-each': 263, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 292: [ + 300: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.array.filter'); @@ -61265,19 +63857,19 @@ exports.default = _default; }, { - '../main': 298, - 'core-js/modules/es.array.filter': 173, - 'core-js/modules/es.array.index-of': 178, - 'core-js/modules/es.array.join': 180, - 'core-js/modules/es.array.map': 182, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.regexp.exec': 205, - 'core-js/modules/es.string.match': 211, - 'core-js/modules/es.string.replace': 214, - 'core-js/modules/es.string.split': 216 + '../main': 306, + 'core-js/modules/es.array.filter': 175, + 'core-js/modules/es.array.index-of': 182, + 'core-js/modules/es.array.join': 184, + 'core-js/modules/es.array.map': 186, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.regexp.exec': 213, + 'core-js/modules/es.string.match': 219, + 'core-js/modules/es.string.replace': 222, + 'core-js/modules/es.string.split': 224 } ], - 293: [ + 301: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -62256,41 +64848,41 @@ }, { '../../../docs/parameterData.json': 1, - '../constants': 286, - '../internationalization': 296, - '../main': 298, - 'core-js/modules/es.array.concat': 169, - 'core-js/modules/es.array.for-each': 175, - 'core-js/modules/es.array.includes': 177, - 'core-js/modules/es.array.index-of': 178, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.join': 180, - 'core-js/modules/es.array.last-index-of': 181, - 'core-js/modules/es.array.map': 182, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.function.name': 186, - 'core-js/modules/es.map': 187, - 'core-js/modules/es.number.constructor': 191, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.get-prototype-of': 198, - 'core-js/modules/es.object.keys': 199, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.reflect.construct': 202, - 'core-js/modules/es.regexp.exec': 205, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.set': 207, - 'core-js/modules/es.string.includes': 209, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.string.split': 216, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.for-each': 255, - 'core-js/modules/web.dom-collections.iterator': 256 + '../constants': 294, + '../internationalization': 304, + '../main': 306, + 'core-js/modules/es.array.concat': 171, + 'core-js/modules/es.array.for-each': 179, + 'core-js/modules/es.array.includes': 181, + 'core-js/modules/es.array.index-of': 182, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.join': 184, + 'core-js/modules/es.array.last-index-of': 185, + 'core-js/modules/es.array.map': 186, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.function.name': 192, + 'core-js/modules/es.map': 193, + 'core-js/modules/es.number.constructor': 197, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.get-prototype-of': 206, + 'core-js/modules/es.object.keys': 207, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.reflect.construct': 210, + 'core-js/modules/es.regexp.exec': 213, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.set': 215, + 'core-js/modules/es.string.includes': 217, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.string.split': 224, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.for-each': 263, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 294: [ + 302: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -62412,19 +65004,19 @@ exports.default = _default; }, { - './constants': 286, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256 + './constants': 294, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 295: [ + 303: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.array.iterator'); @@ -62492,16 +65084,16 @@ waitingForTranslator]).then(_globalInit); }, { - '../core/main': 298, - './internationalization': 296, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.promise': 201, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/main': 306, + './internationalization': 304, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.promise': 209, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 296: [ + 304: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.array.includes'); @@ -62755,25 +65347,25 @@ exports.setTranslatorLanguage = setTranslatorLanguage; }, { - '../../translations': 360, + '../../translations': 369, '../../translations/dev': undefined, - 'core-js/modules/es.array.includes': 177, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.join': 180, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.object.keys': 199, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.promise': 201, - 'core-js/modules/es.regexp.exec': 205, - 'core-js/modules/es.string.includes': 209, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.string.split': 216, - 'core-js/modules/web.dom-collections.iterator': 256, - 'i18next': 267, - 'i18next-browser-languagedetector': 264 + 'core-js/modules/es.array.includes': 181, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.join': 184, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.object.keys': 207, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.promise': 209, + 'core-js/modules/es.regexp.exec': 213, + 'core-js/modules/es.string.includes': 217, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.string.split': 224, + 'core-js/modules/web.dom-collections.iterator': 264, + 'i18next': 275, + 'i18next-browser-languagedetector': 272 } ], - 297: [ + 305: [ function (_dereq_, module, exports) { 'use strict'; Object.defineProperty(exports, '__esModule', { @@ -62812,10 +65404,10 @@ exports.default = _default; }, { - './main': 298 + './main': 306 } ], - 298: [ + 306: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -62972,124 +65564,234 @@ // PUBLIC p5 PROPERTIES AND METHODS ////////////////////////////////////////////// /** - * Called directly before setup(), the preload() function is used to handle - * asynchronous loading of external files in a blocking way. If a preload - * function is defined, setup() will wait until any load calls within have - * finished. Nothing besides load calls (loadImage, loadJSON, loadFont, - * loadStrings, etc.) should be inside the preload function. If asynchronous - * loading is preferred, the load methods can instead be called in setup() - * or anywhere else with the use of a callback parameter. - * - * By default the text "loading..." will be displayed. To make your own - * loading page, include an HTML element with id "p5_loading" in your - * page. More information here. + * A function that's called once to load assets before the sketch runs. + * + * Declaring the function `preload()` sets a code block to run once + * automatically before setup() or + * draw(). It's used to load assets including + * multimedia files, fonts, data, and 3D models: + * + * ```js + * function preload() { + * // Code to run before the rest of the sketch. + * } + * ``` + * + * Functions such as loadImage(), + * loadFont(), + * loadJSON(), and + * loadModel() are guaranteed to either + * finish loading or raise an error if they're called within `preload()`. + * Doing so ensures that assets are available when the sketch begins + * running. * * @method preload + * * @example - *
+ *
+ * * let img; - * let c; + * + * // Load an image and create a p5.Image object. * function preload() { - * // preload() runs once - * img = loadImage('assets/laDefense.jpg'); + * img = loadImage('assets/bricks.jpg'); * } * * function setup() { - * // setup() waits until preload() is done - * img.loadPixels(); - * // get color of middle pixel - * c = img.get(img.width / 2, img.height / 2); - * } - * - * function draw() { - * background(c); - * image(img, 25, 25, 50, 50); - * } - *
+ * createCanvas(100, 100); * - * @alt - * nothing displayed + * // Draw the image. + * image(img, 0, 0); * + * describe('A red brick wall.'); + * } + *
+ *
*/ /** - * The setup() function is called once when the program starts. It's used to - * define initial environment properties such as screen size and background - * color and to load media such as images and fonts as the program starts. - * There can only be one setup() function for each program and it shouldn't - * be called again after its initial execution. + * A function that's called once when the sketch begins running. + * + * Declaring the function `setup()` sets a code block to run once + * automatically when the sketch starts running. It's used to perform + * setup tasks such as creating the canvas and initializing variables: + * + * ```js + * function setup() { + * // Code to run once at the start of the sketch. + * } + * ``` * - * Note: Variables declared within setup() are not accessible within other - * functions, including draw(). + * Code placed in `setup()` will run once before code placed in + * draw() begins looping. If the + * preload() is declared, then `setup()` will + * run immediately after preload() finishes + * loading assets. + * + * Note: `setup()` doesn’t have to be declared, but it’s common practice to do so. * * @method setup + * * @example - *
- * let a = 0; + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); * + * // Draw the circle. + * circle(50, 50, 40); + * + * describe('A white circle on a gray background.'); + * } + * + *
+ * + *
+ * * function setup() { - * background(0); - * noStroke(); - * fill(102); + * createCanvas(100, 100); + * + * // Paint the background once. + * background(200); + * + * describe( + * 'A white circle on a gray background. The circle follows the mouse as the user moves, leaving a trail.' + * ); * } * * function draw() { - * rect(a++ % width, 10, 2, 80); + * // Draw circles repeatedly. + * circle(mouseX, mouseY, 40); * } - *
+ *
+ *
* - * @alt - * nothing displayed + *
+ * + * let img; * + * function preload() { + * img = loadImage('assets/bricks.jpg'); + * } + * + * function setup() { + * createCanvas(100, 100); + * + * // Draw the image. + * image(img, 0, 0); + * + * describe( + * 'A white circle on a brick wall. The circle follows the mouse as the user moves, leaving a trail.' + * ); + * } + * + * function draw() { + * // Style the circle. + * noStroke(); + * + * // Draw the circle. + * circle(mouseX, mouseY, 10); + * } + * + *
*/ /** - * Called directly after setup(), the draw() function continuously executes - * the lines of code contained inside its block until the program is stopped - * or noLoop() is called. Note if noLoop() is called in setup(), draw() will - * still be executed once before stopping. draw() is called automatically and - * should never be called explicitly. - * - * It should always be controlled with noLoop(), redraw() and loop(). After - * noLoop() stops the code in draw() from executing, redraw() causes the - * code inside draw() to execute once, and loop() will cause the code - * inside draw() to resume executing continuously. - * - * The number of times draw() executes in each second may be controlled with - * the frameRate() function. - * - * There can only be one draw() function for each sketch, and draw() must - * exist if you want the code to run continuously, or to process events such - * as mousePressed(). Sometimes, you might have an empty call to draw() in - * your program, as shown in the above example. - * - * It is important to note that the drawing coordinate system will be reset - * at the beginning of each draw() call. If any transformations are performed - * within draw() (ex: scale, rotate, translate), their effects will be - * undone at the beginning of draw(), so transformations will not accumulate - * over time. On the other hand, styling applied (ex: fill, stroke, etc) will - * remain in effect. + * A function that's called repeatedly while the sketch runs. + * + * Declaring the function `draw()` sets a code block to run repeatedly + * once the sketch starts. It’s used to create animations and respond to + * user inputs: + * + * ```js + * function draw() { + * // Code to run repeatedly. + * } + * ``` + * + * This is often called the "draw loop" because p5.js calls the code in + * `draw()` in a loop behind the scenes. By default, `draw()` tries to run + * 60 times per second. The actual rate depends on many factors. The + * drawing rate, called the "frame rate", can be controlled by calling + * frameRate(). The number of times `draw()` + * has run is stored in the system variable + * frameCount(). + * + * Code placed within `draw()` begins looping after + * setup() runs. `draw()` will run until the user + * closes the sketch. `draw()` can be stopped by calling the + * noLoop() function. `draw()` can be resumed by + * calling the loop() function. * * @method draw + * * @example - *
- * let yPos = 0; + *
+ * * function setup() { - * // setup() runs once - * frameRate(30); + * createCanvas(100, 100); + * + * // Paint the background once. + * background(200); + * + * describe( + * 'A white circle on a gray background. The circle follows the mouse as the user moves, leaving a trail.' + * ); * } + * * function draw() { - * // draw() loops forever, until stopped - * background(204); - * yPos = yPos - 1; - * if (yPos < 0) { - * yPos = height; - * } - * line(0, yPos, width, yPos); + * // Draw circles repeatedly. + * circle(mouseX, mouseY, 40); * } - *
+ *
+ *
* - * @alt - * nothing displayed + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A white circle on a gray background. The circle follows the mouse as the user moves.' + * ); + * } + * + * function draw() { + * // Paint the background repeatedly. + * background(200); * + * // Draw circles repeatedly. + * circle(mouseX, mouseY, 40); + * } + * + *
+ * + *
+ * + * // Double-click the canvas to change the circle's color. + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A white circle on a gray background. The circle follows the mouse as the user moves. The circle changes color to pink when the user double-clicks.' + * ); + * } + * + * function draw() { + * // Paint the background repeatedly. + * background(200); + * + * // Draw circles repeatedly. + * circle(mouseX, mouseY, 40); + * } + * + * // Change the fill color when the user double-clicks. + * function doubleClicked() { + * fill('deeppink'); + * } + * + *
*/ ////////////////////////////////////////////// // PRIVATE p5 PROPERTIES AND METHODS @@ -63098,6 +65800,7 @@ this._preloadDone = false; // for handling hidpi this._pixelDensity = Math.ceil(window.devicePixelRatio) || 1; + this._maxAllowedPixelDimensions = 0; this._userNode = node; this._curElement = null; this._elements = [ @@ -63135,6 +65838,8 @@ }; this._millisStart = - 1; this._recording = false; + this.touchstart = false; + this.touchend = false; // States used in the custom random generators this._lcg_random_state = null; this._gaussian_previous = false; @@ -63353,8 +66058,8 @@ } _this.callRegisteredHooksFor('afterSetup'); }; - this._draw = function () { - var now = window.performance.now(); + this._draw = function (requestAnimationFrameTimestamp) { + var now = requestAnimationFrameTimestamp || window.performance.now(); var time_since_last = now - _this._lastTargetFrameTime; var target_time_between_frames = 1000 / _this._targetFrameRate; // only draw if we really need to; don't overextend the browser. @@ -63399,29 +66104,42 @@ } }; /** - * Removes the entire p5 sketch. This will remove the canvas and any - * elements created by p5.js. It will also stop the draw loop and unbind - * any properties or methods from the window global scope. It will - * leave a variable p5 in case you wanted to create a new p5 sketch. - * If you like, you can set p5 = null to erase it. While all functions and - * variables and objects created by the p5 library will be removed, any - * other global variables created by your code will remain. + * Removes the sketch from the web page. + * + * Calling `remove()` stops the draw loop and removes any HTML elements + * created by the sketch, including the canvas. A new sketch can be + * created by using the p5() constructor, as in + * `new p5()`. * * @method remove + * * @example - *
- * function draw() { - * ellipse(50, 50, 10, 10); - * } + *
+ * + * // Double-click to remove the canvas. * - * function mousePressed() { - * remove(); // remove whole sketch on mouse press + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A white circle on a gray background. The circle follows the mouse as the user moves. The sketch disappears when the user double-clicks.' + * ); * } - *
* - * @alt - * nothing displayed + * function draw() { + * // Paint the background repeatedly. + * background(200); + * + * // Draw circles repeatedly. + * circle(mouseX, mouseY, 40); + * } * + * // Remove the sketch when the user double-clicks. + * function doubleClicked() { + * remove(); + * } + *
+ *
*/ this.remove = function () { // Remove start listener to prevent orphan canvas being created @@ -63501,6 +66219,8 @@ p5.instance = null; } }; + // ensure correct reporting of window dimensions + this._updateWindowSize(); // call any registered init functions this._registeredMethods.init.forEach(function (f) { if (typeof f !== 'undefined') { @@ -63727,27 +66447,37 @@ // global mode. p5.instance = null; /** - * Turn off some features of the friendly error system (FES), which can give - * a significant boost to performance when needed. - * - * Note that this will disable the parts of the FES that cause performance - * slowdown (like argument checking). Friendly errors that have no performance - * cost (like giving a descriptive error if a file load fails, or warning you - * if you try to override p5.js functions in the global space), - * will remain in place. + * Turns off the parts of the Friendly Error System (FES) that impact performance. * - * See - * disabling the friendly error system. + * The FES + * can cause sketches to draw slowly because it does extra work behind the + * scenes. For example, the FES checks the arguments passed to functions, + * which takes time to process. Disabling the FES can significantly improve + * performance by turning off these checks. * * @property {Boolean} disableFriendlyErrors + * * @example - *
+ *
+ * + * // Disable the FES. * p5.disableFriendlyErrors = true; * * function setup() { - * createCanvas(100, 50); + * createCanvas(100, 100); + * + * background(200); + * + * // The circle() function requires three arguments. The + * // next line would normally display a friendly error that + * // points this out. Instead, nothing happens and it fails + * // silently. + * circle(50, 50); + * + * describe('A gray square.'); * } - *
+ *
+ *
*/ p5.disableFriendlyErrors = false; // attach constants to p5 prototype @@ -63786,25 +66516,25 @@ exports.default = _default; }, { - './constants': 286, - './shim': 309, - 'core-js/modules/es.array.for-each': 175, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.array.splice': 185, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.get-own-property-names': 197, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.for-each': 255, - 'core-js/modules/web.dom-collections.iterator': 256 + './constants': 294, + './shim': 317, + 'core-js/modules/es.array.for-each': 179, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.array.splice': 189, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.get-own-property-names': 205, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.for-each': 263, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 299: [ + 307: [ function (_dereq_, module, exports) { 'use strict'; Object.defineProperty(exports, '__esModule', { @@ -63844,6 +66574,7 @@ /** * A class to describe an * HTML element. + * * Sketches can use many elements. Common elements include the drawing canvas, * buttons, sliders, webcam feeds, and so on. * @@ -63890,9 +66621,11 @@ function _class(elt, pInst) { _classCallCheck(this, _class); /** - * Underlying + * The element's underlying `HTMLElement` object. + * + * The * HTMLElement - * object. Its properties and methods can be used directly. + * object's properties and methods can be used directly. * * @example *
@@ -63927,19 +66660,23 @@ this._events = { }; /** + * A `Number` property that stores the element's width. + * * @type {Number} * @property width * @name width */ this.width = this.elt.offsetWidth; /** + * A `Number` property that stores the element's height. + * * @type {Number} * @property height * @name height */ this.height = this.elt.offsetHeight; } /** - * Attaches this element to a parent element. + * Attaches the element to a parent element. * * For example, a `<div></div>` element may be used as a box to * hold two pieces of text, a header and a paragraph. The @@ -63953,7 +66690,7 @@ * `myElement.parent(myDiv)`. Finally, `parent` can be an `HTMLElement` * object, as in `myElement.parent(anotherElement)`. * - * Calling `myElement.parent()` without an argument returns this element's + * Calling `myElement.parent()` without an argument returns the element's * parent. * * @method parent @@ -63969,19 +66706,25 @@ * * // Create a div element. * let div = createDiv(); + * * // Place the div in the top-left corner. * div.position(10, 20); + * * // Set its width and height. * div.size(80, 60); + * * // Set its background color to white * div.style('background-color', 'white'); + * * // Align any text to the center. * div.style('text-align', 'center'); + * * // Set its ID to "container". * div.id('container'); * * // Create a paragraph element. * let p = createP('p5*js'); + * * // Make the div its parent * // using its ID "container". * p.parent('container'); @@ -63998,10 +66741,13 @@ * * // Create rectangular div element. * let div = createDiv(); + * * // Place the div in the top-left corner. * div.position(10, 20); + * * // Set its width and height. * div.size(80, 60); + * * // Set its background color and align * // any text to the center. * div.style('background-color', 'white'); @@ -64009,6 +66755,7 @@ * * // Create a paragraph element. * let p = createP('p5*js'); + * * // Make the div its parent. * p.parent(div); * @@ -64024,10 +66771,13 @@ * * // Create rectangular div element. * let div = createDiv(); + * * // Place the div in the top-left corner. * div.position(10, 20); + * * // Set its width and height. * div.size(80, 60); + * * // Set its background color and align * // any text to the center. * div.style('background-color', 'white'); @@ -64035,6 +66785,7 @@ * * // Create a paragraph element. * let p = createP('p5*js'); + * * // Make the div its parent * // using the underlying * // HTMLElement. @@ -64068,7 +66819,7 @@ p.appendChild(this.elt); return this; } /** - * Sets this element's ID using a given string. + * Sets the element's ID using a given string. * * Calling `myElement.id()` without an argument returns its ID as a string. * @@ -64118,7 +66869,7 @@ } /** * Adds a * class attribute - * to the element. + * to the element using a given string. * * Calling `myElement.class()` without an argument returns a string with its current classes. * @@ -64167,6 +66918,7 @@ return this; } /** * Calls a function when the mouse is pressed over the element. + * * Calling `myElement.mousePressed(false)` disables the function. * * Note: Some mobile browsers may also trigger this event when the element @@ -64177,6 +66929,7 @@ * pressed over the element. * `false` disables the function. * @chainable + * * @example *
* @@ -64202,28 +66955,6 @@ * } * *
- * - *
- * - * function setup() { - * // Create a canvas element and - * // assign it to cnv. - * let cnv = createCanvas(100, 100); - * - * background(200); - * - * // Paint the background either - * // red, yellow, blue, or green - * // when the canvas is pressed. - * cnv.mousePressed(() => { - * let c = random(['red', 'yellow', 'blue', 'green']); - * background(c); - * }); - * - * describe('A gray square changes color when the mouse is pressed.'); - * } - * - *
*/ }, @@ -64244,6 +66975,7 @@ return this; } /** * Calls a function when the mouse is pressed twice over the element. + * * Calling `myElement.doubleClicked(false)` disables the function. * * @method doubleClicked @@ -64251,6 +66983,7 @@ * double clicked over the element. * `false` disables the function. * @chainable + * * @example *
* @@ -64276,28 +67009,6 @@ * } * *
- * - *
- * - * function setup() { - * // Create a canvas element and - * // assign it to cnv. - * let cnv = createCanvas(100, 100); - * - * background(200); - * - * // Paint the background either - * // red, yellow, blue, or green - * // when the canvas is double-clicked. - * cnv.doubleClicked(() => { - * let c = random(['red', 'yellow', 'blue', 'green']); - * background(c); - * }); - * - * describe('A gray square changes color when the user double-clicks the canvas.'); - * } - * - *
*/ }, @@ -64307,7 +67018,7 @@ _main.default.Element._adjustListener('dblclick', fxn, this); return this; } /** - * Calls a function when the mouse wheel scrolls over th element. + * Calls a function when the mouse wheel scrolls over the element. * * The callback function, `fxn`, is passed an `event` object. `event` has * two numeric properties, `deltaY` and `deltaX`. `event.deltaY` is @@ -64323,6 +67034,7 @@ * scrolled over the element. * `false` disables the function. * @chainable + * * @example *
* @@ -64358,28 +67070,6 @@ * * background(200); * - * // Paint the background either - * // red, yellow, blue, or green - * // when the mouse wheel moves. - * cnv.mouseWheel(() => { - * let c = random(['red', 'yellow', 'blue', 'green']); - * background(c); - * }); - * - * describe('A gray square changes color when the user scrolls the mouse wheel over the canvas.'); - * } - * - *
- * - *
- * - * function setup() { - * // Create a canvas element and - * // assign it to cnv. - * let cnv = createCanvas(100, 100); - * - * background(200); - * * // Call changeBackground() when the * // mouse wheel moves. * cnv.mouseWheel(changeBackground); @@ -64416,8 +67106,9 @@ _main.default.Element._adjustListener('wheel', fxn, this); return this; } /** - * Calls a function when the mouse is released over the element. Calling - * `myElement.mouseReleased(false)` disables the function. + * Calls a function when the mouse is released over the element. + * + * Calling `myElement.mouseReleased(false)` disables the function. * * Note: Some mobile browsers may also trigger this event when the element * receives a quick tap. @@ -64427,6 +67118,7 @@ * pressed over the element. * `false` disables the function. * @chainable + * * @example *
* @@ -64452,28 +67144,6 @@ * } * *
- * - *
- * - * function setup() { - * // Create a canvas element and - * // assign it to cnv. - * let cnv = createCanvas(100, 100); - * - * background(200); - * - * // Paint the background either - * // red, yellow, blue, or green - * // when a mouse press ends. - * cnv.mouseReleased(() => { - * let c = random(['red', 'yellow', 'blue', 'green']); - * background(c); - * }); - * - * describe('A gray square changes color when the user releases a mouse press.'); - * } - * - *
*/ }, @@ -64484,6 +67154,7 @@ return this; } /** * Calls a function when the mouse is pressed and released over the element. + * * Calling `myElement.mouseReleased(false)` disables the function. * * Note: Some mobile browsers may also trigger this event when the element @@ -64494,6 +67165,7 @@ * pressed and released over the element. * `false` disables the function. * @chainable + * * @example *
* @@ -64519,28 +67191,6 @@ * } * *
- * - *
- * - * function setup() { - * // Create a canvas element and - * // assign it to cnv. - * let cnv = createCanvas(100, 100); - * - * background(200); - * - * // Paint the background either - * // red, yellow, blue, or green - * // when a mouse press ends. - * cnv.mouseClicked(() => { - * let c = random(['red', 'yellow', 'blue', 'green']); - * background(c); - * }); - * - * describe('A gray square changes color when the user releases a mouse press.'); - * } - * - *
*/ }, @@ -64550,14 +67200,16 @@ _main.default.Element._adjustListener('click', fxn, this); return this; } /** - * Calls a function when the mouse moves over the element. Calling - * `myElement.mouseMoved(false)` disables the function. + * Calls a function when the mouse moves over the element. + * + * Calling `myElement.mouseMoved(false)` disables the function. * * @method mouseMoved * @param {Function|Boolean} fxn function to call when the mouse * moves over the element. * `false` disables the function. * @chainable + * * @example *
* @@ -64583,28 +67235,6 @@ * } * *
- * - *
- * - * function setup() { - * // Create a canvas element and - * // assign it to cnv. - * let cnv = createCanvas(100, 100); - * - * background(200); - * - * // Paint the background either - * // red, yellow, blue, or green - * // when the mouse moves. - * cnv.mouseMoved(() => { - * let c = random(['red', 'yellow', 'blue', 'green']); - * background(c); - * }); - * - * describe('A gray square changes color when the mouse moves over the canvas.'); - * } - * - *
*/ }, @@ -64614,14 +67244,16 @@ _main.default.Element._adjustListener('mousemove', fxn, this); return this; } /** - * Calls a function when the mouse moves onto the element. Calling - * `myElement.mouseOver(false)` disables the function. + * Calls a function when the mouse moves onto the element. + * + * Calling `myElement.mouseOver(false)` disables the function. * * @method mouseOver * @param {Function|Boolean} fxn function to call when the mouse * moves onto the element. * `false` disables the function. * @chainable + * * @example *
* @@ -64647,29 +67279,6 @@ * } * *
- * - *
- * - * function setup() { - * // Create a canvas element and - * // assign it to cnv. - * let cnv = createCanvas(100, 100); - * - * background(200); - * - * // Paint the background either - * // red, yellow, blue, or green - * // when the mouse moves onto - * // the canvas. - * cnv.mouseOver(() => { - * let c = random(['red', 'yellow', 'blue', 'green']); - * background(c); - * }); - * - * describe('A gray square changes color when the mouse moves onto the canvas.'); - * } - * - *
*/ }, @@ -64679,14 +67288,16 @@ _main.default.Element._adjustListener('mouseover', fxn, this); return this; } /** - * Calls a function when the mouse moves off the element. Calling - * `myElement.mouseOut(false)` disables the function. + * Calls a function when the mouse moves off the element. + * + * Calling `myElement.mouseOut(false)` disables the function. * * @method mouseOut * @param {Function|Boolean} fxn function to call when the mouse * moves off the element. * `false` disables the function. * @chainable + * * @example *
* @@ -64712,29 +67323,6 @@ * } * *
- * - *
- * - * function setup() { - * // Create a canvas element and - * // assign it to cnv. - * let cnv = createCanvas(100, 100); - * - * background(200); - * - * // Paint the background either - * // red, yellow, blue, or green - * // when the mouse moves off - * // the canvas. - * cnv.mouseOut(() => { - * let c = random(['red', 'yellow', 'blue', 'green']); - * background(c); - * }); - * - * describe('A gray square changes color when the mouse moves off the canvas.'); - * } - * - *
*/ }, @@ -64744,8 +67332,9 @@ _main.default.Element._adjustListener('mouseout', fxn, this); return this; } /** - * Calls a function when the element is touched. Calling - * `myElement.touchStarted(false)` disables the function. + * Calls a function when the element is touched. + * + * Calling `myElement.touchStarted(false)` disables the function. * * Note: Touch functions only work on mobile devices. * @@ -64754,6 +67343,7 @@ * starts. * `false` disables the function. * @chainable + * * @example *
* @@ -64779,29 +67369,6 @@ * } * *
- * - *
- * - * function setup() { - * // Create a canvas element and - * // assign it to cnv. - * let cnv = createCanvas(100, 100); - * - * background(200); - * - * // Paint the background either - * // red, yellow, blue, or green - * // when the user touches the - * // canvas. - * cnv.touchStarted(() => { - * let c = random(['red', 'yellow', 'blue', 'green']); - * background(c); - * }); - * - * describe('A gray square changes color when the user touches the canvas.'); - * } - * - *
*/ }, @@ -64811,9 +67378,9 @@ _main.default.Element._adjustListener('touchstart', fxn, this); return this; } /** - * Calls a function when the user touches the element and moves their - * finger. Calling `myElement.touchMoved(false)` disables the - * function. + * Calls a function when the user touches the element and moves. + * + * Calling `myElement.touchMoved(false)` disables the function. * * Note: Touch functions only work on mobile devices. * @@ -64848,29 +67415,6 @@ * } *
*
- * - *
- * - * function setup() { - * // Create a canvas element and - * // assign it to cnv. - * let cnv = createCanvas(100, 100); - * - * background(200); - * - * // Paint the background either - * // red, yellow, blue, or green - * // when the user touches the - * // canvas and moves. - * cnv.touchMoved(() => { - * let c = random(['red', 'yellow', 'blue', 'green']); - * background(c); - * }); - * - * describe('A gray square changes color when the user touches the canvas and moves.'); - * } - * - *
*/ }, @@ -64880,8 +67424,9 @@ _main.default.Element._adjustListener('touchmove', fxn, this); return this; } /** - * Calls a function when the user stops touching the element. Calling - * `myElement.touchMoved(false)` disables the function. + * Calls a function when the user stops touching the element. + * + * Calling `myElement.touchMoved(false)` disables the function. * * Note: Touch functions only work on mobile devices. * @@ -64916,30 +67461,6 @@ * } * *
- * - *
- * - * function setup() { - * // Create a canvas element and - * // assign it to cnv. - * let cnv = createCanvas(100, 100); - * - * background(200); - * - * // Paint the background either - * // red, yellow, blue, or green - * // when the user touches the - * // canvas, then lifts their - * // finger. - * cnv.touchEnded(() => { - * let c = random(['red', 'yellow', 'blue', 'green']); - * background(c); - * }); - * - * describe('A gray square changes color when the user touches the canvas, then lifts their finger.'); - * } - * - *
*/ }, @@ -64949,14 +67470,16 @@ _main.default.Element._adjustListener('touchend', fxn, this); return this; } /** - * Calls a function when a file is dragged over the element. Calling - * `myElement.dragOver(false)` disables the function. + * Calls a function when a file is dragged over the element. + * + * Calling `myElement.dragOver(false)` disables the function. * * @method dragOver * @param {Function|Boolean} fxn function to call when the file is * dragged over the element. * `false` disables the function. * @chainable + * * @example *
* @@ -64982,29 +67505,6 @@ * } * *
- * - *
- * - * // Drag a file over the canvas to test. - * - * function setup() { - * // Create a canvas element and - * // assign it to cnv. - * let cnv = createCanvas(100, 100); - * - * background(200); - * - * // Say "hello, file" when a - * // file is dragged over - * // the canvas. - * cnv.dragOver(() => { - * text('hello, file', 50, 50); - * }); - * - * describe('A gray square. The text "hello, file" appears when a file is dragged over the square.'); - * } - * - *
*/ }, @@ -65014,7 +67514,8 @@ _main.default.Element._adjustListener('dragover', fxn, this); return this; } /** - * Calls a function when a file is dragged off the element. Calling + * Calls a function when a file is dragged off the element. + * * Calling `myElement.dragLeave(false)` disables the function. * * @method dragLeave @@ -65048,30 +67549,6 @@ * } * * - * - *
- * - * // Drag a file over, then off - * // the canvas to test. - * - * function setup() { - * // Create a canvas element and - * // assign it to cnv. - * let cnv = createCanvas(100, 100); - * - * background(200); - * - * // Say "bye, file" when a - * // file is dragged over, - * // then off the canvas. - * cnv.dragLeave(() => { - * text('bye, file', 50, 50); - * }); - * - * describe('A gray square. The text "bye, file" appears when a file is dragged over, then off the square.'); - * } - * - *
*/ }, @@ -65156,10 +67633,10 @@ exports.default = _default; }, { - './main': 298 + './main': 306 } ], - 300: [ + 308: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -65344,20 +67821,90 @@ * @for p5 */ /** - * Thin wrapper around a renderer, to be used for creating a - * graphics buffer object. Use this class if you need - * to draw into an off-screen graphics buffer. The two parameters define the - * width and height in pixels. The fields and methods for this class are - * extensive, but mirror the normal drawing API for p5. + * A class to describe a drawing surface that's separate from the main canvas. + * + * Each `p5.Graphics` object provides a dedicated drawing surface called a + * *graphics buffer*. Graphics buffers are helpful when drawing should happen + * offscreen. For example, separate scenes can be drawn offscreen and + * displayed only when needed. + * + * `p5.Graphics` objects have nearly all the drawing features of the main + * canvas. For example, calling the method `myGraphics.circle(50, 50, 20)` + * draws to the graphics buffer. The resulting image can be displayed on the + * main canvas by passing the `p5.Graphics` object to the + * image() function, as in `image(myGraphics, 0, 0)`. + * + * Note: createGraphics() is the recommended + * way to create an instance of this class. * * @class p5.Graphics * @constructor * @extends p5.Element - * @param {Number} w width - * @param {Number} h height - * @param {Constant} renderer the renderer to use, either P2D or WEBGL - * @param {p5} [pInst] pointer to p5 instance - * @param {HTMLCanvasElement} [canvas] existing html canvas element + * @param {Number} width width of the graphics buffer in pixels. + * @param {Number} height height of the graphics buffer in pixels. + * @param {Constant} renderer renderer to use, either P2D or WEBGL. + * @param {p5} [pInst] sketch instance. + * @param {HTMLCanvasElement} [canvas] existing `<canvas>` element to use. + * + * @example + *
+ * + * let pg; + * + * function setup() { + * createCanvas(100, 100); + * + * // Create a p5.Graphics object. + * pg = createGraphics(50, 50); + * + * // Draw to the p5.Graphics object. + * pg.background(100); + * pg.circle(25, 25, 20); + * + * describe('A dark gray square with a white circle at its center drawn on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Display the p5.Graphics object. + * image(pg, 25, 25); + * } + * + *
+ * + *
+ * + * // Click the canvas to display the graphics buffer. + * + * let pg; + * + * function setup() { + * createCanvas(100, 100); + * + * // Create a p5.Graphics object. + * pg = createGraphics(50, 50); + * + * describe('A square appears on a gray background when the user presses the mouse. The square cycles between white and black.'); + * } + * + * function draw() { + * background(200); + * + * // Calculate the background color. + * let bg = frameCount % 255; + * + * // Draw to the p5.Graphics object. + * pg.background(bg); + * + * // Display the p5.Graphics object while + * // the user presses the mouse. + * if (mouseIsPressed === true) { + * image(pg, 25, 25); + * } + * } + * + *
*/ _main.default.Graphics = /*#__PURE__*/ function (_p5$Element) { @@ -65395,6 +67942,11 @@ _this._pixelDensity = pInst._pixelDensity; if (r === constants.WEBGL) { _this._renderer = new _main.default.RendererGL(_this.canvas, _assertThisInitialized(_this), false); + var _this$_renderer$_adju = _this._renderer._adjustDimensions(w, h), + adjustedWidth = _this$_renderer$_adju.adjustedWidth, + adjustedHeight = _this$_renderer$_adju.adjustedHeight; + w = adjustedWidth; + h = adjustedHeight; } else { _this._renderer = new _main.default.Renderer2D(_this.canvas, _assertThisInitialized(_this), false); } @@ -65408,49 +67960,164 @@ _this._renderer._applyDefaults(); return _possibleConstructorReturn(_this, _assertThisInitialized(_this)); } /** - * Resets certain values such as those modified by functions in the Transform category - * and in the Lights category that are not automatically reset - * with graphics buffer objects. Calling this in draw() will copy the behavior - * of the standard canvas. + * Resets the graphics buffer's transformations and lighting. + * + * By default, the main canvas resets certain transformation and lighting + * values each time draw() executes. `p5.Graphics` + * objects must reset these values manually by calling `myGraphics.reset()`. * * @method reset - * @example * - *
+ * @example + *
+ * * let pg; + * * function setup() { * createCanvas(100, 100); - * background(0); - * pg = createGraphics(50, 100); - * pg.fill(0); - * frameRate(5); + * + * // Create a p5.Graphics object. + * pg = createGraphics(60, 60); + * + * describe('A white circle moves downward slowly within a dark square. The circle resets at the top of the dark square when the user presses the mouse.'); * } * * function draw() { - * image(pg, width / 2, 0); - * pg.background(255); - * // p5.Graphics object behave a bit differently in some cases - * // The normal canvas on the left resets the translate - * // with every loop through draw() - * // the graphics object on the right doesn't automatically reset - * // so translate() is additive and it moves down the screen - * rect(0, 0, width / 2, 5); - * pg.rect(0, 0, width / 2, 5); - * translate(0, 5, 0); - * pg.translate(0, 5, 0); + * background(200); + * + * // Translate the p5.Graphics object's coordinate system. + * // The translation accumulates; the white circle moves. + * pg.translate(0, 0.1); + * + * // Draw to the p5.Graphics object. + * pg.background(100); + * pg.circle(30, 0, 10); + * + * // Display the p5.Graphics object. + * image(pg, 20, 20); + * + * // Translate the main canvas' coordinate system. + * // The translation doesn't accumulate; the dark + * // square is always in the same place. + * translate(0, 0.1); + * + * // Reset the p5.Graphics object when the + * // user presses the mouse. + * if (mouseIsPressed === true) { + * pg.reset(); + * } + * } + * + *
+ * + *
+ * + * let pg; + * + * function setup() { + * createCanvas(100, 100); + * + * // Create a p5.Graphics object. + * pg = createGraphics(60, 60); + * + * describe('A white circle at the center of a dark gray square. The image is drawn on a light gray background.'); * } - * function mouseClicked() { - * // if you click you will see that - * // reset() resets the translate back to the initial state - * // of the Graphics object + * + * function draw() { + * background(200); + * + * // Translate the p5.Graphics object's coordinate system. + * pg.translate(30, 30); + * + * // Draw to the p5.Graphics object. + * pg.background(100); + * pg.circle(0, 0, 10); + * + * // Display the p5.Graphics object. + * image(pg, 20, 20); + * + * // Reset the p5.Graphics object automatically. * pg.reset(); * } - *
+ *
+ *
+ * + *
+ * + * let pg; + * + * function setup() { + * createCanvas(100, 100); + * + * // Create a p5.Graphics object using WebGL mode. + * pg = createGraphics(100, 100, WEBGL); + * + * describe("A sphere lit from above with a red light. The sphere's surface becomes glossy while the user clicks and holds the mouse."); + * } + * + * function draw() { + * background(200); + * + * // Add a red point light from the top-right. + * pg.pointLight(255, 0, 0, 50, -100, 50); + * + * // Style the sphere. + * // It should appear glossy when the + * // lighting values are reset. + * pg.noStroke(); + * pg.specularMaterial(255); + * pg.shininess(100); + * + * // Draw the sphere. + * pg.sphere(30); + * + * // Display the p5.Graphics object. + * image(pg, -50, -50); + * + * // Reset the p5.Graphics object when + * // the user presses the mouse. + * if (mouseIsPressed === true) { + * pg.reset(); + * } + * } + * + *
+ * + *
+ * + * let pg; + * + * function setup() { + * createCanvas(100, 100); + * + * // Create a p5.Graphics object using WebGL mode. + * pg = createGraphics(100, 100, WEBGL); + * + * describe('A sphere with a glossy surface is lit from the top-right by a red light.'); + * } + * + * function draw() { + * background(200); + * + * // Add a red point light from the top-right. + * pg.pointLight(255, 0, 0, 50, -100, 50); + * + * // Style the sphere. + * pg.noStroke(); + * pg.specularMaterial(255); + * pg.shininess(100); + * + * // Draw the sphere. + * pg.sphere(30); * - * @alt - * A white line on a black background stays still on the top-left half. - * A black line animates from top to bottom on a white background on the right half. - * When clicked, the black line starts back over at the top. + * // Display the p5.Graphics object. + * image(pg, 0, 0); + * + * // Reset the p5.Graphics object automatically. + * pg.reset(); + * } + * + *
*/ _createClass(_class, [ @@ -65462,58 +68129,66 @@ this._renderer._update(); } } /** - * Removes a Graphics object from the page and frees any resources - * associated with it. + * Removes the graphics buffer from the web page. + * + * Calling `myGraphics.remove()` removes the graphics buffer's + * `<canvas>` element from the web page. The graphics buffer also uses + * a bit of memory on the CPU that can be freed like so: + * + * ```js + * // Remove the graphics buffer from the web page. + * myGraphics.remove(); + * + * // Delete the graphics buffer from CPU memory. + * myGraphics = undefined; + * ``` + * + * Note: All variables that reference the graphics buffer must be assigned + * the value `undefined` to delete the graphics buffer from CPU memory. If any + * variable still refers to the graphics buffer, then it won't be garbage + * collected. * * @method remove * * @example - *
- * let bg; - * function setup() { - * bg = createCanvas(100, 100); - * bg.background(0); - * image(bg, 0, 0); - * bg.remove(); - * } - *
+ *
+ * + * // Double-click to remove the p5.Graphics object. + * + * let pg; * - *
- * let bg; * function setup() { - * pixelDensity(1); * createCanvas(100, 100); - * stroke(255); - * fill(0); * - * // create and draw the background image - * bg = createGraphics(100, 100); - * bg.background(200); - * bg.ellipse(50, 50, 80, 80); + * // Create a p5.Graphics object. + * pg = createGraphics(60, 60); + * + * // Draw to the p5.Graphics object. + * pg.background(100); + * pg.circle(30, 30, 20); + * + * describe('A white circle at the center of a dark gray square disappears when the user double-clicks.'); * } + * * function draw() { - * let t = millis() / 1000; - * // draw the background - * if (bg) { - * image(bg, frameCount % 100, 0); - * image(bg, frameCount % 100 - 100, 0); - * } - * // draw the foreground - * let p = p5.Vector.fromAngle(t, 35).add(50, 50); - * ellipse(p.x, p.y, 30); - * } - * function mouseClicked() { - * // remove the background - * if (bg) { - * bg.remove(); - * bg = null; + * background(200); + * + * // Display the p5.Graphics object if + * // it's available. + * if (pg) { + * image(pg, 20, 20); * } * } - *
* - * @alt - * no image - * a multi-colored circle moving back and forth over a scrolling background. + * // Remove the p5.Graphics object when the + * // the user double-clicks. + * function doubleClicked() { + * // Remove the p5.Graphics object from the web page. + * pg.remove(); + * pg = undefined; + * } + *
+ *
*/ }, @@ -65530,14 +68205,250 @@ for (var elt_ev in this._events) { this.elt.removeEventListener(elt_ev, this._events[elt_ev]); } + this._renderer = undefined; + this.canvas = undefined; + this.elt = undefined; } /** - * Creates and returns a new p5.Framebuffer - * inside a p5.Graphics WebGL context. - * - * This takes the same parameters as the global - * createFramebuffer function. + * Creates a new p5.Framebuffer object with + * the same WebGL context as the graphics buffer. + * + * p5.Framebuffer objects are separate drawing + * surfaces that can be used as textures in WebGL mode. They're similar to + * p5.Graphics objects and generally run much + * faster when used as textures. Creating a + * p5.Framebuffer object in the same context + * as the graphics buffer makes this speedup possible. + * + * The parameter, `options`, is optional. An object can be passed to configure + * the p5.Framebuffer object. The available + * properties are: + * + * - `format`: data format of the texture, either `UNSIGNED_BYTE`, `FLOAT`, or `HALF_FLOAT`. Default is `UNSIGNED_BYTE`. + * - `channels`: whether to store `RGB` or `RGBA` color channels. Default is to match the graphics buffer which is `RGBA`. + * - `depth`: whether to include a depth buffer. Default is `true`. + * - `depthFormat`: data format of depth information, either `UNSIGNED_INT` or `FLOAT`. Default is `FLOAT`. + * - `stencil`: whether to include a stencil buffer for masking. `depth` must be `true` for this feature to work. Defaults to the value of `depth` which is `true`. + * - `antialias`: whether to perform anti-aliasing. If set to `true`, as in `{ antialias: true }`, 2 samples will be used by default. The number of samples can also be set, as in `{ antialias: 4 }`. Default is to match setAttributes() which is `false` (`true` in Safari). + * - `width`: width of the p5.Framebuffer object. Default is to always match the graphics buffer width. + * - `height`: height of the p5.Framebuffer object. Default is to always match the graphics buffer height. + * - `density`: pixel density of the p5.Framebuffer object. Default is to always match the graphics buffer pixel density. + * - `textureFiltering`: how to read values from the p5.Framebuffer object. Either `LINEAR` (nearby pixels will be interpolated) or `NEAREST` (no interpolation). Generally, use `LINEAR` when using the texture as an image and `NEAREST` if reading the texture as data. Default is `LINEAR`. + * + * If the `width`, `height`, or `density` attributes are set, they won't + * automatically match the graphics buffer and must be changed manually. * * @method createFramebuffer + * @param {Object} [options] configuration options. + * @return {p5.Framebuffer} new framebuffer. + * + * @example + *
+ * + * // Click and hold a mouse button to change shapes. + * + * let pg; + * let torusLayer; + * let boxLayer; + * + * function setup() { + * createCanvas(100, 100); + * + * // Create a p5.Graphics object using WebGL mode. + * pg = createGraphics(100, 100, WEBGL); + * + * // Create the p5.Framebuffer objects. + * torusLayer = pg.createFramebuffer(); + * boxLayer = pg.createFramebuffer(); + * + * describe('A grid of white toruses rotating against a dark gray background. The shapes become boxes while the user holds a mouse button.'); + * } + * + * function draw() { + * // Update and draw the layers offscreen. + * drawTorus(); + * drawBox(); + * + * // Choose the layer to display. + * let layer; + * if (mouseIsPressed === true) { + * layer = boxLayer; + * } else { + * layer = torusLayer; + * } + * + * // Draw to the p5.Graphics object. + * pg.background(50); + * + * // Iterate from left to right. + * for (let x = -50; x < 50; x += 25) { + * // Iterate from top to bottom. + * for (let y = -50; y < 50; y += 25) { + * // Draw the layer to the p5.Graphics object + * pg.image(layer, x, y, 25, 25); + * } + * } + * + * // Display the p5.Graphics object. + * image(pg, 0, 0); + * } + * + * // Update and draw the torus layer offscreen. + * function drawTorus() { + * // Start drawing to the torus p5.Framebuffer. + * torusLayer.begin(); + * + * // Clear the drawing surface. + * pg.clear(); + * + * // Turn on the lights. + * pg.lights(); + * + * // Rotate the coordinate system. + * pg.rotateX(frameCount * 0.01); + * pg.rotateY(frameCount * 0.01); + * + * // Style the torus. + * pg.noStroke(); + * + * // Draw the torus. + * pg.torus(20); + * + * // Start drawing to the torus p5.Framebuffer. + * torusLayer.end(); + * } + * + * // Update and draw the box layer offscreen. + * function drawBox() { + * // Start drawing to the box p5.Framebuffer. + * boxLayer.begin(); + * + * // Clear the drawing surface. + * pg.clear(); + * + * // Turn on the lights. + * pg.lights(); + * + * // Rotate the coordinate system. + * pg.rotateX(frameCount * 0.01); + * pg.rotateY(frameCount * 0.01); + * + * // Style the box. + * pg.noStroke(); + * + * // Draw the box. + * pg.box(30); + * + * // Start drawing to the box p5.Framebuffer. + * boxLayer.end(); + * } + * + *
+ * + *
+ * + * // Click and hold a mouse button to change shapes. + * + * let pg; + * let torusLayer; + * let boxLayer; + * + * function setup() { + * createCanvas(100, 100); + * + * // Create an options object. + * let options = { width: 25, height: 25 }; + * + * // Create a p5.Graphics object using WebGL mode. + * pg = createGraphics(100, 100, WEBGL); + * + * // Create the p5.Framebuffer objects. + * // Use options for configuration. + * torusLayer = pg.createFramebuffer(options); + * boxLayer = pg.createFramebuffer(options); + * + * describe('A grid of white toruses rotating against a dark gray background. The shapes become boxes while the user holds a mouse button.'); + * } + * + * function draw() { + * // Update and draw the layers offscreen. + * drawTorus(); + * drawBox(); + * + * // Choose the layer to display. + * let layer; + * if (mouseIsPressed === true) { + * layer = boxLayer; + * } else { + * layer = torusLayer; + * } + * + * // Draw to the p5.Graphics object. + * pg.background(50); + * + * // Iterate from left to right. + * for (let x = -50; x < 50; x += 25) { + * // Iterate from top to bottom. + * for (let y = -50; y < 50; y += 25) { + * // Draw the layer to the p5.Graphics object + * pg.image(layer, x, y); + * } + * } + * + * // Display the p5.Graphics object. + * image(pg, 0, 0); + * } + * + * // Update and draw the torus layer offscreen. + * function drawTorus() { + * // Start drawing to the torus p5.Framebuffer. + * torusLayer.begin(); + * + * // Clear the drawing surface. + * pg.clear(); + * + * // Turn on the lights. + * pg.lights(); + * + * // Rotate the coordinate system. + * pg.rotateX(frameCount * 0.01); + * pg.rotateY(frameCount * 0.01); + * + * // Style the torus. + * pg.noStroke(); + * + * // Draw the torus. + * pg.torus(5, 2.5); + * + * // Start drawing to the torus p5.Framebuffer. + * torusLayer.end(); + * } + * + * // Update and draw the box layer offscreen. + * function drawBox() { + * // Start drawing to the box p5.Framebuffer. + * boxLayer.begin(); + * + * // Clear the drawing surface. + * pg.clear(); + * + * // Turn on the lights. + * pg.lights(); + * + * // Rotate the coordinate system. + * pg.rotateX(frameCount * 0.01); + * pg.rotateY(frameCount * 0.01); + * + * // Style the box. + * pg.noStroke(); + * + * // Draw the box. + * pg.box(7.5); + * + * // Start drawing to the box p5.Framebuffer. + * boxLayer.end(); + * } + * + *
*/ }, @@ -65554,25 +68465,25 @@ exports.default = _default; }, { - './constants': 286, - './main': 298, - 'core-js/modules/es.array.index-of': 178, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.splice': 185, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.get-prototype-of': 198, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.reflect.construct': 202, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256 + './constants': 294, + './main': 306, + 'core-js/modules/es.array.index-of': 182, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.splice': 189, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.get-prototype-of': 206, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.reflect.construct': 210, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 301: [ + 309: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -66277,29 +69188,29 @@ exports.default = _default; }, { - '../core/constants': 286, - './main': 298, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.number.constructor': 191, - 'core-js/modules/es.object.assign': 194, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.get-prototype-of': 198, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.reflect.construct': 202, - 'core-js/modules/es.regexp.exec': 205, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.string.replace': 214, - 'core-js/modules/es.string.split': 216, - 'core-js/modules/es.string.trim': 219, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/constants': 294, + './main': 306, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.number.constructor': 197, + 'core-js/modules/es.object.assign': 201, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.get-prototype-of': 206, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.reflect.construct': 210, + 'core-js/modules/es.regexp.exec': 213, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.string.replace': 222, + 'core-js/modules/es.string.split': 224, + 'core-js/modules/es.string.trim': 227, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 302: [ + 310: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -66318,6 +69229,7 @@ _dereq_('core-js/modules/es.object.to-string'); _dereq_('core-js/modules/es.reflect.construct'); _dereq_('core-js/modules/es.reflect.get'); + _dereq_('core-js/modules/es.regexp.exec'); _dereq_('core-js/modules/es.regexp.to-string'); _dereq_('core-js/modules/es.string.iterator'); _dereq_('core-js/modules/es.weak-map'); @@ -66355,6 +69267,7 @@ _dereq_('core-js/modules/es.number.to-fixed'); _dereq_('core-js/modules/es.object.get-prototype-of'); _dereq_('core-js/modules/es.object.to-string'); + _dereq_('core-js/modules/es.regexp.exec'); _dereq_('core-js/modules/es.regexp.to-string'); Object.defineProperty(exports, '__esModule', { value: true @@ -66897,7 +69810,7 @@ a = 0; var idx = 4 * (y * pixelsState._pixelDensity * (this.width * pixelsState._pixelDensity) + x * pixelsState._pixelDensity); if (!pixelsState.imageData) { - pixelsState.loadPixels.call(pixelsState); + pixelsState.loadPixels(); } if (typeof imgOrCol === 'number') { if (idx < pixelsState.pixels.length) { @@ -66907,7 +69820,7 @@ a = 255; //this.updatePixels.call(this); } - } else if (imgOrCol instanceof Array) { + } else if (Array.isArray(imgOrCol)) { if (imgOrCol.length < 4) { throw new Error('pixel array must be of the form [R, G, B, A]'); } @@ -67082,24 +69995,12 @@ return this; } } - var kappa = 0.5522847498, - // control point offset horizontal - ox = w / 2 * kappa, - // control point offset vertical - oy = h / 2 * kappa, - // x-end - xe = x + w, - // y-end - ye = y + h, - // x-middle - xm = x + w / 2, - ym = y + h / 2; // y-middle + var centerX = x + w / 2, + centerY = y + h / 2, + radiusX = w / 2, + radiusY = h / 2; if (!this._clipping) ctx.beginPath(); - ctx.moveTo(x, ym); - ctx.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); - ctx.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); - ctx.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); - ctx.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); + ctx.ellipse(centerX, centerY, radiusX, radiusY, 0, 0, 2 * Math.PI); if (!this._clipping && doFill) { ctx.fill(); } @@ -67738,7 +70639,12 @@ font = this._textFont.font.familyName; this._setProperty('_textStyle', this._textFont.font.styleName); } - this.drawingContext.font = ''.concat(this._textStyle || 'normal', ' ').concat(this._textSize || 12, 'px ').concat(font || 'sans-serif'); + var fontNameString = font || 'sans-serif'; + if (/\s/.exec(fontNameString)) { + // If the name includes spaces, surround in quotes + fontNameString = '"'.concat(fontNameString, '"'); + } + this.drawingContext.font = ''.concat(this._textStyle || 'normal', ' ').concat(this._textSize || 12, 'px ').concat(fontNameString); this.drawingContext.textAlign = this._textAlign; if (this._textBaseline === constants.CENTER) { this.drawingContext.textBaseline = constants._CTX_MIDDLE; @@ -67804,32 +70710,33 @@ exports.default = _default; }, { - './constants': 286, - './main': 298, - './p5.Renderer': 301, - 'core-js/modules/es.array.concat': 169, - 'core-js/modules/es.array.fill': 172, - 'core-js/modules/es.array.for-each': 175, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.join': 180, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.function.name': 186, - 'core-js/modules/es.number.to-fixed': 193, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.get-prototype-of': 198, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.reflect.construct': 202, - 'core-js/modules/es.reflect.get': 203, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256 + './constants': 294, + './main': 306, + './p5.Renderer': 309, + 'core-js/modules/es.array.concat': 171, + 'core-js/modules/es.array.fill': 174, + 'core-js/modules/es.array.for-each': 179, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.join': 184, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.function.name': 192, + 'core-js/modules/es.number.to-fixed': 200, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.get-prototype-of': 206, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.reflect.construct': 210, + 'core-js/modules/es.reflect.get': 211, + 'core-js/modules/es.regexp.exec': 213, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 303: [ + 311: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -68004,19 +70911,19 @@ }; }, { - './main': 298, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.object.assign': 194, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.promise': 201, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/web.dom-collections.iterator': 256 + './main': 306, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.object.assign': 201, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.promise': 209, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 304: [ + 312: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -68125,60 +71032,115 @@ var defaultId = 'defaultCanvas0'; // this gets set again in createCanvas var defaultClass = 'p5Canvas'; /** - * Creates a canvas element in the document and sets its dimensions - * in pixels. This method should be called only once at the start of setup(). - * Calling createCanvas more than once in a - * sketch will result in very unpredictable behavior. If you want more than - * one drawing canvas you could use createGraphics() - * (hidden by default but it can be shown). + * Creates a canvas element on the web page. * - * Important note: in 2D mode (i.e. when `p5.Renderer` is not set) the origin (0,0) - * is positioned at the top left of the screen. In 3D mode (i.e. when `p5.Renderer` - * is set to `WEBGL`), the origin is positioned at the center of the canvas. - * See [this issue](https://github.com/processing/p5.js/issues/1545) for more information. + * `createCanvas()` creates the main drawing canvas for a sketch. It should + * only be called once at the beginning of setup(). + * Calling `createCanvas()` more than once causes unpredictable behavior. * - * A WebGL canvas will use a WebGL2 context if it is supported by the browser. - * Check the webglVersion property to check what - * version is being used, or call setAttributes({ version: 1 }) - * to create a WebGL1 context. + * The first two parameters, `width` and `height`, are optional. They set the + * dimensions of the canvas and the values of the + * width and height system + * variables. For example, calling `createCanvas(900, 500)` creates a canvas + * that's 900×500 pixels. By default, `width` and `height` are both 100. * - * The system variables width and height are set by the parameters passed to this - * function. If createCanvas() is not used, the - * window will be given a default size of 100×100 pixels. + * The third parameter is also optional. If either of the constants `P2D` or + * `WEBGL` is passed, as in `createCanvas(900, 500, WEBGL)`, then it will set + * the sketch's rendering mode. If an existing + * HTMLCanvasElement + * is passed, as in `createCanvas(900, 500, myCanvas)`, then it will be used + * by the sketch. * - * Optionally, an existing canvas can be passed using a selector, ie. `document.getElementById('')`. - * If specified, avoid using `setAttributes()` afterwards, as this will remove and recreate the existing canvas. + * The fourth parameter is also optional. If an existing + * HTMLCanvasElement + * is passed, as in `createCanvas(900, 500, WEBGL, myCanvas)`, then it will be + * used by the sketch. * - * For more ways to position the canvas, see the - * - * positioning the canvas wiki page. + * Note: In WebGL mode, the canvas will use a WebGL2 context if it's supported + * by the browser. Check the webglVersion + * system variable to check what version is being used, or call + * `setAttributes({ version: 1 })` to create a WebGL1 context. * * @method createCanvas - * @param {Number} w width of the canvas - * @param {Number} h height of the canvas - * @param {Constant} [renderer] either P2D or WEBGL - * @param {HTMLCanvasElement} [canvas] existing html canvas element - * @return {p5.Renderer} pointer to p5.Renderer holding canvas + * @param {Number} [width] width of the canvas. Defaults to 100. + * @param {Number} [height] height of the canvas. Defaults to 100. + * @param {Constant} [renderer] either P2D or WEBGL. Defaults to `P2D`. + * @param {HTMLCanvasElement} [canvas] existing canvas element that should be used for the sketch. + * @return {p5.Renderer} new `p5.Renderer` that holds the canvas. + * * @example *
* * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Draw a diagonal line. + * line(0, 0, width, height); + * + * describe('A diagonal line drawn from top-left to bottom-right on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { * createCanvas(100, 50); - * background(153); + * + * background(200); + * + * // Draw a diagonal line. * line(0, 0, width, height); + * + * describe('A diagonal line drawn from top-left to bottom-right on a gray background.'); * } * *
* - * @alt - * Black line extending from top-left of canvas to bottom right. + *
+ * + * // Use WebGL mode. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * background(200); + * + * // Draw a diagonal line. + * line(-width / 2, -height / 2, width / 2, height / 2); + * + * describe('A diagonal line drawn from top-left to bottom-right on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * // Create a p5.Render object. + * let cnv = createCanvas(50, 50); + * + * // Position the canvas. + * cnv.position(10, 20); + * + * background(200); + * + * // Draw a diagonal line. + * line(0, 0, width, height); + * + * describe('A diagonal line drawn from top-left to bottom-right on a gray background.'); + * } + * + *
*/ /** * @method createCanvas - * @param {Number} w - * @param {Number} h + * @param {Number} [width] + * @param {Number} [height] * @param {HTMLCanvasElement} [canvas] - * @return {p5.Renderer} pointer to p5.Renderer holding canvas + * @return {p5.Renderer} */ _main.default.prototype.createCanvas = function (w, h, renderer, canvas) { _main.default._validateParameters('createCanvas', arguments); @@ -68254,6 +71216,9 @@ if (r === constants.WEBGL) { this._setProperty('_renderer', new _main.default.RendererGL(c, this, true)); this._elements.push(this._renderer); + var dimensions = this._renderer._adjustDimensions(w, h); + w = dimensions.adjustedWidth; + h = dimensions.adjustedHeight; } else { //P2D mode if (!this._defaultGraphicsCreated) { @@ -68267,30 +71232,89 @@ return this._renderer; }; /** - * Resizes the canvas to given width and height. The canvas will be cleared - * and draw will be called immediately, allowing the sketch to re-render itself - * in the resized canvas. + * Resizes the canvas to a given width and height. + * + * `resizeCanvas()` immediately clears the canvas and calls + * redraw(). It's common to call `resizeCanvas()` + * within the body of windowResized() like + * so: + * + * ```js + * function windowResized() { + * resizeCanvas(windowWidth, windowHeight); + * } + * ``` + * + * The first two parameters, `width` and `height`, set the dimensions of the + * canvas. They also the values of the width and + * height system variables. For example, calling + * `resizeCanvas(300, 500)` resizes the canvas to 300×500 pixels, then sets + * width to 300 and + * height 500. + * + * The third parameter, `noRedraw`, is optional. If `true` is passed, as in + * `resizeCanvas(300, 500, true)`, then the canvas will be canvas to 300×500 + * pixels but the redraw() function won't be called + * immediately. By default, redraw() is called + * immediately when `resizeCanvas()` finishes executing. + * * @method resizeCanvas - * @param {Number} w width of the canvas - * @param {Number} h height of the canvas - * @param {Boolean} [noRedraw] don't redraw the canvas immediately + * @param {Number} width width of the canvas. + * @param {Number} height height of the canvas. + * @param {Boolean} [noRedraw] whether to delay calling + * redraw(). Defaults + * to `false`. + * * @example - *
+ *
+ * + * // Double-click to resize the canvas. + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A white circle drawn on a gray background. The canvas shrinks by half the first time the user double-clicks.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Draw a circle at the center of the canvas. + * circle(width / 2, height / 2, 20); + * } + * + * // Resize the canvas when the user double-clicks. + * function doubleClicked() { + * resizeCanvas(50, 50); + * } + * + *
+ * + *
+ * + * // Resize the web browser to change the canvas size. + * * function setup() { * createCanvas(windowWidth, windowHeight); + * + * describe('A white circle drawn on a gray background.'); * } * * function draw() { - * background(0, 100, 200); + * background(200); + * + * // Draw a circle at the center of the canvas. + * circle(width / 2, height / 2, 20); * } * + * // Always resize the canvas to fill the browser window. * function windowResized() { * resizeCanvas(windowWidth, windowHeight); * } - *
- * - * @alt - * No image displayed. + *
+ *
*/ _main.default.prototype.resizeCanvas = function (w, h, noRedraw) { _main.default._validateParameters('resizeCanvas', arguments); @@ -68304,6 +71328,11 @@ props[key] = val; } } + if (this._renderer instanceof _main.default.RendererGL) { + var dimensions = this._renderer._adjustDimensions(w, h); + w = dimensions.adjustedWidth; + h = dimensions.adjustedHeight; + } this.width = w; this.height = h; // Make sure width and height are updated before the renderer resizes so @@ -68327,8 +71356,14 @@ } }; /** - * Removes the default canvas for a p5 sketch that doesn't require a canvas + * Removes the default canvas. + * + * By default, a 100×100 pixels canvas is created without needing to call + * createCanvas(). `noCanvas()` removes the + * default canvas for sketches that don't need it. + * * @method noCanvas + * * @example *
* @@ -68337,9 +71372,6 @@ * } * *
- * - * @alt - * no image displayed */ _main.default.prototype.noCanvas = function () { if (this.canvas) { @@ -68347,54 +71379,116 @@ } }; /** - * Creates and returns a new p5.Graphics object. Use this class if you need - * to draw into an off-screen graphics buffer. The two parameters define the - * width and height in pixels. + * Creates a p5.Graphics object. + * + * `createGraphics()` creates an offscreen drawing canvas (graphics buffer) + * and returns it as a p5.Graphics object. Drawing + * to a separate graphics buffer can be helpful for performance and for + * organizing code. * - * A WebGL p5.Graphics will use a WebGL2 context if it is supported by the browser. - * Check the pg.webglVersion property of the renderer - * to check what version is being used, or call pg.setAttributes({ version: 1 }) - * to create a WebGL1 context. + * The first two parameters, `width` and `height`, are optional. They set the + * dimensions of the p5.Graphics object. For + * example, calling `createGraphics(900, 500)` creates a graphics buffer + * that's 900×500 pixels. * - * Optionally, an existing canvas can be passed using a selector, ie. document.getElementById(''). - * By default this canvas will be hidden (offscreen buffer), to make visible, set element's style to display:block; + * The third parameter is also optional. If either of the constants `P2D` or + * `WEBGL` is passed, as in `createGraphics(900, 500, WEBGL)`, then it will set + * the p5.Graphics object's rendering mode. If an + * existing + * HTMLCanvasElement + * is passed, as in `createGraphics(900, 500, myCanvas)`, then it will be used + * by the graphics buffer. + * + * The fourth parameter is also optional. If an existing + * HTMLCanvasElement + * is passed, as in `createGraphics(900, 500, WEBGL, myCanvas)`, then it will be + * used by the graphics buffer. + * + * Note: In WebGL mode, the p5.Graphics object + * will use a WebGL2 context if it's supported by the browser. Check the + * webglVersion system variable to check what + * version is being used, or call `setAttributes({ version: 1 })` to create a + * WebGL1 context. * * @method createGraphics - * @param {Number} w width of the offscreen graphics buffer - * @param {Number} h height of the offscreen graphics buffer - * @param {Constant} [renderer] either P2D or WEBGL - * undefined defaults to p2d - * @param {HTMLCanvasElement} [canvas] existing html canvas element - * @return {p5.Graphics} offscreen graphics buffer + * @param {Number} width width of the graphics buffer. + * @param {Number} height height of the graphics buffer. + * @param {Constant} [renderer] either P2D or WEBGL. Defaults to P2D. + * @param {HTMLCanvasElement} [canvas] existing canvas element that should be + * used for the graphics buffer.. + * @return {p5.Graphics} new graphics buffer. + * * @example *
* + * // Double-click to draw the contents of the graphics buffer. + * * let pg; + * * function setup() { * createCanvas(100, 100); - * pg = createGraphics(100, 100); + * + * background(200); + * + * // Create the p5.Graphics object. + * pg = createGraphics(50, 50); + * + * // Draw to the graphics buffer. + * pg.background(100); + * pg.circle(pg.width / 2, pg.height / 2, 20); + * + * describe('A gray square. A smaller, darker square with a white circle at its center appears when the user double-clicks.'); * } * - * function draw() { + * // Display the graphics buffer when the user double-clicks. + * function doubleClicked() { + * if (mouseX > 0 && mouseX < 100 && mouseY > 0 && mouseY < 100) { + * image(pg, 25, 25); + * } + * } + * + *
+ * + *
+ * + * // Double-click to draw the contents of the graphics buffer. + * + * let pg; + * + * function setup() { + * createCanvas(100, 100); + * * background(200); + * + * // Create the p5.Graphics object in WebGL mode. + * pg = createGraphics(50, 50, WEBGL); + * + * // Draw to the graphics buffer. * pg.background(100); + * pg.lights(); * pg.noStroke(); - * pg.ellipse(pg.width / 2, pg.height / 2, 50, 50); - * image(pg, 50, 50); - * image(pg, 0, 0, 50, 50); + * pg.rotateX(QUARTER_PI); + * pg.rotateY(QUARTER_PI); + * pg.torus(15, 5); + * + * describe('A gray square. A smaller, darker square with a white torus at its center appears when the user double-clicks.'); + * } + * + * // Display the graphics buffer when the user double-clicks. + * function doubleClicked() { + * if (mouseX > 0 && mouseX < 100 && mouseY > 0 && mouseY < 100) { + * image(pg, 25, 25); + * } * } * *
- * - * @alt - * 4 grey squares alternating light and dark grey. White quarter circle mid-left. */ /** * @method createGraphics - * @param {Number} w - * @param {Number} h + * @param {Number} width + * @param {Number} height * @param {HTMLCanvasElement} [canvas] - * @return {p5.Graphics} offscreen graphics buffer + * @return {p5.Graphics} */ _main.default.prototype.createGraphics = function (w, h) { for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { @@ -68412,151 +71506,691 @@ return new _main.default.Graphics(w, h, args[0], this, args[1]); }; /** - * Creates and returns a new p5.Framebuffer, a - * high-performance WebGL object that you can draw to and then use as a texture. + * Creates and a new p5.Framebuffer object. + * + * p5.Framebuffer objects are separate drawing + * surfaces that can be used as textures in WebGL mode. They're similar to + * p5.Graphics objects and generally run much + * faster when used as textures. + * + * The parameter, `options`, is optional. An object can be passed to configure + * the p5.Framebuffer object. The available + * properties are: * - * Options can include: - * - `format`: The data format of the texture, either `UNSIGNED_BYTE`, `FLOAT`, or `HALF_FLOAT`. The default is `UNSIGNED_BYTE`. - * - `channels`: What color channels to store, either `RGB` or `RGBA`. The default is to match the channels in the main canvas (with alpha unless disabled with `setAttributes`.) - * - `depth`: A boolean, whether or not to include a depth buffer. Defaults to true. - * - `depthFormat`: The data format for depth information, either `UNSIGNED_INT` or `FLOAT`. The default is `FLOAT` if available, or `UNSIGNED_INT` otherwise. - * - `stencil`: A boolean, whether or not to include a stencil buffer, which can be used for masking. This may only be used if also using a depth buffer. Defaults to the value of `depth`, which is true if not provided. - * - `antialias`: Boolean or Number, whether or not to render with antialiased edges, and if so, optionally the number of samples to use. Defaults to whether or not the main canvas is antialiased, using a default of 2 samples if so. Antialiasing is only supported when WebGL 2 is available. - * - `width`: The width of the texture. Defaults to matching the main canvas. - * - `height`: The height of the texture. Defaults to matching the main canvas. - * - `density`: The pixel density of the texture. Defaults to the pixel density of the main canvas. - * - `textureFiltering`: Either `LINEAR` (nearby pixels will be interpolated when reading values from the color texture) or `NEAREST` (no interpolation.) Generally, use `LINEAR` when using the texture as an image, and use `NEAREST` if reading the texture as data. Defaults to `LINEAR`. + * - `format`: data format of the texture, either `UNSIGNED_BYTE`, `FLOAT`, or `HALF_FLOAT`. Default is `UNSIGNED_BYTE`. + * - `channels`: whether to store `RGB` or `RGBA` color channels. Default is to match the main canvas which is `RGBA`. + * - `depth`: whether to include a depth buffer. Default is `true`. + * - `depthFormat`: data format of depth information, either `UNSIGNED_INT` or `FLOAT`. Default is `FLOAT`. + * - `stencil`: whether to include a stencil buffer for masking. `depth` must be `true` for this feature to work. Defaults to the value of `depth` which is `true`. + * - `antialias`: whether to perform anti-aliasing. If set to `true`, as in `{ antialias: true }`, 2 samples will be used by default. The number of samples can also be set, as in `{ antialias: 4 }`. Default is to match setAttributes() which is `false` (`true` in Safari). + * - `width`: width of the p5.Framebuffer object. Default is to always match the main canvas width. + * - `height`: height of the p5.Framebuffer object. Default is to always match the main canvas height. + * - `density`: pixel density of the p5.Framebuffer object. Default is to always match the main canvas pixel density. + * - `textureFiltering`: how to read values from the p5.Framebuffer object. Either `LINEAR` (nearby pixels will be interpolated) or `NEAREST` (no interpolation). Generally, use `LINEAR` when using the texture as an image and `NEAREST` if reading the texture as data. Default is `LINEAR`. * - * If `width`, `height`, or `density` are specified, then the framebuffer will - * keep that size until manually changed. Otherwise, it will be autosized, and - * it will update to match the main canvas's size and density when the main - * canvas changes. + * If the `width`, `height`, or `density` attributes are set, they won't automatically match the main canvas and must be changed manually. + * + * Note: `createFramebuffer()` can only be used in WebGL mode. * * @method createFramebuffer - * @param {Object} [options] An optional object with configuration + * @param {Object} [options] configuration options. + * @return {p5.Framebuffer} new framebuffer. * * @example *
* - * let prev, next, cam; + * let myBuffer; + * * function setup() { * createCanvas(100, 100, WEBGL); - * prev = createFramebuffer({ format: FLOAT }); - * next = createFramebuffer({ format: FLOAT }); - * cam = createCamera(); + * + * // Create a p5.Framebuffer object. + * myBuffer = createFramebuffer(); + * + * describe('A grid of white toruses rotating against a dark gray background.'); + * } + * + * function draw() { + * background(50); + * + * // Start drawing to the p5.Framebuffer object. + * myBuffer.begin(); + * + * // Clear the drawing surface. + * clear(); + * + * // Turn on the lights. + * lights(); + * + * // Rotate the coordinate system. + * rotateX(frameCount * 0.01); + * rotateY(frameCount * 0.01); + * + * // Style the torus. + * noStroke(); + * + * // Draw the torus. + * torus(20); + * + * // Stop drawing to the p5.Framebuffer object. + * myBuffer.end(); + * + * // Iterate from left to right. + * for (let x = -50; x < 50; x += 25) { + * // Iterate from top to bottom. + * for (let y = -50; y < 50; y += 25) { + * // Draw the p5.Framebuffer object to the canvas. + * image(myBuffer, x, y, 25, 25); + * } + * } + * } + * + *
+ * + *
+ * + * let myBuffer; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create an options object. + * let options = { width: 25, height: 25 }; + * + * // Create a p5.Framebuffer object. + * // Use options for configuration. + * myBuffer = createFramebuffer(options); + * + * describe('A grid of white toruses rotating against a dark gray background.'); + * } + * + * function draw() { + * background(50); + * + * // Start drawing to the p5.Framebuffer object. + * myBuffer.begin(); + * + * // Clear the drawing surface. + * clear(); + * + * // Turn on the lights. + * lights(); + * + * // Rotate the coordinate system. + * rotateX(frameCount * 0.01); + * rotateY(frameCount * 0.01); + * + * // Style the torus. * noStroke(); + * + * // Draw the torus. + * torus(5, 2.5); + * + * // Stop drawing to the p5.Framebuffer object. + * myBuffer.end(); + * + * // Iterate from left to right. + * for (let x = -50; x < 50; x += 25) { + * // Iterate from top to bottom. + * for (let y = -50; y < 50; y += 25) { + * // Draw the p5.Framebuffer object to the canvas. + * image(myBuffer, x, y); + * } + * } + * } + * + *
+ */ + _main.default.prototype.createFramebuffer = function (options) { + return new _main.default.Framebuffer(this, options); + }; + /** + * Clears the depth buffer in WebGL mode. + * + * `clearDepth()` clears information about how far objects are from the camera + * in 3D space. This information is stored in an object called the + * *depth buffer*. Clearing the depth buffer ensures new objects aren't drawn + * behind old ones. Doing so can be useful for feedback effects in which the + * previous frame serves as the background for the current frame. + * + * The parameter, `depth`, is optional. If a number is passed, as in + * `clearDepth(0.5)`, it determines the range of objects to clear from the + * depth buffer. 0 doesn't clear any depth information, 0.5 clears depth + * information halfway between the near and far clipping planes, and 1 clears + * depth information all the way to the far clipping plane. By default, + * `depth` is 1. + * + * Note: `clearDepth()` can only be used in WebGL mode. + * + * @method clearDepth + * @param {Number} [depth] amount of the depth buffer to clear between 0 + * (none) and 1 (far clipping plane). Defaults to 1. + * + * @example + *
+ * + * let previous; + * let current; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create the p5.Framebuffer objects. + * previous = createFramebuffer({ format: FLOAT }); + * current = createFramebuffer({ format: FLOAT }); + * + * describe( + * 'A multicolor box drifts from side to side on a white background. It leaves a trail that fades over time.' + * ); * } * * function draw() { - * // Swap prev and next so that we can use the previous - * // frame as a texture when drawing the current frame - * [prev, next] = [next, prev]; + * // Swap the previous p5.Framebuffer and the + * // current one so it can be used as a texture. + * [previous, current] = [current, previous]; + * + * // Start drawing to the current p5.Framebuffer. + * current.begin(); * - * // Draw to the framebuffer - * next.begin(); + * // Paint the background. * background(255); * + * // Draw the previous p5.Framebuffer. + * // Clear the depth buffer so the previous + * // frame doesn't block the current one. * push(); - * // Draw the previous texture farther away, but scaled - * // up to fill the screen, plus a bit extra scale so it grows - * translate(0, 0, -200); - * scale(1.001 * (200 + cam.eyeZ) / cam.eyeZ); - * tint(255, 253); - * image(prev, -width/2, -height/2); + * tint(255, 250); + * image(previous, -50, -50); + * clearDepth(); * pop(); * + * // Draw the box on top of the previous frame. * push(); - * normalMaterial(); - * translate(25*sin(frameCount * 0.014), 25*sin(frameCount * 0.02), 0); + * let x = 25 * sin(frameCount * 0.01); + * let y = 25 * sin(frameCount * 0.02); + * translate(x, y, 0); * rotateX(frameCount * 0.01); * rotateY(frameCount * 0.01); + * normalMaterial(); * box(12); * pop(); - * next.end(); * - * image(next, -width/2, -height/2); + * // Stop drawing to the current p5.Framebuffer. + * current.end(); + * + * // Display the current p5.Framebuffer. + * image(current, -50, -50); * } * *
- * - * @alt - * A red, green, and blue box (using normalMaterial) moves and rotates around - * the canvas, leaving a trail behind it that slowly grows and fades away. */ - _main.default.prototype.createFramebuffer = function (options) { - return new _main.default.Framebuffer(this, options); + _main.default.prototype.clearDepth = function (depth) { + this._assert3d('clearDepth'); + this._renderer.clearDepth(depth); }; /** - * Blends the pixels in the display window according to the defined mode. - * There is a choice of the following modes to blend the source pixels (A) - * with the ones of pixels already in the display window (B): - * - * - * (2D) indicates that this blend mode only works in the 2D renderer.
- * (3D) indicates that this blend mode only works in the WEBGL renderer. + * Sets the way colors blend when added to the canvas. + * + * By default, drawing with a solid color paints over the current pixel values + * on the canvas. `blendMode()` offers many options for blending colors. + * + * Shapes, images, and text can be used as sources for drawing to the canvas. + * A source pixel changes the color of the canvas pixel where it's drawn. The + * final color results from blending the source pixel's color with the canvas + * pixel's color. RGB color values from the source and canvas pixels are + * compared, added, subtracted, multiplied, and divided to create different + * effects. Red values with red values, greens with greens, and blues with + * blues. + * + * The parameter, `mode`, sets the blend mode. For example, calling + * `blendMode(ADD)` sets the blend mode to `ADD`. The following blend modes + * are available in both 2D and WebGL mode: + * + * - `BLEND`: color values from the source overwrite the canvas. This is the default mode. + * - `ADD`: color values from the source are added to values from the canvas. + * - `DARKEST`: keeps the darkest color value. + * - `LIGHTEST`: keeps the lightest color value. + * - `EXCLUSION`: similar to `DIFFERENCE` but with less contrast. + * - `MULTIPLY`: color values from the source are multiplied with values from the canvas. The result is always darker. + * - `SCREEN`: all color values are inverted, then multiplied, then inverted again. The result is always lighter. (Opposite of `MULTIPLY`) + * - `REPLACE`: the last source drawn completely replaces the rest of the canvas. + * - `REMOVE`: overlapping pixels are removed by making them completely transparent. + * + * The following blend modes are only available in 2D mode: + * + * - `DIFFERENCE`: color values from the source are subtracted from the values from the canvas. If the difference is a negative number, it's made positive. + * - `OVERLAY`: combines `MULTIPLY` and `SCREEN`. Dark values in the canvas get darker and light values get lighter. + * - `HARD_LIGHT`: combines `MULTIPLY` and `SCREEN`. Dark values in the source get darker and light values get lighter. + * - `SOFT_LIGHT`: a softer version of `HARD_LIGHT`. + * - `DODGE`: lightens light tones and increases contrast. Divides the canvas color values by the inverted color values from the source. + * - `BURN`: darkens dark tones and increases contrast. Divides the source color values by the inverted color values from the canvas, then inverts the result. + * + * The following blend modes are only available in WebGL mode: + * + * - `SUBTRACT`: RGB values from the source are subtracted from the values from the canvas. If the difference is a negative number, it's made positive. Alpha (transparency) values from the source and canvas are added. * * @method blendMode - * @param {Constant} mode blend mode to set for canvas. + * @param {Constant} mode blend mode to set. * either BLEND, DARKEST, LIGHTEST, DIFFERENCE, MULTIPLY, * EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT, * SOFT_LIGHT, DODGE, BURN, ADD, REMOVE or SUBTRACT + * * @example *
* - * blendMode(LIGHTEST); - * strokeWeight(30); - * stroke(80, 150, 255); - * line(25, 25, 75, 75); - * stroke(255, 50, 50); - * line(75, 25, 25, 75); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Use the default blend mode. + * blendMode(BLEND); + * + * // Style the lines. + * strokeWeight(30); + * + * // Draw the blue line. + * stroke('blue'); + * line(25, 25, 75, 75); + * + * // Draw the red line. + * stroke('red'); + * line(75, 25, 25, 75); + * + * describe('A blue line and a red line form an X on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Set the blend mode. + * blendMode(ADD); + * + * // Style the lines. + * strokeWeight(30); + * + * // Draw the blue line. + * stroke('blue'); + * line(25, 25, 75, 75); + * + * // Draw the red line. + * stroke('red'); + * line(75, 25, 25, 75); + * + * describe('A faint blue line and a faint red line form an X on a gray background. The area where they overlap is faint magenta.'); + * } * *
* *
* - * blendMode(MULTIPLY); - * strokeWeight(30); - * stroke(80, 150, 255); - * line(25, 25, 75, 75); - * stroke(255, 50, 50); - * line(75, 25, 25, 75); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Set the blend mode. + * blendMode(DARKEST); + * + * // Style the lines. + * strokeWeight(30); + * + * // Draw the blue line. + * stroke('blue'); + * line(25, 25, 75, 75); + * + * // Draw the red line. + * stroke('red'); + * line(75, 25, 25, 75); + * + * describe('A blue line and a red line form an X on a gray background. The area where they overlap is black.'); + * } * *
* - * @alt - * translucent image thick red & blue diagonal rounded lines intersecting center - * Thick red & blue diagonal rounded lines intersecting center. dark at overlap + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Set the blend mode. + * blendMode(LIGHTEST); + * + * // Style the lines. + * strokeWeight(30); + * + * // Draw the blue line. + * stroke('blue'); + * line(25, 25, 75, 75); + * + * // Draw the red line. + * stroke('red'); + * line(75, 25, 25, 75); + * + * describe('A faint blue line and a faint red line form an X on a gray background. The area where they overlap is faint magenta.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Set the blend mode. + * blendMode(EXCLUSION); + * + * // Style the lines. + * strokeWeight(30); + * + * // Draw the blue line. + * stroke('blue'); + * line(25, 25, 75, 75); + * + * // Draw the red line. + * stroke('red'); + * line(75, 25, 25, 75); + * + * describe('A yellow line and a cyan line form an X on a gray background. The area where they overlap is green.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Set the blend mode. + * blendMode(MULTIPLY); + * + * // Style the lines. + * strokeWeight(30); + * + * // Draw the blue line. + * stroke('blue'); + * line(25, 25, 75, 75); + * + * // Draw the red line. + * stroke('red'); + * line(75, 25, 25, 75); + * + * describe('A blue line and a red line form an X on a gray background. The area where they overlap is black.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Set the blend mode. + * blendMode(SCREEN); + * + * // Style the lines. + * strokeWeight(30); + * + * // Draw the blue line. + * stroke('blue'); + * line(25, 25, 75, 75); + * + * // Draw the red line. + * stroke('red'); + * line(75, 25, 25, 75); + * + * describe('A faint blue line and a faint red line form an X on a gray background. The area where they overlap is faint magenta.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Set the blend mode. + * blendMode(REPLACE); + * + * // Style the lines. + * strokeWeight(30); + * + * // Draw the blue line. + * stroke('blue'); + * line(25, 25, 75, 75); + * + * // Draw the red line. + * stroke('red'); + * line(75, 25, 25, 75); + * + * describe('A diagonal red line.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Set the blend mode. + * blendMode(REMOVE); + * + * // Style the lines. + * strokeWeight(30); + * + * // Draw the blue line. + * stroke('blue'); + * line(25, 25, 75, 75); + * + * // Draw the red line. + * stroke('red'); + * line(75, 25, 25, 75); + * + * describe('The silhouette of an X is missing from a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Set the blend mode. + * blendMode(DIFFERENCE); + * + * // Style the lines. + * strokeWeight(30); + * + * // Draw the blue line. + * stroke('blue'); + * line(25, 25, 75, 75); + * + * // Draw the red line. + * stroke('red'); + * line(75, 25, 25, 75); + * + * describe('A yellow line and a cyan line form an X on a gray background. The area where they overlap is green.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Set the blend mode. + * blendMode(OVERLAY); + * + * // Style the lines. + * strokeWeight(30); + * + * // Draw the blue line. + * stroke('blue'); + * line(25, 25, 75, 75); + * + * // Draw the red line. + * stroke('red'); + * line(75, 25, 25, 75); + * + * describe('A faint blue line and a faint red line form an X on a gray background. The area where they overlap is bright magenta.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Set the blend mode. + * blendMode(HARD_LIGHT); + * + * // Style the lines. + * strokeWeight(30); + * + * // Draw the blue line. + * stroke('blue'); + * line(25, 25, 75, 75); + * + * // Draw the red line. + * stroke('red'); + * line(75, 25, 25, 75); + * + * describe('A blue line and a red line form an X on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Set the blend mode. + * blendMode(SOFT_LIGHT); + * + * // Style the lines. + * strokeWeight(30); + * + * // Draw the blue line. + * stroke('blue'); + * line(25, 25, 75, 75); + * + * // Draw the red line. + * stroke('red'); + * line(75, 25, 25, 75); + * + * describe('A faint blue line and a faint red line form an X on a gray background. The area where they overlap is violet.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Set the blend mode. + * blendMode(DODGE); + * + * // Style the lines. + * strokeWeight(30); + * + * // Draw the blue line. + * stroke('blue'); + * line(25, 25, 75, 75); + * + * // Draw the red line. + * stroke('red'); + * line(75, 25, 25, 75); + * + * describe('A faint blue line and a faint red line form an X on a gray background. The area where they overlap is faint violet.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Set the blend mode. + * blendMode(BURN); + * + * // Style the lines. + * strokeWeight(30); + * + * // Draw the blue line. + * stroke('blue'); + * line(25, 25, 75, 75); + * + * // Draw the red line. + * stroke('red'); + * line(75, 25, 25, 75); + * + * describe('A blue line and a red line form an X on a gray background. The area where they overlap is black.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Set the blend mode. + * blendMode(SUBTRACT); + * + * // Style the lines. + * strokeWeight(30); + * + * // Draw the blue line. + * stroke('blue'); + * line(25, 25, 75, 75); + * + * // Draw the red line. + * stroke('red'); + * line(75, 25, 25, 75); + * + * describe('A yellow line and a turquoise line form an X on a gray background. The area where they overlap is green.'); + * } + * + *
*/ _main.default.prototype.blendMode = function (mode) { _main.default._validateParameters('blendMode', arguments); @@ -68568,54 +72202,84 @@ this._renderer.blendMode(mode); }; /** - * The p5.js API provides a lot of functionality for creating graphics, but there is - * some native HTML5 Canvas functionality that is not exposed by p5. You can still call - * it directly using the variable `drawingContext`, as in the example shown. This is - * the equivalent of calling `canvas.getContext('2d');` or `canvas.getContext('webgl');`. - * See this - * - * reference for the native canvas API for possible drawing functions you can call. + * A system variable that provides direct access to the sketch's + * `<canvas>` element. + * + * The `<canvas>` element provides many specialized features that aren't + * included in the p5.js library. The `drawingContext` system variable + * provides access to these features by exposing the sketch's + * CanvasRenderingContext2D + * object. * * @property drawingContext + * * @example *
* * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the circle using shadows. * drawingContext.shadowOffsetX = 5; * drawingContext.shadowOffsetY = -5; * drawingContext.shadowBlur = 10; * drawingContext.shadowColor = 'black'; - * background(200); - * ellipse(width / 2, height / 2, 50, 50); + * + * // Draw the circle. + * circle(50, 50, 40); + * + * describe("A white circle on a gray background. The circle's edges are shadowy."); * } * *
* - * @alt - * white ellipse with shadow blur effect around edges + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background('skyblue'); + * + * // Style the circle using a color gradient. + * let myGradient = drawingContext.createRadialGradient(50, 50, 3, 50, 50, 40); + * myGradient.addColorStop(0, 'yellow'); + * myGradient.addColorStop(0.6, 'orangered'); + * myGradient.addColorStop(1, 'yellow'); + * drawingContext.fillStyle = myGradient; + * drawingContext.strokeStyle = 'rgba(0, 0, 0, 0)'; + * + * // Draw the circle. + * circle(50, 50, 40); + * + * describe('A fiery sun drawn on a light blue background.'); + * } + * + *
*/ var _default = _main.default; exports.default = _default; }, { - '../webgl/p5.RendererGL': 355, - './constants': 286, - './main': 298, - './p5.Graphics': 300, - './p5.Renderer2D': 302, - 'core-js/modules/es.array.filter': 173, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256 + '../webgl/p5.RendererGL': 364, + './constants': 294, + './main': 306, + './p5.Graphics': 308, + './p5.Renderer2D': 310, + 'core-js/modules/es.array.filter': 175, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 305: [ + 313: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -68807,14 +72471,24 @@ }; }; /** - * Draws an arc to the canvas. Arcs are drawn along the outer edge of an ellipse - * (oval) defined by the `x`, `y`, `w`, and `h` parameters. Use the `start` and `stop` - * parameters to specify the angles (in radians) at which to draw the arc. Arcs are - * always drawn clockwise from `start` to `stop`. The origin of the arc's ellipse may - * be changed with the ellipseMode() function. + * Draws an arc. + * + * An arc is a section of an ellipse defined by the `x`, `y`, `w`, and + * `h` parameters. `x` and `y` set the location of the arc's center. `w` and + * `h` set the arc's width and height. See + * ellipse() and + * ellipseMode() for more details. * - * The optional `mode` parameter determines the arc's fill style. The fill modes are - * a semi-circle (`OPEN`), a closed semi-circle (`CHORD`), or a closed pie segment (`PIE`). + * The fifth and sixth parameters, `start` and `stop`, set the angles + * between which to draw the arc. Arcs are always drawn clockwise from + * `start` to `stop`. Angles are always given in radians. + * + * The seventh parameter, `mode`, is optional. It determines the arc's fill + * style. The fill modes are a semi-circle (`OPEN`), a closed semi-circle + * (`CHORD`), or a closed pie segment (`PIE`). + * + * The eighth parameter, `detail`, is also optional. It determines how many + * vertices are used to draw the arc in WebGL mode. The default value is 25. * * @method arc * @param {Number} x x-coordinate of the arc's ellipse. @@ -68834,71 +72508,203 @@ * @example *
* - * arc(50, 55, 50, 50, 0, HALF_PI); - * noFill(); - * arc(50, 55, 60, 60, HALF_PI, PI); - * arc(50, 55, 70, 70, PI, PI + QUARTER_PI); - * arc(50, 55, 80, 80, PI + QUARTER_PI, TWO_PI); - * describe( - * 'A shattered outline of an ellipse with a quarter of a white circle at the bottom-right.' - * ); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * arc(50, 50, 80, 80, 0, PI + HALF_PI); + * + * describe('A white circle on a gray canvas. The top-right quarter of the circle is missing.'); + * } * *
* + * @example *
* - * arc(50, 50, 80, 80, 0, PI + QUARTER_PI); - * describe('A white ellipse with the top-right third missing. The bottom is outlined in black.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * arc(50, 50, 80, 40, 0, PI + HALF_PI); + * + * describe('A white ellipse on a gray canvas. The top-right quarter of the ellipse is missing.'); + * } * *
* + * @example *
* - * arc(50, 50, 80, 80, 0, PI + QUARTER_PI, OPEN); - * describe( - * 'A white ellipse missing a section from the top-right. The bottom is outlined in black.' - * ); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Bottom-right. + * arc(50, 55, 50, 50, 0, HALF_PI); + * + * noFill(); + * + * // Bottom-left. + * arc(50, 55, 60, 60, HALF_PI, PI); + * + * // Top-left. + * arc(50, 55, 70, 70, PI, PI + QUARTER_PI); + * + * // Top-right. + * arc(50, 55, 80, 80, PI + QUARTER_PI, TWO_PI); + * + * describe( + * 'A shattered outline of an circle with a quarter of a white circle at the bottom-right.' + * ); + * } * *
* *
* - * arc(50, 50, 80, 80, 0, PI + QUARTER_PI, CHORD); - * describe('A white ellipse with a black outline missing a section from the top-right.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Default fill mode. + * arc(50, 50, 80, 80, 0, PI + QUARTER_PI); + * + * describe('A white circle with the top-right third missing. The bottom is outlined in black.'); + * } * *
* *
* - * arc(50, 50, 80, 80, 0, PI + QUARTER_PI, PIE); - * describe('A white ellipse with a black outline. The top-right third is missing.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // OPEN fill mode. + * arc(50, 50, 80, 80, 0, PI + QUARTER_PI, OPEN); + * + * describe( + * 'A white circle missing a section from the top-right. The bottom is outlined in black.' + * ); + * } * *
* - */ - _main.default.prototype.arc = function (x, y, w, h, start, stop, mode, detail) { - _main.default._validateParameters('arc', arguments); - // if the current stroke and fill settings wouldn't result in something - // visible, exit immediately - if (!this._renderer._doStroke && !this._renderer._doFill) { - return this; - } - if (start === stop) { - return this; - } - start = this._toRadians(start); - stop = this._toRadians(stop); - // p5 supports negative width and heights for ellipses - w = Math.abs(w); - h = Math.abs(h); - var vals = _helpers.default.modeAdjust(x, y, w, h, this._renderer._ellipseMode); - var angles = this._normalizeArcAngles(start, stop, vals.w, vals.h, true); - if (angles.correspondToSamePoint) { - // If the arc starts and ends at (near enough) the same place, we choose to - // draw an ellipse instead. This is preferable to faking an ellipse (by - // making stop ever-so-slightly less than start + TWO_PI) because the ends - // join up to each other rather than at a vertex at the centre (leaving - // an unwanted spike in the stroke/fill). + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // CHORD fill mode. + * arc(50, 50, 80, 80, 0, PI + QUARTER_PI, CHORD); + * + * describe('A white circle with a black outline missing a section from the top-right.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // PIE fill mode. + * arc(50, 50, 80, 80, 0, PI + QUARTER_PI, PIE); + * + * describe('A white circle with a black outline. The top-right third is missing.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * background(200); + * + * // PIE fill mode. + * arc(0, 0, 80, 80, 0, PI + QUARTER_PI, PIE); + * + * describe('A white circle with a black outline. The top-right third is missing.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * background(200); + * + * // PIE fill mode with 5 vertices. + * arc(0, 0, 80, 80, 0, PI + QUARTER_PI, PIE, 5); + * + * describe('A white circle with a black outline. The top-right third is missing.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * describe('A yellow circle on a black background. The circle opens and closes its mouth.'); + * } + * + * function draw() { + * background(0); + * + * // Style the arc. + * noStroke(); + * fill(255, 255, 0); + * + * // Update start and stop angles. + * let biteSize = PI / 16; + * let startAngle = biteSize * sin(frameCount * 0.1) + biteSize; + * let endAngle = TWO_PI - startAngle; + * + * // Draw the arc. + * arc(50, 50, 80, 80, startAngle, endAngle, PIE); + * } + * + *
+ */ + _main.default.prototype.arc = function (x, y, w, h, start, stop, mode, detail) { + _main.default._validateParameters('arc', arguments); + // if the current stroke and fill settings wouldn't result in something + // visible, exit immediately + if (!this._renderer._doStroke && !this._renderer._doFill) { + return this; + } + if (start === stop) { + return this; + } + start = this._toRadians(start); + stop = this._toRadians(stop); + // p5 supports negative width and heights for ellipses + w = Math.abs(w); + h = Math.abs(h); + var vals = _helpers.default.modeAdjust(x, y, w, h, this._renderer._ellipseMode); + var angles = this._normalizeArcAngles(start, stop, vals.w, vals.h, true); + if (angles.correspondToSamePoint) { + // If the arc starts and ends at (near enough) the same place, we choose to + // draw an ellipse instead. This is preferable to faking an ellipse (by + // making stop ever-so-slightly less than start + TWO_PI) because the ends + // join up to each other rather than at a vertex at the centre (leaving + // an unwanted spike in the stroke/fill). this._renderer.ellipse([vals.x, vals.y, vals.w, @@ -68924,30 +72730,104 @@ return this; }; /** - * Draws an ellipse (oval) to the canvas. An ellipse with equal width and height - * is a circle. By default, the first two parameters set the location of the - * center of the ellipse. The third and fourth parameters set the shape's width - * and height, respectively. The origin may be changed with the - * ellipseMode() function. + * Draws an ellipse (oval). * - * If no height is specified, the value of width is used for both the width and + * An ellipse is a round shape defined by the `x`, `y`, `w`, and + * `h` parameters. `x` and `y` set the location of its center. `w` and + * `h` set its width and height. See + * ellipseMode() for other ways to set + * its position. + * + * If no height is set, the value of width is used for both the width and * height. If a negative height or width is specified, the absolute value is * taken. * + * The fifth parameter, `detail`, is also optional. It determines how many + * vertices are used to draw the ellipse in WebGL mode. The default value is + * 25. + * * @method ellipse * @param {Number} x x-coordinate of the center of the ellipse. * @param {Number} y y-coordinate of the center of the ellipse. * @param {Number} w width of the ellipse. * @param {Number} [h] height of the ellipse. * @chainable + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * ellipse(50, 50, 80, 80); + * + * describe('A white circle on a gray canvas.'); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * ellipse(50, 50, 80); + * + * describe('A white circle on a gray canvas.'); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * ellipse(50, 50, 80, 40); + * + * describe('A white ellipse on a gray canvas.'); + * } + * + *
+ * * @example *
* - * ellipse(56, 46, 55, 55); - * describe('A white ellipse with black outline in middle of a gray canvas.'); + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * background(200); + * + * ellipse(0, 0, 80, 40); + * + * describe('A white ellipse on a gray canvas.'); + * } * *
* + * @example + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * background(200); + * + * // Use 6 vertices. + * ellipse(0, 0, 80, 40, 6); + * + * describe('A white hexagon on a gray canvas.'); + * } + * + *
*/ /** * @method ellipse @@ -68965,32 +72845,58 @@ return this._renderEllipse.apply(this, arguments); }; /** - * Draws a circle to the canvas. A circle is a round shape. Every point on the - * edge of a circle is the same distance from its center. By default, the first - * two parameters set the location of the center of the circle. The third - * parameter sets the shape's width and height (diameter). The origin may be - * changed with the ellipseMode() function. + * Draws a circle. + * + * A circle is a round shape defined by the `x`, `y`, and `d` parameters. + * `x` and `y` set the location of its center. `d` sets its width and height (diameter). + * Every point on the circle's edge is the same distance, `0.5 * d`, from its center. + * `0.5 * d` (half the diameter) is the circle's radius. + * See ellipseMode() for other ways to set its position. * * @method circle * @param {Number} x x-coordinate of the center of the circle. * @param {Number} y y-coordinate of the center of the circle. * @param {Number} d diameter of the circle. * @chainable + * * @example *
* - * circle(30, 30, 20); - * describe('A white circle with black outline in the middle of a gray canvas.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * circle(50, 50, 25); + * + * describe('A white circle with black outline in the middle of a gray canvas.'); + * } * *
* + * @example + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * background(200); + * + * circle(0, 0, 25); + * + * describe('A white circle with black outline in the middle of a gray canvas.'); + * } + * + *
*/ _main.default.prototype.circle = function () { - _main.default._validateParameters('circle', arguments); - var args = Array.prototype.slice.call(arguments, 0, 2); - args.push(arguments[2]); - args.push(arguments[2]); - return this._renderEllipse.apply(this, _toConsumableArray(args)); + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + _main.default._validateParameters('circle', args); + var argss = args.slice(0, 2); + argss.push(args[2], args[2]); + return this._renderEllipse.apply(this, _toConsumableArray(argss)); }; // internal method for drawing ellipses (without parameter validation) _main.default.prototype._renderEllipse = function (x, y, w, h, detailX) { @@ -69027,15 +72933,17 @@ return this; }; /** - * Draws a line, a straight path between two points. Its default width is one pixel. - * The version of `line()` with four parameters draws the line in 2D. To color a line, - * use the stroke() function. To change its width, use the + * Draws a straight line between two points. + * + * A line's default width is one pixel. The version of `line()` with four + * parameters draws the line in 2D. To color a line, use the + * stroke() function. To change its width, use the * strokeWeight() function. A line - * can't be filled, so the fill() function won't affect - * the color of a line. + * can't be filled, so the fill() function won't + * affect the line's color. * - * The version of `line()` with six parameters allows the line to be drawn in 3D - * space. Doing so requires adding the `WEBGL` argument to + * The version of `line()` with six parameters allows the line to be drawn in + * 3D space. Doing so requires adding the `WEBGL` argument to * createCanvas(). * * @method line @@ -69044,26 +72952,84 @@ * @param {Number} x2 the x-coordinate of the second point. * @param {Number} y2 the y-coordinate of the second point. * @chainable + * * @example *
* - * line(30, 20, 85, 75); - * describe( - * 'A black line on a gray canvas running from top-center to bottom-right.' - * ); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * line(30, 20, 85, 75); + * + * describe( + * 'A black line on a gray canvas running from top-center to bottom-right.' + * ); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the line. + * stroke('magenta'); + * strokeWeight(5); + * + * line(30, 20, 85, 75); + * + * describe( + * 'A thick, magenta line on a gray canvas running from top-center to bottom-right.' + * ); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Top. + * line(30, 20, 85, 20); + * + * // Right. + * stroke(126); + * line(85, 20, 85, 75); + * + * // Bottom. + * stroke(255); + * line(85, 75, 30, 75); + * + * describe( + * 'Three lines drawn in grayscale on a gray canvas. They form the top, right, and bottom sides of a square.' + * ); + * } * *
* + * @example *
* - * line(30, 20, 85, 20); - * stroke(126); - * line(85, 20, 85, 75); - * stroke(255); - * line(85, 75, 30, 75); - * describe( - * 'Three lines drawn in grayscale on a gray canvas. They form the top, right, and bottom sides of a square.' - * ); + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * background(200); + * + * line(-20, -30, 35, 25); + * + * describe( + * 'A black line on a gray canvas running from top-center to bottom-right.' + * ); + * } * *
* @@ -69071,12 +73037,27 @@ * * function setup() { * createCanvas(100, 100, WEBGL); - * describe('A black line drawn on a gray canvas.'); + * + * describe('A black line connecting two spheres. The scene spins slowly.'); * } * * function draw() { - * background(220); - * line(0, 0, 0, 10, 10, 0); + * background(200); + * + * // Rotate around the y-axis. + * rotateY(frameCount * 0.01); + * + * // Draw a line. + * line(0, 0, 0, 30, 20, -10); + * + * // Draw the center sphere. + * sphere(10); + * + * // Translate to the second point. + * translate(30, 20, -10); + * + * // Draw the bottom-right sphere. + * sphere(10); * } * * @@ -69093,8 +73074,8 @@ * @chainable */ _main.default.prototype.line = function () { - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; + for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args[_key2] = arguments[_key2]; } _main.default._validateParameters('line', args); if (this._renderer._doStroke) { @@ -69108,17 +73089,24 @@ return this; }; /** - * Draws a point, a single coordinate in space. Its default size is one pixel. The first two - * parameters are the point's x- and y-coordinates, respectively. To color a point, use - * the stroke() function. To change its size, use the - * strokeWeight() function. + * Draws a single point in space. + * + * A point's default width is one pixel. To color a point, use the + * stroke() function. To change its width, use the + * strokeWeight() function. A point + * can't be filled, so the fill() function won't + * affect the point's color. + * + * The version of `point()` with two parameters allows the point's location to + * be set with its x- and y-coordinates, as in `point(10, 20)`. * - * The version of `point()` with three parameters allows the point to be drawn in 3D - * space. Doing so requires adding the `WEBGL` argument to + * The version of `point()` with three parameters allows the point to be drawn + * in 3D space with x-, y-, and z-coordinates, as in `point(10, 20, 30)`. + * Doing so requires adding the `WEBGL` argument to * createCanvas(). * - * The version of point() with one parameter allows the point's location to be set with - * a p5.Vector object. + * The version of `point()` with one parameter allows the point's location to + * be set with a p5.Vector object. * * @method point * @param {Number} x the x-coordinate. @@ -69128,46 +73116,140 @@ * @example *
* - * point(30, 20); - * point(85, 20); - * point(85, 75); - * point(30, 75); - * describe( - * 'Four small, black points drawn on a gray canvas. The points form the corners of a square.' - * ); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Top-left. + * point(30, 20); + * + * // Top-right. + * point(85, 20); + * + * // Bottom-right. + * point(85, 75); + * + * // Bottom-left. + * point(30, 75); + * + * describe( + * 'Four small, black points drawn on a gray canvas. The points form the corners of a square.' + * ); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Top-left. + * point(30, 20); + * + * // Top-right. + * point(70, 20); + * + * // Style the next points. + * stroke('purple'); + * strokeWeight(10); + * + * // Bottom-right. + * point(70, 80); + * + * // Bottom-left. + * point(30, 80); + * + * describe( + * 'Four points drawn on a gray canvas. Two are black and two are purple. The points form the corners of a square.' + * ); + * } * *
* *
* - * point(30, 20); - * point(85, 20); - * stroke('purple'); - * strokeWeight(10); - * point(85, 75); - * point(30, 75); - * describe( - * 'Four points drawn on a gray canvas. Two are black and two are purple. The points form the corners of a square.' - * ); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Top-left. + * let a = createVector(30, 20); + * point(a); + * + * // Top-right. + * let b = createVector(70, 20); + * point(b); + * + * // Bottom-right. + * let c = createVector(70, 80); + * point(c); + * + * // Bottom-left. + * let d = createVector(30, 80); + * point(d); + * + * describe( + * 'Four small, black points drawn on a gray canvas. The points form the corners of a square.' + * ); + * } * *
* *
* - * let a = createVector(10, 10); - * point(a); - * let b = createVector(10, 20); - * point(b); - * let c = createVector(20, 10); - * point(c); - * let d = createVector(20, 20); - * point(d); - * describe( - * 'Four small, black points drawn on a gray canvas. The points form the corners of a square.' - * ); + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('Two purple points drawn on a gray canvas.'); + * } + * + * function draw() { + * background(200); + * + * // Style the points. + * stroke('purple'); + * strokeWeight(10); + * + * // Top-left. + * point(-20, -30); + * + * // Bottom-right. + * point(20, 30); + * } * *
* + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('Two purple points drawn on a gray canvas. The scene spins slowly.'); + * } + * + * function draw() { + * background(200); + * + * // Rotate around the y-axis. + * rotateY(frameCount * 0.01); + * + * // Style the points. + * stroke('purple'); + * strokeWeight(10); + * + * // Top-left. + * point(-20, -30, 0); + * + * // Bottom-right. + * point(20, 30, -50); + * } + * + *
*/ /** * @method point @@ -69175,8 +73257,8 @@ * @chainable */ _main.default.prototype.point = function () { - for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { - args[_key2] = arguments[_key2]; + for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { + args[_key3] = arguments[_key3]; } _main.default._validateParameters('point', args); if (this._renderer._doStroke) { @@ -69194,17 +73276,22 @@ return this; }; /** - * Draws a quad to the canvas. A quad is a quadrilateral, a four-sided - * polygon. Some examples of quads include rectangles, squares, rhombuses, - * and trapezoids. The first pair of parameters (`x1`,`y1`) sets the quad's - * first point. The following pairs of parameters set the coordinates for - * its next three points. Parameters should proceed clockwise or - * counter-clockwise around the shape. + * Draws a quadrilateral (four-sided shape). + * + * Quadrilaterals include rectangles, squares, rhombuses, and trapezoids. The + * first pair of parameters `(x1, y1)` sets the quad's first point. The next + * three pairs of parameters set the coordinates for its next three points + * `(x2, y2)`, `(x3, y3)`, and `(x4, y4)`. Points should be added in either + * clockwise or counter-clockwise order. * * The version of `quad()` with twelve parameters allows the quad to be drawn * in 3D space. Doing so requires adding the `WEBGL` argument to * createCanvas(). * + * The thirteenth and fourteenth parameters are optional. In WebGL mode, they + * set the number of segments used to draw the quadrilateral in the x- and + * y-directions. They're both 2 by default. + * * @method quad * @param {Number} x1 the x-coordinate of the first point. * @param {Number} y1 the y-coordinate of the first point. @@ -69220,29 +73307,91 @@ * @example *
* - * quad(20, 20, 80, 20, 80, 80, 20, 80); - * describe('A white square with a black outline drawn on a gray canvas.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * quad(20, 20, 80, 20, 80, 80, 20, 80); + * + * describe('A white square with a black outline drawn on a gray canvas.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * quad(20, 30, 80, 30, 80, 70, 20, 70); + * + * describe('A white rectangle with a black outline drawn on a gray canvas.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * quad(50, 62, 86, 50, 50, 38, 14, 50); + * + * describe('A white rhombus with a black outline drawn on a gray canvas.'); + * } * *
* *
* - * quad(20, 30, 80, 30, 80, 70, 20, 70); - * describe('A white rectangle with a black outline drawn on a gray canvas.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * quad(20, 50, 80, 30, 80, 70, 20, 70); + * + * describe('A white trapezoid with a black outline drawn on a gray canvas.'); + * } * *
* *
* - * quad(50, 62, 86, 50, 50, 38, 14, 50); - * describe('A white rhombus with a black outline drawn on a gray canvas.'); + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * background(200); + * + * quad(-30, -30, 30, -30, 30, 30, -30, 30); + * + * describe('A white square with a black outline drawn on a gray canvas.'); + * } * *
* *
* - * quad(20, 50, 80, 30, 80, 70, 20, 70); - * describe('A white trapezoid with a black outline drawn on a gray canvas.'); + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A wavy white surface spins around on gray canvas.'); + * } + * + * function draw() { + * background(200); + * + * // Rotate around the y-axis. + * rotateY(frameCount * 0.01); + * + * // Draw the quad. + * quad(-30, -30, 0, 30, -30, 0, 30, 30, 20, -30, 30, -20); + * } * *
*/ @@ -69265,8 +73414,8 @@ * @chainable */ _main.default.prototype.quad = function () { - for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { - args[_key3] = arguments[_key3]; + for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { + args[_key4] = arguments[_key4]; } _main.default._validateParameters('quad', args); if (this._renderer._doStroke || this._renderer._doFill) { @@ -69285,21 +73434,22 @@ return this; }; /** - * Draws a rectangle to the canvas. A rectangle is a four-sided polygon with - * every angle at ninety degrees. By default, the first two parameters set the - * location of the rectangle's upper-left corner. The third and fourth set the - * shape's the width and height, respectively. The way these parameters are - * interpreted may be changed with the rectMode() - * function. + * Draws a rectangle. + * + * A rectangle is a four-sided shape defined by the `x`, `y`, `w`, and `h` + * parameters. `x` and `y` set the location of its top-left corner. `w` sets + * its width and `h` sets its height. Every angle in the rectangle measures + * 90˚. See rectMode() for other ways to define + * rectangles. * * The version of `rect()` with five parameters creates a rounded rectangle. The - * fifth parameter is used as the radius value for all four corners. + * fifth parameter sets the radius for all four corners. * - * The version of `rect()` with eight parameters also creates a rounded rectangle. - * When using eight parameters, the latter four set the radius of the arc at - * each corner separately. The radii start with the top-left corner and move - * clockwise around the rectangle. If any of these parameters are omitted, they - * are set to the value of the last specified corner radius. + * The version of `rect()` with eight parameters also creates a rounded + * rectangle. Each of the last four parameters set the radius of a corner. The + * radii start with the top-left corner and move clockwise around the + * rectangle. If any of these parameters are omitted, they are set to the + * value of the last radius that was set. * * @method rect * @param {Number} x x-coordinate of the rectangle. @@ -69311,30 +73461,99 @@ * @param {Number} [br] optional radius of bottom-right corner. * @param {Number} [bl] optional radius of bottom-left corner. * @chainable + * * @example *
* - * rect(30, 20, 55, 55); - * describe('A white rectangle with a black outline on a gray canvas.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * rect(30, 20, 55, 55); + * + * describe('A white square with a black outline on a gray canvas.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * rect(30, 20, 55, 40); + * + * describe('A white rectangle with a black outline on a gray canvas.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Give all corners a radius of 20. + * rect(30, 20, 55, 50, 20); + * + * describe('A white rectangle with a black outline and round edges on a gray canvas.'); + * } * *
* *
* - * rect(30, 20, 55, 55, 20); - * describe( - * 'A white rectangle with a black outline and round edges on a gray canvas.' - * ); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Give each corner a unique radius. + * rect(30, 20, 55, 50, 20, 15, 10, 5); + * + * describe('A white rectangle with a black outline and round edges of different radii.'); + * } * *
* *
* - * rect(30, 20, 55, 55, 20, 15, 10, 5); - * describe('A white rectangle with a black outline and round edges of different radii.'); + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * background(200); + * + * rect(-20, -30, 55, 55); + * + * describe('A white square with a black outline on a gray canvas.'); + * } * *
* + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white square spins around on gray canvas.'); + * } + * + * function draw() { + * background(200); + * + * // Rotate around the y-axis. + * rotateY(frameCount * 0.01); + * + * // Draw the rectangle. + * rect(-20, -30, 55, 55); + * } + * + *
*/ /** * @method rect @@ -69347,27 +73566,29 @@ * @chainable */ _main.default.prototype.rect = function () { - for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { - args[_key4] = arguments[_key4]; + for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) { + args[_key5] = arguments[_key5]; } _main.default._validateParameters('rect', args); return this._renderRect.apply(this, args); }; /** - * Draws a square to the canvas. A square is a four-sided polygon with every - * angle at ninety degrees and equal side lengths. By default, the first two - * parameters set the location of the square's upper-left corner. The third - * parameter sets its side size. The way these parameters are interpreted may - * be changed with the rectMode() function. + * Draws a square. + * + * A square is a four-sided shape defined by the `x`, `y`, and `s` + * parameters. `x` and `y` set the location of its top-left corner. `s` sets + * its width and height. Every angle in the square measures 90˚ and all its + * sides are the same length. See rectMode() for + * other ways to define squares. * - * The version of `square()` with four parameters creates a rounded square. The - * fourth parameter is used as the radius value for all four corners. + * The version of `square()` with four parameters creates a rounded square. + * The fourth parameter sets the radius for all four corners. * - * The version of `square()` with seven parameters also creates a rounded square. - * When using seven parameters, the latter four set the radius of the arc at - * each corner separately. The radii start with the top-left corner and move - * clockwise around the square. If any of these parameters are omitted, they - * are set to the value of the last specified corner radius. + * The version of `square()` with seven parameters also creates a rounded + * square. Each of the last four parameters set the radius of a corner. The + * radii start with the top-left corner and move clockwise around the + * square. If any of these parameters are omitted, they are set to the + * value of the last radius that was set. * * @method square * @param {Number} x x-coordinate of the square. @@ -69378,30 +73599,87 @@ * @param {Number} [br] optional radius of bottom-right corner. * @param {Number} [bl] optional radius of bottom-left corner. * @chainable + * * @example *
* - * square(30, 20, 55); - * describe('A white square with a black outline in on a gray canvas.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * square(30, 20, 55); + * + * describe('A white square with a black outline in on a gray canvas.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Give all corners a radius of 20. + * square(30, 20, 55, 20); + * + * describe( + * 'A white square with a black outline and round edges on a gray canvas.' + * ); + * } * *
* *
* - * square(30, 20, 55, 20); - * describe( - * 'A white square with a black outline and round edges on a gray canvas.' - * ); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Give each corner a unique radius. + * square(30, 20, 55, 20, 15, 10, 5); + * + * describe('A white square with a black outline and round edges of different radii.'); + * } * *
* *
* - * square(30, 20, 55, 20, 15, 10, 5); - * describe('A white square with a black outline and round edges of different radii.'); + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * background(200); + * + * square(-20, -30, 55); + * + * describe('A white square with a black outline in on a gray canvas.'); + * } * *
* + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white square spins around on gray canvas.'); + * } + * + * function draw() { + * background(200); + * + * // Rotate around the y-axis. + * rotateY(frameCount * 0.01); + * + * // Draw the square. + * square(-20, -30, 55); + * } + * + *
*/ _main.default.prototype.square = function (x, y, s, tl, tr, br, bl) { _main.default._validateParameters('square', arguments); @@ -69441,10 +73719,12 @@ return this; }; /** - * Draws a triangle to the canvas. A triangle is a three-sided polygon. The - * first two parameters specify the triangle's first point `(x1,y1)`. The middle - * two parameters specify its second point `(x2,y2)`. And the last two parameters - * specify its third point `(x3, y3)`. + * Draws a triangle. + * + * A triangle is a three-sided shape defined by three points. The + * first two parameters specify the triangle's first point `(x1, y1)`. The + * middle two parameters specify its second point `(x2, y2)`. And the last two + * parameters specify its third point `(x3, y3)`. * * @method triangle * @param {Number} x1 x-coordinate of the first point. @@ -69454,18 +73734,59 @@ * @param {Number} x3 x-coordinate of the third point. * @param {Number} y3 y-coordinate of the third point. * @chainable + * * @example *
* - * triangle(30, 75, 58, 20, 86, 75); - * describe('A white triangle with a black outline on a gray canvas.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * triangle(30, 75, 58, 20, 86, 75); + * + * describe('A white triangle with a black outline on a gray canvas.'); + * } * *
* - */ - _main.default.prototype.triangle = function () { - for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) { - args[_key5] = arguments[_key5]; + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * background(200); + * + * triangle(-20, 25, 8, -30, 36, 25); + * + * describe('A white triangle with a black outline on a gray canvas.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white triangle spins around on a gray canvas.'); + * } + * + * function draw() { + * background(200); + * + * // Rotate around the y-axis. + * rotateY(frameCount * 0.01); + * + * // Draw the triangle. + * triangle(-20, 25, 8, -30, 36, 25); + * } + * + *
+ */ + _main.default.prototype.triangle = function () { + for (var _len6 = arguments.length, args = new Array(_len6), _key6 = 0; _key6 < _len6; _key6++) { + args[_key6] = arguments[_key6]; } _main.default._validateParameters('triangle', args); if (this._renderer._doStroke || this._renderer._doFill) { @@ -69481,27 +73802,27 @@ exports.default = _default; }, { - '../constants': 286, - '../friendly_errors/fes_core': 289, - '../friendly_errors/file_errors': 290, - '../friendly_errors/validate_params': 293, - '../helpers': 294, - '../main': 298, - 'core-js/modules/es.array.from': 176, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256 + '../constants': 294, + '../friendly_errors/fes_core': 297, + '../friendly_errors/file_errors': 298, + '../friendly_errors/validate_params': 301, + '../helpers': 302, + '../main': 306, + 'core-js/modules/es.array.from': 180, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 306: [ + 314: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -69597,50 +73918,77 @@ * @requires constants */ /** - * Modifies the location from which ellipses, circles, and arcs are drawn. By default, the - * first two parameters are the x- and y-coordinates of the shape's center. The next - * parameters are its width and height. This is equivalent to calling `ellipseMode(CENTER)`. + * Changes where ellipses, circles, and arcs are drawn. + * + * By default, the first two parameters of + * ellipse(), circle(), + * and arc() + * are the x- and y-coordinates of the shape's center. The next parameters set + * the shape's width and height. This is the same as calling + * `ellipseMode(CENTER)`. * - * `ellipseMode(RADIUS)` also uses the first two parameters to set the x- and y-coordinates - * of the shape's center. The next parameters are half of the shapes's width and height. - * Calling `ellipse(0, 0, 10, 15)` draws a shape with a width of 20 and height of 30. + * `ellipseMode(RADIUS)` also uses the first two parameters to set the x- and + * y-coordinates of the shape's center. The next parameters are half of the + * shapes's width and height. Calling `ellipse(0, 0, 10, 15)` draws a shape + * with a width of 20 and height of 30. * - * `ellipseMode(CORNER)` uses the first two parameters as the upper-left corner of the - * shape. The next parameters are its width and height. + * `ellipseMode(CORNER)` uses the first two parameters as the upper-left + * corner of the shape. The next parameters are its width and height. * - * `ellipseMode(CORNERS)` uses the first two parameters as the location of one corner - * of the ellipse's bounding box. The third and fourth parameters are the location of the - * opposite corner. + * `ellipseMode(CORNERS)` uses the first two parameters as the location of one + * corner of the ellipse's bounding box. The next parameters are the location + * of the opposite corner. * - * The argument passed to `ellipseMode()` must be written in ALL CAPS because the constants - * `CENTER`, `RADIUS`, `CORNER`, and `CORNERS` are defined this way. JavaScript is a - * case-sensitive language. + * The argument passed to `ellipseMode()` must be written in ALL CAPS because + * the constants `CENTER`, `RADIUS`, `CORNER`, and `CORNERS` are defined this + * way. JavaScript is a case-sensitive language. * * @method ellipseMode * @param {Constant} mode either CENTER, RADIUS, CORNER, or CORNERS * @chainable + * * @example *
* - * ellipseMode(RADIUS); - * fill(255); - * ellipse(50, 50, 30, 30); - * ellipseMode(CENTER); - * fill(100); - * ellipse(50, 50, 30, 30); - * describe('A white circle with a gray circle at its center. Both circles have black outlines.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // White ellipse. + * ellipseMode(RADIUS); + * fill(255); + * ellipse(50, 50, 30, 30); + * + * // Gray ellipse. + * ellipseMode(CENTER); + * fill(100); + * ellipse(50, 50, 30, 30); + * + * describe('A white circle with a gray circle at its center. Both circles have black outlines.'); + * } * *
* *
* - * ellipseMode(CORNER); - * fill(255); - * ellipse(25, 25, 50, 50); - * ellipseMode(CORNERS); - * fill(100); - * ellipse(25, 25, 50, 50); - * describe('A white circle with a gray circle at its top-left corner. Both circles have black outlines.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // White ellipse. + * ellipseMode(CORNER); + * fill(255); + * ellipse(25, 25, 50, 50); + * + * // Gray ellipse. + * ellipseMode(CORNERS); + * fill(100); + * ellipse(25, 25, 50, 50); + * + * describe('A white circle with a gray circle at its top-left corner. Both circles have black outlines.'); + * } * *
*/ @@ -69653,26 +74001,75 @@ return this; }; /** - * Draws all geometry with jagged (aliased) edges. + * Draws certain features with jagged (aliased) edges. * - * smooth() is active by default in 2D mode. It's necessary to call - * noSmooth() to disable smoothing of geometry, images, and fonts. + * smooth() is active by default. In 2D mode, + * `noSmooth()` is helpful for scaling up images without blurring. The + * functions don't affect shapes or fonts. * - * In WebGL mode, noSmooth() is active by default. It's necessary - * to call smooth() to draw smooth (antialiased) edges. + * In WebGL mode, `noSmooth()` causes all shapes to be drawn with jagged + * (aliased) edges. The functions don't affect images or fonts. * * @method noSmooth * @chainable + * * @example *
* - * background(0); - * noStroke(); - * smooth(); - * ellipse(30, 48, 36, 36); - * noSmooth(); - * ellipse(70, 48, 36, 36); - * describe('Two pixelated white circles on a black background.'); + * let heart; + * + * // Load a pixelated heart image from an image data string. + * function preload() { + * heart = loadImage('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAAXNSR0IArs4c6QAAAEZJREFUGFd9jcsNACAIQ9tB2MeR3YdBMBBq8CIXPi2vBICIiOwkOedatllqWO6Y8yOWoyuNf1GZwgmf+RRG2YXr+xVFmA8HZ9Mx/KGPMtcAAAAASUVORK5CYII='); + * } + * + * function setup() { + * createCanvas(100, 100); + * + * background(50); + * + * // Antialiased hearts. + * image(heart, 10, 10); + * image(heart, 20, 10, 16, 16); + * image(heart, 40, 10, 32, 32); + * + * // Aliased hearts. + * noSmooth(); + * image(heart, 10, 60); + * image(heart, 20, 60, 16, 16); + * image(heart, 40, 60, 32, 32); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * background(200); + * + * circle(0, 0, 80); + * + * describe('A white circle on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Disable smoothing. + * noSmooth(); + * + * background(200); + * + * circle(0, 0, 80); + * + * describe('A pixelated white circle on a gray background.'); + * } * *
*/ @@ -69687,22 +74084,26 @@ return this; }; /** - * Modifies the location from which rectangles and squares are drawn. By default, - * the first two parameters are the x- and y-coordinates of the shape's upper-left - * corner. The next parameters are its width and height. This is equivalent to - * calling `rectMode(CORNER)`. + * Changes where rectangles and squares are drawn. * - * `rectMode(CORNERS)` also uses the first two parameters as the location of one of - * the corners. The third and fourth parameters are the location of the opposite - * corner. + * By default, the first two parameters of + * rect() and square(), + * are the x- and y-coordinates of the shape's upper left corner. The next parameters set + * the shape's width and height. This is the same as calling + * `rectMode(CORNER)`. * - * `rectMode(CENTER)` uses the first two parameters as the x- and y-coordinates of - * the shape's center. The next parameters are its width and height. + * `rectMode(CORNERS)` also uses the first two parameters as the location of + * one of the corners. The next parameters are the location of the opposite + * corner. This mode only works for rect(). * - * `rectMode(RADIUS)` also uses the first two parameters as the x- and y-coordinates - * of the shape's center. The next parameters are half of the shape's width and + * `rectMode(CENTER)` uses the first two parameters as the x- and + * y-coordinates of the shape's center. The next parameters are its width and * height. * + * `rectMode(RADIUS)` also uses the first two parameters as the x- and + * y-coordinates of the shape's center. The next parameters are + * half of the shape's width and height. + * * The argument passed to `rectMode()` must be written in ALL CAPS because the * constants `CENTER`, `RADIUS`, `CORNER`, and `CORNERS` are defined this way. * JavaScript is a case-sensitive language. @@ -69710,32 +74111,81 @@ * @method rectMode * @param {Constant} mode either CORNER, CORNERS, CENTER, or RADIUS * @chainable + * * @example *
* - * rectMode(CORNER); - * fill(255); - * rect(25, 25, 50, 50); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * rectMode(CORNER); + * fill(255); + * rect(25, 25, 50, 50); + * + * rectMode(CORNERS); + * fill(100); + * rect(25, 25, 50, 50); + * + * describe('A small gray square drawn at the top-left corner of a white square.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * rectMode(RADIUS); + * fill(255); + * rect(50, 50, 30, 30); + * + * rectMode(CENTER); + * fill(100); + * rect(50, 50, 30, 30); + * + * describe('A small gray square drawn at the center of a white square.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); * - * rectMode(CORNERS); - * fill(100); - * rect(25, 25, 50, 50); + * background(200); + * + * rectMode(CORNER); + * fill(255); + * square(25, 25, 50); * - * describe('A small gray square drawn at the top-left corner of a white square.'); + * describe('A white square.'); + * } * *
* *
* - * rectMode(RADIUS); - * fill(255); - * rect(50, 50, 30, 30); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * rectMode(RADIUS); + * fill(255); + * square(50, 50, 30); * - * rectMode(CENTER); - * fill(100); - * rect(50, 50, 30, 30); + * rectMode(CENTER); + * fill(100); + * square(50, 50, 30); * - * describe('A small gray square drawn at the center of a white square.'); + * describe('A small gray square drawn at the center of a white square.'); + * } * *
*/ @@ -69747,27 +74197,76 @@ return this; }; /** - * Draws all geometry with smooth (anti-aliased) edges. smooth() will also - * improve image quality of resized images. + * Draws certain features with smooth (antialiased) edges. * - * smooth() is active by default in 2D mode. It's necessary to call - * noSmooth() to disable smoothing of geometry, images, and fonts. + * `smooth()` is active by default. In 2D mode, + * noSmooth() is helpful for scaling up images + * without blurring. The functions don't affect shapes or fonts. * - * In WebGL mode, noSmooth() is active by default. It's necessary - * to call smooth() to draw smooth (antialiased) edges. + * In WebGL mode, noSmooth() causes all shapes to + * be drawn with jagged (aliased) edges. The functions don't affect images or + * fonts. * * @method smooth * @chainable + * * @example *
* - * background(0); - * noStroke(); - * smooth(); - * ellipse(30, 48, 36, 36); - * noSmooth(); - * ellipse(70, 48, 36, 36); - * describe('Two pixelated white circles on a black background.'); + * let heart; + * + * // Load a pixelated heart image from an image data string. + * function preload() { + * heart = loadImage('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAAXNSR0IArs4c6QAAAEZJREFUGFd9jcsNACAIQ9tB2MeR3YdBMBBq8CIXPi2vBICIiOwkOedatllqWO6Y8yOWoyuNf1GZwgmf+RRG2YXr+xVFmA8HZ9Mx/KGPMtcAAAAASUVORK5CYII='); + * } + * + * function setup() { + * createCanvas(100, 100); + * + * background(50); + * + * // Antialiased hearts. + * image(heart, 10, 10); + * image(heart, 20, 10, 16, 16); + * image(heart, 40, 10, 32, 32); + * + * // Aliased hearts. + * noSmooth(); + * image(heart, 10, 60); + * image(heart, 20, 60, 16, 16); + * image(heart, 40, 60, 32, 32); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * background(200); + * + * circle(0, 0, 80); + * + * describe('A white circle on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Disable smoothing. + * noSmooth(); + * + * background(200); + * + * circle(0, 0, 80); + * + * describe('A pixelated white circle on a gray background.'); + * } * *
*/ @@ -69781,9 +74280,10 @@ return this; }; /** - * Sets the style for rendering line endings. These ends are either rounded - * (`ROUND`), squared (`SQUARE`), or extended (`PROJECT`). The default cap is - * `ROUND`. + * Sets the style for rendering the ends of lines. + * + * The caps for line endings are either rounded (`ROUND`), squared + * (`SQUARE`), or extended (`PROJECT`). The default cap is `ROUND`. * * The argument passed to `strokeCap()` must be written in ALL CAPS because * the constants `ROUND`, `SQUARE`, and `PROJECT` are defined this way. @@ -69795,14 +74295,29 @@ * @example *
* - * strokeWeight(12.0); - * strokeCap(ROUND); - * line(20, 30, 80, 30); - * strokeCap(SQUARE); - * line(20, 50, 80, 50); - * strokeCap(PROJECT); - * line(20, 70, 80, 70); - * describe('Three horizontal lines. The top line has rounded ends, the middle line has squared ends, and the bottom line has longer, squared ends.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * strokeWeight(12); + * + * // Top. + * strokeCap(ROUND); + * line(20, 30, 80, 30); + * + * // Middle. + * strokeCap(SQUARE); + * line(20, 50, 80, 50); + * + * // Bottom. + * strokeCap(PROJECT); + * line(20, 70, 80, 70); + * + * describe( + * 'Three horizontal lines. The top line has rounded ends, the middle line has squared ends, and the bottom line has longer, squared ends.' + * ); + * } * *
*/ @@ -69814,9 +74329,11 @@ return this; }; /** - * Sets the style of the joints which connect line segments. These joints are - * either mitered (`MITER`), beveled (`BEVEL`), or rounded (`ROUND`). The default - * joint is `MITER` in 2D mode and `ROUND` in WebGL mode. + * Sets the style of the joints that connect line segments. + * + * Joints are either mitered (`MITER`), beveled (`BEVEL`), or rounded + * (`ROUND`). The default joint is `MITER` in 2D mode and `ROUND` in WebGL + * mode. * * The argument passed to `strokeJoin()` must be written in ALL CAPS because * the constants `MITER`, `BEVEL`, and `ROUND` are defined this way. @@ -69828,43 +74345,73 @@ * @example *
* - * noFill(); - * strokeWeight(10.0); - * strokeJoin(MITER); - * beginShape(); - * vertex(35, 20); - * vertex(65, 50); - * vertex(35, 80); - * endShape(); - * describe('A right-facing arrowhead shape with a pointed tip in center of canvas.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the line. + * noFill(); + * strokeWeight(10); + * strokeJoin(MITER); + * + * // Draw the line. + * beginShape(); + * vertex(35, 20); + * vertex(65, 50); + * vertex(35, 80); + * endShape(); + * + * describe('A right-facing arrowhead shape with a pointed tip in center of canvas.'); + * } * *
* *
* - * noFill(); - * strokeWeight(10.0); - * strokeJoin(BEVEL); - * beginShape(); - * vertex(35, 20); - * vertex(65, 50); - * vertex(35, 80); - * endShape(); - * describe('A right-facing arrowhead shape with a flat tip in center of canvas.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the line. + * noFill(); + * strokeWeight(10); + * strokeJoin(BEVEL); + * + * // Draw the line. + * beginShape(); + * vertex(35, 20); + * vertex(65, 50); + * vertex(35, 80); + * endShape(); + * + * describe('A right-facing arrowhead shape with a flat tip in center of canvas.'); + * } * *
* *
* - * noFill(); - * strokeWeight(10.0); - * strokeJoin(ROUND); - * beginShape(); - * vertex(35, 20); - * vertex(65, 50); - * vertex(35, 80); - * endShape(); - * describe('A right-facing arrowhead shape with a rounded tip in center of canvas.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the line. + * noFill(); + * strokeWeight(10); + * strokeJoin(ROUND); + * + * // Draw the line. + * beginShape(); + * vertex(35, 20); + * vertex(65, 50); + * vertex(35, 80); + * endShape(); + * + * describe('A right-facing arrowhead shape with a rounded tip in center of canvas.'); + * } * *
*/ @@ -69876,11 +74423,11 @@ return this; }; /** - * Sets the width of the stroke used for lines, points, and the border around - * shapes. All widths are set in units of pixels. + * Sets the width of the stroke used for points, lines, and the outlines of + * shapes. * - * Note that `strokeWeight()` is affected by any transformation or scaling that - * has been applied previously. + * Note: `strokeWeight()` is affected by transformations, especially calls to + * scale(). * * @method strokeWeight * @param {Number} weight the weight of the stroke (in pixels). @@ -69888,27 +74435,45 @@ * @example *
* - * // Default. - * line(20, 20, 80, 20); - * // Thicker. - * strokeWeight(4); - * line(20, 40, 80, 40); - * // Beastly. - * strokeWeight(10); - * line(20, 70, 80, 70); - * describe('Three horizontal black lines. The top line is thin, the middle is medium, and the bottom is thick.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Top. + * line(20, 20, 80, 20); + * + * // Middle. + * strokeWeight(4); + * line(20, 40, 80, 40); + * + * // Bottom. + * strokeWeight(10); + * line(20, 70, 80, 70); + * + * describe('Three horizontal black lines. The top line is thin, the middle is medium, and the bottom is thick.'); + * } * *
* *
* - * // Default. - * line(20, 20, 80, 20); - * // Adding scale transformation. - * scale(5); - * // Coordinates adjusted for scaling. - * line(4, 8, 16, 8); - * describe('Two horizontal black lines. The top line is thin and the bottom is five times thicker than the top.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Top. + * line(20, 20, 80, 20); + * + * // Scale by a factor of 5. + * scale(5); + * + * // Bottom. Coordinates are adjusted for scaling. + * line(4, 8, 16, 8); + * + * describe('Two horizontal black lines. The top line is thin and the bottom is five times thicker than the top.'); + * } * *
*/ @@ -69921,20 +74486,20 @@ exports.default = _default; }, { - '../constants': 286, - '../main': 298, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256 + '../constants': 294, + '../main': 306, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 307: [ + 315: [ function (_dereq_, module, exports) { 'use strict'; Object.defineProperty(exports, '__esModule', { @@ -69957,67 +74522,196 @@ * @requires core */ /** - * Draws a cubic Bezier curve on the screen. These curves are defined by a - * series of anchor and control points. The first two parameters specify - * the first anchor point and the last two parameters specify the other - * anchor point, which become the first and last points on the curve. The - * middle parameters specify the two control points which define the shape - * of the curve. Approximately speaking, control points "pull" the curve - * towards them. + * Draws a Bézier curve. + * + * Bézier curves can form shapes and curves that slope gently. They're defined + * by two anchor points and two control points. Bézier curves provide more + * control than the spline curves created with the + * curve() function. + * + * The first two parameters, `x1` and `y1`, set the first anchor point. The + * first anchor point is where the curve starts. * - * Bezier curves were developed by French automotive engineer Pierre Bezier, - * and are commonly used in computer graphics to define gently sloping curves. - * See also curve(). + * The next four parameters, `x2`, `y2`, `x3`, and `y3`, set the two control + * points. The control points "pull" the curve towards them. + * + * The seventh and eighth parameters, `x4` and `y4`, set the last anchor + * point. The last anchor point is where the curve ends. + * + * Bézier curves can also be drawn in 3D using WebGL mode. The 3D version of + * `bezier()` has twelve arguments because each point has x-, y-, + * and z-coordinates. * * @method bezier - * @param {Number} x1 x-coordinate for the first anchor point - * @param {Number} y1 y-coordinate for the first anchor point - * @param {Number} x2 x-coordinate for the first control point - * @param {Number} y2 y-coordinate for the first control point - * @param {Number} x3 x-coordinate for the second control point - * @param {Number} y3 y-coordinate for the second control point - * @param {Number} x4 x-coordinate for the second anchor point - * @param {Number} y4 y-coordinate for the second anchor point + * @param {Number} x1 x-coordinate of the first anchor point. + * @param {Number} y1 y-coordinate of the first anchor point. + * @param {Number} x2 x-coordinate of the first control point. + * @param {Number} y2 y-coordinate of the first control point. + * @param {Number} x3 x-coordinate of the second control point. + * @param {Number} y3 y-coordinate of the second control point. + * @param {Number} x4 x-coordinate of the second anchor point. + * @param {Number} y4 y-coordinate of the second anchor point. * @chainable + * * @example *
* - * noFill(); - * stroke(255, 102, 0); - * line(85, 20, 10, 10); - * line(90, 90, 15, 80); - * stroke(0, 0, 0); - * bezier(85, 20, 10, 10, 90, 90, 15, 80); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Draw the anchor points in black. + * stroke(0); + * strokeWeight(5); + * point(85, 20); + * point(15, 80); + * + * // Draw the control points in red. + * stroke(255, 0, 0); + * point(10, 10); + * point(90, 90); + * + * // Draw a black bezier curve. + * noFill(); + * stroke(0); + * strokeWeight(1); + * bezier(85, 20, 10, 10, 90, 90, 15, 80); + * + * // Draw red lines from the anchor points to the control points. + * stroke(255, 0, 0); + * line(85, 20, 10, 10); + * line(15, 80, 90, 90); + * + * describe( + * 'A gray square with three curves. A black s-curve has two straight, red lines that extend from its ends. The endpoints of all the curves are marked with dots.' + * ); + * } + * + *
+ * + *
+ * + * // Click the mouse near the red dot in the top-left corner + * // and drag to change the curve's shape. + * + * let x2 = 10; + * let y2 = 10; + * let isChanging = false; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with three curves. A black s-curve has two straight, red lines that extend from its ends. The endpoints of all the curves are marked with dots.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Draw the anchor points in black. + * stroke(0); + * strokeWeight(5); + * point(85, 20); + * point(15, 80); + * + * // Draw the control points in red. + * stroke(255, 0, 0); + * point(x2, y2); + * point(90, 90); + * + * // Draw a black bezier curve. + * noFill(); + * stroke(0); + * strokeWeight(1); + * bezier(85, 20, x2, y2, 90, 90, 15, 80); + * + * // Draw red lines from the anchor points to the control points. + * stroke(255, 0, 0); + * line(85, 20, x2, y2); + * line(15, 80, 90, 90); + * } + * + * // Start changing the first control point if the user clicks near it. + * function mousePressed() { + * if (dist(mouseX, mouseY, x2, y2) < 20) { + * isChanging = true; + * } + * } + * + * // Stop changing the first control point when the user releases the mouse. + * function mouseReleased() { + * isChanging = false; + * } + * + * // Update the first control point while the user drags the mouse. + * function mouseDragged() { + * if (isChanging === true) { + * x2 = mouseX; + * y2 = mouseY; + * } + * } * *
* *
* - * background(0, 0, 0); - * noFill(); - * stroke(255); - * bezier(250, 250, 0, 100, 100, 0, 100, 0, 0, 0, 100, 0); + * function setup() { + * createCanvas(100, 100); + * + * background('skyblue'); + * + * // Draw the red balloon. + * fill('red'); + * bezier(50, 60, 5, 15, 95, 15, 50, 60); + * + * // Draw the balloon string. + * line(50, 60, 50, 80); + * + * describe('A red balloon in a blue sky.'); + * } * *
* - * @alt - * stretched black s-shape in center with orange lines extending from end points. - * a white colored curve on black background from the upper-right corner to the lower right corner. + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A red balloon in a blue sky. The balloon rotates slowly, revealing that it is flat.'); + * } + * + * function draw() { + * background('skyblue'); + * + * // Rotate around the y-axis. + * rotateY(frameCount * 0.01); + * + * // Draw the red balloon. + * fill('red'); + * bezier(0, 0, 0, -45, -45, 0, 45, -45, 0, 0, 0, 0); + * + * // Draw the balloon string. + * line(0, 0, 0, 0, 20, 0); + * } + * + *
*/ /** * @method bezier * @param {Number} x1 * @param {Number} y1 - * @param {Number} z1 z-coordinate for the first anchor point + * @param {Number} z1 z-coordinate of the first anchor point. * @param {Number} x2 * @param {Number} y2 - * @param {Number} z2 z-coordinate for the first control point + * @param {Number} z2 z-coordinate of the first control point. * @param {Number} x3 * @param {Number} y3 - * @param {Number} z3 z-coordinate for the second control point + * @param {Number} z3 z-coordinate of the second control point. * @param {Number} x4 * @param {Number} y4 - * @param {Number} z4 z-coordinate for the second anchor point + * @param {Number} z4 z-coordinate of the second anchor point. * @chainable */ @@ -70035,37 +74729,101 @@ return this; }; /** - * Sets the resolution at which Bezier's curve is displayed. The default value is 20. + * Sets the number of segments used to draw Bézier curves in WebGL mode. * - * Note, This function is only useful when using the WEBGL renderer - * as the default canvas renderer does not use this information. + * In WebGL mode, smooth shapes are drawn using many flat segments. Adding + * more flat segments makes shapes appear smoother. + * + * The parameter, `detail`, is the number of segments to use while drawing a + * Bézier curve. For example, calling `bezierDetail(5)` will use 5 segments to + * draw curves with the bezier() function. By + * default,`detail` is 20. + * + * Note: `bezierDetail()` has no effect in 2D mode. * * @method bezierDetail - * @param {Number} detail resolution of the curves + * @param {Number} detail number of segments to use. Defaults to 20. * @chainable + * * @example - *
+ *
* + * // Draw the original curve. + * * function setup() { - * createCanvas(100, 100, WEBGL); + * createCanvas(100, 100); + * + * background(200); + * + * // Draw the anchor points in black. + * stroke(0); + * strokeWeight(5); + * point(85, 20); + * point(15, 80); + * + * // Draw the control points in red. + * stroke(255, 0, 0); + * point(10, 10); + * point(90, 90); + * + * // Draw a black bezier curve. * noFill(); - * bezierDetail(5); + * stroke(0); + * strokeWeight(1); + * bezier(85, 20, 10, 10, 90, 90, 15, 80); + * + * // Draw red lines from the anchor points to the control points. + * stroke(255, 0, 0); + * line(85, 20, 10, 10); + * line(15, 80, 90, 90); + * + * describe( + * 'A gray square with three curves. A black s-curve has two straight, red lines that extend from its ends. The endpoints of all the curves are marked with dots.' + * ); * } + * + *
+ * + *
+ * + * // Draw the curve with less detail. + * + * function setup() { + * createCanvas(100, 100, WEBGL); * - * function draw() { * background(200); - * bezier( - * -40, -40, 0, - * 90, -40, 0, - * -90, 40, 0, - * 40, 40, 0 + * + * // Set the curveDetail() to 5. + * bezierDetail(5); + * + * // Draw the anchor points in black. + * stroke(0); + * strokeWeight(5); + * point(35, -30, 0); + * point(-35, 30, 0); + * + * // Draw the control points in red. + * stroke(255, 0, 0); + * point(-40, -40, 0); + * point(40, 40, 0); + * + * // Draw a black bezier curve. + * noFill(); + * stroke(0); + * strokeWeight(1); + * bezier(35, -30, 0, -40, -40, 0, 40, 40, 0, -35, 30, 0); + * + * // Draw red lines from the anchor points to the control points. + * stroke(255, 0, 0); + * line(35, -30, -40, -40); + * line(-35, 30, 40, 40); + * + * describe( + * 'A gray square with three curves. A black s-curve is drawn with jagged segments. Two straight, red lines that extend from its ends. The endpoints of all the curves are marked with dots.' * ); * } * *
- * - * @alt - * stretched black s-shape with a low level of bezier detail */ _main.default.prototype.bezierDetail = function (d) { _main.default._validateParameters('bezierDetail', arguments); @@ -70073,47 +74831,118 @@ return this; }; /** - * Given the x or y co-ordinate values of control and anchor points of a bezier - * curve, it evaluates the x or y coordinate of the bezier at position t. The - * parameters a and d are the x or y coordinates of first and last points on the - * curve while b and c are of the control points.The final parameter t is the - * position of the resultant point which is given between 0 and 1. - * This can be done once with the x coordinates and a second time - * with the y coordinates to get the location of a bezier curve at t. + * Calculates coordinates along a Bézier curve using interpolation. + * + * `bezierPoint()` calculates coordinates along a Bézier curve using the + * anchor and control points. It expects points in the same order as the + * bezier() function. `bezierPoint()` works one axis + * at a time. Passing the anchor and control points' x-coordinates will + * calculate the x-coordinate of a point on the curve. Passing the anchor and + * control points' y-coordinates will calculate the y-coordinate of a point on + * the curve. + * + * The first parameter, `a`, is the coordinate of the first anchor point. + * + * The second and third parameters, `b` and `c`, are the coordinates of the + * control points. + * + * The fourth parameter, `d`, is the coordinate of the last anchor point. + * + * The fifth parameter, `t`, is the amount to interpolate along the curve. 0 + * is the first anchor point, 1 is the second anchor point, and 0.5 is halfway + * between them. * * @method bezierPoint - * @param {Number} a coordinate of first point on the curve - * @param {Number} b coordinate of first control point - * @param {Number} c coordinate of second control point - * @param {Number} d coordinate of second point on the curve - * @param {Number} t value between 0 and 1 - * @return {Number} the value of the Bezier at position t + * @param {Number} a coordinate of first control point. + * @param {Number} b coordinate of first anchor point. + * @param {Number} c coordinate of second anchor point. + * @param {Number} d coordinate of second control point. + * @param {Number} t amount to interpolate between 0 and 1. + * @return {Number} coordinate of the point on the curve. + * * @example *
* - * noFill(); - * let x1 = 85, - x2 = 10, - x3 = 90, - x4 = 15; - * let y1 = 20, - y2 = 10, - y3 = 90, - y4 = 80; - * bezier(x1, y1, x2, y2, x3, y3, x4, y4); - * fill(255); - * let steps = 10; - * for (let i = 0; i <= steps; i++) { - * let t = i / steps; + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Set the coordinates for the curve's anchor and control points. + * let x1 = 85; + * let x2 = 10; + * let x3 = 90; + * let x4 = 15; + * let y1 = 20; + * let y2 = 10; + * let y3 = 90; + * let y4 = 80; + * + * // Style the curve. + * noFill(); + * + * // Draw the curve. + * bezier(x1, y1, x2, y2, x3, y3, x4, y4); + * + * // Draw circles along the curve's path. + * fill(255); + * + * // Top-right. + * let x = bezierPoint(x1, x2, x3, x4, 0); + * let y = bezierPoint(y1, y2, y3, y4, 0); + * circle(x, y, 5); + * + * // Center. + * x = bezierPoint(x1, x2, x3, x4, 0.5); + * y = bezierPoint(y1, y2, y3, y4, 0.5); + * circle(x, y, 5); + * + * // Bottom-left. + * x = bezierPoint(x1, x2, x3, x4, 1); + * y = bezierPoint(y1, y2, y3, y4, 1); + * circle(x, y, 5); + * + * describe('A black s-curve on a gray square. The endpoints and center of the curve are marked with white circles.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * describe('A black s-curve on a gray square. A white circle moves back and forth along the curve.'); + * } + * + * function draw() { + * background(200); + * + * // Set the coordinates for the curve's anchor and control points. + * let x1 = 85; + * let x2 = 10; + * let x3 = 90; + * let x4 = 15; + * let y1 = 20; + * let y2 = 10; + * let y3 = 90; + * let y4 = 80; + * + * // Draw the curve. + * noFill(); + * bezier(x1, y1, x2, y2, x3, y3, x4, y4); + * + * // Calculate the circle's coordinates. + * let t = 0.5 * sin(frameCount * 0.01) + 0.5; * let x = bezierPoint(x1, x2, x3, x4, t); * let y = bezierPoint(y1, y2, y3, y4, t); + * + * // Draw the circle. + * fill(255); * circle(x, y, 5); * } * *
- * - * @alt - * 10 points plotted on a given bezier at equal distances. */ _main.default.prototype.bezierPoint = function (a, b, c, d, t) { _main.default._validateParameters('bezierPoint', arguments); @@ -70121,69 +74950,110 @@ return Math.pow(adjustedT, 3) * a + 3 * Math.pow(adjustedT, 2) * t * b + 3 * adjustedT * Math.pow(t, 2) * c + Math.pow(t, 3) * d; }; /** - * Evaluates the tangent to the Bezier at position t for points a, b, c, d. - * The parameters a and d are the first and last points - * on the curve, and b and c are the control points. - * The final parameter t varies between 0 and 1. + * Calculates coordinates along a line that's tangent to a Bézier curve. + * + * Tangent lines skim the surface of a curve. A tangent line's slope equals + * the curve's slope at the point where it intersects. + * + * `bezierTangent()` calculates coordinates along a tangent line using the + * Bézier curve's anchor and control points. It expects points in the same + * order as the bezier() function. `bezierTangent()` + * works one axis at a time. Passing the anchor and control points' + * x-coordinates will calculate the x-coordinate of a point on the tangent + * line. Passing the anchor and control points' y-coordinates will calculate + * the y-coordinate of a point on the tangent line. + * + * The first parameter, `a`, is the coordinate of the first anchor point. + * + * The second and third parameters, `b` and `c`, are the coordinates of the + * control points. + * + * The fourth parameter, `d`, is the coordinate of the last anchor point. + * + * The fifth parameter, `t`, is the amount to interpolate along the curve. 0 + * is the first anchor point, 1 is the second anchor point, and 0.5 is halfway + * between them. * * @method bezierTangent - * @param {Number} a coordinate of first point on the curve - * @param {Number} b coordinate of first control point - * @param {Number} c coordinate of second control point - * @param {Number} d coordinate of second point on the curve - * @param {Number} t value between 0 and 1 - * @return {Number} the tangent at position t + * @param {Number} a coordinate of first anchor point. + * @param {Number} b coordinate of first control point. + * @param {Number} c coordinate of second control point. + * @param {Number} d coordinate of second anchor point. + * @param {Number} t amount to interpolate between 0 and 1. + * @return {Number} coordinate of a point on the tangent line. + * * @example *
* - * noFill(); - * bezier(85, 20, 10, 10, 90, 90, 15, 80); - * let steps = 6; - * fill(255); - * for (let i = 0; i <= steps; i++) { - * let t = i / steps; - * // Get the location of the point - * let x = bezierPoint(85, 10, 90, 15, t); - * let y = bezierPoint(20, 10, 90, 80, t); - * // Get the tangent points - * let tx = bezierTangent(85, 10, 90, 15, t); - * let ty = bezierTangent(20, 10, 90, 80, t); - * // Calculate an angle from the tangent points - * let a = atan2(ty, tx); - * a += PI; - * stroke(255, 102, 0); - * line(x, y, cos(a) * 30 + x, sin(a) * 30 + y); - * // The following line of code makes a line - * // inverse of the above line - * //line(x, y, cos(a)*-30 + x, sin(a)*-30 + y); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Set the coordinates for the curve's anchor and control points. + * let x1 = 85; + * let x2 = 10; + * let x3 = 90; + * let x4 = 15; + * let y1 = 20; + * let y2 = 10; + * let y3 = 90; + * let y4 = 80; + * + * // Style the curve. + * noFill(); + * + * // Draw the curve. + * bezier(x1, y1, x2, y2, x3, y3, x4, y4); + * + * // Draw tangents along the curve's path. + * fill(255); + * + * // Top-right circle. * stroke(0); - * ellipse(x, y, 5, 5); - * } - * - *
+ * let x = bezierPoint(x1, x2, x3, x4, 0); + * let y = bezierPoint(y1, y2, y3, y4, 0); + * circle(x, y, 5); * - *
- * - * noFill(); - * bezier(85, 20, 10, 10, 90, 90, 15, 80); - * stroke(255, 102, 0); - * let steps = 16; - * for (let i = 0; i <= steps; i++) { - * let t = i / steps; - * let x = bezierPoint(85, 10, 90, 15, t); - * let y = bezierPoint(20, 10, 90, 80, t); - * let tx = bezierTangent(85, 10, 90, 15, t); - * let ty = bezierTangent(20, 10, 90, 80, t); - * let a = atan2(ty, tx); - * a -= HALF_PI; - * line(x, y, cos(a) * 8 + x, sin(a) * 8 + y); + * // Top-right tangent line. + * // Scale the tangent point to draw a shorter line. + * stroke(255, 0, 0); + * let tx = 0.1 * bezierTangent(x1, x2, x3, x4, 0); + * let ty = 0.1 * bezierTangent(y1, y2, y3, y4, 0); + * line(x + tx, y + ty, x - tx, y - ty); + * + * // Center circle. + * stroke(0); + * x = bezierPoint(x1, x2, x3, x4, 0.5); + * y = bezierPoint(y1, y2, y3, y4, 0.5); + * circle(x, y, 5); + * + * // Center tangent line. + * // Scale the tangent point to draw a shorter line. + * stroke(255, 0, 0); + * tx = 0.1 * bezierTangent(x1, x2, x3, x4, 0.5); + * ty = 0.1 * bezierTangent(y1, y2, y3, y4, 0.5); + * line(x + tx, y + ty, x - tx, y - ty); + * + * // Bottom-left circle. + * stroke(0); + * x = bezierPoint(x1, x2, x3, x4, 1); + * y = bezierPoint(y1, y2, y3, y4, 1); + * circle(x, y, 5); + * + * // Bottom-left tangent. + * // Scale the tangent point to draw a shorter line. + * stroke(255, 0, 0); + * tx = 0.1 * bezierTangent(x1, x2, x3, x4, 1); + * ty = 0.1 * bezierTangent(y1, y2, y3, y4, 1); + * line(x + tx, y + ty, x - tx, y - ty); + * + * describe( + * 'A black s-curve on a gray square. The endpoints and center of the curve are marked with white circles. Red tangent lines extend from the white circles.' + * ); * } * *
- * - * @alt - * s-shaped line with 6 short orange lines showing the tangents at those points. - * s-shaped line with 6 short orange lines showing lines coming out the underside of the bezier. */ _main.default.prototype.bezierTangent = function (a, b, c, d, t) { _main.default._validateParameters('bezierTangent', arguments); @@ -70191,128 +75061,299 @@ return 3 * d * Math.pow(t, 2) - 3 * c * Math.pow(t, 2) + 6 * c * adjustedT * t - 6 * b * adjustedT * t + 3 * b * Math.pow(adjustedT, 2) - 3 * a * Math.pow(adjustedT, 2); }; /** - * Draws a curved line on the screen between two points, given as the - * middle four parameters. The first two parameters are a control point, as - * if the curve came from this point even though it's not drawn. The last - * two parameters similarly describe the other control point.

- * Longer curves can be created by putting a series of curve() functions - * together or using curveVertex(). An additional function called - * curveTightness() provides control for the visual quality of the curve. - * The curve() function is an implementation of Catmull-Rom splines. + * Draws a curve using a Catmull-Rom spline. * - * @method curve - * @param {Number} x1 x-coordinate for the beginning control point - * @param {Number} y1 y-coordinate for the beginning control point - * @param {Number} x2 x-coordinate for the first point - * @param {Number} y2 y-coordinate for the first point - * @param {Number} x3 x-coordinate for the second point - * @param {Number} y3 y-coordinate for the second point - * @param {Number} x4 x-coordinate for the ending control point - * @param {Number} y4 y-coordinate for the ending control point - * @chainable - * @example - *
- * - * noFill(); - * stroke(255, 102, 0); - * curve(5, 26, 5, 26, 73, 24, 73, 61); - * stroke(0); - * curve(5, 26, 73, 24, 73, 61, 15, 65); - * stroke(255, 102, 0); - * curve(73, 24, 73, 61, 15, 65, 15, 65); - * - *
+ * Spline curves can form shapes and curves that slope gently. They’re like + * cables that are attached to a set of points. Splines are defined by two + * anchor points and two control points. * - *
- * - * // Define the curve points as JavaScript objects - * let p1 = { x: 5, y: 26 }; - * let p2 = { x: 73, y: 24 }; - * let p3 = { x: 73, y: 61 }; - * let p4 = { x: 15, y: 65 }; - * noFill(); - * stroke(255, 102, 0); - * curve(p1.x, p1.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); - * stroke(0); - * curve(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y); - * stroke(255, 102, 0); - * curve(p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, p4.x, p4.y); - * - *
+ * The first two parameters, `x1` and `y1`, set the first control point. This + * point isn’t drawn and can be thought of as the curve’s starting point. * - *
- * - * noFill(); - * stroke(255, 102, 0); - * curve(5, 26, 0, 5, 26, 0, 73, 24, 0, 73, 61, 0); - * stroke(0); - * curve(5, 26, 0, 73, 24, 0, 73, 61, 0, 15, 65, 0); - * stroke(255, 102, 0); - * curve(73, 24, 0, 73, 61, 0, 15, 65, 0, 15, 65, 0); - * - *
+ * The next four parameters, `x2`, `y2`, `x3`, and `y3`, set the two anchor + * points. The anchor points are the start and end points of the curve’s + * visible segment. * - * @alt - * horseshoe shape with orange ends facing left and black curved center. - * horseshoe shape with orange ends facing left and black curved center. - * curving black and orange lines. - */ - /** - * @method curve - * @param {Number} x1 - * @param {Number} y1 - * @param {Number} z1 z-coordinate for the beginning control point - * @param {Number} x2 - * @param {Number} y2 - * @param {Number} z2 z-coordinate for the first point - * @param {Number} x3 - * @param {Number} y3 - * @param {Number} z3 z-coordinate for the second point - * @param {Number} x4 - * @param {Number} y4 - * @param {Number} z4 z-coordinate for the ending control point - * @chainable - */ - _main.default.prototype.curve = function () { - for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { - args[_key2] = arguments[_key2]; - } - _main.default._validateParameters('curve', args); - if (this._renderer._doStroke) { - var _this$_renderer2; - (_this$_renderer2 = this._renderer).curve.apply(_this$_renderer2, args); - } - return this; - }; - /** - * Sets the resolution at which curves display. The default value is 20 while - * the minimum value is 3. + * The seventh and eighth parameters, `x4` and `y4`, set the last control + * point. This point isn’t drawn and can be thought of as the curve’s ending + * point. * - * This function is only useful when using the WEBGL renderer - * as the default canvas renderer does not use this - * information. + * Spline curves can also be drawn in 3D using WebGL mode. The 3D version of + * `curve()` has twelve arguments because each point has x-, y-, and + * z-coordinates. * - * @method curveDetail - * @param {Number} resolution resolution of the curves + * @method curve + * @param {Number} x1 x-coordinate of the first control point. + * @param {Number} y1 y-coordinate of the first control point. + * @param {Number} x2 x-coordinate of the first anchor point. + * @param {Number} y2 y-coordinate of the first anchor point. + * @param {Number} x3 x-coordinate of the second anchor point. + * @param {Number} y3 y-coordinate of the second anchor point. + * @param {Number} x4 x-coordinate of the second control point. + * @param {Number} y4 y-coordinate of the second control point. * @chainable + * * @example - *
+ *
* * function setup() { - * createCanvas(100, 100, WEBGL); + * createCanvas(100, 100); * - * curveDetail(5); - * } - * function draw() { * background(200); * - * curve(250, 600, 0, -30, 40, 0, 30, 30, 0, -250, 600, 0); + * // Draw a black spline curve. + * noFill(); + * strokeWeight(1); + * stroke(0); + * curve(5, 26, 73, 24, 73, 61, 15, 65); + * + * // Draw red spline curves from the anchor points to the control points. + * stroke(255, 0, 0); + * curve(5, 26, 5, 26, 73, 24, 73, 61); + * curve(73, 24, 73, 61, 15, 65, 15, 65); + * + * // Draw the anchor points in black. + * strokeWeight(5); + * stroke(0); + * point(73, 24); + * point(73, 61); + * + * // Draw the control points in red. + * stroke(255, 0, 0); + * point(5, 26); + * point(15, 65); + * + * describe( + * 'A gray square with a curve drawn in three segments. The curve is a sideways U shape with red segments on top and bottom, and a black segment on the right. The endpoints of all the segments are marked with dots.' + * ); * } * *
* - * @alt - * white arch shape with a low level of curve detail. + *
+ * + * let x1 = 5; + * let y1 = 26; + * let isChanging = false; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with a curve drawn in three segments. The curve is a sideways U shape with red segments on top and bottom, and a black segment on the right. The endpoints of all the segments are marked with dots.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Draw a black spline curve. + * noFill(); + * strokeWeight(1); + * stroke(0); + * curve(x1, y1, 73, 24, 73, 61, 15, 65); + * + * // Draw red spline curves from the anchor points to the control points. + * stroke(255, 0, 0); + * curve(x1, y1, x1, y1, 73, 24, 73, 61); + * curve(73, 24, 73, 61, 15, 65, 15, 65); + * + * // Draw the anchor points in black. + * strokeWeight(5); + * stroke(0); + * point(73, 24); + * point(73, 61); + * + * // Draw the control points in red. + * stroke(255, 0, 0); + * point(x1, y1); + * point(15, 65); + * } + * + * // Start changing the first control point if the user clicks near it. + * function mousePressed() { + * if (dist(mouseX, mouseY, x1, y1) < 20) { + * isChanging = true; + * } + * } + * + * // Stop changing the first control point when the user releases the mouse. + * function mouseReleased() { + * isChanging = false; + * } + * + * // Update the first control point while the user drags the mouse. + * function mouseDragged() { + * if (isChanging === true) { + * x1 = mouseX; + * y1 = mouseY; + * } + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background('skyblue'); + * + * // Draw the red balloon. + * fill('red'); + * curve(-150, 275, 50, 60, 50, 60, 250, 275); + * + * // Draw the balloon string. + * line(50, 60, 50, 80); + * + * describe('A red balloon in a blue sky.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A red balloon in a blue sky.'); + * } + * + * function draw() { + * background('skyblue'); + * + * // Rotate around the y-axis. + * rotateY(frameCount * 0.01); + * + * // Draw the red balloon. + * fill('red'); + * curve(-200, 225, 0, 0, 10, 0, 0, 10, 0, 200, 225, 0); + * + * // Draw the balloon string. + * line(0, 10, 0, 0, 30, 0); + * } + * + *
+ */ + /** + * @method curve + * @param {Number} x1 + * @param {Number} y1 + * @param {Number} z1 z-coordinate of the first control point. + * @param {Number} x2 + * @param {Number} y2 + * @param {Number} z2 z-coordinate of the first anchor point. + * @param {Number} x3 + * @param {Number} y3 + * @param {Number} z3 z-coordinate of the second anchor point. + * @param {Number} x4 + * @param {Number} y4 + * @param {Number} z4 z-coordinate of the second control point. + * @chainable + */ + _main.default.prototype.curve = function () { + for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args[_key2] = arguments[_key2]; + } + _main.default._validateParameters('curve', args); + if (this._renderer._doStroke) { + var _this$_renderer2; + (_this$_renderer2 = this._renderer).curve.apply(_this$_renderer2, args); + } + return this; + }; + /** + * Sets the number of segments used to draw spline curves in WebGL mode. + * + * In WebGL mode, smooth shapes are drawn using many flat segments. Adding + * more flat segments makes shapes appear smoother. + * + * The parameter, `detail`, is the number of segments to use while drawing a + * spline curve. For example, calling `curveDetail(5)` will use 5 segments to + * draw curves with the curve() function. By + * default,`detail` is 20. + * + * Note: `curveDetail()` has no effect in 2D mode. + * + * @method curveDetail + * @param {Number} resolution number of segments to use. Defaults to 20. + * @chainable + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Draw a black spline curve. + * noFill(); + * strokeWeight(1); + * stroke(0); + * curve(5, 26, 73, 24, 73, 61, 15, 65); + * + * // Draw red spline curves from the anchor points to the control points. + * stroke(255, 0, 0); + * curve(5, 26, 5, 26, 73, 24, 73, 61); + * curve(73, 24, 73, 61, 15, 65, 15, 65); + * + * // Draw the anchor points in black. + * strokeWeight(5); + * stroke(0); + * point(73, 24); + * point(73, 61); + * + * // Draw the control points in red. + * stroke(255, 0, 0); + * point(5, 26); + * point(15, 65); + * + * describe( + * 'A gray square with a curve drawn in three segments. The curve is a sideways U shape with red segments on top and bottom, and a black segment on the right. The endpoints of all the segments are marked with dots.' + * ); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * background(200); + * + * // Set the curveDetail() to 3. + * curveDetail(3); + * + * // Draw a black spline curve. + * noFill(); + * strokeWeight(1); + * stroke(0); + * curve(-45, -24, 0, 23, -26, 0, 23, 11, 0, -35, 15, 0); + * + * // Draw red spline curves from the anchor points to the control points. + * stroke(255, 0, 0); + * curve(-45, -24, 0, -45, -24, 0, 23, -26, 0, 23, 11, 0); + * curve(23, -26, 0, 23, 11, 0, -35, 15, 0, -35, 15, 0); + * + * // Draw the anchor points in black. + * strokeWeight(5); + * stroke(0); + * point(23, -26); + * point(23, 11); + * + * // Draw the control points in red. + * stroke(255, 0, 0); + * point(-45, -24); + * point(-35, 15); + * + * describe( + * 'A gray square with a jagged curve drawn in three segments. The curve is a sideways U shape with red segments on top and bottom, and a black segment on the right. The endpoints of all the segments are marked with dots.' + * ); + * } + * + *
*/ _main.default.prototype.curveDetail = function (d) { _main.default._validateParameters('curveDetail', arguments); @@ -70324,30 +75365,42 @@ return this; }; /** - * Modifies the quality of forms created with curve() - * and curveVertex().The parameter tightness - * determines how the curve fits to the vertex points. The value 0.0 is the - * default value for tightness (this value defines the curves to be Catmull-Rom - * splines) and the value 1.0 connects all the points with straight lines. - * Values within the range -5.0 and 5.0 will deform the curves but will leave - * them recognizable and as values increase in magnitude, they will continue to deform. + * Adjusts the way curve() and + * curveVertex() draw. + * + * Spline curves are like cables that are attached to a set of points. + * `curveTightness()` adjusts how tightly the cable is attached to the points. + * + * The parameter, `tightness`, determines how the curve fits to the vertex + * points. By default, `tightness` is set to 0. Setting tightness to 1, + * as in `curveTightness(1)`, connects the curve's points using straight + * lines. Values in the range from –5 to 5 deform curves while leaving them + * recognizable. * * @method curveTightness - * @param {Number} amount amount of deformation from the original vertices + * @param {Number} amount amount of tightness. * @chainable + * * @example *
* - * // Move the mouse left and right to see the curve change + * // Move the mouse left and right to see the curve change. + * * function setup() { * createCanvas(100, 100); - * noFill(); + * + * describe('A black curve forms a sideways U shape. The curve deforms as the user moves the mouse from left to right'); * } * * function draw() { - * background(204); - * let t = map(mouseX, 0, width, -5, 5); + * background(200); + * + * // Set the curve's tightness using the mouse. + * let t = map(mouseX, 0, 100, -5, 5, true); * curveTightness(t); + * + * // Draw the curve. + * noFill(); * beginShape(); * curveVertex(10, 26); * curveVertex(10, 26); @@ -70359,9 +75412,6 @@ * } * *
- * - * @alt - * Line shaped like right-facing arrow,points move with mouse-x and warp shape. */ _main.default.prototype.curveTightness = function (t) { _main.default._validateParameters('curveTightness', arguments); @@ -70369,41 +75419,116 @@ return this; }; /** - * Evaluates the curve at position t for points a, b, c, d. - * The parameter t varies between 0 and 1, a and d are control points - * of the curve, and b and c are the start and end points of the curve. - * This can be done once with the x coordinates and a second time - * with the y coordinates to get the location of a curve at t. + * Calculates coordinates along a spline curve using interpolation. + * + * `curvePoint()` calculates coordinates along a spline curve using the + * anchor and control points. It expects points in the same order as the + * curve() function. `curvePoint()` works one axis + * at a time. Passing the anchor and control points' x-coordinates will + * calculate the x-coordinate of a point on the curve. Passing the anchor and + * control points' y-coordinates will calculate the y-coordinate of a point on + * the curve. + * + * The first parameter, `a`, is the coordinate of the first control point. + * + * The second and third parameters, `b` and `c`, are the coordinates of the + * anchor points. + * + * The fourth parameter, `d`, is the coordinate of the last control point. + * + * The fifth parameter, `t`, is the amount to interpolate along the curve. 0 + * is the first anchor point, 1 is the second anchor point, and 0.5 is halfway + * between them. * * @method curvePoint - * @param {Number} a coordinate of first control point of the curve - * @param {Number} b coordinate of first point - * @param {Number} c coordinate of second point - * @param {Number} d coordinate of second control point - * @param {Number} t value between 0 and 1 - * @return {Number} Curve value at position t + * @param {Number} a coordinate of first anchor point. + * @param {Number} b coordinate of first control point. + * @param {Number} c coordinate of second control point. + * @param {Number} d coordinate of second anchor point. + * @param {Number} t amount to interpolate between 0 and 1. + * @return {Number} coordinate of a point on the curve. + * * @example *
* - * noFill(); - * curve(5, 26, 5, 26, 73, 24, 73, 61); - * curve(5, 26, 73, 24, 73, 61, 15, 65); - * fill(255); - * ellipseMode(CENTER); - * let steps = 6; - * for (let i = 0; i <= steps; i++) { - * let t = i / steps; - * let x = curvePoint(5, 5, 73, 73, t); - * let y = curvePoint(26, 26, 24, 61, t); - * ellipse(x, y, 5, 5); - * x = curvePoint(5, 73, 73, 15, t); - * y = curvePoint(26, 24, 61, 65, t); - * ellipse(x, y, 5, 5); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Set the coordinates for the curve's anchor and control points. + * let x1 = 5; + * let y1 = 26; + * let x2 = 73; + * let y2 = 24; + * let x3 = 73; + * let y3 = 61; + * let x4 = 15; + * let y4 = 65; + * + * // Draw the curve. + * noFill(); + * curve(x1, y1, x2, y2, x3, y3, x4, y4); + * + * // Draw circles along the curve's path. + * fill(255); + * + * // Top. + * let x = curvePoint(x1, x2, x3, x4, 0); + * let y = curvePoint(y1, y2, y3, y4, 0); + * circle(x, y, 5); + * + * // Center. + * x = curvePoint(x1, x2, x3, x4, 0.5); + * y = curvePoint(y1, y2, y3, y4, 0.5); + * circle(x, y, 5); + * + * // Bottom. + * x = curvePoint(x1, x2, x3, x4, 1); + * y = curvePoint(y1, y2, y3, y4, 1); + * circle(x, y, 5); + * + * describe('A black curve on a gray square. The endpoints and center of the curve are marked with white circles.'); * } * *
* - *line hooking down to right-bottom with 13 5×5 white ellipse points + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * describe('A black curve on a gray square. A white circle moves back and forth along the curve.'); + * } + * + * function draw() { + * background(200); + * + * // Set the coordinates for the curve's anchor and control points. + * let x1 = 5; + * let y1 = 26; + * let x2 = 73; + * let y2 = 24; + * let x3 = 73; + * let y3 = 61; + * let x4 = 15; + * let y4 = 65; + * + * // Draw the curve. + * noFill(); + * curve(x1, y1, x2, y2, x3, y3, x4, y4); + * + * // Calculate the circle's coordinates. + * let t = 0.5 * sin(frameCount * 0.01) + 0.5; + * let x = curvePoint(x1, x2, x3, x4, t); + * let y = curvePoint(y1, y2, y3, y4, t); + * + * // Draw the circle. + * fill(255); + * circle(x, y, 5); + * } + * + *
*/ _main.default.prototype.curvePoint = function (a, b, c, d, t) { _main.default._validateParameters('curvePoint', arguments); @@ -70417,39 +75542,108 @@ return a * f1 + b * f2 + c * f3 + d * f4; }; /** - * Evaluates the tangent to the curve at position t for points a, b, c, d. - * The parameter t varies between 0 and 1, a and d are points on the curve, - * and b and c are the control points. + * Calculates coordinates along a line that's tangent to a spline curve. + * + * Tangent lines skim the surface of a curve. A tangent line's slope equals + * the curve's slope at the point where it intersects. + * + * `curveTangent()` calculates coordinates along a tangent line using the + * spline curve's anchor and control points. It expects points in the same + * order as the curve() function. `curveTangent()` + * works one axis at a time. Passing the anchor and control points' + * x-coordinates will calculate the x-coordinate of a point on the tangent + * line. Passing the anchor and control points' y-coordinates will calculate + * the y-coordinate of a point on the tangent line. + * + * The first parameter, `a`, is the coordinate of the first control point. + * + * The second and third parameters, `b` and `c`, are the coordinates of the + * anchor points. + * + * The fourth parameter, `d`, is the coordinate of the last control point. + * + * The fifth parameter, `t`, is the amount to interpolate along the curve. 0 + * is the first anchor point, 1 is the second anchor point, and 0.5 is halfway + * between them. * * @method curveTangent - * @param {Number} a coordinate of first control point - * @param {Number} b coordinate of first point on the curve - * @param {Number} c coordinate of second point on the curve - * @param {Number} d coordinate of second conrol point - * @param {Number} t value between 0 and 1 - * @return {Number} the tangent at position t + * @param {Number} a coordinate of first control point. + * @param {Number} b coordinate of first anchor point. + * @param {Number} c coordinate of second anchor point. + * @param {Number} d coordinate of second control point. + * @param {Number} t amount to interpolate between 0 and 1. + * @return {Number} coordinate of a point on the tangent line. + * * @example *
* - * noFill(); - * curve(5, 26, 73, 24, 73, 61, 15, 65); - * let steps = 6; - * for (let i = 0; i <= steps; i++) { - * let t = i / steps; - * let x = curvePoint(5, 73, 73, 15, t); - * let y = curvePoint(26, 24, 61, 65, t); - * //ellipse(x, y, 5, 5); - * let tx = curveTangent(5, 73, 73, 15, t); - * let ty = curveTangent(26, 24, 61, 65, t); - * let a = atan2(ty, tx); - * a -= PI / 2.0; - * line(x, y, cos(a) * 8 + x, sin(a) * 8 + y); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Set the coordinates for the curve's anchor and control points. + * let x1 = 5; + * let y1 = 26; + * let x2 = 73; + * let y2 = 24; + * let x3 = 73; + * let y3 = 61; + * let x4 = 15; + * let y4 = 65; + * + * // Draw the curve. + * noFill(); + * curve(x1, y1, x2, y2, x3, y3, x4, y4); + * + * // Draw tangents along the curve's path. + * fill(255); + * + * // Top circle. + * stroke(0); + * let x = curvePoint(x1, x2, x3, x4, 0); + * let y = curvePoint(y1, y2, y3, y4, 0); + * circle(x, y, 5); + * + * // Top tangent line. + * // Scale the tangent point to draw a shorter line. + * stroke(255, 0, 0); + * let tx = 0.2 * curveTangent(x1, x2, x3, x4, 0); + * let ty = 0.2 * curveTangent(y1, y2, y3, y4, 0); + * line(x + tx, y + ty, x - tx, y - ty); + * + * // Center circle. + * stroke(0); + * x = curvePoint(x1, x2, x3, x4, 0.5); + * y = curvePoint(y1, y2, y3, y4, 0.5); + * circle(x, y, 5); + * + * // Center tangent line. + * // Scale the tangent point to draw a shorter line. + * stroke(255, 0, 0); + * tx = 0.2 * curveTangent(x1, x2, x3, x4, 0.5); + * ty = 0.2 * curveTangent(y1, y2, y3, y4, 0.5); + * line(x + tx, y + ty, x - tx, y - ty); + * + * // Bottom circle. + * stroke(0); + * x = curvePoint(x1, x2, x3, x4, 1); + * y = curvePoint(y1, y2, y3, y4, 1); + * circle(x, y, 5); + * + * // Bottom tangent line. + * // Scale the tangent point to draw a shorter line. + * stroke(255, 0, 0); + * tx = 0.2 * curveTangent(x1, x2, x3, x4, 1); + * ty = 0.2 * curveTangent(y1, y2, y3, y4, 1); + * line(x + tx, y + ty, x - tx, y - ty); + * + * describe( + * 'A black curve on a gray square. A white circle moves back and forth along the curve.' + * ); * } * *
- * - * @alt - * right curving line mid-right of canvas with 7 short lines radiating from it. */ _main.default.prototype.curveTangent = function (a, b, c, d, t) { _main.default._validateParameters('curveTangent', arguments); @@ -70466,13 +75660,13 @@ exports.default = _default; }, { - '../friendly_errors/fes_core': 289, - '../friendly_errors/file_errors': 290, - '../friendly_errors/validate_params': 293, - '../main': 298 + '../friendly_errors/fes_core': 297, + '../friendly_errors/file_errors': 298, + '../friendly_errors/validate_params': 301, + '../main': 306 } ], - 308: [ + 316: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -70581,45 +75775,103 @@ var isContour = false; var isFirstContour = true; /** - * Use the beginContour() and - * endContour() functions to create negative shapes - * within shapes such as the center of the letter 'O'. beginContour() - * begins recording vertices for the shape and endContour() stops recording. - * The vertices that define a negative shape must "wind" in the opposite direction - * from the exterior shape. First draw vertices for the exterior clockwise order, then for internal shapes, draw vertices - * shape in counter-clockwise. - * - * These functions can only be used within a beginShape()/endShape() pair and - * transformations such as translate(), rotate(), and scale() do not work - * within a beginContour()/endContour() pair. It is also not possible to use - * other shapes, such as ellipse() or rect() within. + * Begins creating a hole within a flat shape. + * + * The `beginContour()` and endContour() + * functions allow for creating negative space within custom shapes that are + * flat. `beginContour()` begins adding vertices to a negative space and + * endContour() stops adding them. + * `beginContour()` and endContour() must be + * called between beginShape() and + * endShape(). + * + * Transformations such as translate(), + * rotate(), and scale() + * don't work between `beginContour()` and + * endContour(). It's also not possible to use + * other shapes, such as ellipse() or + * rect(), between `beginContour()` and + * endContour(). + * + * Note: The vertices that define a negative space must "wind" in the opposite + * direction from the outer shape. First, draw vertices for the outer shape + * clockwise order. Then, draw vertices for the negative space in + * counter-clockwise order. * * @method beginContour * @chainable + * * @example *
* - * translate(50, 50); - * stroke(255, 0, 0); - * beginShape(); - * // Exterior part of shape, clockwise winding - * vertex(-40, -40); - * vertex(40, -40); - * vertex(40, 40); - * vertex(-40, 40); - * // Interior part of shape, counter-clockwise winding - * beginContour(); - * vertex(-20, -20); - * vertex(-20, 20); - * vertex(20, 20); - * vertex(20, -20); - * endContour(); - * endShape(CLOSE); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Start drawing the shape. + * beginShape(); + * + * // Exterior vertices, clockwise winding. + * vertex(10, 10); + * vertex(90, 10); + * vertex(90, 90); + * vertex(10, 90); + * + * // Interior vertices, counter-clockwise winding. + * beginContour(); + * vertex(30, 30); + * vertex(30, 70); + * vertex(70, 70); + * vertex(70, 30); + * endContour(); + * + * // Stop drawing the shape. + * endShape(CLOSE); + * + * describe('A white square with a square hole in its center drawn on a gray background.'); + * } * *
* - * @alt - * white rect and smaller grey rect with red outlines in center of canvas. + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white square with a square hole in its center drawn on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Start drawing the shape. + * beginShape(); + * + * // Exterior vertices, clockwise winding. + * vertex(-40, -40); + * vertex(40, -40); + * vertex(40, 40); + * vertex(-40, 40); + * + * // Interior vertices, counter-clockwise winding. + * beginContour(); + * vertex(-20, -20); + * vertex(-20, 20); + * vertex(20, 20); + * vertex(20, -20); + * endContour(); + * + * // Stop drawing the shape. + * endShape(CLOSE); + * } + * + *
*/ _main.default.prototype.beginContour = function () { if (this._renderer.isP3D) { @@ -70632,205 +75884,393 @@ return this; }; /** - * Using the beginShape() and endShape() functions allow creating more - * complex forms. beginShape() begins recording vertices for a shape and - * endShape() stops recording. The value of the kind parameter tells it which - * types of shapes to create from the provided vertices. With no mode - * specified, the shape can be any irregular polygon. + * Begins adding vertices to a custom shape. + * + * The `beginShape()` and endShape() functions + * allow for creating custom shapes in 2D or 3D. `beginShape()` begins adding + * vertices to a custom shape and endShape() stops + * adding them. + * + * The parameter, `kind`, sets the kind of shape to make. By default, any + * irregular polygon can be drawn. The available modes for kind are: + * + * - `POINTS` to draw a series of points. + * - `LINES` to draw a series of unconnected line segments. + * - `TRIANGLES` to draw a series of separate triangles. + * - `TRIANGLE_FAN` to draw a series of connected triangles sharing the first vertex in a fan-like fashion. + * - `TRIANGLE_STRIP` to draw a series of connected triangles in strip fashion. + * - `QUADS` to draw a series of separate quadrilaterals (quads). + * - `QUAD_STRIP` to draw quad strip using adjacent edges to form the next quad. + * - `TESS` to create a filling curve by explicit tessellation (WebGL only). + * + * After calling `beginShape()`, shapes can be built by calling + * vertex(), + * bezierVertex(), + * quadraticVertex(), and/or + * curveVertex(). Calling + * endShape() will stop adding vertices to the + * shape. Each shape will be outlined with the current stroke color and filled + * with the current fill color. + * + * Transformations such as translate(), + * rotate(), and + * scale() don't work between `beginShape()` and + * endShape(). It's also not possible to use + * other shapes, such as ellipse() or + * rect(), between `beginShape()` and + * endShape(). + * + * @method beginShape + * @param {Constant} [kind] either POINTS, LINES, TRIANGLES, TRIANGLE_FAN + * TRIANGLE_STRIP, QUADS, QUAD_STRIP or TESS. + * @chainable * - * The parameters available for beginShape() are: + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); * - * POINTS - * Draw a series of points + * background(200); * - * LINES - * Draw a series of unconnected line segments (individual lines) + * // Start drawing the shape. + * beginShape(); * - * TRIANGLES - * Draw a series of separate triangles + * // Add vertices. + * vertex(30, 20); + * vertex(85, 20); + * vertex(85, 75); + * vertex(30, 75); * - * TRIANGLE_FAN - * Draw a series of connected triangles sharing the first vertex in a fan-like fashion + * // Stop drawing the shape. + * endShape(CLOSE); * - * TRIANGLE_STRIP - * Draw a series of connected triangles in strip fashion + * describe('A white square on a gray background.'); + * } + * + *
* - * QUADS - * Draw a series of separate quads + *
+ * + * function setup() { + * createCanvas(100, 100); * - * QUAD_STRIP - * Draw quad strip using adjacent edges to form the next quad + * background(200); * - * TESS (WEBGL only) - * Handle irregular polygon for filling curve by explicit tessellation + * // Start drawing the shape. + * // Only draw the vertices (points). + * beginShape(POINTS); * - * After calling the beginShape() function, a series of vertex() commands must follow. To stop - * drawing the shape, call endShape(). Each shape will be outlined with the - * current stroke color and filled with the fill color. + * // Add vertices. + * vertex(30, 20); + * vertex(85, 20); + * vertex(85, 75); + * vertex(30, 75); * - * Transformations such as translate(), rotate(), and scale() do not work - * within beginShape(). It is also not possible to use other shapes, such as - * ellipse() or rect() within beginShape(). + * // Stop drawing the shape. + * endShape(); * - * @method beginShape - * @param {Constant} [kind] either POINTS, LINES, TRIANGLES, TRIANGLE_FAN - * TRIANGLE_STRIP, QUADS, QUAD_STRIP or TESS - * @chainable - * @example - *
- * - * beginShape(); - * vertex(30, 20); - * vertex(85, 20); - * vertex(85, 75); - * vertex(30, 75); - * endShape(CLOSE); + * describe('Four black dots that form a square are drawn on a gray background.'); + * } * *
* *
* - * beginShape(POINTS); - * vertex(30, 20); - * vertex(85, 20); - * vertex(85, 75); - * vertex(30, 75); - * endShape(); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Start drawing the shape. + * // Only draw lines between alternating pairs of vertices. + * beginShape(LINES); + * + * // Add vertices. + * vertex(30, 20); + * vertex(85, 20); + * vertex(85, 75); + * vertex(30, 75); + * + * // Stop drawing the shape. + * endShape(); + * + * describe('Two horizontal black lines on a gray background.'); + * } * *
* *
* - * beginShape(LINES); - * vertex(30, 20); - * vertex(85, 20); - * vertex(85, 75); - * vertex(30, 75); - * endShape(); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the shape. + * noFill(); + * + * // Start drawing the shape. + * beginShape(); + * + * // Add vertices. + * vertex(30, 20); + * vertex(85, 20); + * vertex(85, 75); + * vertex(30, 75); + * + * // Stop drawing the shape. + * endShape(); + * + * describe('Three black lines form a sideways U shape on a gray background.'); + * } * *
* *
* - * noFill(); - * beginShape(); - * vertex(30, 20); - * vertex(85, 20); - * vertex(85, 75); - * vertex(30, 75); - * endShape(); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the shape. + * noFill(); + * + * // Start drawing the shape. + * beginShape(); + * + * // Add vertices. + * vertex(30, 20); + * vertex(85, 20); + * vertex(85, 75); + * vertex(30, 75); + * + * // Stop drawing the shape. + * // Connect the first and last vertices. + * endShape(CLOSE); + * + * describe('A black outline of a square drawn on a gray background.'); + * } * *
* *
* - * noFill(); - * beginShape(); - * vertex(30, 20); - * vertex(85, 20); - * vertex(85, 75); - * vertex(30, 75); - * endShape(CLOSE); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Start drawing the shape. + * // Draw a series of triangles. + * beginShape(TRIANGLES); + * + * // Left triangle. + * vertex(30, 75); + * vertex(40, 20); + * vertex(50, 75); + * + * // Right triangle. + * vertex(60, 20); + * vertex(70, 75); + * vertex(80, 20); + * + * // Stop drawing the shape. + * endShape(); + * + * describe('Two white triangles drawn on a gray background.'); + * } * *
* *
* - * beginShape(TRIANGLES); - * vertex(30, 75); - * vertex(40, 20); - * vertex(50, 75); - * vertex(60, 20); - * vertex(70, 75); - * vertex(80, 20); - * endShape(); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Start drawing the shape. + * // Draw a series of triangles. + * beginShape(TRIANGLE_STRIP); + * + * // Add vertices. + * vertex(30, 75); + * vertex(40, 20); + * vertex(50, 75); + * vertex(60, 20); + * vertex(70, 75); + * vertex(80, 20); + * vertex(90, 75); + * + * // Stop drawing the shape. + * endShape(); + * + * describe('Five white triangles that are interleaved drawn on a gray background.'); + * } * *
* *
* - * beginShape(TRIANGLE_STRIP); - * vertex(30, 75); - * vertex(40, 20); - * vertex(50, 75); - * vertex(60, 20); - * vertex(70, 75); - * vertex(80, 20); - * vertex(90, 75); - * endShape(); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Start drawing the shape. + * // Draw a series of triangles that share their first vertex. + * beginShape(TRIANGLE_FAN); + * + * // Add vertices. + * vertex(57.5, 50); + * vertex(57.5, 15); + * vertex(92, 50); + * vertex(57.5, 85); + * vertex(22, 50); + * vertex(57.5, 15); + * + * // Stop drawing the shape. + * endShape(); + * + * describe('Four white triangles form a square are drawn on a gray background.'); + * } * *
* *
* - * beginShape(TRIANGLE_FAN); - * vertex(57.5, 50); - * vertex(57.5, 15); - * vertex(92, 50); - * vertex(57.5, 85); - * vertex(22, 50); - * vertex(57.5, 15); - * endShape(); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Start drawing the shape. + * // Draw a series of quadrilaterals. + * beginShape(QUADS); + * + * // Left rectangle. + * vertex(30, 20); + * vertex(30, 75); + * vertex(50, 75); + * vertex(50, 20); + * + * // Right rectangle. + * vertex(65, 20); + * vertex(65, 75); + * vertex(85, 75); + * vertex(85, 20); + * + * // Stop drawing the shape. + * endShape(); + * + * describe('Two white rectangles drawn on a gray background.'); + * } * *
* *
* - * beginShape(QUADS); - * vertex(30, 20); - * vertex(30, 75); - * vertex(50, 75); - * vertex(50, 20); - * vertex(65, 20); - * vertex(65, 75); - * vertex(85, 75); - * vertex(85, 20); - * endShape(); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Start drawing the shape. + * // Draw a series of quadrilaterals. + * beginShape(QUAD_STRIP); + * + * // Add vertices. + * vertex(30, 20); + * vertex(30, 75); + * vertex(50, 20); + * vertex(50, 75); + * vertex(65, 20); + * vertex(65, 75); + * vertex(85, 20); + * vertex(85, 75); + * + * // Stop drawing the shape. + * endShape(); + * + * describe('Three white rectangles that share edges are drawn on a gray background.'); + * } * *
* *
* - * beginShape(QUAD_STRIP); - * vertex(30, 20); - * vertex(30, 75); - * vertex(50, 20); - * vertex(50, 75); - * vertex(65, 20); - * vertex(65, 75); - * vertex(85, 20); - * vertex(85, 75); - * endShape(); + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * background(200); + * + * // Start drawing the shape. + * // Draw a series of quadrilaterals. + * beginShape(TESS); + * + * // Add the vertices. + * vertex(-30, -30, 0); + * vertex(30, -30, 0); + * vertex(30, -10, 0); + * vertex(-10, -10, 0); + * vertex(-10, 10, 0); + * vertex(30, 10, 0); + * vertex(30, 30, 0); + * vertex(-30, 30, 0); + * + * // Stop drawing the shape. + * // Connect the first and last vertices. + * endShape(CLOSE); + * + * describe('A blocky C shape drawn in white on a gray background.'); + * } * *
* *
* - * beginShape(TESS); - * vertex(20, 20); - * vertex(80, 20); - * vertex(80, 40); - * vertex(40, 40); - * vertex(40, 60); - * vertex(80, 60); - * vertex(80, 80); - * vertex(20, 80); - * endShape(CLOSE); + * // Click and drag with the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A blocky C shape drawn in red, blue, and green on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Start drawing the shape. + * // Draw a series of quadrilaterals. + * beginShape(TESS); + * + * // Add the vertices. + * fill('red'); + * stroke('red'); + * vertex(-30, -30, 0); + * vertex(30, -30, 0); + * vertex(30, -10, 0); + * fill('green'); + * stroke('green'); + * vertex(-10, -10, 0); + * vertex(-10, 10, 0); + * vertex(30, 10, 0); + * fill('blue'); + * stroke('blue'); + * vertex(30, 30, 0); + * vertex(-30, 30, 0); + * + * // Stop drawing the shape. + * // Connect the first and last vertices. + * endShape(CLOSE); + * } * *
- * - * @alt - * white square-shape with black outline in middle-right of canvas. - * 4 black points in a square shape in middle-right of canvas. - * 2 horizontal black lines. In the top-right and bottom-right of canvas. - * 3 line shape with horizontal on top, vertical in middle and horizontal bottom. - * square line shape in middle-right of canvas. - * 2 white triangle shapes mid-right canvas. left one pointing up and right down. - * 5 horizontal interlocking and alternating white triangles in mid-right canvas. - * 4 interlocking white triangles in 45 degree rotated square-shape. - * 2 white rectangle shapes in mid-right canvas. Both 20×55. - * 3 side-by-side white rectangles center rect is smaller in mid-right canvas. - * Thick white l-shape with black outline mid-top-left of canvas. */ _main.default.prototype.beginShape = function (kind) { _main.default._validateParameters('beginShape', arguments); @@ -70851,97 +76291,264 @@ return this; }; /** - * Specifies vertex coordinates for Bezier curves. Each call to - * bezierVertex() defines the position of two control points and - * one anchor point of a Bezier curve, adding a new segment to a - * line or shape. For WebGL mode bezierVertex() can be used in 2D - * as well as 3D mode. 2D mode expects 6 parameters, while 3D mode - * expects 9 parameters (including z coordinates). + * Adds a Bézier curve segment to a custom shape. + * + * `bezierVertex()` adds a curved segment to custom shapes. The Bézier curves + * it creates are defined like those made by the + * bezier() function. `bezierVertex()` must be + * called between the + * beginShape() and + * endShape() functions. The curved segment uses + * the previous vertex as the first anchor point, so there must be at least + * one call to vertex() before `bezierVertex()` can + * be used. + * + * The first four parameters, `x2`, `y2`, `x3`, and `y3`, set the curve’s two + * control points. The control points "pull" the curve towards them. + * + * The fifth and sixth parameters, `x4`, and `y4`, set the last anchor point. + * The last anchor point is where the curve ends. * - * The first time bezierVertex() is used within a beginShape() - * call, it must be prefaced with a call to vertex() to set the first anchor - * point. This function must be used between beginShape() and endShape() - * and only when there is no MODE or POINTS parameter specified to + * Bézier curves can also be drawn in 3D using WebGL mode. The 3D version of + * `bezierVertex()` has eight arguments because each point has x-, y-, and + * z-coordinates. + * + * Note: `bezierVertex()` won’t work when an argument is passed to * beginShape(). * * @method bezierVertex - * @param {Number} x2 x-coordinate for the first control point - * @param {Number} y2 y-coordinate for the first control point - * @param {Number} x3 x-coordinate for the second control point - * @param {Number} y3 y-coordinate for the second control point - * @param {Number} x4 x-coordinate for the anchor point - * @param {Number} y4 y-coordinate for the anchor point + * @param {Number} x2 x-coordinate of the first control point. + * @param {Number} y2 y-coordinate of the first control point. + * @param {Number} x3 x-coordinate of the second control point. + * @param {Number} y3 y-coordinate of the second control point. + * @param {Number} x4 x-coordinate of the anchor point. + * @param {Number} y4 y-coordinate of the anchor point. * @chainable * * @example *
* - * noFill(); - * beginShape(); - * vertex(30, 20); - * bezierVertex(80, 0, 80, 75, 30, 75); - * endShape(); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the shape. + * noFill(); + * + * // Start drawing the shape. + * beginShape(); + * + * // Add the first anchor point. + * vertex(30, 20); + * + * // Add the Bézier vertex. + * bezierVertex(80, 0, 80, 75, 30, 75); + * + * // Stop drawing the shape. + * endShape(); + * + * describe('A black C curve on a gray background.'); + * } * *
* *
* - * beginShape(); - * vertex(30, 20); - * bezierVertex(80, 0, 80, 75, 30, 75); - * bezierVertex(50, 80, 60, 25, 30, 20); - * endShape(); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Draw the anchor points in black. + * stroke(0); + * strokeWeight(5); + * point(30, 20); + * point(30, 75); + * + * // Draw the control points in red. + * stroke(255, 0, 0); + * point(80, 0); + * point(80, 75); + * + * // Style the shape. + * noFill(); + * stroke(0); + * strokeWeight(1); + * + * // Start drawing the shape. + * beginShape(); + * + * // Add the first anchor point. + * vertex(30, 20); + * + * // Add the Bézier vertex. + * bezierVertex(80, 0, 80, 75, 30, 75); + * + * // Stop drawing the shape. + * endShape(); + * + * // Draw red lines from the anchor points to the control points. + * stroke(255, 0, 0); + * line(30, 20, 80, 0); + * line(30, 75, 80, 75); + * + * describe( + * 'A gray square with three curves. A black curve has two straight, red lines that extend from its ends. The endpoints of all the curves are marked with dots.' + * ); + * } * *
* *
* + * // Click the mouse near the red dot in the top-right corner + * // and drag to change the curve's shape. + * + * let x2 = 80; + * let y2 = 0; + * let isChanging = false; + * * function setup() { - * createCanvas(100, 100, WEBGL); - * setAttributes('antialias', true); + * createCanvas(100, 100); + * + * describe( + * 'A gray square with three curves. A black curve has two straight, red lines that extend from its ends. The endpoints of all the curves are marked with dots.' + * ); * } + * * function draw() { - * orbitControl(); - * background(50); - * strokeWeight(4); - * stroke(255); - * point(-25, 30); - * point(25, 30); - * point(25, -30); - * point(-25, -30); + * background(200); * - * strokeWeight(1); + * // Draw the anchor points in black. + * stroke(0); + * strokeWeight(5); + * point(30, 20); + * point(30, 75); + * + * // Draw the control points in red. + * stroke(255, 0, 0); + * point(x2, y2); + * point(80, 75); + * + * // Style the shape. * noFill(); + * stroke(0); + * strokeWeight(1); * + * // Start drawing the shape. * beginShape(); - * vertex(-25, 30); - * bezierVertex(25, 30, 25, -30, -25, -30); - * endShape(); * - * beginShape(); - * vertex(-25, 30, 20); - * bezierVertex(25, 30, 20, 25, -30, 20, -25, -30, 20); + * // Add the first anchor point. + * vertex(30, 20); + * + * // Add the Bézier vertex. + * bezierVertex(x2, y2, 80, 75, 30, 75); + * + * // Stop drawing the shape. * endShape(); + * + * // Draw red lines from the anchor points to the control points. + * stroke(255, 0, 0); + * line(30, 20, x2, y2); + * line(30, 75, 80, 75); * } - * - *
* - * @alt - * crescent-shaped line in middle of canvas. Points facing left. - * white crescent shape in middle of canvas. Points facing left. - * crescent shape in middle of canvas with another crescent shape on positive z-axis. - */ + * // Start changing the first control point if the user clicks near it. + * function mousePressed() { + * if (dist(mouseX, mouseY, x2, y2) < 20) { + * isChanging = true; + * } + * } + * + * // Stop changing the first control point when the user releases the mouse. + * function mouseReleased() { + * isChanging = false; + * } + * + * // Update the first control point while the user drags the mouse. + * function mouseDragged() { + * if (isChanging === true) { + * x2 = mouseX; + * y2 = mouseY; + * } + * } + *
+ *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Start drawing the shape. + * beginShape(); + * + * // Add the first anchor point. + * vertex(30, 20); + * + * // Add the Bézier vertices. + * bezierVertex(80, 0, 80, 75, 30, 75); + * bezierVertex(50, 80, 60, 25, 30, 20); + * + * // Stop drawing the shape. + * endShape(); + * + * describe('A crescent moon shape drawn in white on a gray background.'); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A crescent moon shape drawn in white on a blue background. When the user drags the mouse, the scene rotates and a second moon is revealed.'); + * } + * + * function draw() { + * background('midnightblue'); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Style the moons. + * noStroke(); + * fill('lemonchiffon'); + * + * // Draw the first moon. + * beginShape(); + * vertex(-20, -30, 0); + * bezierVertex(30, -50, 0, 30, 25, 0, -20, 25, 0); + * bezierVertex(0, 30, 0, 10, -25, 0, -20, -30, 0); + * endShape(); + * + * // Draw the second moon. + * beginShape(); + * vertex(-20, -30, -20); + * bezierVertex(30, -50, -20, 30, 25, -20, -20, 25, -20); + * bezierVertex(0, 30, -20, 10, -25, -20, -20, -30, -20); + * endShape(); + * } + * + *
+ */ /** * @method bezierVertex * @param {Number} x2 * @param {Number} y2 - * @param {Number} z2 z-coordinate for the first control point (for WebGL mode) + * @param {Number} z2 z-coordinate of the first control point. * @param {Number} x3 * @param {Number} y3 - * @param {Number} z3 z-coordinate for the second control point (for WebGL mode) + * @param {Number} z3 z-coordinate of the second control point. * @param {Number} x4 * @param {Number} y4 - * @param {Number} z4 z-coordinate for the anchor point (for WebGL mode) + * @param {Number} z4 z-coordinate of the anchor point. * @chainable */ _main.default.prototype.bezierVertex = function () { @@ -70973,101 +76580,384 @@ return this; }; /** - * Specifies vertex coordinates for curves. This function may only - * be used between beginShape() and endShape() and only when there - * is no MODE parameter specified to beginShape(). - * For WebGL mode curveVertex() can be used in 2D as well as 3D mode. - * 2D mode expects 2 parameters, while 3D mode expects 3 parameters. + * Adds a spline curve segment to a custom shape. * - * The first and last points in a series of curveVertex() lines will be used to - * guide the beginning and end of the curve. A minimum of four - * points is required to draw a tiny curve between the second and - * third points. Adding a fifth point with curveVertex() will draw - * the curve between the second, third, and fourth points. The - * curveVertex() function is an implementation of Catmull-Rom - * splines. + * `curveVertex()` adds a curved segment to custom shapes. The spline curves + * it creates are defined like those made by the + * curve() function. `curveVertex()` must be called + * between the beginShape() and + * endShape() functions. + * + * Spline curves can form shapes and curves that slope gently. They’re like + * cables that are attached to a set of points. Splines are defined by two + * anchor points and two control points. `curveVertex()` must be called at + * least four times between + * beginShape() and + * endShape() in order to draw a curve: * - * @method curveVertex - * @param {Number} x x-coordinate of the vertex - * @param {Number} y y-coordinate of the vertex - * @chainable - * @example - *
* - * strokeWeight(5); - * point(84, 91); - * point(68, 19); - * point(21, 17); - * point(32, 91); - * strokeWeight(1); + * beginShape(); + * + * // Add the first control point. + * curveVertex(84, 91); * - * noFill(); + * // Add the anchor points to draw between. + * curveVertex(68, 19); + * curveVertex(21, 17); + * + * // Add the second control point. + * curveVertex(32, 91); + * + * endShape(); + * + * + * The code snippet above would only draw the curve between the anchor points, + * similar to the curve() function. The segments + * between the control and anchor points can be drawn by calling + * `curveVertex()` with the coordinates of the control points: + * + * * beginShape(); + * + * // Add the first control point and draw a segment to it. * curveVertex(84, 91); * curveVertex(84, 91); + * + * // Add the anchor points to draw between. * curveVertex(68, 19); * curveVertex(21, 17); + * + * // Add the second control point. * curveVertex(32, 91); - * curveVertex(32, 91); + * + * // Uncomment the next line to draw the segment to the second control point. + * // curveVertex(32, 91); + * * endShape(); * + * + * The first two parameters, `x` and `y`, set the vertex’s location. For + * example, calling `curveVertex(10, 10)` adds a point to the curve at + * `(10, 10)`. + * + * Spline curves can also be drawn in 3D using WebGL mode. The 3D version of + * `curveVertex()` has three arguments because each point has x-, y-, and + * z-coordinates. By default, the vertex’s z-coordinate is set to 0. + * + * Note: `curveVertex()` won’t work when an argument is passed to + * beginShape(). + * + * @method curveVertex + * @param {Number} x x-coordinate of the vertex + * @param {Number} y y-coordinate of the vertex + * @chainable + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the shape. + * noFill(); + * strokeWeight(1); + * + * // Start drawing the shape. + * beginShape(); + * + * // Add the first control point. + * curveVertex(32, 91); + * + * // Add the anchor points. + * curveVertex(21, 17); + * curveVertex(68, 19); + * + * // Add the second control point. + * curveVertex(84, 91); + * + * // Stop drawing the shape. + * endShape(); + * + * // Style the anchor and control points. + * strokeWeight(5); + * + * // Draw the anchor points in black. + * stroke(0); + * point(21, 17); + * point(68, 19); + * + * // Draw the control points in red. + * stroke(255, 0, 0); + * point(32, 91); + * point(84, 91); + * + * describe( + * 'A black curve drawn on a gray background. The curve has black dots at its ends. Two red dots appear near the bottom of the canvas.' + * ); + * } + * *
* - * @alt - * Upside-down u-shape line, mid canvas. left point extends beyond canvas view. + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the shape. + * noFill(); + * strokeWeight(1); + * + * // Start drawing the shape. + * beginShape(); + * + * // Add the first control point and draw a segment to it. + * curveVertex(32, 91); + * curveVertex(32, 91); + * + * // Add the anchor points. + * curveVertex(21, 17); + * curveVertex(68, 19); + * + * // Add the second control point. + * curveVertex(84, 91); + * + * // Stop drawing the shape. + * endShape(); + * + * // Style the anchor and control points. + * strokeWeight(5); + * + * // Draw the anchor points in black. + * stroke(0); + * point(21, 17); + * point(68, 19); + * + * // Draw the control points in red. + * stroke(255, 0, 0); + * point(32, 91); + * point(84, 91); + * + * describe( + * 'A black curve drawn on a gray background. The curve passes through one red dot and two black dots. Another red dot appears near the bottom of the canvas.' + * ); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the shape. + * noFill(); + * strokeWeight(1); + * + * // Start drawing the shape. + * beginShape(); + * + * // Add the first control point and draw a segment to it. + * curveVertex(32, 91); + * curveVertex(32, 91); + * + * // Add the anchor points. + * curveVertex(21, 17); + * curveVertex(68, 19); + * + * // Add the second control point and draw a segment to it. + * curveVertex(84, 91); + * curveVertex(84, 91); + * + * // Stop drawing the shape. + * endShape(); + * + * // Style the anchor and control points. + * strokeWeight(5); + * + * // Draw the anchor points in black. + * stroke(0); + * point(21, 17); + * point(68, 19); + * + * // Draw the control points in red. + * stroke(255, 0, 0); + * point(32, 91); + * point(84, 91); + * + * describe( + * 'A black U curve drawn upside down on a gray background. The curve passes from one red dot through two black dots and ends at another red dot.' + * ); + * } + * + *
+ * + *
+ * + * // Click the mouse near the red dot in the bottom-left corner + * // and drag to change the curve's shape. + * + * let x1 = 32; + * let y1 = 91; + * let isChanging = false; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A black U curve drawn upside down on a gray background. The curve passes from one red dot through two black dots and ends at another red dot.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Style the shape. + * noFill(); + * stroke(0); + * strokeWeight(1); + * + * // Start drawing the shape. + * beginShape(); + * + * // Add the first control point and draw a segment to it. + * curveVertex(x1, y1); + * curveVertex(x1, y1); + * + * // Add the anchor points. + * curveVertex(21, 17); + * curveVertex(68, 19); + * + * // Add the second control point and draw a segment to it. + * curveVertex(84, 91); + * curveVertex(84, 91); + * + * // Stop drawing the shape. + * endShape(); + * + * // Style the anchor and control points. + * strokeWeight(5); + * + * // Draw the anchor points in black. + * stroke(0); + * point(21, 17); + * point(68, 19); + * + * // Draw the control points in red. + * stroke(255, 0, 0); + * point(x1, y1); + * point(84, 91); + * } + * + * // Start changing the first control point if the user clicks near it. + * function mousePressed() { + * if (dist(mouseX, mouseY, x1, y1) < 20) { + * isChanging = true; + * } + * } + * + * // Stop changing the first control point when the user releases the mouse. + * function mouseReleased() { + * isChanging = false; + * } + * + * // Update the first control point while the user drags the mouse. + * function mouseDragged() { + * if (isChanging === true) { + * x1 = mouseX; + * y1 = mouseY; + * } + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Start drawing the shape. + * beginShape(); + * + * // Add the first control point and draw a segment to it. + * curveVertex(32, 91); + * curveVertex(32, 91); + * + * // Add the anchor points. + * curveVertex(21, 17); + * curveVertex(68, 19); + * + * // Add the second control point. + * curveVertex(84, 91); + * curveVertex(84, 91); + * + * // Stop drawing the shape. + * endShape(); + * + * describe('A ghost shape drawn in white on a gray background.'); + * } + * + *
*/ /** * @method curveVertex * @param {Number} x * @param {Number} y - * @param {Number} [z] z-coordinate of the vertex (for WebGL mode) + * @param {Number} [z] z-coordinate of the vertex. * @chainable + * * @example *
* + * // Click and drag the mouse to view the scene from different angles. + * * function setup() { * createCanvas(100, 100, WEBGL); - * setAttributes('antialias', true); + * + * describe('A ghost shape drawn in white on a blue background. When the user drags the mouse, the scene rotates to reveal the outline of a second ghost.'); * } + * * function draw() { - * orbitControl(); - * background(50); - * strokeWeight(4); - * stroke(255); + * background('midnightblue'); * - * point(-25, 25); - * point(-25, 25); - * point(-25, -25); - * point(25, -25); - * point(25, 25); - * point(25, 25); + * // Enable orbiting with the mouse. + * orbitControl(); * - * strokeWeight(1); - * noFill(); + * // Draw the first ghost. + * noStroke(); + * fill('ghostwhite'); * * beginShape(); - * curveVertex(-25, 25); - * curveVertex(-25, 25); - * curveVertex(-25, -25); - * curveVertex(25, -25); - * curveVertex(25, 25); - * curveVertex(25, 25); + * curveVertex(-28, 41, 0); + * curveVertex(-28, 41, 0); + * curveVertex(-29, -33, 0); + * curveVertex(18, -31, 0); + * curveVertex(34, 41, 0); + * curveVertex(34, 41, 0); * endShape(); * + * // Draw the second ghost. + * noFill(); + * stroke('ghostwhite'); + * * beginShape(); - * curveVertex(-25, 25, 20); - * curveVertex(-25, 25, 20); - * curveVertex(-25, -25, 20); - * curveVertex(25, -25, 20); - * curveVertex(25, 25, 20); - * curveVertex(25, 25, 20); + * curveVertex(-28, 41, -20); + * curveVertex(-28, 41, -20); + * curveVertex(-29, -33, -20); + * curveVertex(18, -31, -20); + * curveVertex(34, 41, -20); + * curveVertex(34, 41, -20); * endShape(); * } * *
- * - * @alt - * Upside-down u-shape line, mid canvas with the same shape in positive z-axis. */ _main.default.prototype.curveVertex = function () { for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { @@ -71084,45 +76974,102 @@ return this; }; /** - * Use the beginContour() and endContour() functions to create negative - * shapes within shapes such as the center of the letter 'O'. beginContour() - * begins recording vertices for the shape and endContour() stops recording. - * The vertices that define a negative shape must "wind" in the opposite - * direction from the exterior shape. First draw vertices for the exterior - * clockwise order, then for internal shapes, draw vertices - * shape in counter-clockwise. + * Stops creating a hole within a flat shape. * - * These functions can only be used within a beginShape()/endShape() pair and - * transformations such as translate(), rotate(), and scale() do not work - * within a beginContour()/endContour() pair. It is also not possible to use - * other shapes, such as ellipse() or rect() within. + * The beginContour() and `endContour()` + * functions allow for creating negative space within custom shapes that are + * flat. beginContour() begins adding vertices + * to a negative space and `endContour()` stops adding them. + * beginContour() and `endContour()` must be + * called between beginShape() and + * endShape(). + * + * Transformations such as translate(), + * rotate(), and scale() + * don't work between beginContour() and + * `endContour()`. It's also not possible to use other shapes, such as + * ellipse() or rect(), + * between beginContour() and `endContour()`. + * + * Note: The vertices that define a negative space must "wind" in the opposite + * direction from the outer shape. First, draw vertices for the outer shape + * clockwise order. Then, draw vertices for the negative space in + * counter-clockwise order. * * @method endContour * @chainable + * * @example *
* - * translate(50, 50); - * stroke(255, 0, 0); - * beginShape(); - * // Exterior part of shape, clockwise winding - * vertex(-40, -40); - * vertex(40, -40); - * vertex(40, 40); - * vertex(-40, 40); - * // Interior part of shape, counter-clockwise winding - * beginContour(); - * vertex(-20, -20); - * vertex(-20, 20); - * vertex(20, 20); - * vertex(20, -20); - * endContour(); - * endShape(CLOSE); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Start drawing the shape. + * beginShape(); + * + * // Exterior vertices, clockwise winding. + * vertex(10, 10); + * vertex(90, 10); + * vertex(90, 90); + * vertex(10, 90); + * + * // Interior vertices, counter-clockwise winding. + * beginContour(); + * vertex(30, 30); + * vertex(30, 70); + * vertex(70, 70); + * vertex(70, 30); + * endContour(); + * + * // Stop drawing the shape. + * endShape(CLOSE); + * + * describe('A white square with a square hole in its center drawn on a gray background.'); + * } * *
* - * @alt - * white rect and smaller grey rect with red outlines in center of canvas. + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white square with a square hole in its center drawn on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Start drawing the shape. + * beginShape(); + * + * // Exterior vertices, clockwise winding. + * vertex(-40, -40); + * vertex(40, -40); + * vertex(40, 40); + * vertex(-40, 40); + * + * // Interior vertices, counter-clockwise winding. + * beginContour(); + * vertex(-20, -20); + * vertex(-20, 20); + * vertex(20, 20); + * vertex(20, -20); + * endContour(); + * + * // Stop drawing the shape. + * endShape(CLOSE); + * } + * + *
*/ _main.default.prototype.endContour = function () { if (this._renderer.isP3D) { @@ -71143,47 +77090,86 @@ return this; }; /** - * The endShape() function is the companion to beginShape() and may only be - * called after beginShape(). When endShape() is called, all of the image - * data defined since the previous call to beginShape() is written into the image - * buffer. The constant CLOSE is the value for the `mode` parameter to close - * the shape (to connect the beginning and the end). - * When using instancing with endShape() the instancing will not apply to the strokes. - * When the count parameter is used with a value greater than 1, it enables instancing for shapes built when in WEBGL mode. Instancing - * is a feature that allows the GPU to efficiently draw multiples of the same shape. It's often used for particle effects or other - * times when you need a lot of repetition. In order to take advantage of instancing, you will also need to write your own custom - * shader using the gl_InstanceID keyword. You can read more about instancing - * here or by working from the example on this - * page. + * Begins adding vertices to a custom shape. + * + * The beginShape() and `endShape()` functions + * allow for creating custom shapes in 2D or 3D. + * beginShape() begins adding vertices to a + * custom shape and `endShape()` stops adding them. + * + * The first parameter, `mode`, is optional. By default, the first and last + * vertices of a shape aren't connected. If the constant `CLOSE` is passed, as + * in `endShape(CLOSE)`, then the first and last vertices will be connected. + * + * The second parameter, `count`, is also optional. In WebGL mode, it’s more + * efficient to draw many copies of the same shape using a technique called + * instancing. + * The `count` parameter tells WebGL mode how many copies to draw. For + * example, calling `endShape(CLOSE, 400)` after drawing a custom shape will + * make it efficient to draw 400 copies. This feature requires + * writing a custom shader. + * + * After calling beginShape(), shapes can be + * built by calling vertex(), + * bezierVertex(), + * quadraticVertex(), and/or + * curveVertex(). Calling + * `endShape()` will stop adding vertices to the + * shape. Each shape will be outlined with the current stroke color and filled + * with the current fill color. + * + * Transformations such as translate(), + * rotate(), and + * scale() don't work between + * beginShape() and `endShape()`. It's also not + * possible to use other shapes, such as ellipse() or + * rect(), between + * beginShape() and `endShape()`. * * @method endShape * @param {Constant} [mode] use CLOSE to close the shape * @param {Integer} [count] number of times you want to draw/instance the shape (for WebGL mode). * @chainable + * * @example *
* - * noFill(); + * function setup() { + * createCanvas(100, 100); * - * beginShape(); - * vertex(20, 20); - * vertex(45, 20); - * vertex(45, 80); - * endShape(CLOSE); + * background(200); * - * beginShape(); - * vertex(50, 20); - * vertex(75, 20); - * vertex(75, 80); - * endShape(); + * // Style the shapes. + * noFill(); + * + * // Left triangle. + * beginShape(); + * vertex(20, 20); + * vertex(45, 20); + * vertex(45, 80); + * endShape(CLOSE); + * + * // Right triangle. + * beginShape(); + * vertex(50, 20); + * vertex(75, 20); + * vertex(75, 80); + * endShape(); + * + * describe( + * 'Two sets of black lines drawn on a gray background. The three lines on the left form a right triangle. The two lines on the right form a right angle.' + * ); + * } * *
* - * @example *
* - * let fx; - * let vs = `#version 300 es + * // Note: A "uniform" is a global variable within a shader program. + * + * // Create a string with the vertex shader program. + * // The vertex shader is called for each vertex. + * let vertSrc = `#version 300 es * * precision mediump float; * @@ -71195,21 +77181,24 @@ * * void main() { * - * // copy the instance ID to the fragment shader + * // Copy the instance ID to the fragment shader. * instanceID = gl_InstanceID; * vec4 positionVec4 = vec4(aPosition, 1.0); * - * // gl_InstanceID represents a numeric value for each instance - * // using gl_InstanceID allows us to move each instance separately - * // here we move each instance horizontally by id * 40 - * float xOffset = float(gl_InstanceID) * 40.0; + * // gl_InstanceID represents a numeric value for each instance. + * // Using gl_InstanceID allows us to move each instance separately. + * // Here we move each instance horizontally by ID * 23. + * float xOffset = float(gl_InstanceID) * 23.0; * - * // apply the offset to the final position - * gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4 - - * vec4(xOffset, 0.0, 0.0, 0.0); + * // Apply the offset to the final position. + * gl_Position = uProjectionMatrix * uModelViewMatrix * (positionVec4 - + * vec4(xOffset, 0.0, 0.0, 0.0)); * } * `; - * let fs = `#version 300 es + * + * // Create a string with the fragment shader program. + * // The fragment shader is called for each pixel. + * let fragSrc = `#version 300 es * * precision mediump float; * @@ -71221,30 +77210,35 @@ * vec4 red = vec4(1.0, 0.0, 0.0, 1.0); * vec4 blue = vec4(0.0, 0.0, 1.0, 1.0); * - * // Normalize the instance id + * // Normalize the instance ID. * float normId = float(instanceID) / numInstances; * - * // Mix between two colors using the normalized instance id + * // Mix between two colors using the normalized instance ID. * outColor = mix(red, blue, normId); * } * `; * * function setup() { * createCanvas(100, 100, WEBGL); - * fx = createShader(vs, fs); - * } * - * function draw() { + * // Create a p5.Shader object. + * let myShader = createShader(vertSrc, fragSrc); + * * background(220); * - * // strokes aren't instanced, and are rather used for debug purposes - * shader(fx); - * fx.setUniform('numInstances', 4); + * // Compile and apply the p5.Shader. + * shader(myShader); * - * // this doesn't have to do with instancing, this is just for centering the squares + * // Set the numInstances uniform. + * myShader.setUniform('numInstances', 4); + * + * // Translate the origin to help align the drawing. * translate(25, -10); * - * // here we draw the squares we want to instance + * // Style the shapes. + * noStroke(); + * + * // Draw the shapes. * beginShape(); * vertex(0, 0); * vertex(0, 20); @@ -71253,13 +77247,10 @@ * vertex(0, 0); * endShape(CLOSE, 4); * - * resetShader(); + * describe('A row of four squares. Their colors transition from purple on the left to red on the right'); * } * *
- * - * @alt - * Triangle line shape with smallest interior angle on bottom and upside-down L. */ _main.default.prototype.endShape = function (mode) { var count = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; @@ -71302,121 +77293,244 @@ return this; }; /** - * Specifies vertex coordinates for quadratic Bezier curves. Each call to - * quadraticVertex() defines the position of one control points and one - * anchor point of a Bezier curve, adding a new segment to a line or shape. - * The first time quadraticVertex() is used within a beginShape() call, it - * must be prefaced with a call to vertex() to set the first anchor point. - * For WebGL mode quadraticVertex() can be used in 2D as well as 3D mode. - * 2D mode expects 4 parameters, while 3D mode expects 6 parameters - * (including z coordinates). + * Adds a quadratic Bézier curve segment to a custom shape. * - * This function must be used between beginShape() and endShape() - * and only when there is no MODE or POINTS parameter specified to + * `quadraticVertex()` adds a curved segment to custom shapes. The Bézier + * curve segments it creates are similar to those made by the + * bezierVertex() function. + * `quadraticVertex()` must be called between the + * beginShape() and + * endShape() functions. The curved segment uses + * the previous vertex as the first anchor point, so there must be at least + * one call to vertex() before `quadraticVertex()` can + * be used. + * + * The first two parameters, `cx` and `cy`, set the curve’s control point. + * The control point "pulls" the curve towards its. + * + * The last two parameters, `x3`, and `y3`, set the last anchor point. The + * last anchor point is where the curve ends. + * + * Bézier curves can also be drawn in 3D using WebGL mode. The 3D version of + * `bezierVertex()` has eight arguments because each point has x-, y-, and + * z-coordinates. + * + * Note: `quadraticVertex()` won’t work when an argument is passed to * beginShape(). * * @method quadraticVertex - * @param {Number} cx x-coordinate for the control point - * @param {Number} cy y-coordinate for the control point - * @param {Number} x3 x-coordinate for the anchor point - * @param {Number} y3 y-coordinate for the anchor point + * @param {Number} cx x-coordinate of the control point. + * @param {Number} cy y-coordinate of the control point. + * @param {Number} x3 x-coordinate of the anchor point. + * @param {Number} y3 y-coordinate of the anchor point. * @chainable * * @example *
* - * strokeWeight(5); - * point(20, 20); - * point(80, 20); - * point(50, 50); + * function setup() { + * createCanvas(100, 100); * - * noFill(); - * strokeWeight(1); - * beginShape(); - * vertex(20, 20); - * quadraticVertex(80, 20, 50, 50); - * endShape(); + * background(200); + * + * // Style the curve. + * noFill(); + * + * // Draw the curve. + * beginShape(); + * vertex(20, 20); + * quadraticVertex(80, 20, 50, 50); + * endShape(); + * + * describe('A black curve drawn on a gray square. The curve starts at the top-left corner and ends at the center.'); + * } * *
* *
* - * strokeWeight(5); - * point(20, 20); - * point(80, 20); - * point(50, 50); + * function setup() { + * createCanvas(100, 100); * - * point(20, 80); - * point(80, 80); - * point(80, 60); + * background(200); * - * noFill(); - * strokeWeight(1); - * beginShape(); - * vertex(20, 20); - * quadraticVertex(80, 20, 50, 50); - * quadraticVertex(20, 80, 80, 80); - * vertex(80, 60); - * endShape(); + * // Draw the curve. + * noFill(); + * beginShape(); + * vertex(20, 20); + * quadraticVertex(80, 20, 50, 50); + * endShape(); + * + * // Draw red lines from the anchor points to the control point. + * stroke(255, 0, 0); + * line(20, 20, 80, 20); + * line(50, 50, 80, 20); + * + * // Draw the anchor points in black. + * strokeWeight(5); + * stroke(0); + * point(20, 20); + * point(50, 50); + * + * // Draw the control point in red. + * stroke(255, 0, 0); + * point(80, 20); + * + * describe('A black curve that starts at the top-left corner and ends at the center. Its anchor and control points are marked with dots. Red lines connect both anchor points to the control point.'); + * } * *
* - * @alt - * arched-shaped black line with 4 pixel thick stroke weight. - * backwards s-shaped black line with 4 pixel thick stroke weight. - */ - /** - * @method quadraticVertex - * @param {Number} cx - * @param {Number} cy - * @param {Number} cz z-coordinate for the control point (for WebGL mode) - * @param {Number} x3 - * @param {Number} y3 - * @param {Number} z3 z-coordinate for the anchor point (for WebGL mode) - * @chainable + *
+ * + * // Click the mouse near the red dot in the top-right corner + * // and drag to change the curve's shape. + * + * let x2 = 80; + * let y2 = 20; + * let isChanging = false; + * + * function setup() { + * createCanvas(100, 100); + * + * describe('A black curve that starts at the top-left corner and ends at the center. Its anchor and control points are marked with dots. Red lines connect both anchor points to the control point.'); + * } + * + * function draw() { + * background(200); + * + * // Style the curve. + * noFill(); + * strokeWeight(1); + * stroke(0); + * + * // Draw the curve. + * beginShape(); + * vertex(20, 20); + * quadraticVertex(x2, y2, 50, 50); + * endShape(); + * + * // Draw red lines from the anchor points to the control point. + * stroke(255, 0, 0); + * line(20, 20, x2, y2); + * line(50, 50, x2, y2); + * + * // Draw the anchor points in black. + * strokeWeight(5); + * stroke(0); + * point(20, 20); + * point(50, 50); + * + * // Draw the control point in red. + * stroke(255, 0, 0); + * point(x2, y2); + * } + * + * // Start changing the first control point if the user clicks near it. + * function mousePressed() { + * if (dist(mouseX, mouseY, x2, y2) < 20) { + * isChanging = true; + * } + * } + * + * // Stop changing the first control point when the user releases the mouse. + * function mouseReleased() { + * isChanging = false; + * } + * + * // Update the first control point while the user drags the mouse. + * function mouseDragged() { + * if (isChanging === true) { + * x2 = mouseX; + * y2 = mouseY; + * } + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Start drawing the shape. + * beginShape(); + * + * // Add the curved segments. + * vertex(20, 20); + * quadraticVertex(80, 20, 50, 50); + * quadraticVertex(20, 80, 80, 80); + * + * // Add the straight segments. + * vertex(80, 10); + * vertex(20, 10); + * vertex(20, 20); + * + * // Stop drawing the shape. + * endShape(); + * + * describe('A white puzzle piece drawn on a gray background.'); + * } + * + *
* - * @example *
* + * // Click the and drag the mouse to view the scene from a different angle. + * * function setup() { * createCanvas(100, 100, WEBGL); - * setAttributes('antialias', true); + * + * describe('A white puzzle piece on a dark gray background. When the user clicks and drags the scene, the outline of a second puzzle piece is revealed.'); * } + * * function draw() { - * orbitControl(); * background(50); - * strokeWeight(4); - * stroke(255); * - * point(-35, -35); - * point(35, -35); - * point(0, 0); - * point(-35, 35); - * point(35, 35); - * point(35, 10); + * // Enable orbiting with the mouse. + * orbitControl(); * - * strokeWeight(1); - * noFill(); + * // Style the first puzzle piece. + * noStroke(); + * fill(255); * + * // Draw the first puzzle piece. * beginShape(); - * vertex(-35, -35); - * quadraticVertex(35, -35, 0, 0); - * quadraticVertex(-35, 35, 35, 35); - * vertex(35, 10); + * vertex(-30, -30, 0); + * quadraticVertex(30, -30, 0, 0, 0, 0); + * quadraticVertex(-30, 30, 0, 30, 30, 0); + * vertex(30, -40, 0); + * vertex(-30, -40, 0); + * vertex(-30, -30, 0); * endShape(); * + * // Style the second puzzle piece. + * stroke(255); + * noFill(); + * + * // Draw the second puzzle piece. * beginShape(); - * vertex(-35, -35, 20); - * quadraticVertex(35, -35, 20, 0, 0, 20); - * quadraticVertex(-35, 35, 20, 35, 35, 20); - * vertex(35, 10, 20); + * vertex(-30, -30, -20); + * quadraticVertex(30, -30, -20, 0, 0, -20); + * quadraticVertex(-30, 30, -20, 30, 30, -20); + * vertex(30, -40, -20); + * vertex(-30, -40, -20); + * vertex(-30, -30, -20); * endShape(); * } * *
- * - * @alt - * backwards s-shaped black line with the same s-shaped line in positive z-axis. + */ + /** + * @method quadraticVertex + * @param {Number} cx + * @param {Number} cy + * @param {Number} cz z-coordinate of the control point. + * @param {Number} x3 + * @param {Number} y3 + * @param {Number} z3 z-coordinate of the anchor point. */ _main.default.prototype.quadraticVertex = function () { for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { @@ -71460,142 +77574,181 @@ return this; }; /** - * All shapes are constructed by connecting a series of vertices. vertex() - * is used to specify the vertex coordinates for points, lines, triangles, - * quads, and polygons. It is used exclusively within the beginShape() and + * Adds a vertex to a custom shape. + * + * `vertex()` sets the coordinates of vertices drawn between the + * beginShape() and * endShape() functions. * + * The first two parameters, `x` and `y`, set the x- and y-coordinates of the + * vertex. + * + * The third parameter, `z`, is optional. It sets the z-coordinate of the + * vertex in WebGL mode. By default, `z` is 0. + * + * The fourth and fifth parameters, `u` and `v`, are also optional. They set + * the u- and v-coordinates for the vertex’s texture when used with + * endShape(). By default, `u` and `v` are both 0. + * * @method vertex - * @param {Number} x x-coordinate of the vertex - * @param {Number} y y-coordinate of the vertex + * @param {Number} x x-coordinate of the vertex. + * @param {Number} y y-coordinate of the vertex. * @chainable + * * @example *
* - * strokeWeight(3); - * beginShape(POINTS); - * vertex(30, 20); - * vertex(85, 20); - * vertex(85, 75); - * vertex(30, 75); - * endShape(); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the shape. + * strokeWeight(3); + * + * // Start drawing the shape. + * // Only draw the vertices. + * beginShape(POINTS); + * + * // Add the vertices. + * vertex(30, 20); + * vertex(85, 20); + * vertex(85, 75); + * vertex(30, 75); + * + * // Stop drawing the shape. + * endShape(); + * + * describe('Four black dots that form a square are drawn on a gray background.'); + * } * *
* *
* - * createCanvas(100, 100, WEBGL); - * background(240, 240, 240); - * fill(237, 34, 93); - * noStroke(); - * beginShape(); - * vertex(0, 35); - * vertex(35, 0); - * vertex(0, -35); - * vertex(-35, 0); - * endShape(); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Start drawing the shape. + * beginShape(); + * + * // Add vertices. + * vertex(30, 20); + * vertex(85, 20); + * vertex(85, 75); + * vertex(30, 75); + * + * // Stop drawing the shape. + * endShape(CLOSE); + * + * describe('A white square on a gray background.'); + * } * *
* *
* - * createCanvas(100, 100, WEBGL); - * background(240, 240, 240); - * fill(237, 34, 93); - * noStroke(); - * beginShape(); - * vertex(-10, 10); - * vertex(0, 35); - * vertex(10, 10); - * vertex(35, 0); - * vertex(10, -8); - * vertex(0, -35); - * vertex(-10, -8); - * vertex(-35, 0); - * endShape(); + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * background(200); + * + * // Start drawing the shape. + * beginShape(); + * + * // Add vertices. + * vertex(-20, -30, 0); + * vertex(35, -30, 0); + * vertex(35, 25, 0); + * vertex(-20, 25, 0); + * + * // Stop drawing the shape. + * endShape(CLOSE); + * + * describe('A white square on a gray background.'); + * } * *
* *
* - * strokeWeight(3); - * stroke(237, 34, 93); - * beginShape(LINES); - * vertex(10, 35); - * vertex(90, 35); - * vertex(10, 65); - * vertex(90, 65); - * vertex(35, 10); - * vertex(35, 90); - * vertex(65, 10); - * vertex(65, 90); - * endShape(); + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white square spins around slowly on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Rotate around the y-axis. + * rotateY(frameCount * 0.01); + * + * // Start drawing the shape. + * beginShape(); + * + * // Add vertices. + * vertex(-20, -30, 0); + * vertex(35, -30, 0); + * vertex(35, 25, 0); + * vertex(-20, 25, 0); + * + * // Stop drawing the shape. + * endShape(CLOSE); + * } * *
* *
* - * // Click to change the number of sides. - * // In WebGL mode, custom shapes will only - * // display hollow fill sections when - * // all calls to vertex() use the same z-value. + * let img; * - * let sides = 3; - * let angle, px, py; + * // Load an image to apply as a texture. + * function preload() { + * img = loadImage('assets/laDefense.jpg'); + * } * * function setup() { * createCanvas(100, 100, WEBGL); - * setAttributes('antialias', true); - * fill(237, 34, 93); - * strokeWeight(3); + * + * describe('A photograph of a ceiling rotates slowly against a gray background.'); * } * * function draw() { * background(200); - * rotateX(frameCount * 0.01); - * rotateZ(frameCount * 0.01); - * ngon(sides, 0, 0, 80); - * } * - * function mouseClicked() { - * if (sides > 6) { - * sides = 3; - * } else { - * sides++; - * } - * } + * // Rotate around the y-axis. + * rotateY(frameCount * 0.01); * - * function ngon(n, x, y, d) { - * beginShape(TESS); - * for (let i = 0; i < n + 1; i++) { - * angle = TWO_PI / n * i; - * px = x + sin(angle) * d / 2; - * py = y - cos(angle) * d / 2; - * vertex(px, py, 0); - * } - * for (let i = 0; i < n + 1; i++) { - * angle = TWO_PI / n * i; - * px = x + sin(angle) * d / 4; - * py = y - cos(angle) * d / 4; - * vertex(px, py, 0); - * } + * // Style the shape. + * noStroke(); + * + * // Apply the texture. + * texture(img); + * textureMode(NORMAL); + * + * // Start drawing the shape + * beginShape(); + * + * // Add vertices. + * vertex(-20, -30, 0, 0, 0); + * vertex(35, -30, 0, 1, 0); + * vertex(35, 25, 0, 1, 1); + * vertex(-20, 25, 0, 0, 1); + * + * // Stop drawing the shape. * endShape(); * } * *
- * @alt - * 4 black points in a square shape in middle-right of canvas. - * 4 points making a diamond shape. - * 8 points making a star. - * 8 points making 4 lines. - * A rotating 3D shape with a hollow section in the middle. */ /** * @method vertex * @param {Number} x * @param {Number} y - * @param {Number} [z] z-coordinate of the vertex. - * Defaults to 0 if not specified. + * @param {Number} [z] z-coordinate of the vertex. Defaults to 0. * @chainable */ /** @@ -71603,8 +77756,8 @@ * @param {Number} x * @param {Number} y * @param {Number} [z] - * @param {Number} [u] the vertex's texture u-coordinate - * @param {Number} [v] the vertex's texture v-coordinate + * @param {Number} [u] u-coordinate of the vertex's texture. Defaults to 0. + * @param {Number} [v] v-coordinate of the vertex's texture. Defaults to 0. * @chainable */ _main.default.prototype.vertex = function (x, y, moveTo, u, v) { @@ -71637,36 +77790,174 @@ return this; }; /** - * Sets the 3d vertex normal to use for subsequent vertices drawn with - * vertex(). A normal is a vector that is generally - * nearly perpendicular to a shape's surface which controls how much light will - * be reflected from that part of the surface. + * Sets the normal vector for vertices in a custom 3D shape. + * + * 3D shapes created with beginShape() and + * endShape() are made by connecting sets of + * points called vertices. Each vertex added with + * vertex() has a normal vector that points away + * from it. The normal vector controls how light reflects off the shape. + * + * `normal()` can be called two ways with different parameters to define the + * normal vector's components. + * + * The first way to call `normal()` has three parameters, `x`, `y`, and `z`. + * If `Number`s are passed, as in `normal(1, 2, 3)`, they set the x-, y-, and + * z-components of the normal vector. + * + * The second way to call `normal()` has one parameter, `vector`. If a + * p5.Vector object is passed, as in + * `normal(myVector)`, its components will be used to set the normal vector. + * + * `normal()` changes the normal vector of vertices added to a custom shape + * with vertex(). `normal()` must be called between + * the beginShape() and + * endShape() functions, just like + * vertex(). The normal vector set by calling + * `normal()` will affect all following vertices until `normal()` is called + * again: + * + * + * beginShape(); + * + * // Set the vertex normal. + * normal(-0.4, -0.4, 0.8); + * + * // Add a vertex. + * vertex(-30, -30, 0); + * + * // Set the vertex normal. + * normal(0, 0, 1); + * + * // Add vertices. + * vertex(30, -30, 0); + * vertex(30, 30, 0); + * + * // Set the vertex normal. + * normal(0.4, -0.4, 0.8); + * + * // Add a vertex. + * vertex(-30, 30, 0); + * + * endShape(); + * * * @method normal - * @param {Vector} vector A p5.Vector representing the vertex normal. + * @param {p5.Vector} vector vertex normal as a p5.Vector object. * @chainable + * * @example *
* + * // Click the and drag the mouse to view the scene from a different angle. + * * function setup() { * createCanvas(100, 100, WEBGL); - * noStroke(); + * + * describe( + * 'A colorful square on a black background. The square changes color and rotates when the user drags the mouse. Parts of its surface reflect light in different directions.' + * ); * } * * function draw() { - * background(255); - * rotateY(frameCount / 100); + * background(0); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Style the shape. * normalMaterial(); - * beginShape(TRIANGLE_STRIP); - * normal(-0.4, 0.4, 0.8); + * noStroke(); + * + * // Draw the shape. + * beginShape(); + * vertex(-30, -30, 0); + * vertex(30, -30, 0); + * vertex(30, 30, 0); * vertex(-30, 30, 0); + * endShape(); + * } + * + *
+ * + *
+ * + * // Click the and drag the mouse to view the scene from a different angle. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe( + * 'A colorful square on a black background. The square changes color and rotates when the user drags the mouse. Parts of its surface reflect light in different directions.' + * ); + * } + * + * function draw() { + * background(0); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Style the shape. + * normalMaterial(); + * noStroke(); + * + * // Draw the shape. + * // Use normal() to set vertex normals. + * beginShape(); + * normal(-0.4, -0.4, 0.8); + * vertex(-30, -30, 0); * * normal(0, 0, 1); - * vertex(-30, -30, 30); - * vertex(30, 30, 30); + * vertex(30, -30, 0); + * vertex(30, 30, 0); * * normal(0.4, -0.4, 0.8); + * vertex(-30, 30, 0); + * endShape(); + * } + * + *
+ * + *
+ * + * // Click the and drag the mouse to view the scene from a different angle. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe( + * 'A colorful square on a black background. The square changes color and rotates when the user drags the mouse. Parts of its surface reflect light in different directions.' + * ); + * } + * + * function draw() { + * background(0); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Style the shape. + * normalMaterial(); + * noStroke(); + * + * // Create p5.Vector objects. + * let n1 = createVector(-0.4, -0.4, 0.8); + * let n2 = createVector(0, 0, 1); + * let n3 = createVector(0.4, -0.4, 0.8); + * + * // Draw the shape. + * // Use normal() to set vertex normals. + * beginShape(); + * normal(n1); + * vertex(-30, -30, 0); + * + * normal(n2); * vertex(30, -30, 0); + * vertex(30, 30, 0); + * + * normal(n3); + * vertex(-30, 30, 0); * endShape(); * } * @@ -71674,9 +77965,9 @@ */ /** * @method normal - * @param {Number} x The x component of the vertex normal. - * @param {Number} y The y component of the vertex normal. - * @param {Number} z The z component of the vertex normal. + * @param {Number} x x-component of the vertex normal. + * @param {Number} y y-component of the vertex normal. + * @param {Number} z z-component of the vertex normal. * @chainable */ _main.default.prototype.normal = function (x, y, z) { @@ -71690,260 +77981,28 @@ exports.default = _default; }, { - '../constants': 286, - '../main': 298, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256 + '../constants': 294, + '../main': 306, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 309: [ + 317: [ function (_dereq_, module, exports) { 'use strict'; - _dereq_('core-js/modules/es.symbol'); - _dereq_('core-js/modules/es.symbol.description'); - _dereq_('core-js/modules/es.symbol.iterator'); - _dereq_('core-js/modules/es.array.filter'); - _dereq_('core-js/modules/es.array.from'); - _dereq_('core-js/modules/es.array.iterator'); - _dereq_('core-js/modules/es.array.slice'); - _dereq_('core-js/modules/es.object.assign'); - _dereq_('core-js/modules/es.object.keys'); - _dereq_('core-js/modules/es.object.to-string'); - _dereq_('core-js/modules/es.regexp.to-string'); - _dereq_('core-js/modules/es.string.iterator'); - _dereq_('core-js/modules/es.typed-array.uint8-clamped-array'); - _dereq_('core-js/modules/es.typed-array.copy-within'); - _dereq_('core-js/modules/es.typed-array.every'); - _dereq_('core-js/modules/es.typed-array.fill'); - _dereq_('core-js/modules/es.typed-array.filter'); - _dereq_('core-js/modules/es.typed-array.find'); - _dereq_('core-js/modules/es.typed-array.find-index'); - _dereq_('core-js/modules/es.typed-array.for-each'); - _dereq_('core-js/modules/es.typed-array.includes'); - _dereq_('core-js/modules/es.typed-array.index-of'); - _dereq_('core-js/modules/es.typed-array.iterator'); - _dereq_('core-js/modules/es.typed-array.join'); - _dereq_('core-js/modules/es.typed-array.last-index-of'); - _dereq_('core-js/modules/es.typed-array.map'); - _dereq_('core-js/modules/es.typed-array.reduce'); - _dereq_('core-js/modules/es.typed-array.reduce-right'); - _dereq_('core-js/modules/es.typed-array.reverse'); - _dereq_('core-js/modules/es.typed-array.set'); - _dereq_('core-js/modules/es.typed-array.slice'); - _dereq_('core-js/modules/es.typed-array.some'); - _dereq_('core-js/modules/es.typed-array.sort'); - _dereq_('core-js/modules/es.typed-array.subarray'); - _dereq_('core-js/modules/es.typed-array.to-locale-string'); - _dereq_('core-js/modules/es.typed-array.to-string'); - _dereq_('core-js/modules/web.dom-collections.iterator'); - function _typeof2(obj) { - if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { - _typeof2 = function _typeof2(obj) { - return typeof obj; - }; - } else { - _typeof2 = function _typeof2(obj) { - return obj && typeof Symbol === 'function' && obj.constructor === Symbol && obj !== Symbol.prototype ? 'symbol' : typeof obj; - }; - } - return _typeof2(obj); - } - _dereq_('core-js/modules/es.symbol'); - _dereq_('core-js/modules/es.symbol.description'); - _dereq_('core-js/modules/es.symbol.iterator'); - _dereq_('core-js/modules/es.array.filter'); - _dereq_('core-js/modules/es.array.iterator'); - _dereq_('core-js/modules/es.array.slice'); - _dereq_('core-js/modules/es.object.assign'); - _dereq_('core-js/modules/es.object.keys'); - _dereq_('core-js/modules/es.object.to-string'); - _dereq_('core-js/modules/es.string.iterator'); - _dereq_('core-js/modules/es.typed-array.uint8-clamped-array'); - _dereq_('core-js/modules/es.typed-array.copy-within'); - _dereq_('core-js/modules/es.typed-array.every'); - _dereq_('core-js/modules/es.typed-array.fill'); - _dereq_('core-js/modules/es.typed-array.filter'); - _dereq_('core-js/modules/es.typed-array.find'); - _dereq_('core-js/modules/es.typed-array.find-index'); - _dereq_('core-js/modules/es.typed-array.for-each'); - _dereq_('core-js/modules/es.typed-array.includes'); - _dereq_('core-js/modules/es.typed-array.index-of'); - _dereq_('core-js/modules/es.typed-array.iterator'); - _dereq_('core-js/modules/es.typed-array.join'); - _dereq_('core-js/modules/es.typed-array.last-index-of'); - _dereq_('core-js/modules/es.typed-array.map'); - _dereq_('core-js/modules/es.typed-array.reduce'); - _dereq_('core-js/modules/es.typed-array.reduce-right'); - _dereq_('core-js/modules/es.typed-array.reverse'); - _dereq_('core-js/modules/es.typed-array.set'); - _dereq_('core-js/modules/es.typed-array.slice'); - _dereq_('core-js/modules/es.typed-array.some'); - _dereq_('core-js/modules/es.typed-array.sort'); - _dereq_('core-js/modules/es.typed-array.subarray'); - _dereq_('core-js/modules/es.typed-array.to-locale-string'); - _dereq_('core-js/modules/es.typed-array.to-string'); - _dereq_('core-js/modules/web.dom-collections.iterator'); - function _toConsumableArray(arr) { - return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); - } - function _nonIterableSpread() { - throw new TypeError('Invalid attempt to spread non-iterable instance'); - } - function _iterableToArray(iter) { - if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === '[object Arguments]') return Array.from(iter); - } - function _arrayWithoutHoles(arr) { - if (Array.isArray(arr)) { - for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { - arr2[i] = arr[i]; - } - return arr2; - } - } - function _typeof(obj) { - if (typeof Symbol === 'function' && _typeof2(Symbol.iterator) === 'symbol') { - _typeof = function _typeof(obj) { - return _typeof2(obj); - }; - } else { - _typeof = function _typeof(obj) { - return obj && typeof Symbol === 'function' && obj.constructor === Symbol && obj !== Symbol.prototype ? 'symbol' : _typeof2(obj); - }; - } - return _typeof(obj); - } // requestAnim shim layer by Paul Irish - // http://paulirish.com/2011/requestanimationframe-for-smart-animating/ - // http://my.opera.com/emoller/blog/2011/12/20/ - // requestanimationframe-for-smart-er-animating - // requestAnimationFrame polyfill by Erik Möller - // fixes from Paul Irish and Tino Zijdel - - window.requestAnimationFrame = function () { - return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback, element) { - // should '60' here be framerate? - window.setTimeout(callback, 1000 / 60); - }; - }(); - /** - * shim for Uint8ClampedArray.slice - * (allows arrayCopy to work with pixels[]) - * with thanks to http://halfpapstudios.com/blog/tag/html5-canvas/ - * Enumerable set to false to protect for...in from - * Uint8ClampedArray.prototype pollution. - */ - (function () { - if (typeof Uint8ClampedArray !== 'undefined' && !Uint8ClampedArray.prototype.slice) { - Object.defineProperty(Uint8ClampedArray.prototype, 'slice', { - value: Array.prototype.slice, - writable: true, - configurable: true, - enumerable: false - }); - } - }) (); - /** - * this is implementation of Object.assign() which is unavailable in - * IE11 and (non-Chrome) Android browsers. - * The assign() method is used to copy the values of all enumerable - * own properties from one or more source objects to a target object. - * It will return the target object. - * Modified from https://github.com/ljharb/object.assign - */ - (function () { - if (!Object.assign) { - var keys = Object.keys; - var defineProperty = Object.defineProperty; - var canBeObject = function canBeObject(obj) { - return typeof obj !== 'undefined' && obj !== null; - }; - var hasSymbols = typeof Symbol === 'function' && _typeof(Symbol()) === 'symbol'; - var propIsEnumerable = Object.prototype.propertyIsEnumerable; - var isEnumerableOn = function isEnumerableOn(obj) { - return function isEnumerable(prop) { - return propIsEnumerable.call(obj, prop); - }; - }; - // per ES6 spec, this function has to have a length of 2 - var assignShim = function assign(target, source1) { - if (!canBeObject(target)) { - throw new TypeError('target must be an object'); - } - var objTarget = Object(target); - var s, - source, - i, - props; - for (s = 1; s < arguments.length; ++s) { - source = Object(arguments[s]); - props = keys(source); - if (hasSymbols && Object.getOwnPropertySymbols) { - var _props; - (_props = props).push.apply(_props, _toConsumableArray(Object.getOwnPropertySymbols(source).filter(isEnumerableOn(source)))); - } - for (i = 0; i < props.length; ++i) { - objTarget[props[i]] = source[props[i]]; - } - } - return objTarget; - }; - defineProperty(Object, 'assign', { - value: assignShim, - configurable: true, - enumerable: false, - writable: true - }); - } - }) (); }, { - 'core-js/modules/es.array.filter': 173, - 'core-js/modules/es.array.from': 176, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.object.assign': 194, - 'core-js/modules/es.object.keys': 199, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.typed-array.copy-within': 223, - 'core-js/modules/es.typed-array.every': 224, - 'core-js/modules/es.typed-array.fill': 225, - 'core-js/modules/es.typed-array.filter': 226, - 'core-js/modules/es.typed-array.find': 228, - 'core-js/modules/es.typed-array.find-index': 227, - 'core-js/modules/es.typed-array.for-each': 231, - 'core-js/modules/es.typed-array.includes': 232, - 'core-js/modules/es.typed-array.index-of': 233, - 'core-js/modules/es.typed-array.iterator': 236, - 'core-js/modules/es.typed-array.join': 237, - 'core-js/modules/es.typed-array.last-index-of': 238, - 'core-js/modules/es.typed-array.map': 239, - 'core-js/modules/es.typed-array.reduce': 241, - 'core-js/modules/es.typed-array.reduce-right': 240, - 'core-js/modules/es.typed-array.reverse': 242, - 'core-js/modules/es.typed-array.set': 243, - 'core-js/modules/es.typed-array.slice': 244, - 'core-js/modules/es.typed-array.some': 245, - 'core-js/modules/es.typed-array.sort': 246, - 'core-js/modules/es.typed-array.subarray': 247, - 'core-js/modules/es.typed-array.to-locale-string': 248, - 'core-js/modules/es.typed-array.to-string': 249, - 'core-js/modules/es.typed-array.uint8-clamped-array': 253, - 'core-js/modules/web.dom-collections.iterator': 256 } ], - 310: [ + 318: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.object.assign'); @@ -71965,119 +78024,210 @@ * @requires core */ /** - * Stops p5.js from continuously executing the code within draw(). - * If loop() is called, the code in draw() - * begins to run continuously again. If using noLoop() - * in setup(), it should be the last line inside the block. - * - * When noLoop() is used, it's not possible to manipulate - * or access the screen inside event handling functions such as - * mousePressed() or - * keyPressed(). Instead, use those functions to - * call redraw() or loop(), - * which will run draw(), which can update the screen - * properly. This means that when noLoop() has been - * called, no drawing can happen, and functions like saveFrames() - * or loadPixels() may not be used. + * Stops the code in draw() from running repeatedly. * - * Note that if the sketch is resized, redraw() will - * be called to update the sketch, even after noLoop() - * has been specified. Otherwise, the sketch would enter an odd state until - * loop() was called. + * By default, draw() tries to run 60 times per + * second. Calling `noLoop()` stops draw() from + * repeating. The draw loop can be restarted by calling + * loop(). draw() can be run + * once by calling redraw(). * - * Use isLooping() to check the current state of loop(). + * The isLooping() function can be used to check + * whether a sketch is looping, as in `isLooping() === true`. * * @method noLoop + * * @example *
* * function setup() { * createCanvas(100, 100); - * background(200); + * + * // Turn off the draw loop. * noLoop(); + * + * describe('A white half-circle on the left edge of a gray square.'); * } - + * * function draw() { - * line(10, 10, 90, 90); + * background(200); + * + * // Calculate the circle's x-coordinate. + * let x = frameCount; + * + * // Draw the circle. + * // Normally, the circle would move from left to right. + * circle(x, 50, 20); * } * *
* *
* - * let x = 0; + * // Double-click to stop the draw loop. + * * function setup() { * createCanvas(100, 100); + * + * // Slow the frame rate. + * frameRate(5); + * + * describe('A white circle moves randomly on a gray background. It stops moving when the user double-clicks.'); * } * * function draw() { - * background(204); - * x = x + 0.1; - * if (x > width) { - * x = 0; - * } - * line(x, 0, x, height); + * background(200); + * + * // Calculate the circle's coordinates. + * let x = random(0, 100); + * let y = random(0, 100); + * + * // Draw the circle. + * // Normally, the circle would move from left to right. + * circle(x, y, 20); * } * - * function mousePressed() { + * // Stop the draw loop when the user double-clicks. + * function doubleClicked() { * noLoop(); * } + * + *
* - * function mouseReleased() { - * loop(); + *
+ * + * let startButton; + * let stopButton; + * + * function setup() { + * createCanvas(100, 100); + * + * // Create the button elements and place them + * // beneath the canvas. + * startButton = createButton('▶'); + * startButton.position(0, 100); + * startButton.size(50, 20); + * stopButton = createButton('◾'); + * stopButton.position(50, 100); + * stopButton.size(50, 20); + * + * // Set functions to call when the buttons are pressed. + * startButton.mousePressed(loop); + * stopButton.mousePressed(noLoop); + * + * // Slow the frame rate. + * frameRate(5); + * + * describe( + * 'A white circle moves randomly on a gray background. Play and stop buttons are shown beneath the canvas. The circle stops or starts moving when the user presses a button.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Calculate the circle's coordinates. + * let x = random(0, 100); + * let y = random(0, 100); + * + * // Draw the circle. + * // Normally, the circle would move from left to right. + * circle(x, y, 20); * } * *
- * - * @alt - * 113 pixel long line extending from top-left to bottom right of canvas. - * horizontal line moves slowly from left. Loops but stops on mouse press. */ _main.default.prototype.noLoop = function () { this._loop = false; }; /** - * By default, p5.js loops through draw() continuously, executing the code within - * it. However, the draw() loop may be stopped by calling - * noLoop(). In that case, the draw() - * loop can be resumed with loop(). + * Resumes the draw loop after noLoop() has been + * called. * - * Avoid calling loop() from inside setup(). + * By default, draw() tries to run 60 times per + * second. Calling noLoop() stops + * draw() from repeating. The draw loop can be + * restarted by calling `loop()`. * - * Use isLooping() to check the current state of loop(). + * The isLooping() function can be used to check + * whether a sketch is looping, as in `isLooping() === true`. * * @method loop + * * @example *
* - * let x = 0; * function setup() { * createCanvas(100, 100); + * + * // Turn off the draw loop. * noLoop(); + * + * describe( + * 'A white half-circle on the left edge of a gray square. The circle starts moving to the right when the user double-clicks.' + * ); * } * * function draw() { - * background(204); - * x = x + 0.1; - * if (x > width) { - * x = 0; - * } - * line(x, 0, x, height); + * background(200); + * + * // Calculate the circle's x-coordinate. + * let x = frameCount; + * + * // Draw the circle. + * circle(x, 50, 20); * } * - * function mousePressed() { + * // Resume the draw loop when the user double-clicks. + * function doubleClicked() { * loop(); * } + * + *
* - * function mouseReleased() { - * noLoop(); + *
+ * + * let startButton; + * let stopButton; + * + * function setup() { + * createCanvas(100, 100); + * + * // Create the button elements and place them + * // beneath the canvas. + * startButton = createButton('▶'); + * startButton.position(0, 100); + * startButton.size(50, 20); + * stopButton = createButton('◾'); + * stopButton.position(50, 100); + * stopButton.size(50, 20); + * + * // Set functions to call when the buttons are pressed. + * startButton.mousePressed(loop); + * stopButton.mousePressed(noLoop); + * + * // Slow the frame rate. + * frameRate(5); + * + * describe( + * 'A white circle moves randomly on a gray background. Play and stop buttons are shown beneath the canvas. The circle stops or starts moving when the user presses a button.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Calculate the circle's coordinates. + * let x = random(0, 100); + * let y = random(0, 100); + * + * // Draw the circle. + * // Normally, the circle would move from left to right. + * circle(x, y, 20); * } * *
- * - * @alt - * horizontal line moves slowly from left. Loops but stops on mouse press. */ _main.default.prototype.loop = function () { if (!this._loop) { @@ -72088,336 +78238,710 @@ } }; /** - * By default, p5.js loops through draw() continuously, - * executing the code within it. If the sketch is stopped with - * noLoop() or resumed with loop(), - * isLooping() returns the current state for use within custom event handlers. + * Returns `true` if the draw loop is running and `false` if not. + * + * By default, draw() tries to run 60 times per + * second. Calling noLoop() stops + * draw() from repeating. The draw loop can be + * restarted by calling loop(). + * + * The `isLooping()` function can be used to check whether a sketch is + * looping, as in `isLooping() === true`. * * @method isLooping * @returns {boolean} + * * @example *
* - * let checkbox, button, colBG, colFill; - * * function setup() { * createCanvas(100, 100); * - * button = createButton('Colorize if loop()'); - * button.position(0, 120); - * button.mousePressed(changeBG); - * - * checkbox = createCheckbox('loop()', true); - * checkbox.changed(checkLoop); - * - * colBG = color(0); - * colFill = color(255); + * describe('A white circle drawn against a gray background. When the user double-clicks, the circle stops or resumes following the mouse.'); * } * - * function changeBG() { - * if (isLooping()) { - * colBG = color(random(255), random(255), random(255)); - * colFill = color(random(255), random(255), random(255)); - * } + * function draw() { + * background(200); + * + * // Draw the circle at the mouse's position. + * circle(mouseX, mouseY, 20); * } * - * function checkLoop() { - * if (this.checked()) { - * loop(); - * } else { + * // Toggle the draw loop when the user double-clicks. + * function doubleClicked() { + * if (isLooping() === true) { * noLoop(); + * } else { + * loop(); * } * } - * - * function draw() { - * background(colBG); - * fill(colFill); - * ellipse(frameCount % width, height / 2, 50); - * } * *
- * - * @alt - * Ellipse moves slowly from left. Checkbox toggles loop()/noLoop(). - * Button colorizes sketch if isLooping(). - * */ _main.default.prototype.isLooping = function () { return this._loop; }; /** - * The push() function saves the current drawing style - * settings and transformations, while pop() restores these - * settings. Note that these functions are always used together. They allow you to - * change the style and transformation settings and later return to what you had. - * When a new state is started with push(), it builds on - * the current style and transform information. The push() - * and pop() functions can be embedded to provide more - * control. (See the second example for a demonstration.) - * - * push() stores information related to the current transformation state - * and style settings controlled by the following functions: - * fill(), - * noFill(), - * noStroke(), - * stroke(), - * tint(), - * noTint(), - * strokeWeight(), - * strokeCap(), - * strokeJoin(), - * imageMode(), - * rectMode(), - * ellipseMode(), - * colorMode(), - * textAlign(), - * textFont(), - * textSize(), - * textLeading(), - * applyMatrix(), - * resetMatrix(), - * rotate(), - * scale(), - * shearX(), - * shearY(), - * translate(), - * noiseSeed(). + * Begins a drawing group that contains its own styles and transformations. * - * In WEBGL mode additional style settings are stored. These are controlled by the - * following functions: setCamera(), - * ambientLight(), - * directionalLight(), - * pointLight(), texture(), - * specularMaterial(), - * shininess(), - * normalMaterial() - * and shader(). + * By default, styles such as fill() and + * transformations such as rotate() are applied to + * all drawing that follows. The `push()` and pop() + * functions can limit the effect of styles and transformations to a specific + * group of shapes, images, and text. For example, a group of shapes could be + * translated to follow the mouse without affecting the rest of the sketch: * - * @method push - * @example - *
- * - * ellipse(0, 50, 33, 33); // Left circle + * ```js + * // Begin the drawing group. + * push(); * - * push(); // Start a new drawing state - * strokeWeight(10); - * fill(204, 153, 0); - * translate(50, 0); - * ellipse(0, 50, 33, 33); // Middle circle - * pop(); // Restore original state + * // Translate the origin to the mouse's position. + * translate(mouseX, mouseY); * - * ellipse(100, 50, 33, 33); // Right circle - * - *
+ * // Style the face. + * noStroke(); + * fill('green'); * - *
- * - * ellipse(0, 50, 33, 33); // Left circle + * // Draw the face. + * circle(0, 0, 60); * - * push(); // Start a new drawing state - * strokeWeight(10); - * fill(204, 153, 0); - * ellipse(33, 50, 33, 33); // Left-middle circle + * // Style the eyes. + * fill('white'); * - * push(); // Start another new drawing state - * stroke(0, 102, 153); - * ellipse(66, 50, 33, 33); // Right-middle circle - * pop(); // Restore previous state + * // Draw the left eye. + * ellipse(-20, -20, 30, 20); * - * pop(); // Restore original state + * // Draw the right eye. + * ellipse(20, -20, 30, 20); * - * ellipse(100, 50, 33, 33); // Right circle - * - *
+ * // End the drawing group. + * pop(); * - * @alt - * Gold ellipse + thick black outline @center 2 white ellipses on left and right. - * 2 Gold ellipses left black right blue stroke. 2 white ellipses on left+right. - */ - _main.default.prototype.push = function () { - this._styles.push({ - props: { - _colorMode: this._colorMode - }, - renderer: this._renderer.push() - }); - }; - /** - * The push() function saves the current drawing style - * settings and transformations, while pop() restores - * these settings. Note that these functions are always used together. They allow - * you to change the style and transformation settings and later return to what - * you had. When a new state is started with push(), it - * builds on the current style and transform information. The push() - * and pop() functions can be embedded to provide more - * control. (See the second example for a demonstration.) - * - * push() stores information related to the current transformation state - * and style settings controlled by the following functions: - * fill(), - * noFill(), - * noStroke(), - * stroke(), - * tint(), - * noTint(), - * strokeWeight(), - * strokeCap(), - * strokeJoin(), - * imageMode(), - * rectMode(), - * ellipseMode(), - * colorMode(), - * textAlign(), - * textFont(), - * textSize(), - * textLeading(), - * applyMatrix(), - * resetMatrix(), - * rotate(), - * scale(), - * shearX(), - * shearY(), - * translate(), - * noiseSeed(). + * // Draw a bug. + * let x = random(0, 100); + * let y = random(0, 100); + * text('🦟', x, y); + * ``` * - * In WEBGL mode additional style settings are stored. These are controlled by - * the following functions: - * setCamera(), - * ambientLight(), - * directionalLight(), - * pointLight(), - * texture(), - * specularMaterial(), - * shininess(), - * normalMaterial() and - * shader(). + * In the code snippet above, the bug's position isn't affected by + * `translate(mouseX, mouseY)` because that transformation is contained + * between `push()` and pop(). The bug moves around + * the entire canvas as expected. + * + * Note: `push()` and pop() are always called as a + * pair. Both functions are required to begin and end a drawing group. + * + * `push()` and pop() can also be nested to create + * subgroups. For example, the code snippet above could be changed to give + * more detail to the frog’s eyes: + * + * ```js + * // Begin the drawing group. + * push(); + * + * // Translate the origin to the mouse's position. + * translate(mouseX, mouseY); + * + * // Style the face. + * noStroke(); + * fill('green'); + * + * // Draw a face. + * circle(0, 0, 60); + * + * // Style the eyes. + * fill('white'); + * + * // Draw the left eye. + * push(); + * translate(-20, -20); + * ellipse(0, 0, 30, 20); + * fill('black'); + * circle(0, 0, 8); + * pop(); + * + * // Draw the right eye. + * push(); + * translate(20, -20); + * ellipse(0, 0, 30, 20); + * fill('black'); + * circle(0, 0, 8); + * pop(); + * + * // End the drawing group. + * pop(); + * + * // Draw a bug. + * let x = random(0, 100); + * let y = random(0, 100); + * text('🦟', x, y); + * ``` + * + * In this version, the code to draw each eye is contained between its own + * `push()` and pop() functions. Doing so makes it + * easier to add details in the correct part of a drawing. + * + * `push()` and pop() contain the effects of the + * following functions: + * + * - fill() + * - noFill() + * - noStroke() + * - stroke() + * - tint() + * - noTint() + * - strokeWeight() + * - strokeCap() + * - strokeJoin() + * - imageMode() + * - rectMode() + * - ellipseMode() + * - colorMode() + * - textAlign() + * - textFont() + * - textSize() + * - textLeading() + * - applyMatrix() + * - resetMatrix() + * - rotate() + * - scale() + * - shearX() + * - shearY() + * - translate() + * + * In WebGL mode, `push()` and pop() contain the + * effects of a few additional styles: + * + * - setCamera() + * - ambientLight() + * - directionalLight() + * - pointLight() texture() + * - specularMaterial() + * - shininess() + * - normalMaterial() + * - shader() + * + * @method push * - * @method pop * @example *
* - * ellipse(0, 50, 33, 33); // Left circle + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Draw the left circle. + * circle(25, 50, 20); + * + * // Begin the drawing group. + * push(); + * + * // Translate the origin to the center. + * translate(50, 50); + * + * // Style the circle. + * strokeWeight(5); + * stroke('royalblue'); + * fill('orange'); + * + * // Draw the circle. + * circle(0, 0, 20); + * + * // End the drawing group. + * pop(); * - * push(); // Start a new drawing state - * translate(50, 0); - * strokeWeight(10); - * fill(204, 153, 0); - * ellipse(0, 50, 33, 33); // Middle circle - * pop(); // Restore original state + * // Draw the right circle. + * circle(75, 50, 20); * - * ellipse(100, 50, 33, 33); // Right circle + * describe( + * 'Three circles drawn in a row on a gray background. The left and right circles are white with thin, black borders. The middle circle is orange with a thick, blue border.' + * ); + * } * *
* *
* - * ellipse(0, 50, 33, 33); // Left circle + * function setup() { + * createCanvas(100, 100); * - * push(); // Start a new drawing state - * strokeWeight(10); - * fill(204, 153, 0); - * ellipse(33, 50, 33, 33); // Left-middle circle + * // Slow the frame rate. + * frameRate(24); * - * push(); // Start another new drawing state - * stroke(0, 102, 153); - * ellipse(66, 50, 33, 33); // Right-middle circle - * pop(); // Restore previous state + * describe('A mosquito buzzes in front of a green frog. The frog follows the mouse as the user moves.'); + * } * - * pop(); // Restore original state + * function draw() { + * background(200); * - * ellipse(100, 50, 33, 33); // Right circle - * - *
+ * // Begin the drawing group. + * push(); * - * @alt - * Gold ellipse + thick black outline @center 2 white ellipses on left and right. - * 2 Gold ellipses left black right blue stroke. 2 white ellipses on left+right. - */ - _main.default.prototype.pop = function () { - var style = this._styles.pop(); - if (style) { - this._renderer.pop(style.renderer); - Object.assign(this, style.props); - } else { - console.warn('pop() was called without matching push()'); - } - }; - /** - * Executes the code within draw() one time. This - * function allows the program to update the display window only when necessary, - * for example when an event registered by mousePressed() - * or keyPressed() occurs. + * // Translate the origin to the mouse's position. + * translate(mouseX, mouseY); * - * In structuring a program, it only makes sense to call redraw() - * within events such as mousePressed(). This - * is because redraw() does not run - * draw() immediately (it only sets a flag that indicates - * an update is needed). + * // Style the face. + * noStroke(); + * fill('green'); * - * The redraw() function does not work properly when - * called inside draw().To enable/disable animations, - * use loop() and noLoop(). + * // Draw a face. + * circle(0, 0, 60); * - * In addition you can set the number of redraws per method call. Just - * add an integer as single parameter for the number of redraws. + * // Style the eyes. + * fill('white'); * - * @method redraw - * @param {Integer} [n] Redraw for n-times. The default value is 1. - * @example - *
- * let x = 0; + * // Draw the left eye. + * push(); + * translate(-20, -20); + * ellipse(0, 0, 30, 20); + * fill('black'); + * circle(0, 0, 8); + * pop(); * - * function setup() { - * createCanvas(100, 100); - * noLoop(); - * } + * // Draw the right eye. + * push(); + * translate(20, -20); + * ellipse(0, 0, 30, 20); + * fill('black'); + * circle(0, 0, 8); + * pop(); * - * function draw() { - * background(204); - * line(x, 0, x, height); - * } + * // End the drawing group. + * pop(); * - * function mousePressed() { - * x += 1; - * redraw(); + * // Draw a bug. + * let x = random(0, 100); + * let y = random(0, 100); + * text('🦟', x, y); * } * *
* - *
+ *
* - * let x = 0; + * // Click and drag the mouse to view the scene from different angles. * * function setup() { - * createCanvas(100, 100); - * noLoop(); + * createCanvas(100, 100, WEBGL); + * + * describe( + * 'Two spheres drawn on a gray background. The sphere on the left is red and lit from the front. The sphere on the right is a blue wireframe.' + * ); * } * * function draw() { - * background(204); - * x += 1; - * line(x, 0, x, height); - * } + * background(200); * - * function mousePressed() { - * redraw(5); + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the red sphere. + * push(); + * translate(-25, 0, 0); + * noStroke(); + * directionalLight(255, 0, 0, 0, 0, -1); + * sphere(20); + * pop(); + * + * // Draw the blue sphere. + * push(); + * translate(25, 0, 0); + * strokeWeight(0.3); + * stroke(0, 0, 255); + * noFill(); + * sphere(20); + * pop(); * } * *
- * - * @alt - * black line on far left of canvas - * black line on far left of canvas */ - _main.default.prototype.redraw = function (n) { - if (this._inUserDraw || !this._setupDone) { - return; - } - var numberOfRedraws = parseInt(n); - if (isNaN(numberOfRedraws) || numberOfRedraws < 1) { - numberOfRedraws = 1; - } - var context = this._isGlobal ? window : this; + _main.default.prototype.push = function () { + this._styles.push({ + props: { + _colorMode: this._colorMode + }, + renderer: this._renderer.push() + }); + }; + /** + * Ends a drawing group that contains its own styles and transformations. + * + * By default, styles such as fill() and + * transformations such as rotate() are applied to + * all drawing that follows. The push() and `pop()` + * functions can limit the effect of styles and transformations to a specific + * group of shapes, images, and text. For example, a group of shapes could be + * translated to follow the mouse without affecting the rest of the sketch: + * + * ```js + * // Begin the drawing group. + * push(); + * + * // Translate the origin to the mouse's position. + * translate(mouseX, mouseY); + * + * // Style the face. + * noStroke(); + * fill('green'); + * + * // Draw the face. + * circle(0, 0, 60); + * + * // Style the eyes. + * fill('white'); + * + * // Draw the left eye. + * ellipse(-20, -20, 30, 20); + * + * // Draw the right eye. + * ellipse(20, -20, 30, 20); + * + * // End the drawing group. + * pop(); + * + * // Draw a bug. + * let x = random(0, 100); + * let y = random(0, 100); + * text('🦟', x, y); + * ``` + * + * In the code snippet above, the bug's position isn't affected by + * `translate(mouseX, mouseY)` because that transformation is contained + * between push() and `pop()`. The bug moves around + * the entire canvas as expected. + * + * Note: push() and `pop()` are always called as a + * pair. Both functions are required to begin and end a drawing group. + * + * push() and `pop()` can also be nested to create + * subgroups. For example, the code snippet above could be changed to give + * more detail to the frog’s eyes: + * + * ```js + * // Begin the drawing group. + * push(); + * + * // Translate the origin to the mouse's position. + * translate(mouseX, mouseY); + * + * // Style the face. + * noStroke(); + * fill('green'); + * + * // Draw a face. + * circle(0, 0, 60); + * + * // Style the eyes. + * fill('white'); + * + * // Draw the left eye. + * push(); + * translate(-20, -20); + * ellipse(0, 0, 30, 20); + * fill('black'); + * circle(0, 0, 8); + * pop(); + * + * // Draw the right eye. + * push(); + * translate(20, -20); + * ellipse(0, 0, 30, 20); + * fill('black'); + * circle(0, 0, 8); + * pop(); + * + * // End the drawing group. + * pop(); + * + * // Draw a bug. + * let x = random(0, 100); + * let y = random(0, 100); + * text('🦟', x, y); + * ``` + * + * In this version, the code to draw each eye is contained between its own + * push() and `pop()` functions. Doing so makes it + * easier to add details in the correct part of a drawing. + * + * push() and `pop()` contain the effects of the + * following functions: + * + * - fill() + * - noFill() + * - noStroke() + * - stroke() + * - tint() + * - noTint() + * - strokeWeight() + * - strokeCap() + * - strokeJoin() + * - imageMode() + * - rectMode() + * - ellipseMode() + * - colorMode() + * - textAlign() + * - textFont() + * - textSize() + * - textLeading() + * - applyMatrix() + * - resetMatrix() + * - rotate() + * - scale() + * - shearX() + * - shearY() + * - translate() + * + * In WebGL mode, push() and `pop()` contain the + * effects of a few additional styles: + * + * - setCamera() + * - ambientLight() + * - directionalLight() + * - pointLight() texture() + * - specularMaterial() + * - shininess() + * - normalMaterial() + * - shader() + * + * @method pop + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Draw the left circle. + * circle(25, 50, 20); + * + * // Begin the drawing group. + * push(); + * + * // Translate the origin to the center. + * translate(50, 50); + * + * // Style the circle. + * strokeWeight(5); + * stroke('royalblue'); + * fill('orange'); + * + * // Draw the circle. + * circle(0, 0, 20); + * + * // End the drawing group. + * pop(); + * + * // Draw the right circle. + * circle(75, 50, 20); + * + * describe( + * 'Three circles drawn in a row on a gray background. The left and right circles are white with thin, black borders. The middle circle is orange with a thick, blue border.' + * ); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * // Slow the frame rate. + * frameRate(24); + * + * describe('A mosquito buzzes in front of a green frog. The frog follows the mouse as the user moves.'); + * } + * + * function draw() { + * background(200); + * + * // Begin the drawing group. + * push(); + * + * // Translate the origin to the mouse's position. + * translate(mouseX, mouseY); + * + * // Style the face. + * noStroke(); + * fill('green'); + * + * // Draw a face. + * circle(0, 0, 60); + * + * // Style the eyes. + * fill('white'); + * + * // Draw the left eye. + * push(); + * translate(-20, -20); + * ellipse(0, 0, 30, 20); + * fill('black'); + * circle(0, 0, 8); + * pop(); + * + * // Draw the right eye. + * push(); + * translate(20, -20); + * ellipse(0, 0, 30, 20); + * fill('black'); + * circle(0, 0, 8); + * pop(); + * + * // End the drawing group. + * pop(); + * + * // Draw a bug. + * let x = random(0, 100); + * let y = random(0, 100); + * text('🦟', x, y); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe( + * 'Two spheres drawn on a gray background. The sphere on the left is red and lit from the front. The sphere on the right is a blue wireframe.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the red sphere. + * push(); + * translate(-25, 0, 0); + * noStroke(); + * directionalLight(255, 0, 0, 0, 0, -1); + * sphere(20); + * pop(); + * + * // Draw the blue sphere. + * push(); + * translate(25, 0, 0); + * strokeWeight(0.3); + * stroke(0, 0, 255); + * noFill(); + * sphere(20); + * pop(); + * } + * + *
+ */ + _main.default.prototype.pop = function () { + var style = this._styles.pop(); + if (style) { + this._renderer.pop(style.renderer); + Object.assign(this, style.props); + } else { + console.warn('pop() was called without matching push()'); + } + }; + /** + * Runs the code in draw() once. + * + * By default, draw() tries to run 60 times per + * second. Calling noLoop() stops + * draw() from repeating. Calling `redraw()` will + * execute the code in the draw() function a set + * number of times. + * + * The parameter, `n`, is optional. If a number is passed, as in `redraw(5)`, + * then the draw loop will run the given number of times. By default, `n` is + * 1. + * + * @method redraw + * @param {Integer} [n] number of times to run draw(). Defaults to 1. + * + * @example + *
+ * + * // Double-click the canvas to move the circle. + * + * let x = 0; + * + * function setup() { + * createCanvas(100, 100); + * + * // Turn off the draw loop. + * noLoop(); + * + * describe( + * 'A white half-circle on the left edge of a gray square. The circle moves a little to the right when the user double-clicks.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Draw the circle. + * circle(x, 50, 20); + * + * // Increment x. + * x += 5; + * } + * + * // Run the draw loop when the user double-clicks. + * function doubleClicked() { + * redraw(); + * } + * + *
+ * + *
+ * + * // Double-click the canvas to move the circle. + * + * let x = 0; + * + * function setup() { + * createCanvas(100, 100); + * + * // Turn off the draw loop. + * noLoop(); + * + * describe( + * 'A white half-circle on the left edge of a gray square. The circle hops to the right when the user double-clicks.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Draw the circle. + * circle(x, 50, 20); + * + * // Increment x. + * x += 5; + * } + * + * // Run the draw loop three times when the user double-clicks. + * function doubleClicked() { + * redraw(3); + * } + * + *
+ */ + _main.default.prototype.redraw = function (n) { + if (this._inUserDraw || !this._setupDone) { + return; + } + var numberOfRedraws = parseInt(n); + if (isNaN(numberOfRedraws) || numberOfRedraws < 1) { + numberOfRedraws = 1; + } + var context = this._isGlobal ? window : this; if (typeof context.draw === 'function') { if (typeof context.setup === 'undefined') { context.scale(context._pixelDensity, context._pixelDensity); @@ -72443,64 +78967,204 @@ } }; /** - * The `p5()` constructor enables you to activate "instance mode" instead of normal - * "global mode". This is an advanced topic. A short description and example is - * included below. Please see - * - * Dan Shiffman's Coding Train video tutorial or this - * tutorial page - * for more info. + * Creates a new sketch in "instance" mode. + * + * All p5.js sketches are instances of the `p5` class. Put another way, all + * p5.js sketches are objects with methods including `pInst.setup()`, + * `pInst.draw()`, `pInst.circle()`, and `pInst.fill()`. By default, sketches + * run in "global mode" to hide some of this complexity. + * + * In global mode, a default instance of the `p5` class is created + * automatically. The default `p5` instance searches the web page's source + * code for declarations of system functions such as `setup()`, `draw()`, + * and `mousePressed()`, then attaches those functions to itself as methods. + * Calling a function such as `circle()` in global mode actually calls the + * default `p5` object's `pInst.circle()` method. * - * By default, all p5.js functions are in the global namespace (i.e. bound to the window - * object), meaning you can call them simply `ellipse()`, `fill()`, etc. However, this - * might be inconvenient if you are mixing with other JS libraries (synchronously or - * asynchronously) or writing long programs of your own. p5.js currently supports a - * way around this problem called "instance mode". In instance mode, all p5 functions - * are bound up in a single variable instead of polluting your global namespace. + * It's often helpful to isolate the code within sketches from the rest of the + * code on a web page. Two common use cases are web pages that use other + * JavaScript libraries and web pages with multiple sketches. "Instance mode" + * makes it easy to support both of these scenarios. * - * Optionally, you can specify a default container for the canvas and any other elements - * to append to with a second argument. You can give the ID of an element in your html, - * or an html node itself. + * Instance mode sketches support the same API as global mode sketches. They + * use a function to bundle, or encapsulate, an entire sketch. The function + * containing the sketch is then passed to the `p5()` constructor. * - * Note that creating instances like this also allows you to have more than one p5 sketch on - * a single web page, as they will each be wrapped up with their own set up variables. Of - * course, you could also use iframes to have multiple sketches in global mode. + * The first parameter, `sketch`, is a function that contains the sketch. For + * example, the statement `new p5(mySketch)` would create a new instance mode + * sketch from a function named `mySketch`. The function should have one + * parameter, `p`, that's a `p5` object. + * + * The second parameter, `node`, is optional. If a string is passed, as in + * `new p5(mySketch, 'sketch-one')` the new instance mode sketch will become a + * child of the HTML element with the id `sketch-one`. If an HTML element is + * passed, as in `new p5(mySketch, myElement)`, then the new instance mode + * sketch will become a child of the `Element` object called `myElement`. * * @method p5 - * @param {Object} sketch a function containing a p5.js sketch - * @param {String|Object} node ID or pointer to HTML DOM node to contain sketch in + * @param {Object} sketch function containing the sketch. + * @param {String|HTMLElement} node ID or reference to the HTML element that will contain the sketch. + * * @example - *
- * const s = p => { - * let x = 100; - * let y = 100; + *
+ * + * // Declare the function containing the sketch. + * function sketch(p) { + * + * // Declare the setup() method. + * p.setup = function () { + * p.createCanvas(100, 100); * - * p.setup = function() { - * p.createCanvas(700, 410); + * p.describe('A white circle drawn on a gray background.'); * }; * - * p.draw = function() { - * p.background(0); - * p.fill(255); - * p.rect(x, y, 50, 50); + * // Declare the draw() method. + * p.draw = function () { + * p.background(200); + * + * // Draw the circle. + * p.circle(50, 50, 20); * }; - * }; + * } * - * new p5(s); // invoke p5 - *
+ * // Initialize the sketch. + * new p5(sketch); + *
+ *
* - * @alt - * white rectangle on black background + *
+ * + * // Declare the function containing the sketch. + * function sketch(p) { + * // Create the sketch's variables within its scope. + * let x = 50; + * let y = 50; + * + * // Declare the setup() method. + * p.setup = function () { + * p.createCanvas(100, 100); + * + * p.describe('A white circle moves randomly on a gray background.'); + * }; + * + * // Declare the draw() method. + * p.draw = function () { + * p.background(200); + * + * // Update x and y. + * x += p.random(-1, 1); + * y += p.random(-1, 1); + * + * // Draw the circle. + * p.circle(x, y, 20); + * }; + * } + * + * // Initialize the sketch. + * new p5(sketch); + * + *
+ * + *
+ * + * // Declare the function containing the sketch. + * function sketch(p) { + * + * // Declare the setup() method. + * p.setup = function () { + * p.createCanvas(100, 100); + * + * p.describe('A white circle drawn on a gray background.'); + * }; + * + * // Declare the draw() method. + * p.draw = function () { + * p.background(200); + * + * // Draw the circle. + * p.circle(50, 50, 20); + * }; + * } + * + * // Select the web page's body element. + * let body = document.querySelector('body'); + * + * // Initialize the sketch and attach it to the web page's body. + * new p5(sketch, body); + * + *
+ * + *
+ * + * // Declare the function containing the sketch. + * function sketch(p) { + * + * // Declare the setup() method. + * p.setup = function () { + * p.createCanvas(100, 100); + * + * p.describe( + * 'A white circle drawn on a gray background. The circle follows the mouse as the user moves.' + * ); + * }; + * + * // Declare the draw() method. + * p.draw = function () { + * p.background(200); + * + * // Draw the circle. + * p.circle(p.mouseX, p.mouseY, 20); + * }; + * } + * + * // Initialize the sketch. + * new p5(sketch); + * + *
+ * + *
+ * + * // Declare the function containing the sketch. + * function sketch(p) { + * + * // Declare the setup() method. + * p.setup = function () { + * p.createCanvas(100, 100); + * + * p.describe( + * 'A white circle drawn on a gray background. The circle follows the mouse as the user moves. The circle becomes black when the user double-clicks.' + * ); + * }; + * + * // Declare the draw() method. + * p.draw = function () { + * p.background(200); + * + * // Draw the circle. + * p.circle(p.mouseX, p.mouseY, 20); + * }; + * + * // Declare the doubleClicked() method. + * p.doubleClicked = function () { + * // Change the fill color when the user double-clicks. + * p.fill(0); + * }; + * } + * + * // Initialize the sketch. + * new p5(sketch); + * + *
*/ var _default = _main.default; exports.default = _default; }, { - './main': 298, - 'core-js/modules/es.object.assign': 194 + './main': 306, + 'core-js/modules/es.object.assign': 201 } ], - 311: [ + 319: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -72599,41 +79263,74 @@ * @requires constants */ /** - * Multiplies the current matrix by the one specified through the parameters. - * This is a powerful operation that can perform the equivalent of translate, - * scale, shear and rotate all at once. You can learn more about transformation - * matrices on - * Wikipedia. + * Applies a transformation matrix to the coordinate system. + * + * Transformations such as + * translate(), + * rotate(), and + * scale() + * use matrix-vector multiplication behind the scenes. A table of numbers, + * called a matrix, encodes each transformation. The values in the matrix + * then multiply each point on the canvas, which is represented by a vector. * - * The naming of the arguments here follows the naming of the - * WHATWG specification and corresponds to a - * transformation matrix of the - * form: + * `applyMatrix()` allows for many transformations to be applied at once. See + * Wikipedia + * and MDN + * for more details about transformations. + * + * There are two ways to call `applyMatrix()` in two and three dimensions. + * + * In 2D mode, the parameters `a`, `b`, `c`, `d`, `e`, and `f`, correspond to + * elements in the following transformation matrix: * * > The transformation matrix used when applyMatrix is called + * alt="The transformation matrix used when applyMatrix is called in 2D mode."/> + * + * The numbers can be passed individually, as in + * `applyMatrix(2, 0, 0, 0, 2, 0)`. They can also be passed in an array, as in + * `applyMatrix([2, 0, 0, 0, 2, 0])`. + * + * In 3D mode, the parameters `a`, `b`, `c`, `d`, `e`, `f`, `g`, `h`, `i`, + * `j`, `k`, `l`, `m`, `n`, `o`, and `p` correspond to elements in the + * following transformation matrix: * * The transformation matrix used when applyMatrix is called with 4x4 matrix + * alt="The transformation matrix used when applyMatrix is called in 3D mode."/> + * + * The numbers can be passed individually, as in + * `applyMatrix(2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1)`. They can + * also be passed in an array, as in + * `applyMatrix([2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1])`. + * + * By default, transformations accumulate. The + * push() and pop() functions + * can be used to isolate transformations within distinct drawing groups. + * + * Note: Transformations are reset at the beginning of the draw loop. Calling + * `applyMatrix()` inside the draw() function won't + * cause shapes to transform continuously. * * @method applyMatrix - * @param {Array} arr an array of numbers - should be 6 or 16 length (2×3 or 4×4 matrix values) + * @param {Array} arr an array containing the elements of the transformation matrix. Its length should be either 6 (2D) or 16 (3D). * @chainable + * * @example *
* * function setup() { - * frameRate(10); - * rectMode(CENTER); + * createCanvas(100, 100); + * + * describe('A white circle on a gray background.'); * } * * function draw() { - * let step = frameCount % 20; * background(200); - * // Equivalent to translate(x, y); - * applyMatrix(1, 0, 0, 1, 40 + step, 50); - * rect(0, 0, 50, 50); + * + * // Translate the origin to the center. + * applyMatrix(1, 0, 0, 1, 50, 50); + * + * // Draw the circle at coordinates (0, 0). + * circle(0, 0, 40); * } * *
@@ -72641,17 +79338,20 @@ *
* * function setup() { - * frameRate(10); - * rectMode(CENTER); + * createCanvas(100, 100); + * + * describe('A white circle on a gray background.'); * } * * function draw() { - * let step = frameCount % 20; * background(200); - * translate(50, 50); - * // Equivalent to scale(x, y); - * applyMatrix(1 / step, 0, 0, 1 / step, 0, 0); - * rect(0, 0, 50, 50); + * + * // Translate the origin to the center. + * let m = [1, 0, 0, 1, 50, 50]; + * applyMatrix(m); + * + * // Draw the circle at coordinates (0, 0). + * circle(0, 0, 40); * } * *
@@ -72659,20 +79359,22 @@ *
* * function setup() { - * frameRate(10); - * rectMode(CENTER); + * createCanvas(100, 100); + * + * describe("A white rectangle on a gray background. The rectangle's long axis runs from top-left to bottom-right."); * } * * function draw() { - * let step = frameCount % 20; - * let angle = map(step, 0, 20, 0, TWO_PI); - * let cos_a = cos(angle); - * let sin_a = sin(angle); * background(200); - * translate(50, 50); - * // Equivalent to rotate(angle); - * applyMatrix(cos_a, sin_a, -sin_a, cos_a, 0, 0); - * rect(0, 0, 50, 50); + * + * // Rotate the coordinate system 1/8 turn. + * let angle = QUARTER_PI; + * let ca = cos(angle); + * let sa = sin(angle); + * applyMatrix(ca, sa, -sa, ca, 0, 0); + * + * // Draw a rectangle at coordinates (50, 0). + * rect(50, 0, 40, 20); * } * *
@@ -72680,78 +79382,89 @@ *
* * function setup() { - * frameRate(10); - * rectMode(CENTER); + * createCanvas(100, 100); + * + * describe( + * 'Two white squares on a gray background. The larger square appears at the top-center. The smaller square appears at the top-left.' + * ); * } * * function draw() { - * let step = frameCount % 20; - * let angle = map(step, 0, 20, -PI / 4, PI / 4); * background(200); - * translate(50, 50); - * // equivalent to shearX(angle); - * let shear_factor = 1 / tan(PI / 2 - angle); - * applyMatrix(1, 0, shear_factor, 1, 0, 0); - * rect(0, 0, 50, 50); + * + * // Draw a square at (30, 20). + * square(30, 20, 40); + * + * // Scale the coordinate system by a factor of 0.5. + * applyMatrix(0.5, 0, 0, 0.5, 0, 0); + * + * // Draw a square at (30, 20). + * // It appears at (15, 10) after scaling. + * square(30, 20, 40); * } * *
* - *
+ *
* * function setup() { - * createCanvas(100, 100, WEBGL); - * noFill(); + * createCanvas(100, 100); + * + * describe('A white quadrilateral on a gray background.'); * } * * function draw() { * background(200); - * rotateY(PI / 6); - * stroke(153); - * box(35); - * let rad = millis() / 1000; - * // Set rotation angles - * let ct = cos(rad); - * let st = sin(rad); - * // Matrix for rotation around the Y axis - * applyMatrix( - * ct, 0.0, st, 0.0, - * 0.0, 1.0, 0.0, 0.0, - * -st, 0.0, ct, 0.0, - * 0.0, 0.0, 0.0, 1.0 - * ); - * stroke(255); - * box(50); + * + * // Calculate the shear factor. + * let angle = QUARTER_PI; + * let shearFactor = 1 / tan(HALF_PI - angle); + * + * // Shear the coordinate system along the x-axis. + * applyMatrix(1, 0, shearFactor, 1, 0, 0); + * + * // Draw the square. + * square(0, 0, 50); * } * *
* *
* + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white cube rotates slowly against a gray background.'); + * } + * * function draw() { * background(200); - * let testMatrix = [1, 0, 0, 1, 0, 0]; - * applyMatrix(testMatrix); - * rect(0, 0, 50, 50); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Rotate the coordinate system a little more each frame. + * let angle = frameCount * 0.01; + * let ca = cos(angle); + * let sa = sin(angle); + * applyMatrix(ca, 0, sa, 0, 0, 1, 0, 0, -sa, 0, ca, 0, 0, 0, 0, 1); + * + * // Draw a box. + * box(); * } * *
- * - * @alt - * A rectangle translating to the right - * A rectangle shrinking to the center - * A rectangle rotating clockwise about the center - * A rectangle shearing - * A rectangle in the upper left corner */ /** * @method applyMatrix - * @param {Number} a numbers which define the 2×3 or 4×4 matrix to be multiplied - * @param {Number} b numbers which define the 2×3 or 4×4 matrix to be multiplied - * @param {Number} c numbers which define the 2×3 or 4×4 matrix to be multiplied - * @param {Number} d numbers which define the 2×3 or 4×4 matrix to be multiplied - * @param {Number} e numbers which define the 2×3 or 4×4 matrix to be multiplied - * @param {Number} f numbers which define the 2×3 or 4×4 matrix to be multiplied + * @param {Number} a an element of the transformation matrix. + * @param {Number} b an element of the transformation matrix. + * @param {Number} c an element of the transformation matrix. + * @param {Number} d an element of the transformation matrix. + * @param {Number} e an element of the transformation matrix. + * @param {Number} f an element of the transformation matrix. * @chainable */ /** @@ -72762,16 +79475,16 @@ * @param {Number} d * @param {Number} e * @param {Number} f - * @param {Number} g numbers which define the 4×4 matrix to be multiplied - * @param {Number} h numbers which define the 4×4 matrix to be multiplied - * @param {Number} i numbers which define the 4×4 matrix to be multiplied - * @param {Number} j numbers which define the 4×4 matrix to be multiplied - * @param {Number} k numbers which define the 4×4 matrix to be multiplied - * @param {Number} l numbers which define the 4×4 matrix to be multiplied - * @param {Number} m numbers which define the 4×4 matrix to be multiplied - * @param {Number} n numbers which define the 4×4 matrix to be multiplied - * @param {Number} o numbers which define the 4×4 matrix to be multiplied - * @param {Number} p numbers which define the 4×4 matrix to be multiplied + * @param {Number} g an element of the transformation matrix. + * @param {Number} h an element of the transformation matrix. + * @param {Number} i an element of the transformation matrix. + * @param {Number} j an element of the transformation matrix. + * @param {Number} k an element of the transformation matrix. + * @param {Number} l an element of the transformation matrix. + * @param {Number} m an element of the transformation matrix. + * @param {Number} n an element of the transformation matrix. + * @param {Number} o an element of the transformation matrix. + * @param {Number} p an element of the transformation matrix. * @chainable */ @@ -72787,221 +79500,796 @@ return this; }; /** - * Replaces the current matrix with the identity matrix. + * Clears all transformations applied to the coordinate system. * * @method resetMatrix * @chainable + * * @example *
* - * translate(50, 50); - * applyMatrix(0.5, 0.5, -0.5, 0.5, 0, 0); - * rect(0, 0, 20, 20); - * // Note that the translate is also reset. - * resetMatrix(); - * rect(0, 0, 20, 20); + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'Two circles drawn on a gray background. A blue circle is at the top-left and a red circle is at the bottom-right.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Translate the origin to the center. + * translate(50, 50); + * + * // Draw a blue circle at the coordinates (25, 25). + * fill('blue'); + * circle(25, 25, 20); + * + * // Clear all transformations. + * // The origin is now at the top-left corner. + * resetMatrix(); + * + * // Draw a red circle at the coordinates (25, 25). + * fill('red'); + * circle(25, 25, 20); + * } * *
- * - * @alt - * A rotated rectangle in the center with another at the top left corner */ _main.default.prototype.resetMatrix = function () { this._renderer.resetMatrix(); return this; }; /** - * Rotates a shape by the amount specified by the angle parameter. This - * function accounts for angleMode, so angles - * can be entered in either RADIANS or DEGREES. + * Rotates the coordinate system. + * + * By default, the positive x-axis points to the right and the positive y-axis + * points downward. The `rotate()` function changes this orientation by + * rotating the coordinate system about the origin. Everything drawn after + * `rotate()` is called will appear to be rotated. + * + * The first parameter, `angle`, is the amount to rotate. For example, calling + * `rotate(1)` rotates the coordinate system clockwise 1 radian which is + * nearly 57˚. `rotate()` interprets angle values using the current + * angleMode(). + * + * The second parameter, `axis`, is optional. It's used to orient 3D rotations + * in WebGL mode. If a p5.Vector is passed, as in + * `rotate(QUARTER_PI, myVector)`, then the coordinate system will rotate + * `QUARTER_PI` radians about `myVector`. If an array of vector components is + * passed, as in `rotate(QUARTER_PI, [1, 0, 0])`, then the coordinate system + * will rotate `QUARTER_PI` radians about a vector with the components + * `[1, 0, 0]`. * - * Objects are always rotated around their relative position to the - * origin and positive numbers rotate objects in a clockwise direction. - * Transformations apply to everything that happens after and subsequent - * calls to the function accumulate the effect. For example, calling - * rotate(HALF_PI) and then rotate(HALF_PI) is the same as rotate(PI). - * All transformations are reset when draw() begins again. + * By default, transformations accumulate. For example, calling `rotate(1)` + * twice has the same effect as calling `rotate(2)` once. The + * push() and pop() functions + * can be used to isolate transformations within distinct drawing groups. * - * Technically, rotate() multiplies the current transformation matrix - * by a rotation matrix. This function can be further controlled by - * push() and pop(). + * Note: Transformations are reset at the beginning of the draw loop. Calling + * `rotate(1)` inside the draw() function won't cause + * shapes to spin. * * @method rotate - * @param {Number} angle the angle of rotation, specified in radians - * or degrees, depending on current angleMode - * @param {p5.Vector|Number[]} [axis] (in 3d) the axis to rotate around + * @param {Number} angle angle of rotation in the current angleMode(). + * @param {p5.Vector|Number[]} [axis] axis to rotate about in 3D. * @chainable + * * @example *
* - * translate(width / 2, height / 2); - * rotate(PI / 3.0); - * rect(-26, -26, 52, 52); + * function setup() { + * createCanvas(100, 100); + * + * describe( + * "A white rectangle on a gray background. The rectangle's long axis runs from top-left to bottom-right." + * ); + * } + * + * function draw() { + * background(200); + * + * // Rotate the coordinate system 1/8 turn. + * rotate(QUARTER_PI); + * + * // Draw a rectangle at coordinates (50, 0). + * rect(50, 0, 40, 20); + * } * *
* - * @alt - * white 52×52 rect with black outline at center rotated counter 45 degrees - */ - _main.default.prototype.rotate = function (angle, axis) { - _main.default._validateParameters('rotate', arguments); - this._renderer.rotate(this._toRadians(angle), axis); - return this; - }; - /** - * Rotates a shape around X axis by the amount specified in angle parameter. - * The angles can be entered in either RADIANS or DEGREES. + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * "A white rectangle on a gray background. The rectangle's long axis runs from top-left to bottom-right." + * ); + * } * - * Objects are always rotated around their relative position to the - * origin and positive numbers rotate objects in a clockwise direction. - * All transformations are reset when draw() begins again. + * function draw() { + * background(200); * - * @method rotateX - * @param {Number} angle the angle of rotation, specified in radians - * or degrees, depending on current angleMode - * @chainable - * @example - *
+ * // Rotate the coordinate system 1/16 turn. + * rotate(QUARTER_PI / 2); + * + * // Rotate the coordinate system another 1/16 turn. + * rotate(QUARTER_PI / 2); + * + * // Draw a rectangle at coordinates (50, 0). + * rect(50, 0, 40, 20); + * } + * + *
+ * + *
* * function setup() { - * createCanvas(100, 100, WEBGL); + * createCanvas(100, 100); + * + * // Use degrees. + * angleMode(DEGREES); + * + * describe( + * "A white rectangle on a gray background. The rectangle's long axis runs from top-left to bottom-right." + * ); * } + * * function draw() { - * background(255); - * rotateX(millis() / 1000); - * box(); + * background(200); + * + * // Rotate the coordinate system 1/8 turn. + * rotate(45); + * + * // Draw a rectangle at coordinates (50, 0). + * rect(50, 0, 40, 20); * } * *
* - * @alt - * 3d box rotating around the x axis. - */ - _main.default.prototype.rotateX = function (angle) { - this._assert3d('rotateX'); - _main.default._validateParameters('rotateX', arguments); - this._renderer.rotateX(this._toRadians(angle)); - return this; - }; - /** - * Rotates a shape around Y axis by the amount specified in angle parameter. - * The angles can be entered in either RADIANS or DEGREES. + *
+ * + * function setup() { + * createCanvas(100, 100); * - * Objects are always rotated around their relative position to the - * origin and positive numbers rotate objects in a clockwise direction. - * All transformations are reset when draw() begins again. + * describe( + * 'A white rectangle on a gray background. The rectangle rotates slowly about the top-left corner. It disappears and reappears periodically.' + * ); + * } * - * @method rotateY - * @param {Number} angle the angle of rotation, specified in radians - * or degrees, depending on current angleMode - * @chainable - * @example - *
+ * function draw() { + * background(200); + * + * // Rotate the coordinate system a little more each frame. + * let angle = frameCount * 0.01; + * rotate(angle); + * + * // Draw a rectangle at coordinates (50, 0). + * rect(50, 0, 40, 20); + * } + * + *
+ * + *
* * function setup() { * createCanvas(100, 100, WEBGL); + * + * describe("A cube on a gray background. The cube's front face points to the top-right."); * } + * * function draw() { - * background(255); - * rotateY(millis() / 1000); + * background(200); + * + * // Rotate the coordinate system 1/8 turn about + * // the axis [1, 1, 0]. + * let axis = createVector(1, 1, 0); + * rotate(QUARTER_PI, axis); + * + * // Draw a box. * box(); * } * *
* - * @alt - * 3d box rotating around the y axis. - */ - _main.default.prototype.rotateY = function (angle) { - this._assert3d('rotateY'); - _main.default._validateParameters('rotateY', arguments); - this._renderer.rotateY(this._toRadians(angle)); - return this; - }; - /** - * Rotates a shape around Z axis by the amount specified in angle parameter. - * The angles can be entered in either RADIANS or DEGREES. - * - * This method works in WEBGL mode only. - * - * Objects are always rotated around their relative position to the - * origin and positive numbers rotate objects in a clockwise direction. - * All transformations are reset when draw() begins again. - * - * @method rotateZ - * @param {Number} angle the angle of rotation, specified in radians - * or degrees, depending on current angleMode - * @chainable - * @example - *
+ *
* * function setup() { * createCanvas(100, 100, WEBGL); + * + * describe("A cube on a gray background. The cube's front face points to the top-right."); * } + * * function draw() { - * background(255); - * rotateZ(millis() / 1000); + * background(200); + * + * // Rotate the coordinate system 1/8 turn about + * // the axis [1, 1, 0]. + * let axis = [1, 1, 0]; + * rotate(QUARTER_PI, axis); + * + * // Draw a box. * box(); * } * *
- * - * @alt - * 3d box rotating around the z axis. */ - _main.default.prototype.rotateZ = function (angle) { - this._assert3d('rotateZ'); - _main.default._validateParameters('rotateZ', arguments); - this._renderer.rotateZ(this._toRadians(angle)); + _main.default.prototype.rotate = function (angle, axis) { + _main.default._validateParameters('rotate', arguments); + this._renderer.rotate(this._toRadians(angle), axis); return this; }; /** - * Increases or decreases the size of a shape by expanding or contracting - * vertices. Objects always scale from their relative origin to the - * coordinate system. Scale values are specified as decimal percentages. - * For example, the function call scale(2.0) increases the dimension of a - * shape by 200%. + * Rotates the coordinate system about the x-axis in WebGL mode. * - * Transformations apply to everything that happens after and subsequent - * calls to the function multiply the effect. For example, calling scale(2.0) - * and then scale(1.5) is the same as scale(3.0). If scale() is called - * within draw(), the transformation is reset when the loop begins again. + * The parameter, `angle`, is the amount to rotate. For example, calling + * `rotateX(1)` rotates the coordinate system about the x-axis by 1 radian. + * `rotateX()` interprets angle values using the current + * angleMode(). * - * Using this function with the z parameter is only available in WEBGL mode. - * This function can be further controlled with push() and pop(). + * By default, transformations accumulate. For example, calling `rotateX(1)` + * twice has the same effect as calling `rotateX(2)` once. The + * push() and pop() functions + * can be used to isolate transformations within distinct drawing groups. * - * @method scale - * @param {Number|p5.Vector|Number[]} s - * percent to scale the object, or percentage to - * scale the object in the x-axis if multiple arguments - * are given - * @param {Number} [y] percent to scale the object in the y-axis - * @param {Number} [z] percent to scale the object in the z-axis (webgl only) + * Note: Transformations are reset at the beginning of the draw loop. Calling + * `rotateX(1)` inside the draw() function won't cause + * shapes to spin. + * + * @method rotateX + * @param {Number} angle angle of rotation in the current angleMode(). * @chainable + * * @example *
* - * rect(30, 20, 50, 50); - * scale(0.5); - * rect(30, 20, 50, 50); - * - *
+ * // Click and drag the mouse to view the scene from different angles. * - *
- * - * rect(30, 20, 50, 50); - * scale(0.5, 1.3); - * rect(30, 20, 50, 50); - * - *
+ * function setup() { + * createCanvas(100, 100, WEBGL); * - * @alt - * white 52×52 rect with black outline at center rotated counter 45 degrees - * 2 white rects with black outline- 1 50×50 at center. other 25×65 bottom left - */ - /** + * describe('A white cube on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Rotate the coordinate system 1/8 turn. + * rotateX(QUARTER_PI); + * + * // Draw a box. + * box(); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white cube on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Rotate the coordinate system 1/16 turn. + * rotateX(QUARTER_PI / 2); + * + * // Rotate the coordinate system 1/16 turn. + * rotateX(QUARTER_PI / 2); + * + * // Draw a box. + * box(); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Use degrees. + * angleMode(DEGREES); + * + * describe('A white cube on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Rotate the coordinate system 1/8 turn. + * rotateX(45); + * + * // Draw a box. + * box(); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white cube rotates slowly against a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Rotate the coordinate system a little more each frame. + * let angle = frameCount * 0.01; + * rotateX(angle); + * + * // Draw a box. + * box(); + * } + * + *
+ */ + _main.default.prototype.rotateX = function (angle) { + this._assert3d('rotateX'); + _main.default._validateParameters('rotateX', arguments); + this._renderer.rotateX(this._toRadians(angle)); + return this; + }; + /** + * Rotates the coordinate system about the y-axis in WebGL mode. + * + * The parameter, `angle`, is the amount to rotate. For example, calling + * `rotateY(1)` rotates the coordinate system about the y-axis by 1 radian. + * `rotateY()` interprets angle values using the current + * angleMode(). + * + * By default, transformations accumulate. For example, calling `rotateY(1)` + * twice has the same effect as calling `rotateY(2)` once. The + * push() and pop() functions + * can be used to isolate transformations within distinct drawing groups. + * + * Note: Transformations are reset at the beginning of the draw loop. Calling + * `rotateY(1)` inside the draw() function won't cause + * shapes to spin. + * + * @method rotateY + * @param {Number} angle angle of rotation in the current angleMode(). + * @chainable + * + * @example + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white cube on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Rotate the coordinate system 1/8 turn. + * rotateY(QUARTER_PI); + * + * // Draw a box. + * box(); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white cube on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Rotate the coordinate system 1/16 turn. + * rotateY(QUARTER_PI / 2); + * + * // Rotate the coordinate system 1/16 turn. + * rotateY(QUARTER_PI / 2); + * + * // Draw a box. + * box(); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Use degrees. + * angleMode(DEGREES); + * + * describe('A white cube on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Rotate the coordinate system 1/8 turn. + * rotateY(45); + * + * // Draw a box. + * box(); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white cube rotates slowly against a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Rotate the coordinate system a little more each frame. + * let angle = frameCount * 0.01; + * rotateY(angle); + * + * // Draw a box. + * box(); + * } + * + *
+ */ + _main.default.prototype.rotateY = function (angle) { + this._assert3d('rotateY'); + _main.default._validateParameters('rotateY', arguments); + this._renderer.rotateY(this._toRadians(angle)); + return this; + }; + /** + * Rotates the coordinate system about the z-axis in WebGL mode. + * + * The parameter, `angle`, is the amount to rotate. For example, calling + * `rotateZ(1)` rotates the coordinate system about the z-axis by 1 radian. + * `rotateZ()` interprets angle values using the current + * angleMode(). + * + * By default, transformations accumulate. For example, calling `rotateZ(1)` + * twice has the same effect as calling `rotateZ(2)` once. The + * push() and pop() functions + * can be used to isolate transformations within distinct drawing groups. + * + * Note: Transformations are reset at the beginning of the draw loop. Calling + * `rotateZ(1)` inside the draw() function won't cause + * shapes to spin. + * + * @method rotateZ + * @param {Number} angle angle of rotation in the current angleMode(). + * @chainable + * + * @example + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white cube on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Rotate the coordinate system 1/8 turn. + * rotateZ(QUARTER_PI); + * + * // Draw a box. + * box(); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white cube on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Rotate the coordinate system 1/16 turn. + * rotateZ(QUARTER_PI / 2); + * + * // Rotate the coordinate system 1/16 turn. + * rotateZ(QUARTER_PI / 2); + * + * // Draw a box. + * box(); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Use degrees. + * angleMode(DEGREES); + * + * describe('A white cube on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Rotate the coordinate system 1/8 turn. + * rotateZ(45); + * + * // Draw a box. + * box(); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white cube rotates slowly against a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Rotate the coordinate system a little more each frame. + * let angle = frameCount * 0.01; + * rotateZ(angle); + * + * // Draw a box. + * box(); + * } + * + *
+ */ + _main.default.prototype.rotateZ = function (angle) { + this._assert3d('rotateZ'); + _main.default._validateParameters('rotateZ', arguments); + this._renderer.rotateZ(this._toRadians(angle)); + return this; + }; + /** + * Scales the coordinate system. + * + * By default, shapes are drawn at their original scale. A rectangle that's 50 + * pixels wide appears to take up half the width of a 100 pixel-wide canvas. + * The `scale()` function can shrink or stretch the coordinate system so that + * shapes appear at different sizes. There are two ways to call `scale()` with + * parameters that set the scale factor(s). + * + * The first way to call `scale()` uses numbers to set the amount of scaling. + * The first parameter, `s`, sets the amount to scale each axis. For example, + * calling `scale(2)` stretches the x-, y-, and z-axes by a factor of 2. The + * next two parameters, `y` and `z`, are optional. They set the amount to + * scale the y- and z-axes. For example, calling `scale(2, 0.5, 1)` stretches + * the x-axis by a factor of 2, shrinks the y-axis by a factor of 0.5, and + * leaves the z-axis unchanged. + * + * The second way to call `scale()` uses a p5.Vector + * object to set the scale factors. For example, calling `scale(myVector)` + * uses the x-, y-, and z-components of `myVector` to set the amount of + * scaling along the x-, y-, and z-axes. Doing so is the same as calling + * `scale(myVector.x, myVector.y, myVector.z)`. + * + * By default, transformations accumulate. For example, calling `scale(1)` + * twice has the same effect as calling `scale(2)` once. The + * push() and pop() functions + * can be used to isolate transformations within distinct drawing groups. + * + * Note: Transformations are reset at the beginning of the draw loop. Calling + * `scale(2)` inside the draw() function won't cause + * shapes to grow continuously. + * + * @method scale + * @param {Number|p5.Vector|Number[]} s amount to scale along the positive x-axis. + * @param {Number} [y] amount to scale along the positive y-axis. Defaults to `s`. + * @param {Number} [z] amount to scale along the positive z-axis. Defaults to `y`. + * @chainable + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'Two white squares on a gray background. The larger square appears at the top-center. The smaller square appears at the top-left.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Draw a square at (30, 20). + * square(30, 20, 40); + * + * // Scale the coordinate system by a factor of 0.5. + * scale(0.5); + * + * // Draw a square at (30, 20). + * // It appears at (15, 10) after scaling. + * square(30, 20, 40); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * describe('A rectangle and a square drawn in white on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Draw a square at (30, 20). + * square(30, 20, 40); + * + * // Scale the coordinate system by factors of + * // 0.5 along the x-axis and + * // 1.3 along the y-axis. + * scale(0.5, 1.3); + * + * // Draw a square at (30, 20). + * // It appears as a rectangle at (15, 26) after scaling. + * square(30, 20, 40); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * describe('A rectangle and a square drawn in white on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Draw a square at (30, 20). + * square(30, 20, 40); + * + * // Create a p5.Vector object. + * let v = createVector(0.5, 1.3); + * + * // Scale the coordinate system by factors of + * // 0.5 along the x-axis and + * // 1.3 along the y-axis. + * scale(v); + * + * // Draw a square at (30, 20). + * // It appears as a rectangle at (15, 26) after scaling. + * square(30, 20, 40); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe( + * 'A red box and a blue box drawn on a gray background. The red box appears embedded in the blue box.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * lights(); + * + * // Style the spheres. + * noStroke(); + * + * // Draw the red sphere. + * fill('red'); + * box(); + * + * // Scale the coordinate system by factors of + * // 0.5 along the x-axis and + * // 1.3 along the y-axis and + * // 2 along the z-axis. + * scale(0.5, 1.3, 2); + * + * // Draw the blue sphere. + * fill('blue'); + * box(); + * } + * + *
+ */ + /** * @method scale - * @param {p5.Vector|Number[]} scales per-axis percents to scale the object + * @param {p5.Vector|Number[]} scales vector whose components should be used to scale. * @chainable */ _main.default.prototype.scale = function (x, y, z) { @@ -73012,7 +80300,7 @@ x = v.x; y = v.y; z = v.z; - } else if (x instanceof Array) { + } else if (Array.isArray(x)) { var rg = x; x = rg[0]; y = rg[1]; @@ -73023,40 +80311,78 @@ } else if (isNaN(z)) { z = 1; } - this._renderer.scale.call(this._renderer, x, y, z); + this._renderer.scale(x, y, z); return this; }; /** - * Shears a shape around the x-axis by the amount specified by the angle - * parameter. Angles should be specified in the current angleMode. - * Objects are always sheared around their relative position to the origin - * and positive numbers shear objects in a clockwise direction. + * Shears the x-axis so that shapes appear skewed. + * + * By default, the x- and y-axes are perpendicular. The `shearX()` function + * transforms the coordinate system so that x-coordinates are translated while + * y-coordinates are fixed. * - * Transformations apply to everything that happens after and subsequent - * calls to the function accumulates the effect. For example, calling - * shearX(PI/2) and then shearX(PI/2) is the same as shearX(PI). - * If shearX() is called within the draw(), - * the transformation is reset when the loop begins again. + * The first parameter, `angle`, is the amount to shear. For example, calling + * `shearX(1)` transforms all x-coordinates using the formula + * `x = x + y * tan(angle)`. `shearX()` interprets angle values using the + * current angleMode(). * - * Technically, shearX() multiplies the current - * transformation matrix by a rotation matrix. This function can be further - * controlled by the push() and pop() functions. + * By default, transformations accumulate. For example, calling + * `shearX(1)` twice has the same effect as calling `shearX(2)` once. The + * push() and + * pop() functions can be used to isolate + * transformations within distinct drawing groups. + * + * Note: Transformations are reset at the beginning of the draw loop. Calling + * `shearX(1)` inside the draw() function won't + * cause shapes to shear continuously. * * @method shearX - * @param {Number} angle angle of shear specified in radians or degrees, - * depending on current angleMode + * @param {Number} angle angle to shear by in the current angleMode(). * @chainable + * * @example *
* - * translate(width / 4, height / 4); - * shearX(PI / 4.0); - * rect(0, 0, 30, 30); + * function setup() { + * createCanvas(100, 100); + * + * describe('A white quadrilateral on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Shear the coordinate system along the x-axis. + * shearX(QUARTER_PI); + * + * // Draw the square. + * square(0, 0, 50); + * } * *
* - * @alt - * white irregular quadrilateral with black outline at top middle. + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * // Use degrees. + * angleMode(DEGREES); + * + * describe('A white quadrilateral on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Shear the coordinate system along the x-axis. + * shearX(45); + * + * // Draw the square. + * square(0, 0, 50); + * } + * + *
*/ _main.default.prototype.shearX = function (angle) { _main.default._validateParameters('shearX', arguments); @@ -73065,36 +80391,74 @@ return this; }; /** - * Shears a shape around the y-axis the amount specified by the angle - * parameter. Angles should be specified in the current angleMode. Objects - * are always sheared around their relative position to the origin and - * positive numbers shear objects in a clockwise direction. + * Shears the y-axis so that shapes appear skewed. * - * Transformations apply to everything that happens after and subsequent - * calls to the function accumulates the effect. For example, calling - * shearY(PI/2) and then shearY(PI/2) is the same as shearY(PI). If - * shearY() is called within the draw(), the transformation is reset when - * the loop begins again. + * By default, the x- and y-axes are perpendicular. The `shearY()` function + * transforms the coordinate system so that y-coordinates are translated while + * x-coordinates are fixed. * - * Technically, shearY() multiplies the current transformation matrix by a - * rotation matrix. This function can be further controlled by the - * push() and pop() functions. + * The first parameter, `angle`, is the amount to shear. For example, calling + * `shearY(1)` transforms all y-coordinates using the formula + * `y = y + x * tan(angle)`. `shearY()` interprets angle values using the + * current angleMode(). + * + * By default, transformations accumulate. For example, calling + * `shearY(1)` twice has the same effect as calling `shearY(2)` once. The + * push() and + * pop() functions can be used to isolate + * transformations within distinct drawing groups. + * + * Note: Transformations are reset at the beginning of the draw loop. Calling + * `shearY(1)` inside the draw() function won't + * cause shapes to shear continuously. * * @method shearY - * @param {Number} angle angle of shear specified in radians or degrees, - * depending on current angleMode + * @param {Number} angle angle to shear by in the current angleMode(). * @chainable + * * @example *
* - * translate(width / 4, height / 4); - * shearY(PI / 4.0); - * rect(0, 0, 30, 30); + * function setup() { + * createCanvas(100, 100); + * + * describe('A white quadrilateral on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Shear the coordinate system along the x-axis. + * shearY(QUARTER_PI); + * + * // Draw the square. + * square(0, 0, 50); + * } * *
* - * @alt - * white irregular quadrilateral with black outline at middle bottom. + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * // Use degrees. + * angleMode(DEGREES); + * + * describe('A white quadrilateral on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Shear the coordinate system along the x-axis. + * shearY(45); + * + * // Draw the square. + * square(0, 0, 50); + * } + * + *
*/ _main.default.prototype.shearY = function (angle) { _main.default._validateParameters('shearY', arguments); @@ -73103,61 +80467,179 @@ return this; }; /** - * Specifies an amount to displace objects within the display window. - * The x parameter specifies left/right translation, the y parameter - * specifies up/down translation. - * - * Transformations are cumulative and apply to everything that happens after - * and subsequent calls to the function accumulates the effect. For example, - * calling translate(50, 0) and then translate(20, 0) is the same as - * translate(70, 0). If translate() is called within draw(), the - * transformation is reset when the loop begins again. This function can be - * further controlled by using push() and pop(). + * Translates the coordinate system. + * + * By default, the origin `(0, 0)` is at the sketch's top-left corner in 2D + * mode and center in WebGL mode. The `translate()` function shifts the origin + * to a different position. Everything drawn after `translate()` is called + * will appear to be shifted. There are two ways to call `translate()` with + * parameters that set the origin's position. + * + * The first way to call `translate()` uses numbers to set the amount of + * translation. The first two parameters, `x` and `y`, set the amount to + * translate along the positive x- and y-axes. For example, calling + * `translate(20, 30)` translates the origin 20 pixels along the x-axis and 30 + * pixels along the y-axis. The third parameter, `z`, is optional. It sets the + * amount to translate along the positive z-axis. For example, calling + * `translate(20, 30, 40)` translates the origin 20 pixels along the x-axis, + * 30 pixels along the y-axis, and 40 pixels along the z-axis. + * + * The second way to call `translate()` uses a + * p5.Vector object to set the amount of + * translation. For example, calling `translate(myVector)` uses the x-, y-, + * and z-components of `myVector` to set the amount to translate along the x-, + * y-, and z-axes. Doing so is the same as calling + * `translate(myVector.x, myVector.y, myVector.z)`. + * + * By default, transformations accumulate. For example, calling + * `translate(10, 0)` twice has the same effect as calling + * `translate(20, 0)` once. The push() and + * pop() functions can be used to isolate + * transformations within distinct drawing groups. + * + * Note: Transformations are reset at the beginning of the draw loop. Calling + * `translate(10, 0)` inside the draw() function won't + * cause shapes to move continuously. * * @method translate - * @param {Number} x left/right translation - * @param {Number} y up/down translation - * @param {Number} [z] forward/backward translation (WEBGL only) + * @param {Number} x amount to translate along the positive x-axis. + * @param {Number} y amount to translate along the positive y-axis. + * @param {Number} [z] amount to translate along the positive z-axis. * @chainable + * * @example *
* - * translate(30, 20); - * rect(0, 0, 55, 55); + * function setup() { + * createCanvas(100, 100); + * + * describe('A white circle on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Translate the origin to the center. + * translate(50, 50); + * + * // Draw a circle at coordinates (0, 0). + * circle(0, 0, 40); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'Two circles drawn on a gray background. The blue circle on the right overlaps the red circle at the center.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Translate the origin to the center. + * translate(50, 50); + * + * // Draw the red circle. + * fill('red'); + * circle(0, 0, 40); + * + * // Translate the origin to the right. + * translate(25, 0); + * + * // Draw the blue circle. + * fill('blue'); + * circle(0, 0, 40); + * } * *
* *
* - * rect(0, 0, 55, 55); // Draw rect at original 0,0 - * translate(30, 20); - * rect(0, 0, 55, 55); // Draw rect at new 0,0 - * translate(14, 14); - * rect(0, 0, 55, 55); // Draw rect at new 0,0 + * function setup() { + * createCanvas(100, 100); + * + * describe('A white circle moves slowly from left to right on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Calculate the x-coordinate. + * let x = frameCount * 0.2; + * + * // Translate the origin. + * translate(x, 50); + * + * // Draw a circle at coordinates (0, 0). + * circle(0, 0, 40); + * } * *
* - *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('A white circle on a gray background.'); + * } + * * function draw() { * background(200); - * rectMode(CENTER); - * translate(width / 2, height / 2); - * translate(p5.Vector.fromAngle(millis() / 1000, 40)); - * rect(0, 0, 20, 20); + * + * // Create a p5.Vector object. + * let v = createVector(50, 50); + * + * // Translate the origin by the vector. + * translate(v); + * + * // Draw a circle at coordinates (0, 0). + * circle(0, 0, 40); * } * *
* - * @alt - * white 55×55 rect with black outline at center right. - * 3 white 55×55 rects with black outlines at top-l, center-r and bottom-r. - * a 20×20 white rect moving in a circle around the canvas + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe( + * 'Two spheres sitting side-by-side on gray background. The sphere at the center is red. The sphere on the right is blue.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Turn on the lights. + * lights(); + * + * // Style the spheres. + * noStroke(); + * + * // Draw the red sphere. + * fill('red'); + * sphere(10); + * + * // Translate the origin to the right. + * translate(30, 0, 0); + * + * // Draw the blue sphere. + * fill('blue'); + * sphere(10); + * } + * + *
*/ /** * @method translate - * @param {p5.Vector} vector the vector to translate by + * @param {p5.Vector} vector vector by which to translate. * @chainable */ _main.default.prototype.translate = function (x, y, z) { @@ -73173,55 +80655,60 @@ exports.default = _default; }, { - './main': 298, - 'core-js/modules/es.array.from': 176, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.object.get-prototype-of': 198, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.typed-array.copy-within': 223, - 'core-js/modules/es.typed-array.every': 224, - 'core-js/modules/es.typed-array.fill': 225, - 'core-js/modules/es.typed-array.filter': 226, - 'core-js/modules/es.typed-array.find': 228, - 'core-js/modules/es.typed-array.find-index': 227, - 'core-js/modules/es.typed-array.for-each': 231, - 'core-js/modules/es.typed-array.includes': 232, - 'core-js/modules/es.typed-array.index-of': 233, - 'core-js/modules/es.typed-array.iterator': 236, - 'core-js/modules/es.typed-array.join': 237, - 'core-js/modules/es.typed-array.last-index-of': 238, - 'core-js/modules/es.typed-array.map': 239, - 'core-js/modules/es.typed-array.reduce': 241, - 'core-js/modules/es.typed-array.reduce-right': 240, - 'core-js/modules/es.typed-array.reverse': 242, - 'core-js/modules/es.typed-array.set': 243, - 'core-js/modules/es.typed-array.slice': 244, - 'core-js/modules/es.typed-array.some': 245, - 'core-js/modules/es.typed-array.sort': 246, - 'core-js/modules/es.typed-array.subarray': 247, - 'core-js/modules/es.typed-array.to-locale-string': 248, - 'core-js/modules/es.typed-array.to-string': 249, - 'core-js/modules/es.typed-array.uint8-array': 252, - 'core-js/modules/web.dom-collections.iterator': 256 + './main': 306, + 'core-js/modules/es.array.from': 180, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.object.get-prototype-of': 206, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.typed-array.copy-within': 231, + 'core-js/modules/es.typed-array.every': 232, + 'core-js/modules/es.typed-array.fill': 233, + 'core-js/modules/es.typed-array.filter': 234, + 'core-js/modules/es.typed-array.find': 236, + 'core-js/modules/es.typed-array.find-index': 235, + 'core-js/modules/es.typed-array.for-each': 239, + 'core-js/modules/es.typed-array.includes': 240, + 'core-js/modules/es.typed-array.index-of': 241, + 'core-js/modules/es.typed-array.iterator': 244, + 'core-js/modules/es.typed-array.join': 245, + 'core-js/modules/es.typed-array.last-index-of': 246, + 'core-js/modules/es.typed-array.map': 247, + 'core-js/modules/es.typed-array.reduce': 249, + 'core-js/modules/es.typed-array.reduce-right': 248, + 'core-js/modules/es.typed-array.reverse': 250, + 'core-js/modules/es.typed-array.set': 251, + 'core-js/modules/es.typed-array.slice': 252, + 'core-js/modules/es.typed-array.some': 253, + 'core-js/modules/es.typed-array.sort': 254, + 'core-js/modules/es.typed-array.subarray': 255, + 'core-js/modules/es.typed-array.to-locale-string': 256, + 'core-js/modules/es.typed-array.to-string': 257, + 'core-js/modules/es.typed-array.uint8-array': 260, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 312: [ + 320: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); _dereq_('core-js/modules/es.symbol.description'); _dereq_('core-js/modules/es.symbol.iterator'); + _dereq_('core-js/modules/es.array.for-each'); _dereq_('core-js/modules/es.array.from'); _dereq_('core-js/modules/es.array.iterator'); + _dereq_('core-js/modules/es.object.keys'); _dereq_('core-js/modules/es.object.to-string'); + _dereq_('core-js/modules/es.regexp.exec'); _dereq_('core-js/modules/es.regexp.to-string'); _dereq_('core-js/modules/es.string.ends-with'); _dereq_('core-js/modules/es.string.iterator'); + _dereq_('core-js/modules/es.string.replace'); + _dereq_('core-js/modules/web.dom-collections.for-each'); _dereq_('core-js/modules/web.dom-collections.iterator'); function _typeof2(obj) { if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { @@ -73238,12 +80725,17 @@ _dereq_('core-js/modules/es.symbol'); _dereq_('core-js/modules/es.symbol.description'); _dereq_('core-js/modules/es.symbol.iterator'); + _dereq_('core-js/modules/es.array.for-each'); _dereq_('core-js/modules/es.array.iterator'); + _dereq_('core-js/modules/es.object.keys'); _dereq_('core-js/modules/es.object.to-string'); + _dereq_('core-js/modules/es.regexp.exec'); _dereq_('core-js/modules/es.regexp.to-string'); _dereq_('core-js/modules/es.string.ends-with'); _dereq_('core-js/modules/es.string.iterator'); - _dereq_('core-js/modules/web.dom-collections.iterator'); + _dereq_('core-js/modules/es.string.replace'); + _dereq_('core-js/modules/web.dom-collections.for-each'); + _dereq_('core-js/modules/web.dom-collections.iterator'); var _main = _interopRequireDefault(_dereq_('../core/main')); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { @@ -73287,52 +80779,117 @@ * This module defines the p5 methods for working with local storage */ /** + * Stores a value in the web browser's local storage. + * + * Web browsers can save small amounts of data using the built-in + * localStorage object. + * Data stored in `localStorage` can be retrieved at any point, even after + * refreshing a page or restarting the browser. Data are stored as key-value + * pairs. + * + * `storeItem()` makes it easy to store values in `localStorage` and + * getItem() makes it easy to retrieve them. * - * Stores a value in local storage under the key name. - * Local storage is saved in the browser and persists - * between browsing sessions and page reloads. - * The key can be the name of the variable but doesn't - * have to be. To retrieve stored items - * see getItem. + * The first parameter, `key`, is the name of the value to be stored as a + * string. * - * Sensitive data such as passwords or personal information - * should not be stored in local storage. + * The second parameter, `value`, is the value to be stored. Values can have + * any type. + * + * Note: Sensitive data such as passwords or personal information shouldn't be + * stored in `localStorage`. * * @method storeItem * @for p5 - * @param {String} key - * @param {String|Number|Object|Boolean|p5.Color|p5.Vector} value + * @param {String} key name of the value. + * @param {String|Number|Boolean|Object|Array} value value to be stored. * * @example - *
- * // Type to change the letter in the - * // center of the canvas. - * // If you reload the page, it will - * // still display the last key you entered + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * // Store the player's name. + * storeItem('name', 'Feist'); * - * let myText; + * // Store the player's score. + * storeItem('score', 1234); * + * describe('The text "Feist: 1234" written in black on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(14); + * + * // Retrieve the name. + * let name = getItem('name'); + * + * // Retrieve the score. + * let score = getItem('score'); + * + * // Display the score. + * text(`${name}: ${score}`, 50, 50); + * } + * + *
+ * + *
+ * * function setup() { * createCanvas(100, 100); - * myText = getItem('myText'); - * if (myText === null) { - * myText = ''; - * } - * describe(`When you type the key name is displayed as black text on white background. - * If you reload the page, the last letter typed is still displaying.`); + * + * // Create an object. + * let p = { x: 50, y: 50 }; + * + * // Store the object. + * storeItem('position', p); + * + * describe('A white circle on a gray background.'); * } * * function draw() { - * textSize(40); - * background(255); - * text(myText, width / 2, height / 2); + * background(200); + * + * // Retrieve the object. + * let p = getItem('position'); + * + * // Draw the circle. + * circle(p.x, p.y, 30); * } + * + *
* - * function keyPressed() { - * myText = key; - * storeItem('myText', myText); + * function setup() { + * createCanvas(100, 100); + * + * // Create a p5.Color object. + * let c = color('deeppink'); + * + * // Store the object. + * storeItem('color', c); + * + * describe('A pink circle on a gray background.'); * } - *
+ * + * function draw() { + * background(200); + * + * // Retrieve the object. + * let c = getItem('color'); + * + * // Style the circle. + * fill(c); + * + * // Draw the circle. + * circle(50, 50, 30); + * } + * + *
*/ _main.default.prototype.storeItem = function (key, value) { @@ -73374,44 +80931,119 @@ localStorage.setItem(typeKey, type); }; /** + * Returns a value in the web browser's local storage. + * + * Web browsers can save small amounts of data using the built-in + * localStorage object. + * Data stored in `localStorage` can be retrieved at any point, even after + * refreshing a page or restarting the browser. Data are stored as key-value + * pairs. + * + * storeItem() makes it easy to store values in + * `localStorage` and `getItem()` makes it easy to retrieve them. + * + * The first parameter, `key`, is the name of the value to be stored as a + * string. * - * Returns the value of an item that was stored in local storage - * using storeItem() + * The second parameter, `value`, is the value to be retrieved a string. For + * example, calling `getItem('size')` retrieves the value with the key `size`. + * + * Note: Sensitive data such as passwords or personal information shouldn't be + * stored in `localStorage`. * * @method getItem * @for p5 - * @param {String} key name that you wish to use to store in local storage - * @return {Number|Object|String|Boolean|p5.Color|p5.Vector} Value of stored item + * @param {String} key name of the value. + * @return {String|Number|Boolean|Object|Array} stored item. * * @example - *
- * // Click the mouse to change - * // the color of the background - * // Once you have changed the color - * // it will stay changed even when you - * // reload the page. + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * // Store the player's name. + * storeItem('name', 'Feist'); * - * let myColor; + * // Store the player's score. + * storeItem('score', 1234); + * + * describe('The text "Feist: 1234" written in black on a gray background.'); + * } * + * function draw() { + * background(200); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(14); + * + * // Retrieve the name. + * let name = getItem('name'); + * + * // Retrieve the score. + * let score = getItem('score'); + * + * // Display the score. + * text(`${name}: ${score}`, 50, 50); + * } + * + *
+ * + *
+ * * function setup() { * createCanvas(100, 100); - * myColor = getItem('myColor'); + * + * // Create an object. + * let p = { x: 50, y: 50 }; + * + * // Store the object. + * storeItem('position', p); + * + * describe('A white circle on a gray background.'); * } * * function draw() { - * if (myColor !== null) { - * background(myColor); - * } - * describe(`If you click, the canvas changes to a random color.· - * If you reload the page, the canvas is still the color it was when the - * page was previously loaded.`); + * background(200); + * + * // Retrieve the object. + * let p = getItem('position'); + * + * // Draw the circle. + * circle(p.x, p.y, 30); * } + * + *
* - * function mousePressed() { - * myColor = color(random(255), random(255), random(255)); - * storeItem('myColor', myColor); + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * // Create a p5.Color object. + * let c = color('deeppink'); + * + * // Store the object. + * storeItem('color', c); + * + * describe('A pink circle on a gray background.'); * } - *
+ * + * function draw() { + * background(200); + * + * // Retrieve the object. + * let c = getItem('color'); + * + * // Style the circle. + * fill(c); + * + * // Draw the circle. + * circle(50, 50, 30); + * } + *
+ *
*/ _main.default.prototype.getItem = function (key) { var value = localStorage.getItem(key); @@ -73445,51 +81077,136 @@ return value; }; /** + * Removes all items in the web browser's local storage. + * + * Web browsers can save small amounts of data using the built-in + * localStorage object. + * Data stored in `localStorage` can be retrieved at any point, even after + * refreshing a page or restarting the browser. Data are stored as key-value + * pairs. Calling `clearStorage()` removes all data from `localStorage`. * - * Clears all local storage items set with storeItem() - * for the current domain. + * Note: Sensitive data such as passwords or personal information shouldn't be + * stored in `localStorage`. * * @method clearStorage * @for p5 * * @example - *
+ *
* + * // Double-click to clear localStorage. + * * function setup() { - * let myNum = 10; - * let myBool = false; - * storeItem('myNum', myNum); - * storeItem('myBool', myBool); - * print(getItem('myNum')); // logs 10 to the console - * print(getItem('myBool')); // logs false to the console + * createCanvas(100, 100); + * + * // Store the player's name. + * storeItem('name', 'Feist'); + * + * // Store the player's score. + * storeItem('score', 1234); + * + * describe( + * 'The text "Feist: 1234" written in black on a gray background. The text "null: null" appears when the user double-clicks.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(14); + * + * // Retrieve the name. + * let name = getItem('name'); + * + * // Retrieve the score. + * let score = getItem('score'); + * + * // Display the score. + * text(`${name}: ${score}`, 50, 50); + * } + * + * // Clear localStorage when the user double-clicks. + * function doubleClicked() { * clearStorage(); - * print(getItem('myNum')); // logs null to the console - * print(getItem('myBool')); // logs null to the console * } - *
+ * + *
*/ _main.default.prototype.clearStorage = function () { - localStorage.clear(); + var _this = this; + var keys = Object.keys(localStorage); + keys.forEach(function (key) { + if (key.endsWith('p5TypeID')) { + _this.removeItem(key.replace('p5TypeID', '')); + } + }); }; /** + * Removes an item from the web browser's local storage. * - * Removes an item that was stored with storeItem() + * Web browsers can save small amounts of data using the built-in + * localStorage object. + * Data stored in `localStorage` can be retrieved at any point, even after + * refreshing a page or restarting the browser. Data are stored as key-value + * pairs. + * + * storeItem() makes it easy to store values in + * `localStorage` and `removeItem()` makes it easy to delete them. + * + * The parameter, `key`, is the name of the value to remove as a string. For + * example, calling `removeItem('size')` removes the item with the key `size`. + * + * Note: Sensitive data such as passwords or personal information shouldn't be + * stored in `localStorage`. * * @method removeItem - * @param {String} key + * @param {String} key name of the value to remove. * @for p5 * * @example - *
+ *
* + * // Double-click to remove an item from localStorage. + * * function setup() { - * let myVar = 10; - * storeItem('myVar', myVar); - * print(getItem('myVar')); // logs 10 to the console - * removeItem('myVar'); - * print(getItem('myVar')); // logs null to the console + * createCanvas(100, 100); + * + * // Store the player's name. + * storeItem('name', 'Feist'); + * + * // Store the player's score. + * storeItem('score', 1234); + * + * describe( + * 'The text "Feist: 1234" written in black on a gray background. The text "Feist: null" appears when the user double-clicks.' + * ); * } - *
+ * + * function draw() { + * background(200); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(14); + * + * // Retrieve the name. + * let name = getItem('name'); + * + * // Retrieve the score. + * let score = getItem('score'); + * + * // Display the score. + * text(`${name}: ${score}`, 50, 50); + * } + * + * // Remove the word from localStorage when the user double-clicks. + * function doubleClicked() { + * removeItem('score'); + * } + * + *
*/ _main.default.prototype.removeItem = function (key) { if (typeof key !== 'string') { @@ -73500,20 +81217,25 @@ }; }, { - '../core/main': 298, - 'core-js/modules/es.array.from': 176, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.string.ends-with': 208, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/main': 306, + 'core-js/modules/es.array.for-each': 179, + 'core-js/modules/es.array.from': 180, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.object.keys': 207, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.regexp.exec': 213, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.string.ends-with': 216, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.string.replace': 222, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/web.dom-collections.for-each': 263, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 313: [ + 321: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -74357,22 +82079,22 @@ exports.default = _default; }, { - '../core/main': 298, - 'core-js/modules/es.array.concat': 169, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.object.get-prototype-of': 198, - 'core-js/modules/es.object.keys': 199, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.reflect.construct': 202, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/main': 306, + 'core-js/modules/es.array.concat': 171, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.object.get-prototype-of': 206, + 'core-js/modules/es.object.keys': 207, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.reflect.construct': 210, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 314: [ + 322: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -74388,6 +82110,7 @@ _dereq_('core-js/modules/es.array.slice'); _dereq_('core-js/modules/es.array.splice'); _dereq_('core-js/modules/es.function.name'); + _dereq_('core-js/modules/es.object.assign'); _dereq_('core-js/modules/es.object.get-prototype-of'); _dereq_('core-js/modules/es.object.to-string'); _dereq_('core-js/modules/es.promise'); @@ -74426,6 +82149,7 @@ _dereq_('core-js/modules/es.array.slice'); _dereq_('core-js/modules/es.array.splice'); _dereq_('core-js/modules/es.function.name'); + _dereq_('core-js/modules/es.object.assign'); _dereq_('core-js/modules/es.object.to-string'); _dereq_('core-js/modules/es.promise'); _dereq_('core-js/modules/es.regexp.exec'); @@ -74562,12 +82286,13 @@ /** * Searches the page for the first element that matches the given * CSS selector string. - * The string can be an ID, class, tag name, or a combination. `select()` - * returns a p5.Element object if it finds a match - * and `null` otherwise. + * + * The selector string can be an ID, class, tag name, or a combination. + * `select()` returns a p5.Element object if it + * finds a match and `null` if not. * * The second parameter, `container`, is optional. It specifies a container to - * search within. container can be CSS selector string, a + * search within. `container` can be CSS selector string, a * p5.Element object, or an * HTMLElement object. * @@ -74576,6 +82301,7 @@ * @param {String|p5.Element|HTMLElement} [container] CSS selector string, p5.Element, or * HTMLElement to search within. * @return {p5.Element|null} p5.Element containing the element. + * * @example *
* @@ -74596,6 +82322,7 @@ * * function setup() { * let cnv = createCanvas(100, 100); + * * // Add a class attribute to the canvas. * cnv.class('pinkborder'); * @@ -74603,6 +82330,7 @@ * * // Select the canvas by its class. * cnv = select('.pinkborder'); + * * // Style its border. * cnv.style('border', '5px deeppink dashed'); * @@ -74615,13 +82343,15 @@ * * function setup() { * let cnv = createCanvas(100, 100); - * // Set the canvas ID. + * + * // Set the canvas' ID. * cnv.id('mycanvas'); * * background(200); * * // Select the canvas by its ID. * cnv = select('#mycanvas'); + * * // Style its border. * cnv.style('border', '5px deeppink dashed'); * @@ -74644,12 +82374,13 @@ /** * Searches the page for all elements that matches the given * CSS selector string. - * The string can be an ID, class, tag name, or a combination. `selectAll()` - * returns an array of p5.Element objects if it - * finds any matches and an empty array otherwise. + * + * The selector string can be an ID, class, tag name, or a combination. + * `selectAll()` returns an array of p5.Element + * objects if it finds any matches and an empty array if none are found. * * The second parameter, `container`, is optional. It specifies a container to - * search within. container can be CSS selector string, a + * search within. `container` can be CSS selector string, a * p5.Element object, or an * HTMLElement object. * @@ -74658,10 +82389,13 @@ * @param {String|p5.Element|HTMLElement} [container] CSS selector string, p5.Element, or * HTMLElement to search within. * @return {p5.Element[]} array of p5.Elements containing any elements found. + * * @example *
* * function setup() { + * createCanvas(100, 100); + * * // Create three buttons. * createButton('1'); * createButton('2'); @@ -74701,17 +82435,22 @@ * let pinkButtons = selectAll('.btn-pink'); * * // Style the selected buttons. - * buttons.forEach(btn => { - * btn.style('font-family', 'Comic Sans MS'); - * }); - * - * pinkButtons.forEach(btn => { - * btn.style('background', 'deeppink'); - * btn.style('color', 'white'); - * }); + * buttons.forEach(setFont); + * pinkButtons.forEach(setColor); * * describe('Three buttons stacked vertically. The buttons are labeled, "1", "2", and "3". Buttons "1" and "3" are gray. Button "2" is pink.'); * } + * + * // Set a button's font to Comic Sans MS. + * function setFont(btn) { + * btn.style('font-family', 'Comic Sans MS'); + * } + * + * // Set a button's background and font color. + * function setColor(btn) { + * btn.style('background', 'deeppink'); + * btn.style('color', 'white'); + * } * *
*/ @@ -74767,7 +82506,7 @@ return this.createSelect(new _main.default.Element(elt, this)); } else if (children.length > 0 && children.every(function (c) { return c.tagName === 'INPUT' || c.tagName === 'LABEL'; - })) { + }) && (elt.tagName === 'DIV' || elt.tagName === 'SPAN')) { return this.createRadio(new _main.default.Element(elt, this)); } else { return new _main.default.Element(elt, this); @@ -74775,17 +82514,20 @@ }; /** * Removes all elements created by p5.js, including any event handlers. + * * There are two exceptions: - * canvas elements created by createCanvas + * canvas elements created by createCanvas() * and p5.Render objects created by - * createGraphics. + * createGraphics(). * * @method removeElements + * * @example *
* * function setup() { * createCanvas(100, 100); + * * background(200); * * // Create a paragraph element and place @@ -74796,6 +82538,7 @@ * describe('A gray square with the text "p5*js" written in its center. The text disappears when the mouse is pressed.'); * } * + * // Remove all elements when the mouse is pressed. * function mousePressed() { * removeElements(); * } @@ -74828,6 +82571,7 @@ * background(g); * } * + * // Remove all elements when the mouse is double-clicked. * function doubleClicked() { * removeElements(); * } @@ -74846,59 +82590,72 @@ }); }; /** - * `myElement.changed()` sets a function to call when the value of the - * p5.Element object changes. Calling - * `myElement.changed(false)` disables the function. + * Calls a function when the element changes. + * + * Calling `myElement.changed(false)` disables the function. * * @method changed * @param {Function|Boolean} fxn function to call when the element changes. * `false` disables the function. * @chainable + * * @example *
* + * let dropdown; + * * function setup() { + * createCanvas(100, 100); + * * background(200); * * // Create a dropdown menu and add a few color options. - * let drop = createSelect(); - * drop.position(0, 0); - * drop.option('red'); - * drop.option('green'); - * drop.option('blue'); - * - * // When the color option changes, paint the background with - * // that color. - * drop.changed(() => { - * let c = drop.value(); - * background(c); - * }); + * dropdown = createSelect(); + * dropdown.position(0, 0); + * dropdown.option('red'); + * dropdown.option('green'); + * dropdown.option('blue'); + * + * // Call paintBackground() when the color option changes. + * dropdown.changed(paintBackground); * * describe('A gray square with a dropdown menu at the top. The square changes color when an option is selected.'); * } + * + * // Paint the background with the selected color. + * function paintBackground() { + * let c = dropdown.value(); + * background(c); + * } * *
* *
* + * let checkbox; + * * function setup() { + * createCanvas(100, 100); + * * background(200); * * // Create a checkbox and place it beneath the canvas. - * let checkbox = createCheckbox(' circle'); + * checkbox = createCheckbox(' circle'); * checkbox.position(0, 100); * - * // When the checkbox changes, paint the background gray - * // and determine whether to draw a circle. - * checkbox.changed(() => { - * background(200); - * if (checkbox.checked() === true) { - * circle(50, 50, 30); - * } - * }); + * // Call repaint() when the checkbox changes. + * checkbox.changed(repaint); * * describe('A gray square with a checkbox underneath it that says "circle". A white circle appears when the box is checked and disappears otherwise.'); * } + * + * // Paint the background gray and determine whether to draw a circle. + * function repaint() { + * background(200); + * if (checkbox.checked() === true) { + * circle(50, 50, 30); + * } + * } * *
*/ @@ -74907,57 +82664,70 @@ return this; }; /** - * `myElement.input()` sets a function to call when input is detected within - * the p5.Element object. It's often used to with - * text inputs and sliders. Calling `myElement.input(false)` disables the - * function. + * Calls a function when the element receives input. + * + * `myElement.input()` is often used to with text inputs and sliders. Calling + * `myElement.input(false)` disables the function. * * @method input * @param {Function|Boolean} fxn function to call when input is detected within * the element. * `false` disables the function. * @chainable + * * @example *
* + * let slider; + * * function setup() { + * createCanvas(100, 100); + * * background(200); * * // Create a slider and place it beneath the canvas. - * let slider = createSlider(0, 255, 200); + * slider = createSlider(0, 255, 200); * slider.position(0, 100); * - * // When the slider changes, use its value to paint - * // the background. - * slider.input(() => { - * let g = slider.value(); - * background(g); - * }); + * // Call repaint() when the slider changes. + * slider.input(repaint); * * describe('A gray square with a range slider underneath it. The background changes shades of gray when the slider is moved.'); * } + * + * // Paint the background using slider's value. + * function repaint() { + * let g = slider.value(); + * background(g); + * } * *
* *
* + * let input; + * * function setup() { + * createCanvas(100, 100); + * * background(200); * * // Create an input and place it beneath the canvas. - * let inp = createInput(''); - * inp.position(0, 100); + * input = createInput(''); + * input.position(0, 100); * - * // When input is detected, paint the background gray - * // and display the text. - * inp.input(() => { - * background(200); - * let msg = inp.value(); - * text(msg, 5, 50); - * }); + * // Call repaint() when input is detected. + * input.input(repaint); * * describe('A gray square with a text input bar beneath it. Any text written in the input appears in the middle of the square.'); * } + * + * // Paint the background gray and display the input's value. + * function repaint() { + * background(200); + * let msg = input.value(); + * text(msg, 5, 50); + * } * *
*/ @@ -74975,8 +82745,10 @@ pInst._elements.push(c); return c; } /** - * Creates a `<div></div>` element. It's commonly used as a - * container for other elements. + * Creates a `<div></div>` element. + * + * `<div></div>` elements are commonly used as containers for + * other elements. * * The parameter `html` is optional. It accepts a string that sets the * inner HTML of the new `<div></div>`. @@ -74984,12 +82756,16 @@ * @method createDiv * @param {String} [html] inner HTML for the new `<div></div>` element. * @return {p5.Element} new p5.Element object. + * * @example *
* * function setup() { + * createCanvas(100, 100); + * * background(200); * + * // Create a div element and set its position. * let div = createDiv('p5*js'); * div.position(25, 35); * @@ -75001,6 +82777,8 @@ *
* * function setup() { + * createCanvas(100, 100); + * * background(200); * * // Create an h3 element within the div. @@ -75020,8 +82798,9 @@ return addElement(elt, this); }; /** - * Creates a `<p></p>` element. It's commonly used for - * paragraph-length text. + * Creates a `<p></p>` element. + * + * `<p></p>` elements are commonly used for paragraph-length text. * * The parameter `html` is optional. It accepts a string that sets the * inner HTML of the new `<p></p>`. @@ -75029,12 +82808,16 @@ * @method createP * @param {String} [html] inner HTML for the new `<p></p>` element. * @return {p5.Element} new p5.Element object. + * * @example *
* * function setup() { + * createCanvas(100, 100); + * * background(200); * + * // Create a paragraph element and set its position. * let p = createP('Tell me a story.'); * p.position(5, 0); * @@ -75050,8 +82833,10 @@ return addElement(elt, this); }; /** - * Creates a `<span></span>` element. It's commonly used as a - * container for inline elements. For example, a `<span></span>` + * Creates a `<span></span>` element. + * + * `<span></span>` elements are commonly used as containers + * for inline elements. For example, a `<span></span>` * can hold part of a sentence that's a * different style. * @@ -75061,13 +82846,16 @@ * @method createSpan * @param {String} [html] inner HTML for the new `<span></span>` element. * @return {p5.Element} new p5.Element object. + * * @example *
* * function setup() { + * createCanvas(100, 100); + * * background(200); * - * // Create a span element. + * // Create a span element and set its position. * let span = createSpan('p5*js'); * span.position(25, 35); * @@ -75081,24 +82869,25 @@ * function setup() { * background(200); * - * // Create a div element as - * // a container. + * // Create a div element as a container. * let div = createDiv(); - * // Place the div at the - * // center. + * + * // Place the div at the center. * div.position(25, 35); * * // Create a span element. * let s1 = createSpan('p5'); + * * // Create a second span element. * let s2 = createSpan('*'); - * // Set the span's font color. + * + * // Set the second span's font color. * s2.style('color', 'deeppink'); + * * // Create a third span element. * let s3 = createSpan('js'); * - * // Add all the spans to the - * // container div. + * // Add all the spans to the container div. * s1.parent(div); * s2.parent(div); * s3.parent(div); @@ -75138,10 +82927,13 @@ * @param {String} src relative path or URL for the image. * @param {String} alt alternate text for the image. * @return {p5.Element} new p5.Element object. + * * @example *
* * function setup() { + * createCanvas(100, 100); + * * background(200); * * let img = createImg( @@ -75206,10 +82998,13 @@ * @param {String} [target] target where the new link should open, * either `'_blank'`, `'_self'`, `'_parent'`, or `'_top'`. * @return {p5.Element} new p5.Element object. + * * @example *
* * function setup() { + * createCanvas(100, 100); + * * background(200); * * // Create an anchor element that links to p5js.org. @@ -75226,7 +83021,7 @@ * function setup() { * background(200); * - * // Create an anchor element that links to p5js.org. + * // Create an anchor tag that links to p5js.org. * // Open the link in a new tab. * let a = createA('http://p5js.org/', 'p5*js', '_blank'); * a.position(25, 35); @@ -75246,8 +83041,9 @@ }; /** INPUT **/ /** - * Creates a slider `<input></input>` element. Range sliders are - * useful for quickly selecting numbers from a given range. + * Creates a slider `<input></input>` element. + * + * Range sliders are useful for quickly selecting numbers from a given range. * * The first two parameters, `min` and `max`, are numbers that set the * slider's minimum and maximum. @@ -75265,12 +83061,15 @@ * @param {Number} [value] default value of the slider. * @param {Number} [step] size for each step in the slider's range. * @return {p5.Element} new p5.Element object. + * * @example *
* * let slider; * * function setup() { + * createCanvas(100, 100); + * * // Create a slider and place it at the top of the canvas. * slider = createSlider(0, 255); * slider.position(10, 10); @@ -75292,6 +83091,8 @@ * let slider; * * function setup() { + * createCanvas(100, 100); + * * // Create a slider and place it at the top of the canvas. * // Set its default value to 0. * slider = createSlider(0, 255, 0); @@ -75314,6 +83115,8 @@ * let slider; * * function setup() { + * createCanvas(100, 100); + * * // Create a slider and place it at the top of the canvas. * // Set its default value to 0. * // Set its step size to 50. @@ -75337,6 +83140,8 @@ * let slider; * * function setup() { + * createCanvas(100, 100); + * * // Create a slider and place it at the top of the canvas. * // Set its default value to 0. * // Set its step size to 0 so that it moves smoothly. @@ -75384,24 +83189,30 @@ * @param {String} label label displayed on the button. * @param {String} [value] value of the button. * @return {p5.Element} new p5.Element object. + * * @example *
* * function setup() { + * createCanvas(100, 100); + * * background(200); * * // Create a button and place it beneath the canvas. * let button = createButton('click me'); * button.position(0, 100); * - * // Use the button to change the background color. - * button.mousePressed(() => { - * let g = random(255); - * background(g); - * }); + * // Call repaint() when the button is pressed. + * button.mousePressed(repaint); * * describe('A gray square with a button that says "click me" beneath it. The square changes color when the button is clicked.'); * } + * + * // Change the background color. + * function repaint() { + * let g = random(255); + * background(g); + * } * *
* @@ -75410,17 +83221,17 @@ * let button; * * function setup() { + * createCanvas(100, 100); + * + * background(200); + * * // Create a button and set its value to 0. * // Place the button beneath the canvas. * button = createButton('click me', 'red'); * button.position(0, 100); * - * // Change the button's value when the mouse - * // is pressed. - * button.mousePressed(() => { - * let c = random(['red', 'green', 'blue', 'yellow']); - * button.value(c); - * }); + * // Call randomColor() when the button is pressed. + * button.mousePressed(randomColor); * * describe('A red square with a button that says "click me" beneath it. The square changes color when the button is clicked.'); * } @@ -75430,6 +83241,12 @@ * let c = button.value(); * background(c); * } + * + * // Set the button's value to a random color. + * function randomColor() { + * let c = random(['red', 'green', 'blue', 'yellow']); + * button.value(c); + * } *
*
*/ @@ -75441,10 +83258,11 @@ return addElement(elt, this); }; /** - * Creates a checkbox `<input></input>` element. Checkboxes extend - * the p5.Element class with a `checked()` method. - * Calling `myBox.checked()` returns `true` if it the box is checked and - * `false` otherwise. + * Creates a checkbox `<input></input>` element. + * + * Checkboxes extend the p5.Element class with a + * `checked()` method. Calling `myBox.checked()` returns `true` if it the box + * is checked and `false` if not. * * The first parameter, `label`, is optional. It's a string that sets the label * to display next to the checkbox. @@ -75456,12 +83274,15 @@ * @param {String} [label] label displayed after the checkbox. * @param {boolean} [value] value of the checkbox. Checked is `true` and unchecked is `false`. * @return {p5.Element} new p5.Element object. + * * @example *
* * let checkbox; * * function setup() { + * createCanvas(100, 100); + * * // Create a checkbox and place it beneath the canvas. * checkbox = createCheckbox(); * checkbox.position(0, 100); @@ -75485,6 +83306,8 @@ * let checkbox; * * function setup() { + * createCanvas(100, 100); + * * // Create a checkbox and place it beneath the canvas. * // Label the checkbox "white". * checkbox = createCheckbox(' white'); @@ -75509,6 +83332,8 @@ * let checkbox; * * function setup() { + * createCanvas(100, 100); + * * // Create a checkbox and place it beneath the canvas. * // Label the checkbox "white" and set its value to true. * checkbox = createCheckbox(' white', true); @@ -75599,12 +83424,15 @@ * @method createSelect * @param {boolean} [multiple] support multiple selections. * @return {p5.Element} new p5.Element object. + * * @example *
* * let mySelect; * * function setup() { + * createCanvas(100, 100); + * * // Create a dropdown and place it beneath the canvas. * mySelect = createSelect(); * mySelect.position(0, 100); @@ -75634,6 +83462,8 @@ * let mySelect; * * function setup() { + * createCanvas(100, 100); + * * // Create a dropdown and place it beneath the canvas. * mySelect = createSelect(); * mySelect.position(0, 100); @@ -75666,6 +83496,8 @@ * let mySelect; * * function setup() { + * createCanvas(100, 100); + * * // Create a dropdown and place it beneath the canvas. * mySelect = createSelect(); * mySelect.position(0, 100); @@ -75697,6 +83529,8 @@ * let mySelect; * * function setup() { + * createCanvas(100, 100); + * * // Create a dropdown and allow multiple selections. * // Place it beneath the canvas. * mySelect = createSelect(true); @@ -75716,11 +83550,17 @@ * * // Use the selected value(s) to draw circles. * let colors = mySelect.selected(); - * colors.forEach((c, index) => { - * let x = 10 + index * 20; + * for (let i = 0; i < colors.length; i += 1) { + * // Calculate the x-coordinate. + * let x = 10 + i * 20; + * + * // Access the color. + * let c = colors[i]; + * + * // Draw the circle. * fill(c); * circle(x, 50, 20); - * }); + * } * } * *
@@ -75879,12 +83719,15 @@ * @param {Object} [containerElement] container HTML Element, either a `<div></div>` * or `<span></span>`. * @return {p5.Element} new p5.Element object. + * * @example *
* * let myRadio; * * function setup() { + * createCanvas(100, 100); + * * // Create a radio button element and place it * // in the top-left corner. * myRadio = createRadio(); @@ -75915,6 +83758,8 @@ * let myRadio; * * function setup() { + * createCanvas(100, 100); + * * // Create a radio button element and place it * // in the top-left corner. * myRadio = createRadio(); @@ -75947,6 +83792,8 @@ * let myRadio; * * function setup() { + * createCanvas(100, 100); + * * // Create a radio button element and place it * // in the top-left corner. * myRadio = createRadio(); @@ -75965,10 +83812,8 @@ * let btn = createButton('disable'); * btn.position(0, 100); * - * // Use the button to disable the radio button. - * btn.mousePressed(() => { - * myRadio.disable(true); - * }); + * // Call disableRadio() when btn is pressed. + * btn.mousePressed(disableRadio); * * describe('A yellow square with three options listed, "red", "yellow", and "blue". The square changes color when the user selects a new option. A "disable" button beneath the canvas disables the color options when pressed.'); * } @@ -75978,6 +83823,11 @@ * let c = myRadio.value(); * background(c); * } + * + * // Disable myRadio. + * function disableRadio() { + * myRadio.disable(true); + * } * *
*/ @@ -76255,16 +84105,19 @@ * - `myPicker.value()` returns the current color as a hex string in the format `'#rrggbb'`. * - `myPicker.color()` returns the current color as a p5.Color object. * - * * @method createColorPicker * @param {String|p5.Color} [value] default color as a CSS color string. * @return {p5.Element} new p5.Element object. + * * @example *
* * let myPicker; * * function setup() { + * createCanvas(100, 100); + * + * // Create a color picker and set its position. * myPicker = createColorPicker('deeppink'); * myPicker.position(0, 100); * @@ -76284,6 +84137,9 @@ * let myPicker; * * function setup() { + * createCanvas(100, 100); + * + * // Create a color picker and set its position. * myPicker = createColorPicker('deeppink'); * myPicker.position(0, 100); * @@ -76352,8 +84208,9 @@ return self; }; /** - * Creates a text `<input></input>` element. Call `myInput.size()` - * to set the length of the text box. + * Creates a text `<input></input>` element. + * + * Call `myInput.size()` to set the length of the text box. * * The first parameter, `value`, is optional. It's a string that sets the * input's default value. The input is blank by default. @@ -76367,12 +84224,15 @@ * @param {String} [value] default value of the input box. Defaults to an empty string `''`. * @param {String} [type] type of input. Defaults to `'text'`. * @return {p5.Element} new p5.Element object. + * * @example *
* * let myInput; * * function setup() { + * createCanvas(100, 100); + * * // Create an input element and place it * // beneath the canvas. * myInput = createInput(); @@ -76396,6 +84256,8 @@ * let myInput; * * function setup() { + * createCanvas(100, 100); + * * // Create an input element and place it * // beneath the canvas. Set its default * // text to "hello!". @@ -76431,7 +84293,9 @@ }; /** * Creates an `<input></input>` element of type `'file'`. - * This allows users to select local files for use in a sketch. + * + * `createFileInput()` allows users to select local files for use in a sketch. + * It returns a p5.File object. * * The first parameter, `callback`, is a function that's called when the file * loads. The callback function should have one parameter, `file`, that's a @@ -76444,7 +84308,8 @@ * @method createFileInput * @param {Function} callback function to call once the file loads. * @param {Boolean} [multiple] allow multiple files to be selected. - * @return {p5.Element} new p5.Element object. + * @return {p5.File} new p5.File object. + * * @example *
* @@ -76454,6 +84319,8 @@ * let img; * * function setup() { + * createCanvas(100, 100); + * * // Create a file input and place it beneath * // the canvas. * input = createFileInput(handleImage); @@ -76503,10 +84370,13 @@ * // Draw the images if loaded. Each image * // is drawn 20 pixels lower than the * // previous image. - * images.forEach((img, index) => { - * let y = index * 20; - * image(img, 0, y, width, height); - * }); + * for (let i = 0; i < images.length; i += 1) { + * // Calculate the y-coordinate. + * let y = i * 20; + * + * // Draw the image. + * image(img, 0, y, 100, 100); + * } * * describe('A gray square with a file input beneath it. If the user selects multiple image files to load, they are displayed on the square.'); * } @@ -76622,10 +84492,11 @@ return mediaEl; } /** * Creates a `<video>` element for simple audio/video playback. - * Returns a new p5.MediaElement object. * - * Videos are shown by default. They can be hidden by calling `video.hide()` - * and drawn to the canvas using image(). + * `createVideo()` returns a new + * p5.MediaElement object. Videos are shown by + * default. They can be hidden by calling `video.hide()` and drawn to the + * canvas using image(). * * The first parameter, `src`, is the path the video. If a single string is * passed, as in `'assets/topsecret.mp4'`, a single video is loaded. An array @@ -76644,6 +84515,7 @@ * supporting different browsers. * @param {Function} [callback] function to call once the video is ready to play. * @return {p5.MediaElement} new p5.MediaElement object. + * * @example *
* @@ -76653,6 +84525,7 @@ * // Load a video and add it to the page. * // Note: this may not work in some browsers. * let video = createVideo('assets/small.mp4'); + * * // Show the default video controls. * video.showControls(); * @@ -76671,6 +84544,7 @@ * let video = createVideo( * ['assets/small.mp4', 'assets/small.ogv', 'assets/small.webm'] * ); + * * // Show the default video controls. * video.showControls(); * @@ -76693,6 +84567,7 @@ * ['assets/small.mp4', 'assets/small.ogv', 'assets/small.webm'], * muteVideo * ); + * * // Show the default video controls. * video.showControls(); * @@ -76714,7 +84589,9 @@ /** AUDIO STUFF **/ /** * Creates a hidden `<audio>` element for simple audio playback. - * Returns a new p5.MediaElement object. + * + * `createAudio()` returns a new + * p5.MediaElement object. * * The first parameter, `src`, is the path the video. If a single string is * passed, as in `'assets/video.mp4'`, a single video is loaded. An array @@ -76733,6 +84610,7 @@ * for supporting different browsers. * @param {Function} [callback] function to call once the audio is ready to play. * @return {p5.MediaElement} new p5.MediaElement object. + * * @example *
* @@ -76741,10 +84619,11 @@ * * // Load the audio. * let beat = createAudio('assets/beat.mp3'); + * * // Show the default audio controls. * beat.showControls(); * - * describe('An audio beat plays when the user double-clicks the square.'); + * describe('An audio beat plays when the user double-clicks the square.'); * } * *
@@ -76781,11 +84660,12 @@ }; } /** * Creates a `<video>` element that "captures" the audio/video stream from - * the webcam and microphone. Returns a new - * p5.Element object. + * the webcam and microphone. * - * Videos are shown by default. They can be hidden by calling `capture.hide()` - * and drawn to the canvas using image(). + * `createCapture()` returns a new + * p5.MediaElement object. Videos are shown by + * default. They can be hidden by calling `capture.hide()` and drawn to the + * canvas using image(). * * The first parameter, `type`, is optional. It sets the type of capture to * use. By default, `createCapture()` captures both audio and video. If `VIDEO` @@ -76796,7 +84676,11 @@ * W3C documentation for possible properties. Different browsers support different * properties. * - * The second parameter, `callback`, is optional. It's a function to call once + * The 'flipped' property is an optional property which can be set to `{flipped:true}` + * to mirror the video output.If it is true then it means that video will be mirrored + * or flipped and if nothing is mentioned then by default it will be `false`. + * + * The second parameter,`callback`, is optional. It's a function to call once * the capture is ready for use. The callback function should have one * parameter, `stream`, that's a * MediaStream object. @@ -76809,14 +84693,19 @@ * @param {String|Constant|Object} [type] type of capture, either AUDIO or VIDEO, * or a constraints object. Both video and audio * audio streams are captured by default. + * @param {Object} [flipped] flip the capturing video and mirror the output with `{flipped:true}`. By + * default it is false. * @param {Function} [callback] function to call once the stream * has loaded. - * @return {p5.Element} new p5.Element object. + * @return {p5.MediaElement} new p5.MediaElement object. + * * @example *
* * function setup() { * noCanvas(); + * + * // Create the video capture. * createCapture(VIDEO); * * describe('A video stream from the webcam.'); @@ -76829,6 +84718,8 @@ * let capture; * * function setup() { + * createCanvas(100, 100); + * * // Create the video capture and hide the element. * capture = createCapture(VIDEO); * capture.hide(); @@ -76839,11 +84730,28 @@ * function draw() { * // Draw the video capture within the canvas. * image(capture, 0, 0, width, width * capture.height / capture.width); + * * // Invert the colors in the stream. * filter(INVERT); * } * *
+ *
+ * + * let capture; + * + * function setup() { + * createCanvas(100, 100); + * + * // Create the video capture with mirrored output. + * capture = createCapture(VIDEO,{ flipped:true }); + * capture.size(100,100); + * + * describe('A video stream from the webcam with flipped or mirrored output.'); + * } + * + * + *
* *
* @@ -76876,7 +84784,7 @@ args[_key3] = arguments[_key3]; } _main.default._validateParameters('createCapture', args); - // return if getUserMedia is not supported by browser + // return if getUserMedia is not supported by the browser if (!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia)) { throw new DOMException('getUserMedia not supported in this browser'); } @@ -76884,17 +84792,28 @@ var useAudio = true; var constraints; var callback; + var flipped = false; for (var _i2 = 0, _args = args; _i2 < _args.length; _i2++) { var arg = _args[_i2]; if (arg === _main.default.prototype.VIDEO) useAudio = false; else if (arg === _main.default.prototype.AUDIO) useVideo = false; - else if (_typeof(arg) === 'object') constraints = arg; - else if (typeof arg === 'function') callback = arg; + else if (_typeof(arg) === 'object') { + if (arg.flipped !== undefined) { + flipped = arg.flipped; + delete arg.flipped; + } + constraints = Object.assign({ + }, constraints, arg); + } else if (typeof arg === 'function') { + callback = arg; + } } - if (!constraints) constraints = { + var videoConstraints = { video: useVideo, audio: useAudio }; + constraints = Object.assign({ + }, videoConstraints, constraints); var domElement = document.createElement('video'); // required to work in iOS 11 & up: domElement.setAttribute('playsinline', ''); @@ -76908,7 +84827,11 @@ } catch (err) { domElement.src = stream; } - }, console.log); + }).catch(function (e) { + if (e.name === 'NotFoundError') _main.default._friendlyError('No webcam found on this device', 'createCapture'); + if (e.name === 'NotAllowedError') _main.default._friendlyError('Access to the camera was denied', 'createCapture'); + console.error(e); + }); var videoEl = addElement(domElement, this, true); videoEl.loadedmetadata = false; // set width and height onload metadata @@ -76917,6 +84840,9 @@ if (domElement.width) { videoEl.width = domElement.width; videoEl.height = domElement.height; + if (flipped) { + videoEl.elt.style.transform = 'scaleX(-1)'; + } } else { videoEl.width = videoEl.elt.width = domElement.videoWidth; videoEl.height = videoEl.elt.height = domElement.videoHeight; @@ -76924,6 +84850,7 @@ videoEl.loadedmetadata = true; if (callback) callback(domElement.srcObject); }); + videoEl.flipped = flipped; return videoEl; }; /** @@ -76939,10 +84866,13 @@ * @param {String} tag tag for the new element. * @param {String} [content] HTML content to insert into the element. * @return {p5.Element} new p5.Element object. + * * @example *
* * function setup() { + * createCanvas(100, 100); + * * background(200); * * // Create an h5 element with nothing in it. @@ -76956,11 +84886,13 @@ *
* * function setup() { + * createCanvas(100, 100); + * * background(200); * - * // Create an h5 element with the content - * // "p5*js". + * // Create an h5 element with the content "p5*js". * let h5 = createElement('h5', 'p5*js'); + * * // Set the element's style and position. * h5.style('color', 'deeppink'); * h5.position(30, 15); @@ -76983,17 +84915,31 @@ // ============================================================================= /** * - * Adds specified class to the element. + * Adds a class to the element. * * @for p5.Element * @method addClass - * @param {String} class name of class to add + * @param {String} class name of class to add. * @chainable + * * @example - *
- * let div = createDiv('div'); - * div.addClass('myClass'); - *
+ *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a div element. + * let div = createDiv('div'); + * + * // Add a class to the div. + * div.addClass('myClass'); + * + * describe('A gray square.'); + * } + * + *
*/ _main.default.Element.prototype.addClass = function (c) { if (this.elt.className) { @@ -77006,14 +84952,15 @@ return this; }; /** - * - * Removes specified class from the element. + * Removes a class from the element. * * @method removeClass - * @param {String} class name of class to remove + * @param {String} class name of class to remove. * @chainable + * * @example - *
+ *
+ * * // In this example, a class is set when the div is created * // and removed when mouse is pressed. This could link up * // with a CSS style rule to toggle style properties. @@ -77021,14 +84968,25 @@ * let div; * * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a div element. * div = createDiv('div'); + * + * // Add a class to the div. * div.addClass('myClass'); + * + * describe('A gray square.'); * } * + * // Remove 'myClass' from the div when the user presses the mouse. * function mousePressed() { * div.removeClass('myClass'); * } - *
+ *
+ *
*/ _main.default.Element.prototype.removeClass = function (c) { // Note: Removing a class that does not exist does NOT throw an error in classList.remove method @@ -77036,21 +84994,32 @@ return this; }; /** - * - * Checks if specified class is already applied to element. + * Checks if a class is already applied to element. * * @method hasClass - * @returns {boolean} a boolean value if element has specified class - * @param c {String} class name of class to check + * @returns {boolean} a boolean value if element has specified class. + * @param c {String} name of class to check. + * * @example - *
+ *
+ * * let div; * * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a div element. * div = createDiv('div'); + * + * // Add the class 'show' to the div. * div.addClass('show'); + * + * describe('A gray square.'); * } * + * // Toggle the class 'show' when the mouse is pressed. * function mousePressed() { * if (div.hasClass('show')) { * div.addClass('show'); @@ -77058,31 +85027,44 @@ * div.removeClass('show'); * } * } - *
+ *
+ *
*/ _main.default.Element.prototype.hasClass = function (c) { return this.elt.classList.contains(c); }; /** - * - * Toggles element class. + * Toggles whether a class is applied to the element. * * @method toggleClass - * @param c {String} class name to toggle + * @param c {String} class name to toggle. * @chainable + * * @example - *
+ *
+ * * let div; * * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a div element. * div = createDiv('div'); + * + * // Add the 'show' class to the div. * div.addClass('show'); + * + * describe('A gray square.'); * } * + * // Toggle the 'show' class when the mouse is pressed. * function mousePressed() { * div.toggleClass('show'); * } - *
+ *
+ *
*/ _main.default.Element.prototype.toggleClass = function (c) { // classList also has a toggle() method, but we cannot use that yet as support is unclear. @@ -77096,32 +85078,84 @@ return this; }; /** + * Attaches the element as a child of another element. * - * Attaches the element as a child to the parent specified. - * Accepts either a string ID, DOM node, or p5.Element. - * If no argument is specified, an array of children DOM nodes is returned. + * `myElement.child()` accepts either a string ID, DOM node, or + * p5.Element. For example, + * `myElement.child(otherElement)`. If no argument is provided, an array of + * children DOM nodes is returned. * * @method child - * @returns {Node[]} an array of child nodes + * @returns {Node[]} an array of child nodes. + * * @example - *
- * let div0 = createDiv('this is the parent'); - * let div1 = createDiv('this is the child'); - * div0.child(div1); // use p5.Element - *
- *
- * let div0 = createDiv('this is the parent'); - * let div1 = createDiv('this is the child'); - * div1.id('apples'); - * div0.child('apples'); // use id - *
- *
- * // this example assumes there is a div already on the page - * // with id "myChildDiv" - * let div0 = createDiv('this is the parent'); - * let elt = document.getElementById('myChildDiv'); - * div0.child(elt); // use element from page - *
+ *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create the div elements. + * let div0 = createDiv('Parent'); + * let div1 = createDiv('Child'); + * + * // Make div1 the child of div0 + * // using the p5.Element. + * div0.child(div1); + * + * describe('A gray square with the words "Parent" and "Child" written beneath it.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create the div elements. + * let div0 = createDiv('Parent'); + * let div1 = createDiv('Child'); + * + * // Give div1 an ID. + * div1.id('apples'); + * + * // Make div1 the child of div0 + * // using its ID. + * div0.child('apples'); + * + * describe('A gray square with the words "Parent" and "Child" written beneath it.'); + * } + * + *
+ * + *
+ * + * // This example assumes there is a div already on the page + * // with id "myChildDiv". + * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create the div elements. + * let div0 = createDiv('Parent'); + * + * // Select the child element by its ID. + * let elt = document.getElementById('myChildDiv'); + * + * // Make div1 the child of div0 + * // using its HTMLElement object. + * div0.child(elt); + * + * describe('A gray square with the words "Parent" and "Child" written beneath it.'); + * } + * + *
*/ /** * @method child @@ -77147,23 +85181,38 @@ return this; }; /** - * Centers a p5.Element either vertically, horizontally, - * or both, relative to its parent or according to - * the body if the p5.Element has no parent. If no argument is passed - * the p5.Element is aligned both vertically and horizontally. + * Centers the element either vertically, horizontally, or both. + * + * `center()` will center the element relative to its parent or according to + * the page's body if the element has no parent. + * + * If no argument is passed, as in `myElement.center()` the element is aligned + * both vertically and horizontally. * * @method center - * @param {String} [align] passing 'vertical', 'horizontal' aligns element accordingly + * @param {String} [align] passing 'vertical', 'horizontal' aligns element accordingly * @chainable * * @example - *
+ *
+ * * function setup() { - * let div = createDiv('').size(10, 10); + * createCanvas(100, 100); + * + * background(200); + * + * // Create the div element and style it. + * let div = createDiv(''); + * div.size(10, 10); * div.style('background-color', 'orange'); + * + * // Center the div relative to the page's body. * div.center(); + * + * describe('A gray square and an orange rectangle. The rectangle is at the center of the page.'); * } - *
+ *
+ *
*/ _main.default.Element.prototype.center = function (align) { var style = this.elt.style.display; @@ -77192,25 +85241,73 @@ return this; }; /** + * Sets the inner HTML of the element, replacing any existing HTML. + * + * The second parameter, `append`, is optional. If `true` is passed, as in + * `myElement.html('hi', true)`, the HTML is appended instead of replacing + * existing HTML. * - * If an argument is given, sets the inner HTML of the element, - * replacing any existing HTML. If true is included as a second - * argument, HTML is appended instead of replacing existing HTML. - * If no arguments are given, returns - * the inner HTML of the element. + * If no arguments are passed, as in `myElement.html()`, the element's inner + * HTML is returned. * * @for p5.Element * @method html * @returns {String} the inner HTML of the element + * * @example - *
- * let div = createDiv('').size(100, 100); - * div.html('hi'); - *
- *
- * let div = createDiv('Hello ').size(100, 100); - * div.html('World', true); - *
+ *
+ * + * function setup() { + * createCanvas(100, 100); + * + * // Create the div element and set its size. + * let div = createDiv(''); + * div.size(100, 100); + * + * // Set the inner HTML to "hi". + * div.html('hi'); + * + * describe('A gray square with the word "hi" written beneath it.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create the div element and set its size. + * let div = createDiv('Hello '); + * div.size(100, 100); + * + * // Append "World" to the div's HTML. + * div.html('World', true); + * + * describe('A gray square with the text "Hello World" written beneath it.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create the div element. + * let div = createDiv('Hello'); + * + * // Prints "Hello" to the console. + * print(div.html()); + * + * describe('A gray square with the word "Hello!" written beneath it.'); + * } + * + *
*/ /** * @method html @@ -77230,42 +85327,60 @@ } }; /** + * Sets the element's position. * - * Sets the position of the element. If no position type argument is given, the - * position will be relative to (0, 0) of the window. - * Essentially, this sets position:absolute and left and top - * properties of style. If an optional third argument specifying position type is given, - * the x and y-coordinates will be interpreted based on the positioning scheme. - * If no arguments given, the function returns the x and y position of the element. + * `positionType` is a string that can be either `'static'`, `'fixed'`, + * `'relative'`, `'sticky'`, `'initial'`, or `'inherit'`. * - * found documentation on how to be more specific with object type - * https://stackoverflow.com/questions/14714314/how-do-i-comment-object-literals-in-yuidoc + * If no arguments passed, as in `myElement.position()`, the method returns + * the element's position in an object, as in `{ x: 0, y: 0 }`. * * @method position - * @returns {Object} object of form { x: 0, y: 0 } containing the position of the element in an object + * @returns {Object} object of form `{ x: 0, y: 0 }` containing the element's position. + * * @example - *
+ *
+ * * function setup() { * let cnv = createCanvas(100, 100); - * // positions canvas 50px to the right and 100px - * // below upper left corner of the window + * + * background(200); + * + * // Positions the canvas 50px to the right and 100px + * // below the top-left corner of the window. * cnv.position(50, 100); + * + * describe('A gray square that is 50 pixels to the right and 100 pixels down from the top-left corner of the web page.'); * } - *
- *
+ * + *
+ * + *
+ * * function setup() { * let cnv = createCanvas(100, 100); - * // positions canvas at upper left corner of the window - * // with a 'fixed' position type + * + * background(200); + * + * // Positions the canvas at the top-left corner + * // of the window with a 'fixed' position type. * cnv.position(0, 0, 'fixed'); + * + * describe('A gray square in the top-left corner of the web page.'); * } - *
+ *
+ *
*/ /** * @method position - * @param {Number} [x] x-position relative to upper left of window (optional) - * @param {Number} [y] y-position relative to upper left of window (optional) + * @param {Number} [x] x-position relative to top-left of window (optional) + * @param {Number} [y] y-position relative to top-left of window (optional) * @param {String} [positionType] it can be static, fixed, relative, sticky, initial or inherit (optional) * @chainable */ @@ -77333,15 +85448,15 @@ return this; }; /** - * Applies a style to an element by adding a + * Applies a style to the element by adding a * CSS declaration. * * The first parameter, `property`, is a string. If the name of a style * property is passed, as in `myElement.style('color')`, the method returns * the current value as a string or `null` if it hasn't been set. If a * `property:style` string is passed, as in - * `myElement.style('color:deeppink')`, the method sets `property` to - * `value`. + * `myElement.style('color:deeppink')`, the method sets the style `property` + * to `value`. * * The second parameter, `value`, is optional. It sets the property's value. * `value` can be a string, as in @@ -77352,14 +85467,16 @@ * @method style * @param {String} property style property to set. * @returns {String} value of the property. + * * @example *
* * function setup() { + * createCanvas(100, 100); + * * background(200); * - * // Create a paragraph element and - * // set its font color to "deeppink". + * // Create a paragraph element and set its font color to "deeppink". * let p = createP('p5*js'); * p.position(25, 20); * p.style('color', 'deeppink'); @@ -77372,14 +85489,14 @@ *
* * function setup() { + * createCanvas(100, 100); + * * background(200); * * // Create a p5.Color object. * let c = color('deeppink'); * - * // Create a paragraph element and - * // set its font color using a - * // p5.Color object. + * // Create a paragraph element and set its font color using a p5.Color object. * let p = createP('p5*js'); * p.position(25, 20); * p.style('color', c); @@ -77392,10 +85509,11 @@ *
* * function setup() { + * createCanvas(100, 100); + * * background(200); * - * // Create a paragraph element and - * // set its font color to "deeppink" + * // Create a paragraph element and set its font color to "deeppink" * // using property:value syntax. * let p = createP('p5*js'); * p.position(25, 20); @@ -77409,20 +85527,19 @@ *
* * function setup() { + * createCanvas(100, 100); + * * background(200); * - * // Create an empty paragraph element - * // and set its font color to "deeppink". + * // Create an empty paragraph element and set its font color to "deeppink". * let p = createP(); * p.position(5, 5); * p.style('color', 'deeppink'); * - * // Get the element's color as an - * // RGB color string. + * // Get the element's color as an RGB color string. * let c = p.style('color'); * - * // Set the element's inner HTML - * // using the RGB color string. + * // Set the element's inner HTML using the RGB color string. * p.html(c); * * describe('The text "rgb(255, 20, 147)" written in pink on a gray background.'); @@ -77473,11 +85590,12 @@ /** * Adds an * attribute - * to the element. This method is useful for advanced tasks. + * to the element. * - * Most commonly-used attributes, such as `id`, can be set with their - * dedicated methods. For example, `nextButton.id('next')` sets an element's - * `id` attribute. + * This method is useful for advanced tasks. Most commonly-used attributes, + * such as `id`, can be set with their dedicated methods. For example, + * `nextButton.id('next')` sets an element's `id` attribute. Calling + * `nextButton.attribute('id', 'next')` has the same effect. * * The first parameter, `attr`, is the attribute's name as a string. Calling * `myElement.attribute('align')` returns the attribute's current value as a @@ -77495,32 +85613,26 @@ *
* * function setup() { - * // Create a container div and - * // place it at the top-left - * // corner. + * createCanvas(100, 100); + * + * // Create a container div element and place it at the top-left corner. * let container = createDiv(); * container.position(0, 0); * - * // Create a paragraph element - * // and place it within the container. - * // Set its horizontal alignment to - * // "left". + * // Create a paragraph element and place it within the container. + * // Set its horizontal alignment to "left". * let p1 = createP('hi'); * p1.parent(container); * p1.attribute('align', 'left'); * - * // Create a paragraph element - * // and place it within the container. - * // Set its horizontal alignment to - * // "center". + * // Create a paragraph element and place it within the container. + * // Set its horizontal alignment to "center". * let p2 = createP('hi'); * p2.parent(container); * p2.attribute('align', 'center'); * - * // Create a paragraph element - * // and place it within the container. - * // Set its horizontal alignment to - * // "right". + * // Create a paragraph element and place it within the container. + * // Set its horizontal alignment to "right". * let p3 = createP('hi'); * p3.parent(container); * p3.attribute('align', 'right'); @@ -77571,10 +85683,11 @@ * let p; * * function setup() { + * createCanvas(100, 100); + * * background(200); * - * // Create a paragraph element and place it - * // in the center of the canvas. + * // Create a paragraph element and place it in the center of the canvas. * // Set its "align" attribute to "center". * p = createP('hi'); * p.position(0, 20); @@ -77583,6 +85696,7 @@ * describe('The text "hi" written in black at the center of a gray square. The text moves to the left edge when double-clicked.'); * } * + * // Remove the 'align' attribute when the user double-clicks the paragraph. * function doubleClicked() { * p.removeAttribute('align'); * } @@ -77608,17 +85722,19 @@ * * @method value * @return {String|Number} value of the element. + * * @example *
* - * let inp; + * let input; * * function setup() { - * // Create a text input and place it - * // beneath the canvas. Set its default - * // value to "hello". - * inp = createInput('hello'); - * inp.position(0, 100); + * createCanvas(100, 100); + * + * // Create a text input and place it beneath the canvas. + * // Set its default value to "hello". + * input = createInput('hello'); + * input.position(0, 100); * * describe('The text from an input box is displayed on a gray square.'); * } @@ -77627,7 +85743,7 @@ * background(200); * * // Use the input's value to display a message. - * let msg = inp.value(); + * let msg = input.value(); * text(msg, 0, 55); * } * @@ -77635,14 +85751,15 @@ * *
* - * let inp; + * let input; * * function setup() { - * // Create a text input and place it - * // beneath the canvas. Set its default - * // value to "hello". - * inp = createInput('hello'); - * inp.position(0, 100); + * createCanvas(100, 100); + * + * // Create a text input and place it beneath the canvas. + * // Set its default value to "hello". + * input = createInput('hello'); + * input.position(0, 100); * * describe('The text from an input box is displayed on a gray square. The text resets to "hello" when the user double-clicks the square.'); * } @@ -77651,13 +85768,13 @@ * background(200); * * // Use the input's value to display a message. - * let msg = inp.value(); + * let msg = input.value(); * text(msg, 0, 55); * } * * // Reset the input's value. * function doubleClicked() { - * inp.value('hello'); + * input.value('hello'); * } * *
@@ -77682,12 +85799,15 @@ * * @method show * @chainable + * * @example *
* * let p; * * function setup() { + * createCanvas(100, 100); + * * background(200); * * // Create a paragraph element and hide it. @@ -77698,7 +85818,7 @@ * describe('A gray square. The text "p5*js" appears when the user double-clicks the square.'); * } * - * // Show the paragraph when double-clicked. + * // Show the paragraph when the user double-clicks. * function doubleClicked() { * p.show(); * } @@ -77714,10 +85834,13 @@ * * @method hide * @chainable + * * @example * let p; * * function setup() { + * createCanvas(100, 100); + * * background(200); * * // Create a paragraph element. @@ -77727,7 +85850,7 @@ * describe('The text "p5*js" at the center of a gray square. The text disappears when the user double-clicks the square.'); * } * - * // Hide the paragraph when double-clicked. + * // Hide the paragraph when the user double-clicks. * function doubleClicked() { * p.hide(); * } @@ -77764,20 +85887,21 @@ * * @method size * @return {Object} width and height of the element in an object. + * * @example *
* * function setup() { + * createCanvas(100, 100); + * * background(200); * - * // Create a pink div element and place it at - * // the top-left corner. + * // Create a pink div element and place it at the top-left corner. * let div = createDiv(); * div.position(10, 10); * div.style('background-color', 'deeppink'); * - * // Set the div's width to 80 pixels and - * // height to 20 pixels. + * // Set the div's width to 80 pixels and height to 20 pixels. * div.size(80, 20); * * describe('A gray square with a pink rectangle near its top.'); @@ -77788,21 +85912,22 @@ *
* * function setup() { + * createCanvas(100, 100); + * * background(200); * - * // Create a pink div element and place it at - * // the top-left corner. + * // Create a pink div element and place it at the top-left corner. * let div = createDiv(); * div.position(10, 10); * div.style('background-color', 'deeppink'); * - * // Set the div's width to 80 pixels and - * // height to 40 pixels. + * // Set the div's width to 80 pixels and height to 40 pixels. * div.size(80, 40); * * // Get the div's size as an object. * let s = div.size(); - * // Write the div's dimensions. + * + * // Display the div's dimensions. * div.html(`${s.width} x ${s.height}`); * * describe('A gray square with a pink rectangle near its top. The text "80 x 40" is written within the rectangle.'); @@ -77812,12 +85937,17 @@ * *
* + * let img1; + * let img2; + * * function setup() { + * createCanvas(100, 100); + * * background(200); * * // Load an image of an astronaut on the moon * // and place it at the top-left of the canvas. - * let img1 = createImg( + * img1 = createImg( * 'assets/moonwalk.jpg', * 'An astronaut walking on the moon', * '' @@ -77827,24 +85957,27 @@ * // Load an image of an astronaut on the moon * // and place it at the top-left of the canvas. * // Resize the image once it's loaded. - * let img2 = createImg( + * img2 = createImg( * 'assets/moonwalk.jpg', * 'An astronaut walking on the moon', * '', - * () => { - * img2.size(50, AUTO); - * } + * resizeImage * ); * img2.position(0, 0); * * describe('A gray square two copies of a space image at the top-left. The copy in front is smaller.'); * } + * + * // Resize img2 and keep its aspect ratio. + * function resizeImage() { + * img2.size(50, AUTO); + * } * *
*/ /** * @method size - * @param {Number|Constant} w width of the element, either AUTO, or a number. + * @param {Number|Constant} [w] width of the element, either AUTO, or a number. * @param {Number|Constant} [h] height of the element, either AUTO, or a number. * @chainable */ @@ -77887,13 +86020,13 @@ this.elt.width = aW; this.elt.height = aH; } - this.width = this.elt.offsetWidth; - this.height = this.elt.offsetHeight; + this.width = aW; + this.height = aH; if (this._pInst && this._pInst._curElement) { // main canvas associated with p5 instance if (this._pInst._curElement.elt === this.elt) { - this._pInst._setProperty('width', this.elt.offsetWidth); - this._pInst._setProperty('height', this.elt.offsetHeight); + this._pInst._setProperty('width', aW); + this._pInst._setProperty('height', aH); } } } @@ -77905,12 +86038,15 @@ * callback functions. * * @method remove + * * @example *
* * let p; * * function setup() { + * createCanvas(100, 100); + * * background(200); * * // Create a paragraph element. @@ -77920,7 +86056,7 @@ * describe('The text "p5*js" written at the center of a gray square. '); * } * - * // Remove the paragraph when double-clicked. + * // Remove the paragraph when the user double-clicks. * function doubleClicked() { * p.remove(); * } @@ -77954,7 +86090,7 @@ } }; /** - * Sets a function to call when the user drops a file on the element. + * Calls a function when the user drops a file on the element. * * The first parameter, `callback`, is a function to call once the file loads. * The callback function should have one parameter, `file`, that's a @@ -77970,6 +86106,7 @@ * @param {Function} callback called when a file loads. Called once for each file dropped. * @param {Function} [fxn] called once when any files are dropped. * @chainable + * * @example *
* @@ -77982,25 +86119,26 @@ * * background(200); * - * // Call a function when a file - * // dropped on the canvas has - * // loaded. - * c.drop(file => { - * // Remove the current image, if any. - * if (img) { - * img.remove(); - * } + * // Call handleFile() when a file that's dropped on the canvas has loaded. + * c.drop(handleFile); * - * // Create an element with the - * // dropped file. - * img = createImg(file.data, ''); - * img.hide(); + * describe('A gray square. When the user drops an image on the square, it is displayed.'); + * } * - * // Draw the image. - * image(img, 0, 0, width, height); - * }); + * // Remove the existing image and display the new one. + * function handleFile(file) { + * // Remove the current image, if any. + * if (img) { + * img.remove(); + * } * - * describe('A gray square. When the user drops an image on the square, it is displayed.'); + * // Create an element with the + * // dropped file. + * img = createImg(file.data, ''); + * img.hide(); + * + * // Draw the image. + * image(img, 0, 0, width, height); * } * *
@@ -78017,22 +86155,21 @@ * * background(200); * - * // Call functions when the user - * // drops a file on the canvas + * // Call functions when the user drops a file on the canvas * // and when the file loads. * c.drop(handleFile, handleDrop); * * describe('A gray square. When the user drops an image on the square, it is displayed. The id attribute of canvas element is also displayed.'); * } * + * // Display the image when it loads. * function handleFile(file) { * // Remove the current image, if any. * if (img) { * img.remove(); * } * - * // Create an element with the - * // dropped file. + * // Create an img element with the dropped file. * img = createImg(file.data, ''); * img.hide(); * @@ -78040,23 +86177,21 @@ * image(img, 0, 0, width, height); * } * + * // Display the file's name when it loads. * function handleDrop(event) { * // Remove current paragraph, if any. * if (msg) { * msg.remove(); * } * - * // Use event to get the drop - * // target's id. + * // Use event to get the drop target's id. * let id = event.target.id; * - * // Write the canvas' id - * // beneath it. + * // Write the canvas' id beneath it. * msg = createP(id); * msg.position(0, 100); * - * // Set the font color - * // randomly for each drop. + * // Set the font color randomly for each drop. * let c = random(['red', 'green', 'blue']); * msg.style('color', c); * msg.style('font-size', '12px'); @@ -78118,50 +86253,72 @@ return this; }; /** - * Turns p5.Element into a draggable item. If an argument is given, it will drag that p5.Element instead, ie. drag a entire GUI panel (parent container) with the panel's title bar. + * Makes the element draggable. + * + * The parameter, `elmnt`, is optional. If another + * p5.Element object is passed, as in + * `myElement.draggable(otherElement)`, the other element will become draggable. * * @method draggable - * @param {p5.Element} [elmnt] pass another p5.Element + * @param {p5.Element} [elmnt] another p5.Element. * @chainable * * @example - *
+ *
+ * + * let stickyNote; + * let textInput; + * * function setup() { * createCanvas(100, 100); + * * background(200); * - * createDiv('Post-It') - * .position(5, 5) - * .size(75, 20) - * .style('font-size', '16px') - * .style('background', 'yellow') - * .style('color', '#000') - * .style('border', '1px solid #aaaa00') - * .style('padding', '5px') - * .draggable(); - * // .style('cursor', 'help') // override cursor + * // Create a div element and style it. + * stickyNote = createDiv('Note'); + * stickyNote.position(5, 5); + * stickyNote.size(80, 20); + * stickyNote.style('font-size', '16px'); + * stickyNote.style('font-family', 'Comic Sans MS'); + * stickyNote.style('background', 'orchid'); + * stickyNote.style('padding', '5px'); + * + * // Make the note draggable. + * stickyNote.draggable(); * - * let gui = createDiv('') - * .position(5, 40) - * .size(85, 50) - * .style('font-size', '16px') - * .style('background', 'yellow') - * .style('z-index', '100') - * .style('border', '1px solid #00aaaa'); + * // Create a panel div and style it. + * let panel = createDiv(''); + * panel.position(5, 40); + * panel.size(80, 50); + * panel.style('background', 'orchid'); + * panel.style('font-size', '16px'); + * panel.style('padding', '5px'); + * panel.style('text-align', 'center'); * - * createDiv('= PANEL =') - * .parent(gui) - * .style('background', 'cyan') - * .style('padding', '2px') - * .style('text-align', 'center') - * .draggable(gui); + * // Make the panel draggable. + * panel.draggable(); * - * createSlider(0, 100, random(100)) - * .style('cursor', 'pointer') - * .size(80, 5) - * .parent(gui); + * // Create a text input and style it. + * textInput = createInput('Note'); + * textInput.size(70); + * + * // Add the input to the panel. + * textInput.parent(panel); + * + * // Call handleInput() when text is input. + * textInput.input(handleInput); + * + * describe( + * 'A gray square with two purple rectangles that move when dragged. The top rectangle displays the text that is typed into the bottom rectangle.' + * ); * } - *
+ * + * // Update stickyNote's HTML when text is input. + * function handleInput() { + * stickyNote.html(textInput.value()); + * } + *
+ *
*/ _main.default.Element.prototype.draggable = function (elmMove) { var isTouch = ('ontouchstart' in window); @@ -78245,6 +86402,7 @@ * @constructor * @param {String} elt DOM node that is wrapped * @extends p5.Element + * * @example *
* @@ -78256,6 +86414,8 @@ * // Create a p5.MediaElement using createCapture(). * capture = createCapture(VIDEO); * capture.hide(); + * + * describe('A webcam feed with inverted colors.'); * } * * function draw() { @@ -78295,12 +86455,15 @@ * * @property src * @return {String} src + * * @example *
* * let beat; * * function setup() { + * createCanvas(100, 100); + * * // Create a p5.MediaElement using createAudio(). * beat = createAudio('assets/beat.mp3'); * @@ -78342,19 +86505,26 @@ }; return _this; } /** - * Play audio or video from a media element. + * Plays audio or video from a media element. * * @method play * @chainable + * * @example *
* * let beat; * * function setup() { + * createCanvas(100, 100); + * * background(200); * + * // Style the text. * textAlign(CENTER); + * textSize(16); + * + * // Display a message. * text('Click to play', 50, 50); * * // Create a p5.MediaElement using createAudio(). @@ -78363,8 +86533,7 @@ * describe('The text "Click to play" written in black on a gray background. A beat plays when the user clicks the square.'); * } * - * // Play the beat when the user - * // presses the mouse. + * // Play the beat when the user presses the mouse. * function mousePressed() { * beat.play(); * } @@ -78405,11 +86574,13 @@ } return this; } /** - * Stops a media element and sets its current time to zero. Calling - * `media.play()` will restart playing audio/video from the beginning. + * Stops a media element and sets its current time to 0. + * + * Calling `media.play()` will restart playing audio/video from the beginning. * * @method stop * @chainable + * * @example *
* @@ -78417,6 +86588,8 @@ * let isStopped = true; * * function setup() { + * createCanvas(100, 100); + * * // Create a p5.MediaElement using createAudio(). * beat = createAudio('assets/beat.mp3'); * @@ -78426,7 +86599,11 @@ * function draw() { * background(200); * + * // Style the text. * textAlign(CENTER); + * textSize(16); + * + * // Display different instructions based on playback. * if (isStopped === true) { * text('Click to start', 50, 50); * } else { @@ -78434,17 +86611,14 @@ * } * } * - * // Adjust playback when the user - * // presses the mouse. + * // Adjust playback when the user presses the mouse. * function mousePressed() { * if (isStopped === true) { - * // If the beat is stopped, - * // play it. + * // If the beat is stopped, play it. * beat.play(); * isStopped = false; * } else { - * // If the beat is playing, - * // stop it. + * // If the beat is playing, stop it. * beat.stop(); * isStopped = true; * } @@ -78461,11 +86635,13 @@ this.elt.currentTime = 0; return this; } /** - * Pauses a media element. Calling `media.play()` will resume playing - * audio/video from the moment it paused. + * Pauses a media element. + * + * Calling `media.play()` will resume playing audio/video from the moment it paused. * * @method pause * @chainable + * * @example *
* @@ -78473,6 +86649,8 @@ * let isPaused = true; * * function setup() { + * createCanvas(100, 100); + * * // Create a p5.MediaElement using createAudio(). * beat = createAudio('assets/beat.mp3'); * @@ -78482,9 +86660,11 @@ * function draw() { * background(200); * - * // Display different instructions - * // based on playback. + * // Style the text. * textAlign(CENTER); + * textSize(16); + * + * // Display different instructions based on playback. * if (isPaused === true) { * text('Click to play', 50, 50); * } else { @@ -78492,8 +86672,7 @@ * } * } * - * // Adjust playback when the user - * // presses the mouse. + * // Adjust playback when the user presses the mouse. * function mousePressed() { * if (isPaused === true) { * // If the beat is paused, @@ -78518,10 +86697,11 @@ this.elt.pause(); return this; } /** - * Play the audio/video repeatedly in a loop. + * Plays the audio/video repeatedly in a loop. * * @method loop * @chainable + * * @example *
* @@ -78529,6 +86709,8 @@ * let isLooping = false; * * function setup() { + * createCanvas(100, 100); + * * background(200); * * // Create a p5.MediaElement using createAudio(). @@ -78540,9 +86722,11 @@ * function draw() { * background(200); * - * // Display different instructions - * // based on playback. + * // Style the text. * textAlign(CENTER); + * textSize(16); + * + * // Display different instructions based on playback. * if (isLooping === true) { * text('Click to stop', 50, 50); * } else { @@ -78550,17 +86734,14 @@ * } * } * - * // Adjust playback when the user - * // presses the mouse. + * // Adjust playback when the user presses the mouse. * function mousePressed() { * if (isLooping === true) { - * // If the beat is looping, - * // stop it. + * // If the beat is looping, stop it. * beat.stop(); * isLooping = false; * } else { - * // If the beat is stopped, - * // loop it. + * // If the beat is stopped, loop it. * beat.loop(); * isLooping = true; * } @@ -78577,11 +86758,13 @@ this.play(); return this; } /** - * Stops the audio/video from playing in a loop. It will stop when it - * reaches the end. + * Stops the audio/video from playing in a loop. + * + * The media will stop when it finishes playing. * * @method noLoop * @chainable + * * @example *
* @@ -78589,6 +86772,8 @@ * let isPlaying = false; * * function setup() { + * createCanvas(100, 100); + * * background(200); * * // Create a p5.MediaElement using createAudio(). @@ -78600,9 +86785,11 @@ * function draw() { * background(200); * - * // Display different instructions - * // based on playback. + * // Style the text. * textAlign(CENTER); + * textSize(16); + * + * // Display different instructions based on playback. * if (isPlaying === true) { * text('Click to stop', 50, 50); * } else { @@ -78610,17 +86797,14 @@ * } * } * - * // Adjust playback when the user - * // presses the mouse. + * // Adjust playback when the user presses the mouse. * function mousePressed() { * if (isPlaying === true) { - * // If the beat is playing, - * // stop it. + * // If the beat is playing, stop it. * beat.stop(); * isPlaying = false; * } else { - * // If the beat is stopped, - * // play it. + * // If the beat is stopped, play it. * beat.play(); * isPlaying = true; * } @@ -78672,20 +86856,26 @@ * @method autoplay * @param {Boolean} [shouldAutoplay] whether the element should autoplay. * @chainable + * * @example *
* + * let video; + * * function setup() { * noCanvas(); * - * // Load a video and play it automatically. - * let video = createVideo('assets/fingers.mov', () => { - * video.autoplay(); - * video.size(100, 100); - * }); + * // Call handleVideo() once the video loads. + * video = createVideo('assets/fingers.mov', handleVideo); * * describe('A video of fingers walking on a treadmill.'); * } + * + * // Set the video's size and play it. + * function handleVideo() { + * video.size(100, 100); + * video.autoplay(); + * } * *
* @@ -78695,20 +86885,26 @@ * noCanvas(); * * // Load a video, but don't play it automatically. - * let video = createVideo('assets/fingers.mov', () => { - * video.autoplay(false); - * video.size(100, 100); - * }); + * let video = createVideo('assets/fingers.mov', handleVideo); * * // Play the video when the user clicks on it. - * video.mousePressed(() => { - * video.play(); - * }); + * video.mousePressed(handlePress); * * describe('An image of fingers on a treadmill. They start walking when the user double-clicks on them.'); * } *
*
+ * + * // Set the video's size and playback mode. + * function handleVideo() { + * video.size(100, 100); + * video.autoplay(false); + * } + * + * // Play the video. + * function handleClick() { + * video.play(); + * } */ }, @@ -78737,7 +86933,7 @@ } return this; } /** - * Manages the audio/video volume. + * Sets the audio/video volume. * * Calling `media.volume()` without an argument returns the current volume * as a number in the range 0 (off) to 1 (maximum). @@ -78755,8 +86951,11 @@ * let dragon; * * function setup() { + * createCanvas(100, 100); + * * // Create a p5.MediaElement using createAudio(). * dragon = createAudio('assets/lucky_dragons.mp3'); + * * // Show the default media controls. * dragon.showControls(); * @@ -78768,16 +86967,21 @@ * * // Produce a number between 0 and 1. * let n = 0.5 * sin(frameCount * 0.01) + 0.5; + * * // Use n to set the volume. * dragon.volume(n); * - * // Get the current volume - * // and display it. + * // Get the current volume and display it. * let v = dragon.volume(); - * // Round v to 1 decimal place - * // for display. + * + * // Round v to 1 decimal place for display. * v = round(v, 1); + * + * // Style the text. * textAlign(CENTER); + * textSize(16); + * + * // Display the volume. * text(`Volume: ${v}`, 50, 50); * } *
@@ -78799,14 +87003,15 @@ this.elt.volume = val; } } /** - * Manages the audio/video playback speed. Calling `media.speed()` returns - * the current speed as a number. + * Sets the audio/video playback speed. * * The parameter, `val`, is optional. It's a number that sets the playback * speed. 1 plays the media at normal speed, 0.5 plays it at half speed, 2 * plays it at double speed, and so on. -1 plays the media at normal speed * in reverse. * + * Calling `media.speed()` returns the current speed as a number. + * * Note: Not all browsers support backward playback. Even if they do, * playback might not be smooth. * @@ -78819,6 +87024,8 @@ * let dragon; * * function setup() { + * createCanvas(100, 100); + * * // Create a p5.MediaElement using createAudio(). * dragon = createAudio('assets/lucky_dragons.mp3'); * @@ -78833,16 +87040,21 @@ * * // Produce a number between 0 and 2. * let n = sin(frameCount * 0.01) + 1; + * * // Use n to set the playback speed. * dragon.speed(n); * - * // Get the current speed - * // and display it. + * // Get the current speed and display it. * let s = dragon.speed(); - * // Round s to 1 decimal place - * // for display. + * + * // Round s to 1 decimal place for display. * s = round(s, 1); + * + * // Style the text. * textAlign(CENTER); + * textSize(16); + * + * // Display the speed. * text(`Speed: ${s}`, 50, 50); * } * @@ -78867,13 +87079,16 @@ } } } /** - * Manages the media element's playback time. Calling `media.time()` - * returns the number of seconds the audio/video has played. Time resets to - * 0 when the looping media restarts. + * Sets the media element's playback time. * * The parameter, `time`, is optional. It's a number that specifies the * time, in seconds, to jump to when playback begins. * + * Calling `media.time()` without an argument returns the number of seconds + * the audio/video has played. + * + * Note: Time resets to 0 when looping media restarts. + * * @method time * @return {Number} current time (in seconds). * @@ -78883,8 +87098,11 @@ * let dragon; * * function setup() { + * createCanvas(100, 100); + * * // Create a p5.MediaElement using createAudio(). * dragon = createAudio('assets/lucky_dragons.mp3'); + * * // Show the default media controls. * dragon.showControls(); * @@ -78894,12 +87112,17 @@ * function draw() { * background(200); * - * // Display the current time. + * // Get the current playback time. * let s = dragon.time(); - * // Round s to 1 decimal place - * // for display. + * + * // Round s to 1 decimal place for display. * s = round(s, 1); + * + * // Style the text. * textAlign(CENTER); + * textSize(16); + * + * // Display the playback time. * text(`${s} seconds`, 50, 50); * } * @@ -78910,13 +87133,15 @@ * let dragon; * * function setup() { + * createCanvas(100, 100); + * * // Create a p5.MediaElement using createAudio(). * dragon = createAudio('assets/lucky_dragons.mp3'); + * * // Show the default media controls. * dragon.showControls(); * - * // Jump to 2 seconds - * // to start. + * // Jump to 2 seconds to start. * dragon.time(2); * * describe('The text "S seconds" on a gray square with media controls beneath it. The number "S" increases as the song plays.'); @@ -78925,12 +87150,17 @@ * function draw() { * background(200); * - * // Display the current time. + * // Get the current playback time. * let s = dragon.time(); - * // Round s to 1 decimal place - * // for display. + * + * // Round s to 1 decimal place for display. * s = round(s, 1); + * + * // Style the text. * textAlign(CENTER); + * textSize(16); + * + * // Display the playback time. * text(`${s} seconds`, 50, 50); * } * @@ -78964,10 +87194,13 @@ * let dragon; * * function setup() { + * createCanvas(100, 100); + * * background(200); * * // Create a p5.MediaElement using createAudio(). * dragon = createAudio('assets/lucky_dragons.mp3'); + * * // Show the default media controls. * dragon.showControls(); * @@ -78979,12 +87212,15 @@ * * // Calculate the time remaining. * let s = dragon.duration() - dragon.time(); - * // Round s to 1 decimal place - * // for display. + * + * // Round s to 1 decimal place for display. * s = round(s, 1); * - * // Display the time remaining. + * // Style the text. * textAlign(CENTER); + * textSize(16); + * + * // Display the time remaining. * text(`${s} seconds left`, 50, 50); * } * @@ -79018,7 +87254,15 @@ this.height = this.canvas.height; } this.drawingContext.clearRect(0, 0, this.canvas.width, this.canvas.height); + if (this.flipped === true) { + this.drawingContext.save(); + this.drawingContext.scale( - 1, 1); + this.drawingContext.translate( - this.canvas.width, 0); + } this.drawingContext.drawImage(this.elt, 0, 0, this.canvas.width, this.canvas.height); + if (this.flipped === true) { + this.drawingContext.restore(); + } this.setModified(true); this._frameOnCanvas = this._pInst.frameCount; } @@ -79129,16 +87373,18 @@ value: function setModified(value) { this._modified = value; } /** - * Calls a function when the audio/video reaches the end of its playback - * The function won't be called if the media is looping. + * Calls a function when the audio/video reaches the end of its playback. + * + * The element is passed as an argument to the callback function. * - * The `p5.MediaElement` is passed as an argument to the callback function. + * Note: The function won't be called if the media is looping. * * @method onended * @param {Function} callback function to call when playback ends. * The `p5.MediaElement` is passed as * the argument. * @chainable + * * @example *
* @@ -79147,15 +87393,13 @@ * let isDone = false; * * function setup() { + * createCanvas(100, 100); * * // Create a p5.MediaElement using createAudio(). * beat = createAudio('assets/beat.mp3'); * - * // Set isDone to false when - * // the beat finishes. - * beat.onended(() => { - * isDone = true; - * }); + * // Call handleEnd() when the beat finishes. + * beat.onended(handleEnd); * * describe('The text "Click to play" written in black on a gray square. A beat plays when the user clicks. The text "Done!" appears when the beat finishes playing.'); * } @@ -79163,9 +87407,11 @@ * function draw() { * background(200); * - * // Display different messages - * // based on playback. + * // Style the text. * textAlign(CENTER); + * textSize(16); + * + * // Display different messages based on playback. * if (isDone === true) { * text('Done!', 50, 50); * } else if (isPlaying === false) { @@ -79175,14 +87421,18 @@ * } * } * - * // Play the beat when the - * // user presses the mouse. + * // Play the beat when the user presses the mouse. * function mousePressed() { * if (isPlaying === false) { * isPlaying = true; * beat.play(); * } * } + * + * // Set isDone when playback ends. + * function handleEnd() { + * isDone = false; + * } * *
*/ @@ -79195,12 +87445,16 @@ return this; } /*** CONNECT TO WEB AUDIO API / p5.sound.js ***/ /** - * Send the audio output of this element to a specified audioNode or - * p5.sound object. If no element is provided, connects to p5's main - * output. That connection is established when this method is first called. - * All connections are removed by the .disconnect() method. + * Sends the element's audio to an output. + * + * The parameter, `audioNode`, can be an `AudioNode` or an object from the + * `p5.sound` library. + * + * If no element is provided, as in `myElement.connect()`, the element + * connects to the main output. All connections are removed by the + * `.disconnect()` method. * - * This method is meant to be used with the p5.sound.js addon library. + * Note: This method is meant to be used with the p5.sound.js addon library. * * @method connect * @param {AudioNode|Object} audioNode AudioNode from the Web Audio API, @@ -79243,9 +87497,10 @@ this.audioSourceNode.connect(mainOutput); } } /** - * Disconnect all Web Audio routing, including to main output. - * This is useful if you want to re-route the output through - * audio effects, for example. + * Disconnect all Web Audio routing, including to the main output. + * + * This is useful if you want to re-route the output through audio effects, + * for example. * * @method disconnect */ @@ -79263,21 +87518,30 @@ /** * Show the default * HTMLMediaElement - * controls. These vary between web browser. + * controls. + * + * Note: The controls vary between web browsers. * * @method showControls + * * @example *
* * function setup() { + * createCanvas(100, 100); + * * background('cornflowerblue'); * + * // Style the text. * textAlign(CENTER); * textSize(50); + * + * // Display a dragon. * text('🐉', 50, 50); * * // Create a p5.MediaElement using createAudio(). * let dragon = createAudio('assets/lucky_dragons.mp3'); + * * // Show the default media controls. * dragon.showControls(); * @@ -79300,6 +87564,7 @@ * controls. * * @method hideControls + * * @example *
* @@ -79307,8 +87572,11 @@ * let isHidden = false; * * function setup() { + * createCanvas(100, 100); + * * // Create a p5.MediaElement using createAudio(). * dragon = createAudio('assets/lucky_dragons.mp3'); + * * // Show the default media controls. * dragon.showControls(); * @@ -79318,9 +87586,10 @@ * function draw() { * background(200); * - * // Display a different message when - * // controls are hidden or shown. + * // Style the text. * textAlign(CENTER); + * + * // Display a different message when controls are hidden or shown. * if (isHidden === true) { * text('Double-click to show controls', 10, 20, 80, 80); * } else { @@ -79370,12 +87639,16 @@ * `callback`. * @return {Number} id ID of this cue, * useful for `media.removeCue(id)`. + * * @example *
* * function setup() { + * createCanvas(100, 100); + * * // Create a p5.MediaElement using createAudio(). * let beat = createAudio('assets/beat.mp3'); + * * // Play the beat in a loop. * beat.loop(); * @@ -79388,6 +87661,7 @@ * describe('A red square with a beat playing in the background. Its color changes every 2 seconds while the audio plays.'); * } * + * // Change the background color. * function changeBackground(c) { * background(c); * } @@ -79407,10 +87681,11 @@ } return id; } /** - * Remove a callback based on its ID. + * Removes a callback based on its ID. * * @method removeCue * @param {Number} id ID of the cue, created by `media.addCue()`. + * * @example *
* @@ -79418,8 +87693,11 @@ * let isRemoved = false; * * function setup() { + * createCanvas(100, 100); + * * // Create a p5.MediaElement using createAudio(). * let beat = createAudio('assets/beat.mp3'); + * * // Play the beat in a loop. * beat.loop(); * @@ -79435,6 +87713,9 @@ * } * * function draw() { + * background(200); + * + * // Display different instructions based on the available callbacks. * if (isRemoved === false) { * text('Double-click to remove lavender.', 10, 10, 80, 80); * } else { @@ -79442,12 +87723,12 @@ * } * } * + * // Change the background color. * function changeBackground(c) { * background(c); * } * - * // Remove the lavender color-change cue - * // when the user double-clicks. + * // Remove the lavender color-change cue when the user double-clicks. * function doubleClicked() { * if (isRemoved === false) { * beat.removeCue(lavenderID); @@ -79475,16 +87756,20 @@ * Removes all functions scheduled with `media.addCue()`. * * @method clearCues + * * @example *
* * let isChanging = true; * * function setup() { + * createCanvas(100, 100); + * * background(200); * * // Create a p5.MediaElement using createAudio(). * let beat = createAudio('assets/beat.mp3'); + * * // Play the beat in a loop. * beat.loop(); * @@ -79498,6 +87783,9 @@ * } * * function draw() { + * background(200); + * + * // Display different instructions based on the available callbacks. * if (isChanging === true) { * text('Double-click to stop changing.', 10, 10, 80, 80); * } else { @@ -79505,12 +87793,12 @@ * } * } * + * // Change the background color. * function changeBackground(c) { * background(c); * } * - * // Remove cued functions and stop - * // changing colors when the user + * // Remove cued functions and stop changing colors when the user * // double-clicks. * function doubleClicked() { * if (isChanging === true) { @@ -79563,6 +87851,7 @@ * @class p5.File * @constructor * @param {File} file wrapped file. + * * @example *
* @@ -79570,26 +87859,28 @@ * // file and display its info. * * function setup() { + * createCanvas(100, 100); + * * background(200); * - * // Create a file input and place it beneath - * // the canvas. Call displayInfo() when - * // the file loads. + * // Create a file input and place it beneath the canvas. + * // Call displayInfo() when the file loads. * let input = createFileInput(displayInfo); * input.position(0, 100); * * describe('A gray square with a file input beneath it. If the user loads a file, its info is written in black.'); * } * - * // Display the p5.File's info - * // once it loads. + * // Display the p5.File's info once it loads. * function displayInfo(file) { * background(200); * * // Display the p5.File's name. * text(file.name, 10, 10, 80, 40); + * * // Display the p5.File's type and subtype. * text(`${file.type}/${file.subtype}`, 10, 70); + * * // Display the p5.File's size in bytes. * text(file.size, 10, 90); * } @@ -79603,9 +87894,10 @@ * let img; * * function setup() { - * // Create a file input and place it beneath - * // the canvas. Call handleImage() when - * // the file image loads. + * createCanvas(100, 100); + * + * // Create a file input and place it beneath the canvas. + * // Call handleImage() when the file image loads. * let input = createFileInput(handleImage); * input.position(0, 100); * @@ -79621,17 +87913,14 @@ * } * } * - * // Use the p5.File's data once - * // it loads. + * // Use the p5.File's data once it loads. * function handleImage(file) { * // Check the p5.File's type. * if (file.type === 'image') { - * // Create an image using using - * // the p5.File's data. + * // Create an image using using the p5.File's data. * img = createImg(file.data, ''); * - * // Hide the image element so it - * // doesn't appear twice. + * // Hide the image element so it doesn't appear twice. * img.hide(); * } else { * img = null; @@ -79649,6 +87938,7 @@ * object. All `File` properties and methods are accessible. * * @property file + * * @example *
* @@ -79656,26 +87946,28 @@ * // file and display its info. * * function setup() { + * createCanvas(100, 100); + * * background(200); * - * // Create a file input and place it beneath - * // the canvas. Call displayInfo() when - * // the file loads. + * // Create a file input and place it beneath the canvas. + * // Call displayInfo() when the file loads. * let input = createFileInput(displayInfo); * input.position(0, 100); * * describe('A gray square with a file input beneath it. If the user loads a file, its info is written in black.'); * } * - * // Use the p5.File once - * // it loads. + * // Use the p5.File once it loads. * function displayInfo(file) { * background(200); * * // Display the p5.File's name. * text(file.name, 10, 10, 80, 40); + * * // Display the p5.File's type and subtype. * text(`${file.type}/${file.subtype}`, 10, 70); + * * // Display the p5.File's size in bytes. * text(file.size, 10, 90); * } @@ -79690,29 +87982,31 @@ /** * The file * MIME type - * as a string. For example, `'image'`, `'text'`, and so on. + * as a string. + * + * For example, `'image'` and `'text'` are both MIME types. * * @property type + * * @example *
* - * // Use the file input to load a - * // file and display its info. + * // Use the file input to load a file and display its info. * * function setup() { + * createCanvas(100, 100); + * * background(200); * - * // Create a file input and place it beneath - * // the canvas. Call displayType() when - * // the file loads. + * // Create a file input and place it beneath the canvas. + * // Call displayType() when the file loads. * let input = createFileInput(displayType); * input.position(0, 100); * * describe('A gray square with a file input beneath it. If the user loads a file, its type is written in black.'); * } * - * // Display the p5.File's type - * // once it loads. + * // Display the p5.File's type once it loads. * function displayType(file) { * background(200); * @@ -79724,11 +88018,14 @@ */ this.type = typeList[0]; /** - * The file subtype as a string. For example, a file with an `'image'` + * The file subtype as a string. + * + * For example, a file with an `'image'` * MIME type * may have a subtype such as ``png`` or ``jpeg``. * * @property subtype + * * @example *
* @@ -79736,19 +88033,19 @@ * // file and display its info. * * function setup() { + * createCanvas(100, 100); + * * background(200); * - * // Create a file input and place it beneath - * // the canvas. Call displaySubtype() when - * // the file loads. + * // Create a file input and place it beneath the canvas. + * // Call displaySubtype() when the file loads. * let input = createFileInput(displaySubtype); * input.position(0, 100); * * describe('A gray square with a file input beneath it. If the user loads a file, its subtype is written in black.'); * } * - * // Display the p5.File's type - * // once it loads. + * // Display the p5.File's type once it loads. * function displaySubtype(file) { * background(200); * @@ -79763,6 +88060,7 @@ * The file name as a string. * * @property name + * * @example *
* @@ -79770,19 +88068,19 @@ * // file and display its info. * * function setup() { + * createCanvas(100, 100); + * * background(200); * - * // Create a file input and place it beneath - * // the canvas. Call displayName() when - * // the file loads. + * // Create a file input and place it beneath the canvas. + * // Call displayName() when the file loads. * let input = createFileInput(displayName); * input.position(0, 100); * * describe('A gray square with a file input beneath it. If the user loads a file, its name is written in black.'); * } * - * // Display the p5.File's name - * // once it loads. + * // Display the p5.File's name once it loads. * function displayName(file) { * background(200); * @@ -79797,26 +88095,26 @@ * The number of bytes in the file. * * @property size + * * @example *
* - * // Use the file input to load a - * // file and display its info. + * // Use the file input to load a file and display its info. * * function setup() { + * createCanvas(100, 100); + * * background(200); * - * // Create a file input and place it beneath - * // the canvas. Call displaySize() when - * // the file loads. + * // Create a file input and place it beneath the canvas. + * // Call displaySize() when the file loads. * let input = createFileInput(displaySize); * input.position(0, 100); * * describe('A gray square with a file input beneath it. If the user loads a file, its size in bytes is written in black.'); * } * - * // Display the p5.File's size - * // in bytes once it loads. + * // Display the p5.File's size in bytes once it loads. * function displaySize(file) { * background(200); * @@ -79828,37 +88126,36 @@ */ this.size = file.size; /** - * A string containing either the file's image data, text contents, or - * a parsed object in the case of JSON and - * p5.XML objects. + * A string containing the file's data. + * + * Data can be either image data, text contents, or a parsed object in the + * case of JSON and p5.XML objects. * * @property data + * * @example *
* - * // Use the file input to load a - * // file and display its info. + * // Use the file input to load a file and display its info. * * function setup() { + * createCanvas(100, 100); + * * background(200); * - * // Create a file input and place it beneath - * // the canvas. Call displayData() when - * // the file loads. + * // Create a file input and place it beneath the canvas. + * // Call displayData() when the file loads. * let input = createFileInput(displayData); * input.position(0, 100); * * describe('A gray square with a file input beneath it. If the user loads a file, its data is written in black.'); * } * - * // Display the p5.File's data - * // once it loads. + * // Display the p5.File's data once it loads. * function displayData(file) { * background(200); * - * // Display the p5.File's data, - * // which looks like a random - * // string of characters. + * // Display the p5.File's data, which looks like a random string of characters. * text(file.data, 10, 10, 80, 80); * } * @@ -79913,118 +88210,44 @@ exports.default = _default; }, { - '../core/main': 298, - 'core-js/modules/es.array.every': 171, - 'core-js/modules/es.array.filter': 173, - 'core-js/modules/es.array.for-each': 175, - 'core-js/modules/es.array.from': 176, - 'core-js/modules/es.array.index-of': 178, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.map': 182, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.array.splice': 185, - 'core-js/modules/es.function.name': 186, - 'core-js/modules/es.object.get-prototype-of': 198, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.promise': 201, - 'core-js/modules/es.reflect.construct': 202, - 'core-js/modules/es.regexp.exec': 205, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.string.replace': 214, - 'core-js/modules/es.string.split': 216, - 'core-js/modules/es.string.trim': 219, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/web.dom-collections.for-each': 255, - 'core-js/modules/web.dom-collections.iterator': 256, - 'core-js/modules/web.url': 258 + '../core/main': 306, + 'core-js/modules/es.array.every': 173, + 'core-js/modules/es.array.filter': 175, + 'core-js/modules/es.array.for-each': 179, + 'core-js/modules/es.array.from': 180, + 'core-js/modules/es.array.index-of': 182, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.map': 186, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.array.splice': 189, + 'core-js/modules/es.function.name': 192, + 'core-js/modules/es.object.assign': 201, + 'core-js/modules/es.object.get-prototype-of': 206, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.promise': 209, + 'core-js/modules/es.reflect.construct': 210, + 'core-js/modules/es.regexp.exec': 213, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.string.replace': 222, + 'core-js/modules/es.string.split': 224, + 'core-js/modules/es.string.trim': 227, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/web.dom-collections.for-each': 263, + 'core-js/modules/web.dom-collections.iterator': 264, + 'core-js/modules/web.url': 266 } ], - 315: [ + 323: [ function (_dereq_, module, exports) { 'use strict'; - _dereq_('core-js/modules/es.symbol'); - _dereq_('core-js/modules/es.symbol.description'); - _dereq_('core-js/modules/es.symbol.iterator'); - _dereq_('core-js/modules/es.array.iterator'); - _dereq_('core-js/modules/es.object.get-own-property-descriptor'); - _dereq_('core-js/modules/es.object.to-string'); - _dereq_('core-js/modules/es.string.iterator'); - _dereq_('core-js/modules/es.weak-map'); - _dereq_('core-js/modules/web.dom-collections.iterator'); - function _typeof2(obj) { - if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { - _typeof2 = function _typeof2(obj) { - return typeof obj; - }; - } else { - _typeof2 = function _typeof2(obj) { - return obj && typeof Symbol === 'function' && obj.constructor === Symbol && obj !== Symbol.prototype ? 'symbol' : typeof obj; - }; - } - return _typeof2(obj); - } - function _typeof(obj) { - if (typeof Symbol === 'function' && _typeof2(Symbol.iterator) === 'symbol') { - _typeof = function _typeof(obj) { - return _typeof2(obj); - }; - } else { - _typeof = function _typeof(obj) { - return obj && typeof Symbol === 'function' && obj.constructor === Symbol && obj !== Symbol.prototype ? 'symbol' : _typeof2(obj); - }; - } - return _typeof(obj); - } Object.defineProperty(exports, '__esModule', { value: true }); exports.default = void 0; var _main = _interopRequireDefault(_dereq_('../core/main')); - var constants = _interopRequireWildcard(_dereq_('../core/constants')); - function _getRequireWildcardCache() { - if (typeof WeakMap !== 'function') return null; - var cache = new WeakMap(); - _getRequireWildcardCache = function _getRequireWildcardCache() { - return cache; - }; - return cache; - } - function _interopRequireWildcard(obj) { - if (obj && obj.__esModule) { - return obj; - } - if (obj === null || _typeof(obj) !== 'object' && typeof obj !== 'function') { - return { - default: - obj - }; - } - var cache = _getRequireWildcardCache(); - if (cache && cache.has(obj)) { - return cache.get(obj); - } - var newObj = { - }; - var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; - for (var key in obj) { - if (Object.prototype.hasOwnProperty.call(obj, key)) { - var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; - if (desc && (desc.get || desc.set)) { - Object.defineProperty(newObj, key, desc); - } else { - newObj[key] = obj[key]; - } - } - } - newObj.default = obj; - if (cache) { - cache.set(obj, newObj); - } - return newObj; - } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: @@ -80620,14 +88843,10 @@ */ _main.default.prototype._ondeviceorientation = function (e) { this._updatePRotations(); - if (this._angleMode === constants.radians) { - e.beta = e.beta * (_PI / 180); - e.gamma = e.gamma * (_PI / 180); - e.alpha = e.alpha * (_PI / 180); - } - this._setProperty('rotationX', e.beta); - this._setProperty('rotationY', e.gamma); - this._setProperty('rotationZ', e.alpha); + // Convert from degrees into current angle mode + this._setProperty('rotationX', this._fromDegrees(e.beta)); + this._setProperty('rotationY', this._fromDegrees(e.gamma)); + this._setProperty('rotationZ', this._fromDegrees(e.alpha)); this._handleMotion(); }; _main.default.prototype._ondevicemotion = function (e) { @@ -80652,12 +88871,13 @@ } } if (typeof context.deviceTurned === 'function') { - // The angles given by rotationX etc is from range -180 to 180. - // The following will convert them to 0 to 360 for ease of calculation + // The angles given by rotationX etc is from range [-180 to 180]. + // The following will convert them to [0 to 360] for ease of calculation // of cases when the angles wrapped around. // _startAngleX will be converted back at the end and updated. - var wRX = this.rotationX + 180; - var wPRX = this.pRotationX + 180; + // Rotations are converted to degrees and all calculations are done in degrees + var wRX = this._toDegrees(this.rotationX) + 180; + var wPRX = this._toDegrees(this.pRotationX) + 180; var wSAX = startAngleX + 180; if (wRX - wPRX > 0 && wRX - wPRX < 270 || wRX - wPRX < - 270) { rotateDirectionX = 'clockwise'; @@ -80675,8 +88895,8 @@ this.pRotateDirectionX = rotateDirectionX; startAngleX = wSAX - 180; // Y-axis is identical to X-axis except for changing some names. - var wRY = this.rotationY + 180; - var wPRY = this.pRotationY + 180; + var wRY = this._toDegrees(this.rotationY) + 180; + var wPRY = this._toDegrees(this.pRotationY) + 180; var wSAY = startAngleY + 180; if (wRY - wPRY > 0 && wRY - wPRY < 270 || wRY - wPRY < - 270) { rotateDirectionY = 'clockwise'; @@ -80695,16 +88915,18 @@ startAngleY = wSAY - 180; // Z-axis is already in the range 0 to 360 // so no conversion is needed. - if (this.rotationZ - this.pRotationZ > 0 && this.rotationZ - this.pRotationZ < 270 || this.rotationZ - this.pRotationZ < - 270) { + var rotZ = this._toDegrees(this.rotationZ); + var pRotZ = this._toDegrees(this.pRotationZ); + if (rotZ - pRotZ > 0 && rotZ - pRotZ < 270 || rotZ - pRotZ < - 270) { rotateDirectionZ = 'clockwise'; - } else if (this.rotationZ - this.pRotationZ < 0 || this.rotationZ - this.pRotationZ > 270) { + } else if (rotZ - pRotZ < 0 || rotZ - pRotZ > 270) { rotateDirectionZ = 'counter-clockwise'; } if (rotateDirectionZ !== this.pRotateDirectionZ) { - startAngleZ = this.rotationZ; + startAngleZ = rotZ; } - if (Math.abs(this.rotationZ - startAngleZ) > 90 && Math.abs(this.rotationZ - startAngleZ) < 270) { - startAngleZ = this.rotationZ; + if (Math.abs(rotZ - startAngleZ) > 90 && Math.abs(rotZ - startAngleZ) < 270) { + startAngleZ = rotZ; this._setProperty('turnAxis', 'Z'); context.deviceTurned(); } @@ -80728,20 +88950,10 @@ exports.default = _default; }, { - '../core/constants': 286, - '../core/main': 298, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/main': 306 } ], - 316: [ + 324: [ function (_dereq_, module, exports) { 'use strict'; Object.defineProperty(exports, '__esModule', { @@ -80761,22 +88973,90 @@ * @requires core */ /** - * The boolean system variable keyIsPressed is true if any key is pressed - * and false if no keys are pressed. + * A `Boolean` system variable that's `true` if any key is currently pressed + * and `false` if not. * * @property {Boolean} keyIsPressed * @readOnly + * * @example *
* + * // Click on the canvas to begin detecting key presses. + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with a white square at its center. The white square turns black when the user presses a key.' + * ); + * } + * * function draw() { + * background(200); + * + * // Style the square. * if (keyIsPressed === true) { * fill(0); * } else { * fill(255); * } - * rect(25, 25, 50, 50); - * describe('50-by-50 white rect that turns black on keypress.'); + * + * // Draw the square. + * square(25, 25, 50); + * } + * + *
+ * + *
+ * + * // Click on the canvas to begin detecting key presses. + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with a white square at its center. The white square turns black when the user presses a key.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Style the square. + * if (keyIsPressed) { + * fill(0); + * } else { + * fill(255); + * } + * + * // Draw the square. + * square(25, 25, 50); + * } + * + *
+ * + *
+ * + * // Click on the canvas to begin detecting key presses. + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with the word "false" at its center. The word switches to "true" when the user presses a key.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * + * // Display the value of keyIsPressed. + * text(keyIsPressed, 50, 50); * } * *
@@ -80785,132 +89065,340 @@ _main.default.prototype.isKeyPressed = false; _main.default.prototype.keyIsPressed = false; // khan /** - * The system variable key always contains the value of the most recent - * key on the keyboard that was typed. To get the proper capitalization, it - * is best to use it within keyTyped(). For non-ASCII keys, use the keyCode - * variable. + * A `String` system variable that contains the value of the last key typed. + * + * The key variable is helpful for checking whether an + * ASCII + * key has been typed. For example, the expression `key === "a"` evaluates to + * `true` if the `a` key was typed and `false` if not. `key` doesn’t update + * for special keys such as `LEFT_ARROW` and `ENTER`. Use keyCode instead for + * special keys. The keyIsDown() function should + * be used to check for multiple different key presses at the same time. * * @property {String} key * @readOnly + * * @example - *
- * // Click any key to display it! - * // (Not Guaranteed to be Case Sensitive) + *
+ * + * // Click on the canvas to begin detecting key presses. + * * function setup() { - * fill(245, 123, 158); - * textSize(50); + * createCanvas(100, 100); + * + * describe( + * 'A gray square. The last key pressed is displayed at the center.' + * ); * } * * function draw() { * background(200); - * text(key, 33, 65); // Display last key pressed. - * describe('canvas displays any key value that is pressed in pink font.'); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * + * // Display the last key pressed. + * text(key, 50, 50); * } - *
+ *
+ *
+ * + *
+ * + * // Click on the canvas to begin detecting key presses. + * + * let x = 50; + * let y = 50; + * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * describe( + * 'A gray square with a black circle at its center. The circle moves when the user presses the keys "w", "a", "s", or "d". It leaves a trail as it moves.' + * ); + * } + * + * function draw() { + * // Update x and y if a key is pressed. + * if (keyIsPressed === true) { + * if (key === 'w') { + * y -= 1; + * } else if (key === 's') { + * y += 1; + * } else if (key === 'a') { + * x -= 1; + * } else if (key === 'd') { + * x += 1; + * } + * } + * + * // Style the circle. + * fill(0); + * + * // Draw the circle at (x, y). + * circle(x, y, 5); + * } + * + *
*/ _main.default.prototype.key = ''; /** - * The variable keyCode is used to detect special keys such as BACKSPACE, - * DELETE, ENTER, RETURN, TAB, ESCAPE, SHIFT, CONTROL, OPTION, ALT, UP_ARROW, - * DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW. - * You can also check for custom keys by looking up the keyCode of any key - * on a site like this: keycode.info. + * A `Number` system variable that contains the code of the last key typed. + * + * All keys have a `keyCode`. For example, the `a` key has the `keyCode` 65. + * The `keyCode` variable is helpful for checking whether a special key has + * been typed. For example, the following conditional checks whether the enter + * key has been typed: + * + * ```js + * if (keyCode === 13) { + * // Code to run if the enter key was pressed. + * } + * ``` + * + * The same code can be written more clearly using the system variable `ENTER` + * which has a value of 13: + * + * ```js + * if (keyCode === ENTER) { + * // Code to run if the enter key was pressed. + * } + * ``` + * + * The system variables `BACKSPACE`, `DELETE`, `ENTER`, `RETURN`, `TAB`, + * `ESCAPE`, `SHIFT`, `CONTROL`, `OPTION`, `ALT`, `UP_ARROW`, `DOWN_ARROW`, + * `LEFT_ARROW`, and `RIGHT_ARROW` are all helpful shorthands the key codes of + * special keys. Key codes can be found on websites such as + * keycode.info. * * @property {Integer} keyCode * @readOnly + * * @example - *
- * let fillVal = 126; + *
+ * + * // Click on the canvas to begin detecting key presses. + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square. The last key pressed and its code are displayed at the center.' + * ); + * } + * * function draw() { - * fill(fillVal); - * rect(25, 25, 50, 50); - * describe(`Grey rect center. turns white when up arrow pressed and black when down. - * Display key pressed and its keyCode in a yellow box.`); + * background(200); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * + * // Display the last key pressed and its code. + * text(`${key} : ${keyCode}`, 50, 50); * } + * + *
* - * function keyPressed() { - * if (keyCode === UP_ARROW) { - * fillVal = 255; - * } else if (keyCode === DOWN_ARROW) { - * fillVal = 0; - * } + *
+ * + * // Click on the canvas to begin detecting key presses. + * + * let x = 50; + * let y = 50; + * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * describe( + * 'A gray square with a black circle at its center. The circle moves when the user presses an arrow key. It leaves a trail as it moves.' + * ); * } - *
- *
- * function draw() {} - * function keyPressed() { - * background('yellow'); - * text(`${key} ${keyCode}`, 10, 40); - * print(key, ' ', keyCode); + * + * function draw() { + * // Update x and y if an arrow key is pressed. + * if (keyIsPressed === true) { + * if (keyCode === UP_ARROW) { + * y -= 1; + * } else if (keyCode === DOWN_ARROW) { + * y += 1; + * } else if (keyCode === LEFT_ARROW) { + * x -= 1; + * } else if (keyCode === RIGHT_ARROW) { + * x += 1; + * } + * } + * + * // Style the circle. + * fill(0); + * + * // Draw the circle at (x, y). + * circle(x, y, 5); * } - *
+ *
+ *
*/ _main.default.prototype.keyCode = 0; /** - * The keyPressed() function is called once every time a key is pressed. The - * keyCode for the key that was pressed is stored in the keyCode variable. + * A function that's called once when any key is pressed. * - * For non-ASCII keys, use the keyCode variable. You can check if the keyCode - * equals BACKSPACE, DELETE, ENTER, RETURN, TAB, ESCAPE, SHIFT, CONTROL, - * OPTION, ALT, UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW. + * Declaring the function `keyPressed()` sets a code block to run once + * automatically when the user presses any key: * - * For ASCII keys, the key that was pressed is stored in the key variable. However, it - * does not distinguish between uppercase and lowercase. For this reason, it - * is recommended to use keyTyped() to read the key variable, in which the - * case of the variable will be distinguished. + * ```js + * function keyPressed() { + * // Code to run. + * } + * ``` + * + * The key and keyCode + * variables will be updated with the most recently typed value when + * `keyPressed()` is called by p5.js: + * + * ```js + * function keyPressed() { + * if (key === 'c') { + * // Code to run. + * } + * + * if (keyCode === ENTER) { + * // Code to run. + * } + * } + * ``` + * + * The parameter, `event`, is optional. `keyPressed()` is always passed a + * KeyboardEvent + * object with properties that describe the key press event: + * + * ```js + * function keyPressed(event) { + * // Code to run that uses the event. + * console.log(event); + * } + * ``` * - * Because of how operating systems handle key repeats, holding down a key - * may cause multiple calls to keyTyped() (and keyReleased() as well). The - * rate of repeat is set by the operating system and how each computer is - * configured.

- * Browsers may have different default - * behaviors attached to various key events. To prevent any default - * behavior for this event, add "return false" to the end of the method. + * Browsers may have default behaviors attached to various key events. For + * example, some browsers may jump to the bottom of a web page when the + * `SPACE` key is pressed. To prevent any default behavior for this event, add + * `return false;` to the end of the function. * * @method keyPressed - * @param {KeyboardEvent} [event] optional KeyboardEvent callback argument. + * @param {KeyboardEvent} [event] optional `KeyboardEvent` callback argument. + * * @example *
* + * // Click on the canvas to begin detecting key presses. + * * let value = 0; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with a black square at its center. The inner square changes color when the user presses a key.' + * ); + * } + * * function draw() { + * background(200); + * + * // Style the square. * fill(value); - * rect(25, 25, 50, 50); - * describe(`black rect center. turns white when key pressed and black - * when released.`); + * + * // Draw the square. + * square(25, 25, 50); * } + * + * // Toggle the background color when the user presses a key. * function keyPressed() { * if (value === 0) { * value = 255; * } else { * value = 0; * } + * // Uncomment to prevent any default behavior. + * // return false; * } * *
+ * *
* + * // Click on the canvas to begin detecting key presses. + * * let value = 0; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with a white square at its center. The inner square turns black when the user presses the "b" key. It turns white when the user presses the "a" key.' + * ); + * } + * * function draw() { + * background(200); + * + * // Style the square. * fill(value); - * rect(25, 25, 50, 50); - * describe(`black rect center. turns white when left arrow pressed and - * black when right.`); + * + * // Draw the square. + * square(25, 25, 50); * } + * + * // Reassign value when the user presses the 'a' or 'b' key. * function keyPressed() { - * if (keyCode === LEFT_ARROW) { + * if (key === 'a') { * value = 255; - * } else if (keyCode === RIGHT_ARROW) { + * } else if (key === 'b') { * value = 0; * } + * // Uncomment to prevent any default behavior. + * // return false; * } * *
- *
+ * + *
* + * // Click on the canvas to begin detecting key presses. + * + * let value = 0; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with a black square at its center. The inner square turns white when the user presses the left arrow key. It turns black when the user presses the right arrow key.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Style the square. + * fill(value); + * + * // Draw the square. + * square(25, 25, 50); + * } + * + * // Toggle the background color when the user presses an arrow key. * function keyPressed() { - * // Do something - * return false; // prevent any default behaviour + * if (keyCode === LEFT_ARROW) { + * value = 255; + * } else if (keyCode === RIGHT_ARROW) { + * value = 0; + * } + * // Uncomment to prevent any default behavior. + * // return false; * } * *
@@ -80934,31 +89422,157 @@ } }; /** - * The keyReleased() function is called once every time a key is released. - * See key and keyCode for more information.

- * Browsers may have different default - * behaviors attached to various key events. To prevent any default - * behavior for this event, add "return false" to the end of the function. + * A function that's called once when any key is released. + * + * Declaring the function `keyReleased()` sets a code block to run once + * automatically when the user releases any key: + * + * ```js + * function keyReleased() { + * // Code to run. + * } + * ``` + * + * The key and keyCode + * variables will be updated with the most recently released value when + * `keyReleased()` is called by p5.js: + * + * ```js + * function keyReleased() { + * if (key === 'c') { + * // Code to run. + * } + * + * if (keyCode === ENTER) { + * // Code to run. + * } + * } + * ``` + * + * The parameter, `event`, is optional. `keyReleased()` is always passed a + * KeyboardEvent + * object with properties that describe the key press event: + * + * ```js + * function keyReleased(event) { + * // Code to run that uses the event. + * console.log(event); + * } + * ``` + * + * Browsers may have default behaviors attached to various key events. To + * prevent any default behavior for this event, add `return false;` to the end + * of the function. * * @method keyReleased - * @param {KeyboardEvent} [event] optional KeyboardEvent callback argument. + * @param {KeyboardEvent} [event] optional `KeyboardEvent` callback argument. + * * @example *
* + * // Click on the canvas to begin detecting key presses. + * * let value = 0; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with a black square at its center. The inner square changes color when the user releases a key.' + * ); + * } + * * function draw() { + * background(200); + * + * // Style the square. * fill(value); - * rect(25, 25, 50, 50); - * describe(`black rect center. turns white when key pressed and black - * when pressed again`); + * + * // Draw the square. + * square(25, 25, 50); * } + * + * // Toggle value when the user releases a key. * function keyReleased() { * if (value === 0) { * value = 255; * } else { * value = 0; * } - * return false; // prevent any default behavior + * // Uncomment to prevent any default behavior. + * // return false; + * } + * + *
+ * + *
+ * + * // Click on the canvas to begin detecting key presses. + * + * let value = 0; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with a black square at its center. The inner square becomes white when the user releases the "w" key.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Style the square. + * fill(value); + * + * // Draw the square. + * square(25, 25, 50); + * } + * + * // Set value to 255 the user releases the 'w' key. + * function keyReleased() { + * if (key === 'w') { + * value = 255; + * } + * // Uncomment to prevent any default behavior. + * // return false; + * } + * + *
+ * + *
+ * + * // Click on the canvas to begin detecting key presses. + * + * let value = 0; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with a black square at its center. The inner square turns white when the user presses and releases the left arrow key. It turns black when the user presses and releases the right arrow key.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Style the square. + * fill(value); + * + * // Draw the square. + * square(25, 25, 50); + * } + * + * // Toggle the background color when the user releases an arrow key. + * function keyReleased() { + * if (keyCode === LEFT_ARROW) { + * value = 255; + * } else if (keyCode === RIGHT_ARROW) { + * value = 0; + * } + * // Uncomment to prevent any default behavior. + * // return false; * } * *
@@ -80981,38 +89595,130 @@ } }; /** - * The keyTyped() function is called once every time a key is pressed, but - * action keys such as Backspace, Delete, Ctrl, Shift, and Alt are ignored. If you are trying to detect - * a keyCode for one of these keys, use the keyPressed() function instead. - * The most recent key typed will be stored in the key variable. + * A function that's called once when keys with printable characters are pressed. + * + * Declaring the function `keyTyped()` sets a code block to run once + * automatically when the user presses any key with a printable character such + * as `a` or 1. Modifier keys such as `SHIFT`, `CONTROL`, and the arrow keys + * will be ignored: + * + * ```js + * function keyTyped() { + * // Code to run. + * } + * ``` + * + * The key and keyCode + * variables will be updated with the most recently released value when + * `keyTyped()` is called by p5.js: + * + * ```js + * function keyTyped() { + * // Check for the "c" character using key. + * if (key === 'c') { + * // Code to run. + * } + * + * // Check for "c" using keyCode. + * if (keyCode === 67) { + * // Code to run. + * } + * } + * ``` + * + * The parameter, `event`, is optional. `keyTyped()` is always passed a + * KeyboardEvent + * object with properties that describe the key press event: + * + * ```js + * function keyReleased(event) { + * // Code to run that uses the event. + * console.log(event); + * } + * ``` + * + * Note: Use the keyPressed() function and + * keyCode system variable to respond to modifier + * keys such as `ALT`. * - * Because of how operating systems handle key repeats, holding down a key - * will cause multiple calls to keyTyped() (and keyReleased() as well). The - * rate of repeat is set by the operating system and how each computer is - * configured.

- * Browsers may have different default behaviors attached to various key - * events. To prevent any default behavior for this event, add "return false" - * to the end of the function. + * Browsers may have default behaviors attached to various key events. To + * prevent any default behavior for this event, add `return false;` to the end + * of the function. * * @method keyTyped - * @param {KeyboardEvent} [event] optional KeyboardEvent callback argument. + * @param {KeyboardEvent} [event] optional `KeyboardEvent` callback argument. + * * @example *
* + * // Click on the canvas to begin detecting key presses. + * // Note: Pressing special keys such as SPACE have no effect. + * * let value = 0; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with a white square at its center. The inner square changes color when the user presses a key.' + * ); + * } + * * function draw() { + * background(200); + * + * // Style the square. * fill(value); - * rect(25, 25, 50, 50); - * describe(`black rect center. turns white when 'a' key typed and - * black when 'b' pressed`); + * + * // Draw the square. + * square(25, 25, 50); + * } + * + * // Toggle the square's color when the user types a printable key. + * function keyTyped() { + * if (value === 0) { + * value = 255; + * } else { + * value = 0; + * } + * // Uncomment to prevent any default behavior. + * // return false; + * } + * + *
+ * + *
+ * + * // Click on the canvas to begin detecting key presses. + * + * let value = 0; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with a white square at its center. The inner square turns black when the user types the "b" key. It turns white when the user types the "a" key.' + * ); * } + * + * function draw() { + * background(200); + * + * // Style the square. + * fill(value); + * + * // Draw the square. + * square(25, 25, 50); + * } + * + * // Reassign value when the user types the 'a' or 'b' key. * function keyTyped() { * if (key === 'a') { * value = 255; * } else if (key === 'b') { * value = 0; * } - * // uncomment to prevent any default behavior + * // Uncomment to prevent any default behavior. * // return false; * } * @@ -81044,75 +89750,115 @@ }; }; /** - * The keyIsDown() function checks if the key is currently down, i.e. pressed. - * It can be used if you have an object that moves, and you want several keys - * to be able to affect its behaviour simultaneously, such as moving a - * sprite diagonally. You can put in any number representing the keyCode of - * the key, or use any of the variable keyCode names listed - * here. + * Returns `true` if the key it’s checking is pressed and `false` if not. + * + * `keyIsDown()` is helpful when checking for multiple different key presses. + * For example, `keyIsDown()` can be used to check if both `LEFT_ARROW` and + * `UP_ARROW` are pressed: + * + * ```js + * if (keyIsDown(LEFT_ARROW) && keyIsDown(UP_ARROW)) { + * // Move diagonally. + * } + * ``` + * + * `keyIsDown()` can check for key presses using + * keyCode values, as in `keyIsDown(37)` or + * `keyIsDown(LEFT_ARROW)`. Key codes can be found on websites such as + * keycode.info. * * @method keyIsDown - * @param {Number} code The key to check for. - * @return {Boolean} whether key is down or not + * @param {Number} code key to check. + * @return {Boolean} whether the key is down or not. + * * @example - *
- * let x = 100; - * let y = 100; + *
+ * + * // Click on the canvas to begin detecting key presses. + * + * let x = 50; + * let y = 50; * * function setup() { - * createCanvas(512, 512); - * fill(255, 0, 0); + * createCanvas(100, 100); + * + * background(200); + * + * describe( + * 'A gray square with a black circle at its center. The circle moves when the user presses an arrow key. It leaves a trail as it moves.' + * ); * } * * function draw() { - * if (keyIsDown(LEFT_ARROW)) { - * x -= 5; + * // Update x and y if an arrow key is pressed. + * if (keyIsDown(LEFT_ARROW) === true) { + * x -= 1; * } * - * if (keyIsDown(RIGHT_ARROW)) { - * x += 5; + * if (keyIsDown(RIGHT_ARROW) === true) { + * x += 1; * } * - * if (keyIsDown(UP_ARROW)) { - * y -= 5; + * if (keyIsDown(UP_ARROW) === true) { + * y -= 1; * } * - * if (keyIsDown(DOWN_ARROW)) { - * y += 5; + * if (keyIsDown(DOWN_ARROW) === true) { + * y += 1; * } * - * clear(); - * ellipse(x, y, 50, 50); - * describe(`50-by-50 red ellipse moves left, right, up, and - * down with arrow presses.`); + * // Style the circle. + * fill(0); + * + * // Draw the circle. + * circle(x, y, 5); * } - *
+ *
+ *
* - *
- * let diameter = 50; + *
+ * + * // Click on the canvas to begin detecting key presses. + * + * let x = 50; + * let y = 50; * * function setup() { - * createCanvas(512, 512); + * createCanvas(100, 100); + * + * background(200); + * + * describe( + * 'A gray square with a black circle at its center. The circle moves when the user presses an arrow key. It leaves a trail as it moves.' + * ); * } * * function draw() { - * // 107 and 187 are keyCodes for "+" - * if (keyIsDown(107) || keyIsDown(187)) { - * diameter += 1; + * // Update x and y if an arrow key is pressed. + * if (keyIsDown(37) === true) { + * x -= 1; * } * - * // 109 and 189 are keyCodes for "-" - * if (keyIsDown(109) || keyIsDown(189)) { - * diameter -= 1; + * if (keyIsDown(39) === true) { + * x += 1; * } * - * clear(); - * fill(255, 0, 0); - * ellipse(50, 50, diameter, diameter); - * describe(`50-by-50 red ellipse gets bigger or smaller when - * + or - are pressed.`); + * if (keyIsDown(38) === true) { + * y -= 1; + * } + * + * if (keyIsDown(40) === true) { + * y += 1; + * } + * + * // Style the circle. + * fill(0); + * + * // Draw the circle. + * circle(x, y, 5); * } - *
+ *
+ *
*/ _main.default.prototype.keyIsDown = function (code) { _main.default._validateParameters('keyIsDown', arguments); @@ -81139,20 +89885,18 @@ exports.default = _default; }, { - '../core/main': 298 + '../core/main': 306 } ], - 317: [ + 325: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); _dereq_('core-js/modules/es.symbol.description'); _dereq_('core-js/modules/es.symbol.iterator'); - _dereq_('core-js/modules/es.array.includes'); _dereq_('core-js/modules/es.array.iterator'); _dereq_('core-js/modules/es.object.get-own-property-descriptor'); _dereq_('core-js/modules/es.object.to-string'); - _dereq_('core-js/modules/es.string.includes'); _dereq_('core-js/modules/es.string.iterator'); _dereq_('core-js/modules/es.weak-map'); _dereq_('core-js/modules/web.dom-collections.iterator'); @@ -81180,8 +89924,6 @@ } return _typeof(obj); } - _dereq_('core-js/modules/es.array.includes'); - _dereq_('core-js/modules/es.string.includes'); Object.defineProperty(exports, '__esModule', { value: true }); @@ -81242,30 +89984,44 @@ * @requires constants */ /** + * A `Number` system variable that tracks the mouse's horizontal movement. + * + * `movedX` tracks how many pixels the mouse moves left or right between + * frames. `movedX` will have a negative value if the mouse moves left between + * frames and a positive value if it moves right. `movedX` can be calculated + * as `mouseX - pmouseX`. + * + * Note: `movedX` continues updating even when + * requestPointerLock() is active. * - * The variable movedX contains the horizontal movement of the mouse since the last frame * @property {Number} movedX * @readOnly + * * @example - *
+ *
* - * let x = 50; * function setup() { - * rectMode(CENTER); + * createCanvas(100, 100); + * + * describe( + * 'A gray square. The text ">>" appears when the user moves the mouse to the right. The text "<<" appears when the user moves the mouse to the left.' + * ); * } * * function draw() { - * if (x > 48) { - * x -= 2; - * } else if (x < 48) { - * x += 2; + * background(200); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * + * // Display >> when movedX is positive and + * // << when it's negative. + * if (movedX > 0) { + * text('>>', 50, 50); + * } else if (movedX < 0) { + * text('<<', 50, 50); * } - * x += floor(movedX / 5); - * background(237, 34, 93); - * fill(0); - * rect(x, 50, 50, 50); - * describe(`box moves left and right according to mouse movement - * then slowly back towards the center`); * } * *
@@ -81273,29 +90029,44 @@ _main.default.prototype.movedX = 0; /** - * The variable movedY contains the vertical movement of the mouse since the last frame + * A `Number` system variable that tracks the mouse's vertical movement. + * + * `movedY` tracks how many pixels the mouse moves up or down between + * frames. `movedY` will have a negative value if the mouse moves up between + * frames and a positive value if it moves down. `movedY` can be calculated + * as `mouseY - pmouseY`. + * + * Note: `movedY` continues updating even when + * requestPointerLock() is active. + * * @property {Number} movedY * @readOnly + * * @example - *
+ *
* - * let y = 50; * function setup() { - * rectMode(CENTER); + * createCanvas(100, 100); + * + * describe( + * 'A gray square. The text "▲" appears when the user moves the mouse upward. The text "▼" appears when the user moves the mouse downward.' + * ); * } * * function draw() { - * if (y > 48) { - * y -= 2; - * } else if (y < 48) { - * y += 2; + * background(200); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * + * // Display ▼ when movedY is positive and + * // ▲ when it's negative. + * if (movedY > 0) { + * text('▼', 50, 50); + * } else if (movedY < 0) { + * text('▲', 50, 50); * } - * y += floor(movedY / 5); - * background(237, 34, 93); - * fill(0); - * rect(50, y, 50, 50); - * describe(`box moves up and down according to mouse movement then - * slowly back towards the center`); * } * *
@@ -81309,11 +90080,18 @@ */ _main.default.prototype._hasMouseInteracted = false; /** - * The system variable mouseX always contains the current horizontal - * position of the mouse, relative to (0, 0) of the canvas. The value at - * the top-left corner is (0, 0) for 2-D and (-width/2, -height/2) for WebGL. - * If touch is used instead of mouse input, mouseX will hold the x value - * of the most recent touch point. + * A `Number` system variable that tracks the mouse's horizontal position. + * + * In 2D mode, `mouseX` keeps track of the mouse's position relative to the + * top-left corner of the canvas. For example, if the mouse is 50 pixels from + * the left edge of the canvas, then `mouseX` will be 50. + * + * In WebGL mode, `mouseX` keeps track of the mouse's position relative to the + * center of the canvas. For example, if the mouse is 50 pixels to the right + * of the canvas' center, then `mouseX` will be 50. + * + * If touch is used instead of the mouse, then `mouseX` will hold the + * x-coordinate of the most recent touch point. * * @property {Number} mouseX * @readOnly @@ -81321,44 +90099,224 @@ * @example *
* - * // Move the mouse across the canvas + * function setup() { + * createCanvas(100, 100); + * + * describe("A vertical black line moves left and right following the mouse's x-position."); + * } + * * function draw() { - * background(244, 248, 252); + * background(200); + * + * // Draw a vertical line that follows the mouse's x-coordinate. * line(mouseX, 0, mouseX, 100); - * describe('horizontal black line moves left and right with mouse x-position'); * } * *
- */ - _main.default.prototype.mouseX = 0; - /** - * The system variable mouseY always contains the current vertical - * position of the mouse, relative to (0, 0) of the canvas. The value at - * the top-left corner is (0, 0) for 2-D and (-width/2, -height/2) for WebGL. - * If touch is used instead of mouse input, mouseY will hold the y value - * of the most recent touch point. - * - * @property {Number} mouseY - * @readOnly * - * @example *
* - * // Move the mouse across the canvas + * function setup() { + * createCanvas(100, 100); + * + * describe("A gray square. The mouse's x- and y-coordinates are displayed as the user moves the mouse."); + * } + * * function draw() { - * background(244, 248, 252); - * line(0, mouseY, 100, mouseY); - * describe('vertical black line moves up and down with mouse y-position'); + * background(200); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * + * // Display the mouse's coordinates. + * text(`x: ${mouseX} y: ${mouseY}`, 50, 50); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe("A vertical black line moves left and right following the mouse's x-position."); + * } + * + * function draw() { + * background(200); + * + * // Adjust coordinates for WebGL mode. + * // The origin (0, 0) is at the center of the canvas. + * let mx = mouseX - 50; + * + * // Draw the line. + * line(mx, -50, mx, 50); + * } + * + *
+ * + *
+ * + * let font; + * + * // Load a font for WebGL mode. + * function preload() { + * font = loadFont('assets/inconsolata.otf'); + * } + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe( + * "A gray square. The mouse's x- and y-coordinates are displayed as the user moves the mouse." + * ); + * } + * + * function draw() { + * background(200); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * textFont(font); + * fill(0); + * + * // Display the mouse's coordinates. + * text(`x: ${mouseX} y: ${mouseY}`, 0, 0); + * } + * + *
+ */ + _main.default.prototype.mouseX = 0; + /** + * A `Number` system variable that tracks the mouse's vertical position. + * + * In 2D mode, `mouseY` keeps track of the mouse's position relative to the + * top-left corner of the canvas. For example, if the mouse is 50 pixels from + * the top edge of the canvas, then `mouseY` will be 50. + * + * In WebGL mode, `mouseY` keeps track of the mouse's position relative to the + * center of the canvas. For example, if the mouse is 50 pixels below the + * canvas' center, then `mouseY` will be 50. + * + * If touch is used instead of the mouse, then `mouseY` will hold the + * y-coordinate of the most recent touch point. + * + * @property {Number} mouseY + * @readOnly + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * describe("A horizontal black line moves up and down following the mouse's y-position."); + * } + * + * function draw() { + * background(200); + * + * // Draw a horizontal line that follows the mouse's y-coordinate. + * line(0, mouseY, 0, mouseY); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * describe("A gray square. The mouse's x- and y-coordinates are displayed as the user moves the mouse."); + * } + * + * function draw() { + * background(200); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * + * // Display the mouse's coordinates. + * text(`x: ${mouseX} y: ${mouseY}`, 50, 50); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe("A horizontal black line moves up and down following the mouse's y-position."); + * } + * + * function draw() { + * background(200); + * + * // Adjust coordinates for WebGL mode. + * // The origin (0, 0) is at the center of the canvas. + * let my = mouseY - 50; + * + * // Draw the line. + * line(-50, my, 50, my); + * } + * + *
+ * + *
+ * + * let font; + * + * // Load a font for WebGL mode. + * function preload() { + * font = loadFont('assets/inconsolata.otf'); + * } + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe( + * "A gray square. The mouse's x- and y-coordinates are displayed as the user moves the mouse." + * ); + * } + * + * function draw() { + * background(200); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * textFont(font); + * fill(0); + * + * // Display the mouse's coordinates. + * text(`x: ${mouseX} y: ${mouseY}`, 0, 0); * } * *
*/ _main.default.prototype.mouseY = 0; /** - * The system variable pmouseX always contains the horizontal position of - * the mouse or finger in the frame previous to the current frame, relative to - * (0, 0) of the canvas. The value at the top-left corner is (0, 0) for 2-D and - * (-width/2, -height/2) for WebGL. Note: pmouseX will be reset to the current mouseX + * A `Number` system variable that tracks the mouse's previous horizontal + * position. + * + * In 2D mode, `pmouseX` keeps track of the mouse's position relative to the + * top-left corner of the canvas. Its value is + * mouseX from the previous frame. For example, if + * the mouse was 50 pixels from the left edge of the canvas during the last + * frame, then `pmouseX` will be 50. + * + * In WebGL mode, `pmouseX` keeps track of the mouse's position relative to the + * center of the canvas. For example, if the mouse was 50 pixels to the right + * of the canvas' center during the last frame, then `pmouseX` will be 50. + * + * If touch is used instead of the mouse, then `pmouseX` will hold the + * x-coordinate of the last touch point. + * + * Note: `pmouseX` is reset to the current mouseX * value at the start of each touch event. * * @property {Number} pmouseX @@ -81367,28 +90325,66 @@ * @example *
* - * // Move the mouse across the canvas to leave a trail * function setup() { - * //slow down the frameRate to make it more visible + * createCanvas(100, 100); + * + * // Slow the frame rate. * frameRate(10); + * + * describe('A line follows the mouse as it moves. The line grows longer with faster movements.'); + * } + * + * function draw() { + * background(200); + * + * line(pmouseX, pmouseY, mouseX, mouseY); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A line follows the mouse as it moves. The line grows longer with faster movements.'); * } * * function draw() { - * background(244, 248, 252); - * line(mouseX, mouseY, pmouseX, pmouseY); - * print(pmouseX + ' -> ' + mouseX); - * describe(`line trail is created from cursor movements. - * faster movement make longer line.`); + * background(200); + * + * // Adjust coordinates for WebGL mode. + * // The origin (0, 0) is at the center of the canvas. + * let pmx = pmouseX - 50; + * let pmy = pmouseY - 50; + * let mx = mouseX - 50; + * let my = mouseY - 50; + * + * // Draw the line. + * line(pmx, pmy, mx, my); * } * *
*/ _main.default.prototype.pmouseX = 0; /** - * The system variable pmouseY always contains the vertical position of - * the mouse or finger in the frame previous to the current frame, relative to - * (0, 0) of the canvas. The value at the top-left corner is (0, 0) for 2-D and - * (-width/2, -height/2) for WebGL. Note: pmouseY will be reset to the current mouseY + * A `Number` system variable that tracks the mouse's previous vertical + * position. + * + * In 2D mode, `pmouseY` keeps track of the mouse's position relative to the + * top-left corner of the canvas. Its value is + * mouseY from the previous frame. For example, if + * the mouse was 50 pixels from the top edge of the canvas during the last + * frame, then `pmouseY` will be 50. + * + * In WebGL mode, `pmouseY` keeps track of the mouse's position relative to the + * center of the canvas. For example, if the mouse was 50 pixels below the + * canvas' center during the last frame, then `pmouseY` will be 50. + * + * If touch is used instead of the mouse, then `pmouseY` will hold the + * y-coordinate of the last touch point. + * + * Note: `pmouseY` is reset to the current mouseY * value at the start of each touch event. * * @property {Number} pmouseY @@ -81397,25 +90393,61 @@ * @example *
* + * function setup() { + * createCanvas(100, 100); + * + * // Slow the frame rate. + * frameRate(10); + * + * describe('A line follows the mouse as it moves. The line grows longer with faster movements.'); + * } + * + * function draw() { + * background(200); + * + * line(pmouseX, pmouseY, mouseX, mouseY); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A line follows the mouse as it moves. The line grows longer with faster movements.'); + * } + * * function draw() { - * background(237, 34, 93); - * fill(0); - * //draw a square only if the mouse is not moving - * if (mouseY === pmouseY && mouseX === pmouseX) { - * rect(20, 20, 60, 60); - * } + * background(200); + * + * // Adjust coordinates for WebGL mode. + * // The origin (0, 0) is at the center of the canvas. + * let pmx = pmouseX - 50; + * let pmy = pmouseY - 50; + * let mx = mouseX - 50; + * let my = mouseY - 50; * - * print(pmouseY + ' -> ' + mouseY); - * describe(`60-by-60 black rect center, fuchsia background. - * rect flickers on mouse movement`); + * // Draw the line. + * line(pmx, pmy, mx, my); * } * *
*/ _main.default.prototype.pmouseY = 0; /** - * The system variable winMouseX always contains the current horizontal - * position of the mouse, relative to (0, 0) of the window. + * A `Number` variable that tracks the mouse's horizontal position within the + * browser. + * + * `winMouseX` keeps track of the mouse's position relative to the top-left + * corner of the browser window. For example, if the mouse is 50 pixels from + * the left edge of the browser, then `winMouseX` will be 50. + * + * On a touchscreen device, `winMouseX` will hold the x-coordinate of the most + * recent touch point. + * + * Note: Use mouseX to track the mouse’s + * x-coordinate within the canvas. * * @property {Number} winMouseX * @readOnly @@ -81423,35 +90455,39 @@ * @example *
* - * let myCanvas; - * * function setup() { - * //use a variable to store a pointer to the canvas - * myCanvas = createCanvas(100, 100); - * let body = document.getElementsByTagName('body')[0]; - * myCanvas.parent(body); + * createCanvas(100, 100); + * + * describe("A gray square. The mouse's x- and y-coordinates are displayed as the user moves the mouse."); * } * * function draw() { - * background(237, 34, 93); - * fill(0); + * background(200); * - * //move the canvas to the horizontal mouse position - * //relative to the window - * myCanvas.position(winMouseX + 1, windowHeight / 2); + * // Style the text. + * textAlign(CENTER); + * textSize(16); * - * //the y of the square is relative to the canvas - * rect(20, mouseY, 60, 60); - * describe(`60-by-60 black rect y moves with mouse y and fuchsia - * canvas moves with mouse x`); + * // Display the mouse's coordinates within the browser window. + * text(`x: ${winMouseX} y: ${winMouseY}`, 50, 50); * } * *
*/ _main.default.prototype.winMouseX = 0; /** - * The system variable winMouseY always contains the current vertical - * position of the mouse, relative to (0, 0) of the window. + * A `Number` variable that tracks the mouse's vertical position within the + * browser. + * + * `winMouseY` keeps track of the mouse's position relative to the top-left + * corner of the browser window. For example, if the mouse is 50 pixels from + * the top edge of the browser, then `winMouseY` will be 50. + * + * On a touchscreen device, `winMouseY` will hold the y-coordinate of the most + * recent touch point. + * + * Note: Use mouseY to track the mouse’s + * y-coordinate within the canvas. * * @property {Number} winMouseY * @readOnly @@ -81459,37 +90495,44 @@ * @example *
* - * let myCanvas; - * * function setup() { - * //use a variable to store a pointer to the canvas - * myCanvas = createCanvas(100, 100); - * let body = document.getElementsByTagName('body')[0]; - * myCanvas.parent(body); + * createCanvas(100, 100); + * + * describe("A gray square. The mouse's x- and y-coordinates are displayed as the user moves the mouse."); * } * * function draw() { - * background(237, 34, 93); - * fill(0); + * background(200); * - * //move the canvas to the vertical mouse position - * //relative to the window - * myCanvas.position(windowWidth / 2, winMouseY + 1); + * // Style the text. + * textAlign(CENTER); + * textSize(16); * - * //the x of the square is relative to the canvas - * rect(mouseX, 20, 60, 60); - * describe(`60-by-60 black rect x moves with mouse x and - * fuchsia canvas y moves with mouse y`); + * // Display the mouse's coordinates within the browser window. + * text(`x: ${winMouseX} y: ${winMouseY}`, 50, 50); * } * *
*/ _main.default.prototype.winMouseY = 0; /** - * The system variable pwinMouseX always contains the horizontal position - * of the mouse in the frame previous to the current frame, relative to - * (0, 0) of the window. Note: pwinMouseX will be reset to the current winMouseX - * value at the start of each touch event. + * A `Number` variable that tracks the mouse's previous horizontal position + * within the browser. + * + * `pwinMouseX` keeps track of the mouse's position relative to the top-left + * corner of the browser window. Its value is + * winMouseX from the previous frame. For + * example, if the mouse was 50 pixels from + * the left edge of the browser during the last frame, then `pwinMouseX` will + * be 50. + * + * On a touchscreen device, `pwinMouseX` will hold the x-coordinate of the most + * recent touch point. `pwinMouseX` is reset to the current + * winMouseX value at the start of each touch + * event. + * + * Note: Use pmouseX to track the mouse’s previous + * x-coordinate within the canvas. * * @property {Number} pwinMouseX * @readOnly @@ -81497,37 +90540,69 @@ * @example *
* - * let myCanvas; + * function setup() { + * createCanvas(100, 100); + * + * // Slow the frame rate. + * frameRate(10); + * + * describe('A gray square. A white circle at its center grows larger when the mouse moves horizontally.'); + * } * + * function draw() { + * background(200); + * + * // Calculate the circle's diameter. + * let d = winMouseX - pwinMouseX; + * + * // Draw the circle. + * circle(50, 50, d); + * } + * + *
+ * + *
+ * * function setup() { - * //use a variable to store a pointer to the canvas - * myCanvas = createCanvas(100, 100); - * noStroke(); - * fill(237, 34, 93); + * // Create the canvas and set its position. + * let cnv = createCanvas(100, 100); + * cnv.position(20, 20); + * + * describe('A gray square with a number at its center. The number changes as the user moves the mouse vertically.'); * } * * function draw() { - * clear(); - * //the difference between previous and - * //current x position is the horizontal mouse speed - * let speed = abs(winMouseX - pwinMouseX); - * //change the size of the circle - * //according to the horizontal speed - * ellipse(50, 50, 10 + speed * 5, 10 + speed * 5); - * //move the canvas to the mouse position - * myCanvas.position(winMouseX + 1, winMouseY + 1); - * describe(`fuchsia ellipse moves with mouse x and y. - * Grows and shrinks with mouse speed`); + * background(200); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * + * // Display pwinMouseX. + * text(pwinMouseX, 50, 50); * } * *
*/ _main.default.prototype.pwinMouseX = 0; /** - * The system variable pwinMouseY always contains the vertical position of - * the mouse in the frame previous to the current frame, relative to (0, 0) - * of the window. Note: pwinMouseY will be reset to the current winMouseY - * value at the start of each touch event. + * A `Number` variable that tracks the mouse's previous vertical position + * within the browser. + * + * `pwinMouseY` keeps track of the mouse's position relative to the top-left + * corner of the browser window. Its value is + * winMouseY from the previous frame. For + * example, if the mouse was 50 pixels from + * the top edge of the browser during the last frame, then `pwinMouseY` will + * be 50. + * + * On a touchscreen device, `pwinMouseY` will hold the y-coordinate of the most + * recent touch point. `pwinMouseY` is reset to the current + * winMouseY value at the start of each touch + * event. + * + * Note: Use pmouseY to track the mouse’s previous + * y-coordinate within the canvas. * * @property {Number} pwinMouseY * @readOnly @@ -81535,37 +90610,61 @@ * @example *
* - * let myCanvas; + * function setup() { + * createCanvas(100, 100); + * + * // Slow the frame rate. + * frameRate(10); + * + * describe('A gray square. A white circle at its center grows larger when the mouse moves vertically.'); + * } + * + * function draw() { + * background(200); + * + * // Calculate the circle's diameter. + * let d = winMouseY - pwinMouseY; + * + * // Draw the circle. + * circle(50, 50, d); + * } + * + *
* + *
+ * * function setup() { - * //use a variable to store a pointer to the canvas - * myCanvas = createCanvas(100, 100); - * noStroke(); - * fill(237, 34, 93); + * // Create the canvas and set its position. + * let cnv = createCanvas(100, 100); + * cnv.position(20, 20); + * + * describe('A gray square with a number at its center. The number changes as the user moves the mouse vertically.'); * } * * function draw() { - * clear(); - * //the difference between previous and - * //current y position is the vertical mouse speed - * let speed = abs(winMouseY - pwinMouseY); - * //change the size of the circle - * //according to the vertical speed - * ellipse(50, 50, 10 + speed * 5, 10 + speed * 5); - * //move the canvas to the mouse position - * myCanvas.position(winMouseX + 1, winMouseY + 1); - * describe(`fuchsia ellipse moves with mouse x and y. - * Grows and shrinks with mouse speed`); + * background(200); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * + * // Display pwinMouseY. + * text(pwinMouseY, 50, 50); * } * *
*/ _main.default.prototype.pwinMouseY = 0; /** - * p5 automatically tracks if the mouse button is pressed and which - * button is pressed. The value of the system variable mouseButton is either - * LEFT, RIGHT, or CENTER depending on which button was pressed last. - * Warning: different browsers may track mouseButton differently. + * A String system variable that contains the value of the last mouse button + * pressed. + * + * The `mouseButton` variable is either `LEFT`, `RIGHT`, or `CENTER`, + * depending on which button was pressed last. + * + * Note: Different browsers may track `mouseButton` differently. See + * MDN + * for more information. * * @property {Constant} mouseButton * @readOnly @@ -81573,33 +90672,59 @@ * @example *
* + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with black text at its center. The text changes from 0 to either "left" or "right" when the user clicks a mouse button.' + * ); + * } + * * function draw() { - * background(237, 34, 93); - * fill(0); + * background(200); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * + * // Display the mouse button. + * text(mouseButton, 50, 50); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * "A gray square. Different shapes appear at its center depending on the mouse button that's clicked." + * ); + * } + * + * function draw() { + * background(200); * * if (mouseIsPressed === true) { * if (mouseButton === LEFT) { - * ellipse(50, 50, 50, 50); + * circle(50, 50, 50); * } * if (mouseButton === RIGHT) { - * rect(25, 25, 50, 50); + * square(25, 25, 50); * } * if (mouseButton === CENTER) { * triangle(23, 75, 50, 20, 78, 75); * } * } - * - * print(mouseButton); - * describe(`50-by-50 black ellipse appears on center of fuchsia - * canvas on mouse click/press.`); * } * *
*/ _main.default.prototype.mouseButton = 0; /** - * The boolean system variable mouseIsPressed is true if the mouse is pressed - * and false if not. + * A `Boolean` system variable that's `true` if the mouse is pressed and + * `false` if not. * * @property {Boolean} mouseIsPressed * @readOnly @@ -81607,19 +90732,49 @@ * @example *
* + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with the word "false" at its center. The word changes to "true" when the user presses a mouse button.' + * ); + * } + * * function draw() { - * background(237, 34, 93); - * fill(0); + * background(200); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * + * // Display the mouseIsPressed variable. + * text(mouseIsPressed, 25, 50); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with a white square at its center. The inner square turns black when the user presses the mouse.' + * ); + * } + * + * function draw() { + * background(200); * + * // Style the square. * if (mouseIsPressed === true) { - * ellipse(50, 50, 50, 50); + * fill(0); * } else { - * rect(25, 25, 50, 50); + * fill(255); * } * - * print(mouseIsPressed); - * describe(`black 50-by-50 rect becomes ellipse with mouse click/press. - * fuchsia background.`); + * // Draw the square. + * square(25, 25, 50); * } * *
@@ -81678,104 +90833,176 @@ } }; /** - * The mouseMoved() function is called every time the mouse moves and a mouse - * button is not pressed.

- * Browsers may have different default - * behaviors attached to various mouse events. To prevent any default - * behavior for this event, add "return false" to the end of the method. + * A function that's called when the mouse moves. + * + * Declaring the function `mouseMoved()` sets a code block to run + * automatically when the user moves the mouse without clicking any mouse + * buttons: + * + * ```js + * function mouseMoved() { + * // Code to run. + * } + * ``` + * + * The mouse system variables, such as mouseX and + * mouseY, will be updated with their most recent + * value when `mouseMoved()` is called by p5.js: + * + * ```js + * function mouseMoved() { + * if (mouseX < 50) { + * // Code to run if the mouse is on the left. + * } + * + * if (mouseY > 50) { + * // Code to run if the mouse is near the bottom. + * } + * } + * ``` + * + * The parameter, `event`, is optional. `mouseMoved()` is always passed a + * MouseEvent + * object with properties that describe the mouse move event: + * + * ```js + * function mouseMoved(event) { + * // Code to run that uses the event. + * console.log(event); + * } + * ``` + * + * Browsers may have default behaviors attached to various mouse events. For + * example, some browsers highlight text when the user moves the mouse while + * pressing a mouse button. To prevent any default behavior for this event, + * add `return false;` to the end of the function. * * @method mouseMoved - * @param {MouseEvent} [event] optional MouseEvent callback argument. + * @param {MouseEvent} [event] optional `MouseEvent` argument. + * * @example *
* - * // Move the mouse across the page - * // to change its value - * * let value = 0; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with a black square at its center. The inner square becomes lighter as the mouse moves.' + * ); + * } + * * function draw() { + * background(200); + * + * // Style the square. * fill(value); - * rect(25, 25, 50, 50); - * describe(`black 50-by-50 rect becomes lighter with mouse movements until - * white then resets no image displayed`); + * + * // Draw the square. + * square(25, 25, 50); * } + * * function mouseMoved() { - * value = value + 5; + * // Update the grayscale value. + * value += 5; + * + * // Reset the grayscale value. * if (value > 255) { * value = 0; * } + * // Uncomment to prevent any default behavior. + * // return false; * } * *
+ */ + /** + * A function that's called when the mouse moves while a button is pressed. * - *
- * - * function mouseMoved() { - * ellipse(mouseX, mouseY, 5, 5); - * // prevent default - * return false; + * Declaring the function `mouseDragged()` sets a code block to run + * automatically when the user clicks and drags the mouse: + * + * ```js + * function mouseDragged() { + * // Code to run. * } - * - *
+ * ``` * - *
- * - * // returns a MouseEvent object - * // as a callback argument - * function mouseMoved(event) { + * The mouse system variables, such as mouseX and + * mouseY, will be updated with their most recent + * value when `mouseDragged()` is called by p5.js: + * + * ```js + * function mouseDragged() { + * if (mouseX < 50) { + * // Code to run if the mouse is on the left. + * } + * + * if (mouseY > 50) { + * // Code to run if the mouse is near the bottom. + * } + * } + * ``` + * + * The parameter, `event`, is optional. `mouseDragged()` is always passed a + * MouseEvent + * object with properties that describe the mouse drag event: + * + * ```js + * function mouseDragged(event) { + * // Code to run that uses the event. * console.log(event); * } - * - *
- */ - /** - * The mouseDragged() function is called once every time the mouse moves and - * a mouse button is pressed. If no mouseDragged() function is defined, the - * touchMoved() function will be called instead if it is defined.

- * Browsers may have different default - * behaviors attached to various mouse events. To prevent any default - * behavior for this event, add "return false" to the end of the function. + * ``` + * + * On touchscreen devices, `mouseDragged()` will run when a user moves a touch + * point if touchMoved() isn’t declared. If + * touchMoved() is declared, then + * touchMoved() will run when a user moves a + * touch point and `mouseDragged()` won’t. + * + * Browsers may have default behaviors attached to various mouse events. For + * example, some browsers highlight text when the user moves the mouse while + * pressing a mouse button. To prevent any default behavior for this event, + * add `return false;` to the end of the function. * * @method mouseDragged - * @param {MouseEvent} [event] optional MouseEvent callback argument. + * @param {MouseEvent} [event] optional `MouseEvent` argument. + * * @example *
* - * // Drag the mouse across the page - * // to change its value - * * let value = 0; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with a black square at its center. The inner square becomes lighter as the user drags the mouse.' + * ); + * } + * * function draw() { + * background(200); + * + * // Style the square. * fill(value); - * rect(25, 25, 50, 50); - * describe(`black 50-by-50 rect turns lighter with mouse click and - * drag until white, resets`); + * + * // Draw the square. + * square(25, 25, 50); * } + * * function mouseDragged() { - * value = value + 5; + * // Update the grayscale value. + * value += 5; + * + * // Reset the grayscale value. * if (value > 255) { * value = 0; * } - * } - * - *
- * - *
- * - * function mouseDragged() { - * ellipse(mouseX, mouseY, 5, 5); - * // prevent default - * return false; - * } - * - *
- * - *
- * - * // returns a MouseEvent object - * // as a callback argument - * function mouseDragged(event) { - * console.log(event); + * // Uncomment to prevent any default behavior. + * // return false; * } * *
@@ -81806,55 +91033,146 @@ } }; /** - * The mousePressed() function is called once after every time a mouse button - * is pressed. The mouseButton variable (see the related reference entry) - * can be used to determine which button has been pressed. If no - * mousePressed() function is defined, the touchStarted() function will be - * called instead if it is defined.

- * Browsers may have different default - * behaviors attached to various mouse events. To prevent any default - * behavior for this event, add "return false" to the end of the function. + * A function that's called once when a mouse button is pressed. + * + * Declaring the function `mousePressed()` sets a code block to run + * automatically when the user presses a mouse button: + * + * ```js + * function mousePressed() { + * // Code to run. + * } + * ``` + * + * The mouse system variables, such as mouseX and + * mouseY, will be updated with their most recent + * value when `mousePressed()` is called by p5.js: + * + * ```js + * function mousePressed() { + * if (mouseX < 50) { + * // Code to run if the mouse is on the left. + * } + * + * if (mouseY > 50) { + * // Code to run if the mouse is near the bottom. + * } + * } + * ``` + * + * The parameter, `event`, is optional. `mousePressed()` is always passed a + * MouseEvent + * object with properties that describe the mouse press event: + * + * ```js + * function mousePressed(event) { + * // Code to run that uses the event. + * console.log(event); + * } + * ``` + * + * On touchscreen devices, `mousePressed()` will run when a user’s touch + * begins if touchStarted() isn’t declared. If + * touchStarted() is declared, then + * touchStarted() will run when a user’s touch + * begins and `mousePressed()` won’t. + * + * Browsers may have default behaviors attached to various mouse events. For + * example, some browsers highlight text when the user moves the mouse while + * pressing a mouse button. To prevent any default behavior for this event, + * add `return false;` to the end of the function. + * + * Note: `mousePressed()`, mouseReleased(), + * and mouseClicked() are all related. + * `mousePressed()` runs as soon as the user clicks the mouse. + * mouseReleased() runs as soon as the user + * releases the mouse click. mouseClicked() + * runs immediately after mouseReleased(). * * @method mousePressed - * @param {MouseEvent} [event] optional MouseEvent callback argument. + * @param {MouseEvent} [event] optional `MouseEvent` argument. + * * @example *
* - * // Click anywhere in the webpage to change - * // the color value of the rectangle + * let value = 0; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with a black square at its center. The inner square becomes lighter when the user presses a mouse button.' + * ); + * } * - * let colorValue = 0; * function draw() { - * fill(colorValue); - * rect(25, 25, 50, 50); - * describe('black 50-by-50 rect turns white with mouse click/press.'); + * background(200); + * + * // Style the square. + * fill(value); + * + * // Draw the square. + * square(25, 25, 50); * } + * * function mousePressed() { - * if (colorValue === 0) { - * colorValue = 255; - * } else { - * colorValue = 0; + * // Update the grayscale value. + * value += 5; + * + * // Reset the grayscale value. + * if (value > 255) { + * value = 0; * } + * // Uncomment to prevent any default behavior. + * // return false; * } * *
* - *
+ *
* + * function setup() { + * createCanvas(100, 100); + * + * // Style the circle. + * fill('orange'); + * stroke('royalblue'); + * strokeWeight(10); + * + * describe( + * 'An orange circle with a thick, blue border drawn on a gray background. When the user presses and holds the mouse, the border becomes thin and pink. When the user releases the mouse, the border becomes thicker and changes color to blue.' + * ); + * } + * + * function draw() { + * background(220); + * + * // Draw the circle. + * circle(50, 50, 20); + * } + * + * // Set the stroke color and weight as soon as the user clicks. * function mousePressed() { - * ellipse(mouseX, mouseY, 5, 5); - * // prevent default - * return false; + * stroke('deeppink'); + * strokeWeight(3); * } - * - *
* - *
- * - * // returns a MouseEvent object - * // as a callback argument - * function mousePressed(event) { - * console.log(event); + * // Set the stroke and fill colors as soon as the user releases + * // the mouse. + * function mouseReleased() { + * stroke('royalblue'); + * + * // This is never visible because fill() is called + * // in mouseClicked() which runs immediately after + * // mouseReleased(); + * fill('limegreen'); + * } + * + * // Set the fill color and stroke weight after + * // mousePressed() and mouseReleased() are called. + * function mouseClicked() { + * fill('orange'); + * strokeWeight(10); * } * *
@@ -81865,68 +91183,165 @@ this._setProperty('mouseIsPressed', true); this._setMouseButton(e); this._updateNextMouseCoords(e); + // _ontouchstart triggers first and sets this.touchstart + if (this.touchstart) { + return; + } if (typeof context.mousePressed === 'function') { executeDefault = context.mousePressed(e); if (executeDefault === false) { e.preventDefault(); - } // only safari needs this manual fallback for consistency - - } else if (navigator.userAgent.toLowerCase().includes('safari') && typeof context.touchStarted === 'function') { + } + } else if (typeof context.touchStarted === 'function') { executeDefault = context.touchStarted(e); if (executeDefault === false) { e.preventDefault(); } } + this.touchstart = false; }; /** - * The mouseReleased() function is called every time a mouse button is - * released. If no mouseReleased() function is defined, the touchEnded() - * function will be called instead if it is defined.

- * Browsers may have different default - * behaviors attached to various mouse events. To prevent any default - * behavior for this event, add "return false" to the end of the function. + * A function that's called once when a mouse button is released. * - * @method mouseReleased - * @param {MouseEvent} [event] optional MouseEvent callback argument. - * @example - *
- * - * // Click within the image to change - * // the value of the rectangle - * // after the mouse has been clicked + * Declaring the function `mouseReleased()` sets a code block to run + * automatically when the user releases a mouse button after having pressed + * it: * - * let value = 0; - * function draw() { - * fill(value); - * rect(25, 25, 50, 50); - * describe('black 50-by-50 rect turns white with mouse click/press.'); + * ```js + * function mouseReleased() { + * // Code to run. * } + * ``` + * + * The mouse system variables, such as mouseX and + * mouseY, will be updated with their most recent + * value when `mouseReleased()` is called by p5.js: + * + * ```js * function mouseReleased() { - * if (value === 0) { - * value = 255; - * } else { - * value = 0; + * if (mouseX < 50) { + * // Code to run if the mouse is on the left. + * } + * + * if (mouseY > 50) { + * // Code to run if the mouse is near the bottom. * } * } - * - *
+ * ``` + * + * The parameter, `event`, is optional. `mouseReleased()` is always passed a + * MouseEvent + * object with properties that describe the mouse release event: + * + * ```js + * function mouseReleased(event) { + * // Code to run that uses the event. + * console.log(event); + * } + * ``` + * + * On touchscreen devices, `mouseReleased()` will run when a user’s touch + * ends if touchEnded() isn’t declared. If + * touchEnded() is declared, then + * touchEnded() will run when a user’s touch + * ends and `mouseReleased()` won’t. + * + * Browsers may have default behaviors attached to various mouse events. For + * example, some browsers highlight text when the user moves the mouse while + * pressing a mouse button. To prevent any default behavior for this event, + * add `return false;` to the end of the function. + * + * Note: mousePressed(), `mouseReleased()`, + * and mouseClicked() are all related. + * mousePressed() runs as soon as the user + * clicks the mouse. `mouseReleased()` runs as soon as the user releases the + * mouse click. mouseClicked() runs + * immediately after `mouseReleased()`. + * + * @method mouseReleased + * @param {MouseEvent} [event] optional `MouseEvent` argument. + * + * @example + *
+ * + * let value = 0; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with a black square at its center. The inner square becomes lighter when the user presses and releases a mouse button.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Style the square. + * fill(value); + * + * // Draw the square. + * square(25, 25, 50); + * } * - *
- * * function mouseReleased() { - * ellipse(mouseX, mouseY, 5, 5); - * // prevent default - * return false; + * // Update the grayscale value. + * value += 5; + * + * // Reset the grayscale value. + * if (value > 255) { + * value = 0; + * } + * // Uncomment to prevent any default behavior. + * // return false; * } * *
* - *
+ *
* - * // returns a MouseEvent object - * // as a callback argument - * function mouseReleased(event) { - * console.log(event); + * function setup() { + * createCanvas(100, 100); + * + * // Style the circle. + * fill('orange'); + * stroke('royalblue'); + * strokeWeight(10); + * + * describe( + * 'An orange circle with a thick, blue border drawn on a gray background. When the user presses and holds the mouse, the border becomes thin and pink. When the user releases the mouse, the border becomes thicker and changes color to blue.' + * ); + * } + * + * function draw() { + * background(220); + * + * // Draw the circle. + * circle(50, 50, 20); + * } + * + * // Set the stroke color and weight as soon as the user clicks. + * function mousePressed() { + * stroke('deeppink'); + * strokeWeight(3); + * } + * + * // Set the stroke and fill colors as soon as the user releases + * // the mouse. + * function mouseReleased() { + * stroke('royalblue'); + * + * // This is never visible because fill() is called + * // in mouseClicked() which runs immediately after + * // mouseReleased(); + * fill('limegreen'); + * } + * + * // Set the fill color and stroke weight after + * // mousePressed() and mouseReleased() are called. + * function mouseClicked() { + * fill('orange'); + * strokeWeight(10); * } * *
@@ -81935,6 +91350,10 @@ var context = this._isGlobal ? window : this; var executeDefault; this._setProperty('mouseIsPressed', false); + // _ontouchend triggers first and sets this.touchend + if (this.touchend) { + return; + } if (typeof context.mouseReleased === 'function') { executeDefault = context.mouseReleased(e); if (executeDefault === false) { @@ -81946,61 +91365,152 @@ e.preventDefault(); } } + this.touchend = false; }; _main.default.prototype._ondragend = _main.default.prototype._onmouseup; _main.default.prototype._ondragover = _main.default.prototype._onmousemove; /** - * The mouseClicked() function is called once after a mouse button has been - * pressed and then released.

- * Browsers handle clicks differently, so this function is only guaranteed to be - * run when the left mouse button is clicked. To handle other mouse buttons - * being pressed or released, see mousePressed() or mouseReleased().

- * Browsers may have different default - * behaviors attached to various mouse events. To prevent any default - * behavior for this event, add "return false" to the end of the function. + * A function that's called once after a mouse button is pressed and released. + * + * Declaring the function `mouseClicked()` sets a code block to run + * automatically when the user releases a mouse button after having pressed + * it: + * + * ```js + * function mouseClicked() { + * // Code to run. + * } + * ``` + * + * The mouse system variables, such as mouseX and + * mouseY, will be updated with their most recent + * value when `mouseClicked()` is called by p5.js: + * + * ```js + * function mouseClicked() { + * if (mouseX < 50) { + * // Code to run if the mouse is on the left. + * } + * + * if (mouseY > 50) { + * // Code to run if the mouse is near the bottom. + * } + * } + * ``` + * + * The parameter, `event`, is optional. `mouseClicked()` is always passed a + * MouseEvent + * object with properties that describe the mouse click event: + * + * ```js + * function mouseClicked(event) { + * // Code to run that uses the event. + * console.log(event); + * } + * ``` + * + * On touchscreen devices, `mouseClicked()` will run when a user’s touch + * ends if touchEnded() isn’t declared. If + * touchEnded() is declared, then + * touchEnded() will run when a user’s touch + * ends and `mouseClicked()` won’t. + * + * Browsers may have default behaviors attached to various mouse events. For + * example, some browsers highlight text when the user moves the mouse while + * pressing a mouse button. To prevent any default behavior for this event, + * add `return false;` to the end of the function. + * + * Note: mousePressed(), + * mouseReleased(), + * and `mouseClicked()` are all related. + * mousePressed() runs as soon as the user + * clicks the mouse. mouseReleased() runs as + * soon as the user releases the mouse click. `mouseClicked()` runs + * immediately after mouseReleased(). * * @method mouseClicked - * @param {MouseEvent} [event] optional MouseEvent callback argument. + * @param {MouseEvent} [event] optional `MouseEvent` argument. + * * @example *
* - * // Click within the image to change - * // the value of the rectangle - * // after the mouse has been clicked - * * let value = 0; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with a black square at its center. The inner square changes color when the user presses and releases a mouse button.' + * ); + * } + * * function draw() { + * background(200); + * + * // Style the square. * fill(value); - * rect(25, 25, 50, 50); - * describe('black 50-by-50 rect turns white with mouse click/press.'); + * + * // Draw the square. + * square(25, 25, 50); * } * + * // Toggle the square's color when the user clicks. * function mouseClicked() { * if (value === 0) { * value = 255; * } else { * value = 0; * } + * // Uncomment to prevent any default behavior. + * // return false; * } * *
* - *
+ *
* - * function mouseClicked() { - * ellipse(mouseX, mouseY, 5, 5); - * // prevent default - * return false; + * function setup() { + * createCanvas(100, 100); + * + * // Style the circle. + * fill('orange'); + * stroke('royalblue'); + * strokeWeight(10); + * + * describe( + * 'An orange circle with a thick, blue border drawn on a gray background. When the user presses and holds the mouse, the border becomes thin and pink. When the user releases the mouse, the border becomes thicker and changes color to blue.' + * ); * } - * - *
* - *
- * - * // returns a MouseEvent object - * // as a callback argument - * function mouseClicked(event) { - * console.log(event); + * function draw() { + * background(220); + * + * // Draw the circle. + * circle(50, 50, 20); + * } + * + * // Set the stroke color and weight as soon as the user clicks. + * function mousePressed() { + * stroke('deeppink'); + * strokeWeight(3); + * } + * + * // Set the stroke and fill colors as soon as the user releases + * // the mouse. + * function mouseReleased() { + * stroke('royalblue'); + * + * // This is never visible because fill() is called + * // in mouseClicked() which runs immediately after + * // mouseReleased(); + * fill('limegreen'); + * } + * + * // Set the fill color and stroke weight after + * // mousePressed() and mouseReleased() are called. + * function mouseClicked() { + * fill('orange'); + * strokeWeight(10); * } * *
@@ -82015,56 +91525,121 @@ } }; /** - * The doubleClicked() function is executed every time a event - * listener has detected a dblclick event which is a part of the - * DOM L3 specification. The doubleClicked event is fired when a - * pointing device button (usually a mouse's primary button) - * is clicked twice on a single element. For more info on the - * dblclick event refer to mozilla's documentation here: - * https://developer.mozilla.org/en-US/docs/Web/Events/dblclick + * A function that's called once when a mouse button is clicked twice quickly. + * + * Declaring the function `doubleClicked()` sets a code block to run + * automatically when the user presses and releases the mouse button twice + * quickly: + * + * ```js + * function doubleClicked() { + * // Code to run. + * } + * ``` + * + * The mouse system variables, such as mouseX and + * mouseY, will be updated with their most recent + * value when `doubleClicked()` is called by p5.js: + * + * ```js + * function doubleClicked() { + * if (mouseX < 50) { + * // Code to run if the mouse is on the left. + * } + * + * if (mouseY > 50) { + * // Code to run if the mouse is near the bottom. + * } + * } + * ``` + * + * The parameter, `event`, is optional. `doubleClicked()` is always passed a + * MouseEvent + * object with properties that describe the double-click event: + * + * ```js + * function doubleClicked(event) { + * // Code to run that uses the event. + * console.log(event); + * } + * ``` + * + * On touchscreen devices, code placed in `doubleClicked()` will run after two + * touches that occur within a short time. + * + * Browsers may have default behaviors attached to various mouse events. For + * example, some browsers highlight text when the user moves the mouse while + * pressing a mouse button. To prevent any default behavior for this event, + * add `return false;` to the end of the function. * * @method doubleClicked - * @param {MouseEvent} [event] optional MouseEvent callback argument. + * @param {MouseEvent} [event] optional `MouseEvent` argument. + * * @example *
* - * // Click within the image to change - * // the value of the rectangle - * // after the mouse has been double clicked - * * let value = 0; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with a black square at its center. The inner square changes color when the user double-clicks.' + * ); + * } + * * function draw() { + * background(200); + * + * // Style the square. * fill(value); - * rect(25, 25, 50, 50); - * describe('black 50-by-50 rect turns white with mouse doubleClick/press.'); + * + * // Draw the square. + * square(25, 25, 50); * } * + * // Toggle the square's color when the user double-clicks. * function doubleClicked() { * if (value === 0) { * value = 255; * } else { * value = 0; * } + * // Uncomment to prevent any default behavior. + * // return false; * } * *
* - *
+ *
* - * function doubleClicked() { - * ellipse(mouseX, mouseY, 5, 5); - * // prevent default - * return false; + * let value = 0; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with a black circle at its center. When the user double-clicks on the circle, it changes color to white.' + * ); * } - * - *
* - *
- * - * // returns a MouseEvent object - * // as a callback argument - * function doubleClicked(event) { - * console.log(event); + * function draw() { + * background(200); + * + * // Style the circle. + * fill(value); + * + * // Draw the circle. + * circle(50, 50, 80); + * } + * + * // Reassign value to 255 when the user double-clicks on the circle. + * function doubleClicked() { + * if (dist(50, 50, mouseX, mouseY) < 40) { + * value = 255; + * } + * // Uncomment to prevent any default behavior. + * // return false; * } * *
@@ -82093,41 +91668,123 @@ */ _main.default.prototype._pmouseWheelDeltaY = 0; /** - * The function mouseWheel() is executed every time a vertical mouse wheel - * event is detected either triggered by an actual mouse wheel or by a - * touchpad.

- * The event.delta property returns the amount the mouse wheel - * have scrolled. The values can be positive or negative depending on the - * scroll direction (on macOS with "natural" scrolling enabled, the signs - * are inverted).

- * Browsers may have different default behaviors attached to various - * mouse events. To prevent any default behavior for this event, add - * "return false" to the end of the method.

- * Due to the current support of the "wheel" event on Safari, the function - * may only work as expected if "return false" is included while using Safari. + * A function that's called once when the mouse wheel moves. + * + * Declaring the function `mouseWheel()` sets a code block to run + * automatically when the user scrolls with the mouse wheel: + * + * ```js + * function mouseWheel() { + * // Code to run. + * } + * ``` + * + * The mouse system variables, such as mouseX and + * mouseY, will be updated with their most recent + * value when `mouseWheel()` is called by p5.js: + * + * ```js + * function mouseWheel() { + * if (mouseX < 50) { + * // Code to run if the mouse is on the left. + * } + * + * if (mouseY > 50) { + * // Code to run if the mouse is near the bottom. + * } + * } + * ``` + * + * The parameter, `event`, is optional. `mouseWheel()` is always passed a + * MouseEvent + * object with properties that describe the mouse scroll event: + * + * ```js + * function mouseWheel(event) { + * // Code to run that uses the event. + * console.log(event); + * } + * ``` + * + * The `event` object has many properties including `delta`, a `Number` + * containing the distance that the user scrolled. For example, `event.delta` + * might have the value 5 when the user scrolls up. `event.delta` is positive + * if the user scrolls up and negative if they scroll down. The signs are + * opposite on macOS with "natural" scrolling enabled. + * + * Browsers may have default behaviors attached to various mouse events. For + * example, some browsers highlight text when the user moves the mouse while + * pressing a mouse button. To prevent any default behavior for this event, + * add `return false;` to the end of the function. + * + * Note: On Safari, `mouseWheel()` may only work as expected if + * `return false;` is added at the end of the function. * * @method mouseWheel - * @param {WheelEvent} [event] optional WheelEvent callback argument. + * @param {WheelEvent} [event] optional `WheelEvent` argument. * * @example *
* - * let pos = 25; + * let circleSize = 0; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square. A white circle at its center grows up when the user scrolls the mouse wheel.' + * ); + * } * * function draw() { - * background(237, 34, 93); - * fill(0); - * rect(25, pos, 50, 50); - * describe(`black 50-by-50 rect moves up and down with vertical scroll. - * fuchsia background`); + * background(200); + * + * // Draw the circle + * circle(circleSize, 50, 50); + * } + * + * // Increment circleSize when the user scrolls the mouse wheel. + * function mouseWheel() { + * circleSize += 1; + * // Uncomment to prevent any default behavior. + * // return false; + * } + * + *
+ * + *
+ * + * let direction = ''; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square. An arrow at its center points up when the user scrolls up. The arrow points down when the user scrolls down.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * + * // Draw an arrow that points where + * // the mouse last scrolled. + * text(direction, 50, 50); * } * + * // Change direction when the user scrolls the mouse wheel. * function mouseWheel(event) { - * print(event.delta); - * //move the square according to the vertical scroll amount - * pos += event.delta; - * //uncomment to block page scrolling - * //return false; + * if (event.delta > 0) { + * direction = '▲'; + * } else { + * direction = '▼'; + * } + * // Uncomment to prevent any default behavior. + * // return false; * } * *
@@ -82144,33 +91801,54 @@ } }; /** - * The function requestPointerLock() - * locks the pointer to its current position and makes it invisible. - * Use movedX and movedY to get the difference the mouse was moved since - * the last call of draw. - * Note that not all browsers support this feature. - * This enables you to create experiences that aren't limited by the mouse moving out of the screen - * even if it is repeatedly moved into one direction. - * For example, a first person perspective experience. + * Locks the mouse pointer to its current position and makes it invisible. + * + * `requestPointerLock()` allows the mouse to move forever without leaving the + * screen. Calling `requestPointerLock()` locks the values of + * mouseX, mouseY, + * pmouseX, and pmouseY. + * movedX and movedY + * continue updating and can be used to get the distance the mouse moved since + * the last frame was drawn. Calling + * exitPointerLock() resumes updating the + * mouse system variables. + * + * Note: Most browsers require an input, such as a click, before calling + * `requestPointerLock()`. It’s recommended to call `requestPointerLock()` in + * an event function such as doubleClicked(). * * @method requestPointerLock + * * @example - *
+ *
* - * let cam; + * let score = 0; + * * function setup() { - * createCanvas(100, 100, WEBGL); - * requestPointerLock(); - * cam = createCamera(); + * createCanvas(100, 100); + * + * describe( + * 'A gray square with the text "Score: X" at its center. The score increases when the user moves the mouse upward. It decreases when the user moves the mouse downward.' + * ); * } * * function draw() { - * background(255); - * cam.pan(-movedX * 0.001); - * cam.tilt(movedY * 0.001); - * sphere(25); - * describe(`3D scene moves according to mouse mouse movement in a - * first person perspective`); + * background(200); + * + * // Update the score. + * score -= movedY; + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * + * // Display the score. + * text(`Score: ${score}`, 50, 50); + * } + * + * // Lock the pointer when the user double-clicks. + * function doubleClicked() { + * requestPointerLock(); * } * *
@@ -82187,28 +91865,56 @@ return true; }; /** - * The function exitPointerLock() - * exits a previously triggered pointer Lock - * for example to make ui elements usable etc + * Exits a pointer lock started with + * requestPointerLock. + * + * Calling `requestPointerLock()` locks the values of + * mouseX, mouseY, + * pmouseX, and pmouseY. + * Calling `exitPointerLock()` resumes updating the mouse system variables. + * + * Note: Most browsers require an input, such as a click, before calling + * `requestPointerLock()`. It’s recommended to call `requestPointerLock()` in + * an event function such as doubleClicked(). * * @method exitPointerLock + * * @example - *
+ *
* - * //click the canvas to lock the pointer - * //click again to exit (otherwise escape) - * let locked = false; - * function draw() { - * background(237, 34, 93); - * describe('cursor gets locked / unlocked on mouse-click'); + * let isLocked = false; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with a word at its center. The word changes between "Unlocked" and "Locked" when the user double-clicks.' + * ); * } - * function mouseClicked() { - * if (!locked) { - * locked = true; - * requestPointerLock(); + * + * function draw() { + * background(200); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * + * // Tell the user whether the pointer is locked. + * if (isLocked === true) { + * text('Locked', 50, 50); * } else { + * text('Unlocked', 50, 50); + * } + * } + * + * // Toggle the pointer lock when the user double-clicks. + * function doubleClicked() { + * if (isLocked === true) { * exitPointerLock(); - * locked = false; + * isLocked = false; + * } else { + * requestPointerLock(); + * isLocked = true; * } * } * @@ -82221,28 +91927,22 @@ exports.default = _default; }, { - '../core/constants': 286, - '../core/main': 298, - 'core-js/modules/es.array.includes': 177, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.string.includes': 209, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/constants': 294, + '../core/main': 306, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 318: [ + 326: [ function (_dereq_, module, exports) { 'use strict'; - _dereq_('core-js/modules/es.array.includes'); - _dereq_('core-js/modules/es.string.includes'); - _dereq_('core-js/modules/es.array.includes'); - _dereq_('core-js/modules/es.string.includes'); Object.defineProperty(exports, '__esModule', { value: true }); @@ -82260,13 +91960,35 @@ * @requires core */ /** - * The system variable touches[] contains an array of the positions of all - * current touch points, relative to (0, 0) of the canvas, and IDs identifying a - * unique touch as it moves. Each element in the array is an object with x, y, - * and id properties. + * An `Array` of all the current touch points on a touchscreen device. + * + * The `touches` array is empty by default. When the user touches their + * screen, a new touch point is tracked and added to the array. Touch points + * are `Objects` with the following properties: + * + * ```js + * // Iterate over the touches array. + * for (let touch of touches) { + * // x-coordinate relative to the top-left + * // corner of the canvas. + * console.log(touch.x); * - * The touches[] array is not supported on Safari and IE on touch-based - * desktops (laptops). + * // y-coordinate relative to the top-left + * // corner of the canvas. + * console.log(touch.y); + * + * // x-coordinate relative to the top-left + * // corner of the browser. + * console.log(touch.winX); + * + * // y-coordinate relative to the top-left + * // corner of the browser. + * console.log(touch.winY); + * + * // ID number + * console.log(touch.id); + * } + * ``` * * @property {Object[]} touches * @readOnly @@ -82274,15 +91996,48 @@ * @example *
* - * // On a touchscreen device, touch - * // the canvas using one or more fingers - * // at the same time + * // On a touchscreen device, touch the canvas using one or more fingers + * // at the same time. + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square. White circles appear where the user touches the square.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Draw a circle at each touch point. + * for (let touch of touches) { + * circle(touch.x, touch.y, 40); + * } + * } + * + *
+ * + *
+ * + * // On a touchscreen device, touch the canvas using one or more fingers + * // at the same time. + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square. Labels appear where the user touches the square, displaying the coordinates.' + * ); + * } + * * function draw() { - * clear(); - * let display = touches.length + ' touches'; - * text(display, 5, 10); - * describe(`Number of touches currently registered are displayed - * on the canvas`); + * background(200); + * + * // Draw a label above each touch point. + * for (let touch of touches) { + * text(`${touch.x}, ${touch.y}`, touch.x, touch.y - 40); + * } * } * *
@@ -82314,27 +92069,85 @@ id: touch.identifier }; } /** - * The touchStarted() function is called once after every time a touch is - * registered. If no touchStarted() function is defined, the mousePressed() - * function will be called instead if it is defined.

- * Browsers may have different default behaviors attached to various touch - * events. To prevent any default behavior for this event, add "return false" - * to the end of the method. + * A function that's called once each time the user touches the screen. + * + * Declaring a function called `touchStarted()` sets a code block to run + * automatically each time the user begins touching a touchscreen device: + * + * ```js + * function touchStarted() { + * // Code to run. + * } + * ``` + * + * The touches array will be updated with the most + * recent touch points when `touchStarted()` is called by p5.js: + * + * ```js + * function touchStarted() { + * // Paint over the background. + * background(200); + * + * // Mark each touch point once with a circle. + * for (let touch of touches) { + * circle(touch.x, touch.y, 40); + * } + * } + * ``` + * + * The parameter, event, is optional. `touchStarted()` will be passed a + * TouchEvent + * object with properties that describe the touch event: + * + * ```js + * function touchStarted(event) { + * // Code to run that uses the event. + * console.log(event); + * } + * ``` + * + * On touchscreen devices, mousePressed() will + * run when a user’s touch starts if `touchStarted()` isn’t declared. If + * `touchStarted()` is declared, then `touchStarted()` will run when a user’s + * touch starts and mousePressed() won’t. + * + * Note: `touchStarted()`, touchEnded(), and + * touchMoved() are all related. + * `touchStarted()` runs as soon as the user touches a touchscreen device. + * touchEnded() runs as soon as the user ends a + * touch. touchMoved() runs repeatedly as the + * user moves any touch points. * * @method touchStarted - * @param {TouchEvent} [event] optional TouchEvent callback argument. + * @param {TouchEvent} [event] optional `TouchEvent` argument. + * * @example *
* - * // Touch within the image to change - * // the value of the rectangle + * // On a touchscreen device, touch the canvas using one or more fingers + * // at the same time. * * let value = 0; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with a black square at its center. The inner square switches color between black and white each time the user touches the screen.' + * ); + * } + * * function draw() { + * background(200); + * + * // Style the square. * fill(value); - * rect(25, 25, 50, 50); - * describe('50-by-50 black rect turns white with touch event.'); + * + * // Draw the square. + * square(25, 25, 50); * } + * + * // Toggle colors with each touch. * function touchStarted() { * if (value === 0) { * value = 255; @@ -82345,25 +92158,66 @@ * *
* - *
+ *
* + * // On a touchscreen device, touch the canvas using one or more fingers + * // at the same time. + * + * let bgColor = 50; + * let fillColor = 255; + * let borderWidth = 0.5; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with the number 0 at the top-center. The number tracks the number of places the user is touching the screen. Circles appear at each touch point and change style in response to events.' + * ); + * } + * + * function draw() { + * background(bgColor); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * fill(0); + * noStroke(); + * + * // Display the number of touch points. + * text(touches.length, 50, 20); + * + * // Style the touch points. + * fill(fillColor); + * stroke(0); + * strokeWeight(borderWidth); + * + * // Display the touch points as circles. + * for (let touch of touches) { + * circle(touch.x, touch.y, 40); + * } + * } + * + * // Set the background color to a random grayscale value. * function touchStarted() { - * ellipse(mouseX, mouseY, 5, 5); - * // prevent default - * return false; + * bgColor = random(80, 255); * } - * describe('no image displayed'); - * - *
* - *
- * - * // returns a TouchEvent object - * // as a callback argument - * function touchStarted(event) { - * console.log(event); + * // Set the fill color to a random grayscale value. + * function touchEnded() { + * fillColor = random(0, 255); + * } + * + * // Set the stroke weight. + * function touchMoved() { + * // Increment the border width. + * borderWidth += 0.1; + * + * // Reset the border width once it's too thick. + * if (borderWidth > 20) { + * borderWidth = 0.5; + * } * } - * describe('no image displayed'); * *
*/ @@ -82377,41 +92231,97 @@ this._updateMouseCoords(); // reset pmouseXY at the start of each touch event if (typeof context.touchStarted === 'function') { executeDefault = context.touchStarted(e); - if (executeDefault === false) { - e.preventDefault(); - } // only safari needs this manual fallback for consistency - - } else if (navigator.userAgent.toLowerCase().includes('safari') && typeof context.mousePressed === 'function') { - executeDefault = context.mousePressed(e); if (executeDefault === false) { e.preventDefault(); } + this.touchstart = true; } }; /** - * The touchMoved() function is called every time a touch move is registered. - * If no touchMoved() function is defined, the mouseDragged() function will - * be called instead if it is defined.

- * Browsers may have different default behaviors attached to various touch - * events. To prevent any default behavior for this event, add "return false" - * to the end of the method. + * A function that's called when the user touches the screen and moves. + * + * Declaring the function `touchMoved()` sets a code block to run + * automatically when the user touches a touchscreen device and moves: + * + * ```js + * function touchMoved() { + * // Code to run. + * } + * ``` + * + * The touches array will be updated with the most + * recent touch points when `touchMoved()` is called by p5.js: + * + * ```js + * function touchMoved() { + * // Paint over the background. + * background(200); + * + * // Mark each touch point while the user moves. + * for (let touch of touches) { + * circle(touch.x, touch.y, 40); + * } + * } + * ``` + * + * The parameter, event, is optional. `touchMoved()` will be passed a + * TouchEvent + * object with properties that describe the touch event: + * + * ```js + * function touchMoved(event) { + * // Code to run that uses the event. + * console.log(event); + * } + * ``` + * + * On touchscreen devices, mouseDragged() will + * run when the user’s touch points move if `touchMoved()` isn’t declared. If + * `touchMoved()` is declared, then `touchMoved()` will run when a user’s + * touch points move and mouseDragged() won’t. + * + * Note: touchStarted(), + * touchEnded(), and + * `touchMoved()` are all related. + * touchStarted() runs as soon as the user + * touches a touchscreen device. touchEnded() + * runs as soon as the user ends a touch. `touchMoved()` runs repeatedly as + * the user moves any touch points. * * @method touchMoved - * @param {TouchEvent} [event] optional TouchEvent callback argument. + * @param {TouchEvent} [event] optional TouchEvent argument. + * * @example *
* - * // Move your finger across the page - * // to change its value + * // On a touchscreen device, touch the canvas using one or more fingers + * // at the same time. * * let value = 0; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with a black square at its center. The inner square becomes lighter when the user touches the screen and moves.' + * ); + * } + * * function draw() { + * background(200); + * + * // Style the square. * fill(value); - * rect(25, 25, 50, 50); - * describe('50-by-50 black rect turns lighter with touch until white. resets'); + * + * // Draw the square. + * square(25, 25, 50); * } + * * function touchMoved() { - * value = value + 5; + * // Update the grayscale value. + * value += 5; + * + * // Reset the grayscale value. * if (value > 255) { * value = 0; * } @@ -82419,25 +92329,66 @@ * *
* - *
+ *
* - * function touchMoved() { - * ellipse(mouseX, mouseY, 5, 5); - * // prevent default - * return false; + * // On a touchscreen device, touch the canvas using one or more fingers + * // at the same time. + * + * let bgColor = 50; + * let fillColor = 255; + * let borderWidth = 0.5; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with the number 0 at the top-center. The number tracks the number of places the user is touching the screen. Circles appear at each touch point and change style in response to events.' + * ); * } - * describe('no image displayed'); - * - *
* - *
- * - * // returns a TouchEvent object - * // as a callback argument - * function touchMoved(event) { - * console.log(event); + * function draw() { + * background(bgColor); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * fill(0); + * noStroke(); + * + * // Display the number of touch points. + * text(touches.length, 50, 20); + * + * // Style the touch points. + * fill(fillColor); + * stroke(0); + * strokeWeight(borderWidth); + * + * // Display the touch points as circles. + * for (let touch of touches) { + * circle(touch.x, touch.y, 40); + * } + * } + * + * // Set the background color to a random grayscale value. + * function touchStarted() { + * bgColor = random(80, 255); + * } + * + * // Set the fill color to a random grayscale value. + * function touchEnded() { + * fillColor = random(0, 255); + * } + * + * // Set the stroke weight. + * function touchMoved() { + * // Increment the border width. + * borderWidth += 0.1; + * + * // Reset the border width once it's too thick. + * if (borderWidth > 20) { + * borderWidth = 0.5; + * } * } - * describe('no image displayed'); * *
*/ @@ -82459,56 +92410,156 @@ } }; /** - * The touchEnded() function is called every time a touch ends. If no - * touchEnded() function is defined, the mouseReleased() function will be - * called instead if it is defined.

- * Browsers may have different default behaviors attached to various touch - * events. To prevent any default behavior for this event, add "return false" - * to the end of the method. + * A function that's called once each time a screen touch ends. * - * @method touchEnded - * @param {TouchEvent} [event] optional TouchEvent callback argument. - * @example - *
- * - * // Release touch within the image to - * // change the value of the rectangle + * Declaring the function `touchEnded()` sets a code block to run + * automatically when the user stops touching a touchscreen device: * - * let value = 0; - * function draw() { - * fill(value); - * rect(25, 25, 50, 50); - * describe('50-by-50 black rect turns white with touch.'); - * } + * ```js * function touchEnded() { - * if (value === 0) { - * value = 255; - * } else { - * value = 0; - * } + * // Code to run. * } - * - *
+ * ``` * - *
- * + * The touches array will be updated with the most + * recent touch points when `touchEnded()` is called by p5.js: + * + * ```js * function touchEnded() { - * ellipse(mouseX, mouseY, 5, 5); - * // prevent default - * return false; + * // Paint over the background. + * background(200); + * + * // Mark each remaining touch point when the user stops + * // a touch. + * for (let touch of touches) { + * circle(touch.x, touch.y, 40); + * } * } - * describe('no image displayed'); - * - *
+ * ``` * - *
- * - * // returns a TouchEvent object - * // as a callback argument + * The parameter, event, is optional. `touchEnded()` will be passed a + * TouchEvent + * object with properties that describe the touch event: + * + * ```js * function touchEnded(event) { + * // Code to run that uses the event. * console.log(event); * } - * describe('no image displayed'); + * ``` + * + * On touchscreen devices, mouseReleased() will + * run when the user’s touch ends if `touchEnded()` isn’t declared. If + * `touchEnded()` is declared, then `touchEnded()` will run when a user’s + * touch ends and mouseReleased() won’t. + * + * Note: touchStarted(), + * `touchEnded()`, and touchMoved() are all + * related. touchStarted() runs as soon as the + * user touches a touchscreen device. `touchEnded()` runs as soon as the user + * ends a touch. touchMoved() runs repeatedly as + * the user moves any touch points. + * + * @method touchEnded + * @param {TouchEvent} [event] optional `TouchEvent` argument. + * + * @example + *
+ * + * // On a touchscreen device, touch the canvas using one or more fingers + * // at the same time. + * + * let value = 0; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with a black square at its center. The inner square switches color between black and white each time the user stops touching the screen.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Style the square. + * fill(value); + * + * // Draw the square. + * square(25, 25, 50); + * } + * + * // Toggle colors when a touch ends. + * function touchEnded() { + * if (value === 0) { + * value = 255; + * } else { + * value = 0; + * } + * } + * + *
+ * + *
+ * + * // On a touchscreen device, touch the canvas using one or more fingers + * // at the same time. + * + * let bgColor = 50; + * let fillColor = 255; + * let borderWidth = 0.5; + * + * function setup() { + * createCanvas(100, 100); + * + * describe( + * 'A gray square with the number 0 at the top-center. The number tracks the number of places the user is touching the screen. Circles appear at each touch point and change style in response to events.' + * ); + * } + * + * function draw() { + * background(bgColor); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * fill(0); + * noStroke(); + * + * // Display the number of touch points. + * text(touches.length, 50, 20); + * + * // Style the touch points. + * fill(fillColor); + * stroke(0); + * strokeWeight(borderWidth); + * + * // Display the touch points as circles. + * for (let touch of touches) { + * circle(touch.x, touch.y, 40); + * } + * } + * + * // Set the background color to a random grayscale value. + * function touchStarted() { + * bgColor = random(80, 255); + * } + * + * // Set the fill color to a random grayscale value. + * function touchEnded() { + * fillColor = random(0, 255); + * } + * + * // Set the stroke weight. + * function touchMoved() { + * // Increment the border width. + * borderWidth += 0.1; + * + * // Reset the border width once it's too thick. + * if (borderWidth > 20) { + * borderWidth = 0.5; + * } + * } * *
*/ @@ -82523,23 +92574,17 @@ if (executeDefault === false) { e.preventDefault(); } - } else if (typeof context.mouseReleased === 'function') { - executeDefault = context.mouseReleased(e); - if (executeDefault === false) { - e.preventDefault(); - } + this.touchend = true; } }; var _default = _main.default; exports.default = _default; }, { - '../core/main': 298, - 'core-js/modules/es.array.includes': 177, - 'core-js/modules/es.string.includes': 209 + '../core/main': 306 } ], - 319: [ + 327: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.array.iterator'); @@ -82652,16 +92697,16 @@ } }, /** - * Returns a 32-bit number containing ARGB data at the ith pixel in the - * 1D array containing pixels data. - * - * @private - * - * @param {Uint8ClampedArray} data array returned by _toPixels() - * @param {Integer} i index of a 1D Image Array - * @return {Integer} 32-bit integer value representing - * ARGB value. - */ + * Returns a 32-bit number containing ARGB data at the ith pixel in the + * 1D array containing pixels data. + * + * @private + * + * @param {Uint8ClampedArray} data array returned by _toPixels() + * @param {Integer} i index of a 1D Image Array + * @return {Integer} 32-bit integer value representing + * ARGB value. + */ _getARGB: function _getARGB(data, i) { // Determine the starting position in the 'data' array for the 'i'-th pixel. var offset = i * 4; @@ -82673,14 +92718,14 @@ ); }, /** - * Modifies pixels RGBA values to values contained in the data object. - * - * @private - * - * @param {Uint8ClampedArray} pixels array returned by _toPixels() - * @param {Int32Array} data source 1D array where each value - * represents ARGB values - */ + * Modifies pixels RGBA values to values contained in the data object. + * + * @private + * + * @param {Uint8ClampedArray} pixels array returned by _toPixels() + * @param {Int32Array} data source 1D array where each value + * represents ARGB values + */ _setPixels: function _setPixels(pixels, data) { var offset = 0; for (var i = 0, al = pixels.length; i < al; i++) { @@ -82692,15 +92737,15 @@ } }, /** - * Returns the ImageData object for a canvas. - * https://developer.mozilla.org/en-US/docs/Web/API/ImageData - * - * @private - * - * @param {Canvas|ImageData} canvas canvas to get image data from - * @return {ImageData} Holder of pixel data (and width and - * height) for a canvas - */ + * Returns the ImageData object for a canvas. + * https://developer.mozilla.org/en-US/docs/Web/API/ImageData + * + * @private + * + * @param {Canvas|ImageData} canvas canvas to get image data from + * @return {ImageData} Holder of pixel data (and width and + * height) for a canvas + */ _toImageData: function _toImageData(canvas) { if (canvas instanceof ImageData) { return canvas; @@ -82709,38 +92754,38 @@ } }, /** - * Returns a blank ImageData object. - * - * @private - * - * @param {Integer} width - * @param {Integer} height - * @return {ImageData} - */ + * Returns a blank ImageData object. + * + * @private + * + * @param {Integer} width + * @param {Integer} height + * @return {ImageData} + */ _createImageData: function _createImageData(width, height) { Filters._tmpCanvas = document.createElement('canvas'); Filters._tmpCtx = Filters._tmpCanvas.getContext('2d'); return this._tmpCtx.createImageData(width, height); }, /** - * Applys a filter function to a canvas. - * - * The difference between this and the actual filter functions defined below - * is that the filter functions generally modify the pixel buffer but do - * not actually put that data back to the canvas (where it would actually - * update what is visible). By contrast this method does make the changes - * actually visible in the canvas. - * - * The apply method is the method that callers of this module would generally - * use. It has been separated from the actual filters to support an advanced - * use case of creating a filter chain that executes without actually updating - * the canvas in between everystep. - * - * @private - * @param {HTMLCanvasElement} canvas The input canvas to apply the filter on. - * @param {function(ImageData,Object)} func The filter function to apply to the canvas's pixel data. - * @param {Object} filterParam An optional parameter to pass to the filter function. - */ + * Applys a filter function to a canvas. + * + * The difference between this and the actual filter functions defined below + * is that the filter functions generally modify the pixel buffer but do + * not actually put that data back to the canvas (where it would actually + * update what is visible). By contrast this method does make the changes + * actually visible in the canvas. + * + * The apply method is the method that callers of this module would generally + * use. It has been separated from the actual filters to support an advanced + * use case of creating a filter chain that executes without actually updating + * the canvas in between everystep. + * + * @private + * @param {HTMLCanvasElement} canvas The input canvas to apply the filter on. + * @param {function(ImageData,Object)} func The filter function to apply to the canvas's pixel data. + * @param {Object} filterParam An optional parameter to pass to the filter function. + */ apply: function apply(canvas, func, filterParam) { var pixelsState = canvas.getContext('2d'); var imageData = pixelsState.getImageData(0, 0, canvas.width, canvas.height); @@ -82756,25 +92801,23 @@ } }, /* - * Filters - */ + * Filters + */ /** - * Converts the image to black and white pixels depending if they are above or - * below the threshold defined by the level parameter. The parameter must be - * between 0.0 (black) and 1.0 (white). If no level is specified, 0.5 is used. - * - * Borrowed from http://www.html5rocks.com/en/tutorials/canvas/imagefilters/ - * - * @private - * @param {Canvas} canvas Canvas to apply thershold filter on. - * @param {Float} level Threshold level (0-1). - */ - threshold: function threshold(canvas, level) { + * Converts the image to black and white pixels depending if they are above or + * below the threshold defined by the level parameter. The parameter must be + * between 0.0 (black) and 1.0 (white). If no level is specified, 0.5 is used. + * + * Borrowed from http://www.html5rocks.com/en/tutorials/canvas/imagefilters/ + * + * @private + * @param {Canvas} canvas Canvas to apply thershold filter on. + * @param {Float} level Threshold level (0-1). + */ + threshold: function threshold(canvas) { + var level = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0.5; var pixels = Filters._toPixels(canvas); - if (level === undefined) { - level = 0.5; - } // Calculate threshold value on a (0-255) scale. - + // Calculate threshold value on a (0-255) scale. var thresh = Math.floor(level * 255); for (var i = 0; i < pixels.length; i += 4) { var r = pixels[i]; @@ -82792,14 +92835,14 @@ } }, /** - * Converts any colors in the image to grayscale equivalents. - * No parameter is used. - * - * Borrowed from http://www.html5rocks.com/en/tutorials/canvas/imagefilters/ - * - * @private - * @param {Canvas} canvas Canvas to apply gray filter on. - */ + * Converts any colors in the image to grayscale equivalents. + * No parameter is used. + * + * Borrowed from http://www.html5rocks.com/en/tutorials/canvas/imagefilters/ + * + * @private + * @param {Canvas} canvas Canvas to apply gray filter on. + */ gray: function gray(canvas) { var pixels = Filters._toPixels(canvas); for (var i = 0; i < pixels.length; i += 4) { @@ -82812,11 +92855,11 @@ } }, /** - * Sets the alpha channel to entirely opaque. No parameter is used. - * - * @private - * @param {Canvas} canvas - */ + * Sets the alpha channel to entirely opaque. No parameter is used. + * + * @private + * @param {Canvas} canvas + */ opaque: function opaque(canvas) { var pixels = Filters._toPixels(canvas); for (var i = 0; i < pixels.length; i += 4) { @@ -82825,10 +92868,10 @@ return pixels; }, /** - * Sets each pixel to its inverse value. No parameter is used. - * @private - * @param {Canvas} canvas - */ + * Sets each pixel to its inverse value. No parameter is used. + * @private + * @param {Canvas} canvas + */ invert: function invert(canvas) { var pixels = Filters._toPixels(canvas); for (var i = 0; i < pixels.length; i += 4) { @@ -82838,21 +92881,19 @@ } }, /** - * Limits each channel of the image to the number of colors specified as - * the parameter. The parameter can be set to values between 2 and 255, but - * results are most noticeable in the lower ranges. - * - * Adapted from java based processing implementation - * - * @private - * @param {Canvas} canvas - * @param {Integer} level - */ - posterize: function posterize(canvas, level) { + * Limits each channel of the image to the number of colors specified as + * the parameter. The parameter can be set to values between 2 and 255, but + * results are most noticeable in the lower ranges. + * + * Adapted from java based processing implementation + * + * @private + * @param {Canvas} canvas + * @param {Integer} level + */ + posterize: function posterize(canvas) { + var level = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 4; var pixels = Filters._toPixels(canvas); - if (level === undefined) { - level = 4; - } if (level < 2 || level > 255) { throw new Error('Level must be greater than 2 and less than 255 for posterize'); } @@ -82868,10 +92909,10 @@ } }, /** - * Increases the bright areas in an image. - * @private - * @param {Canvas} canvas - */ + * Increases the bright areas in an image. + * @private + * @param {Canvas} canvas + */ dilate: function dilate(canvas) { var pixels = Filters._toPixels(canvas); var currIdx = 0; @@ -82953,11 +92994,11 @@ Filters._setPixels(pixels, out); }, /** - * Reduces the bright areas in an image. - * Similar to `dilate()`, but updates the output color based on the lowest luminance value. - * @private - * @param {Canvas} canvas - */ + * Reduces the bright areas in an image. + * Similar to `dilate()`, but updates the output color based on the lowest luminance value. + * @private + * @param {Canvas} canvas + */ erode: function erode(canvas) { var pixels = Filters._toPixels(canvas); var currIdx = 0; @@ -83198,36 +93239,36 @@ exports.default = _default; }, { - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.typed-array.copy-within': 223, - 'core-js/modules/es.typed-array.every': 224, - 'core-js/modules/es.typed-array.fill': 225, - 'core-js/modules/es.typed-array.filter': 226, - 'core-js/modules/es.typed-array.find': 228, - 'core-js/modules/es.typed-array.find-index': 227, - 'core-js/modules/es.typed-array.for-each': 231, - 'core-js/modules/es.typed-array.includes': 232, - 'core-js/modules/es.typed-array.index-of': 233, - 'core-js/modules/es.typed-array.int32-array': 235, - 'core-js/modules/es.typed-array.iterator': 236, - 'core-js/modules/es.typed-array.join': 237, - 'core-js/modules/es.typed-array.last-index-of': 238, - 'core-js/modules/es.typed-array.map': 239, - 'core-js/modules/es.typed-array.reduce': 241, - 'core-js/modules/es.typed-array.reduce-right': 240, - 'core-js/modules/es.typed-array.reverse': 242, - 'core-js/modules/es.typed-array.set': 243, - 'core-js/modules/es.typed-array.slice': 244, - 'core-js/modules/es.typed-array.some': 245, - 'core-js/modules/es.typed-array.sort': 246, - 'core-js/modules/es.typed-array.subarray': 247, - 'core-js/modules/es.typed-array.to-locale-string': 248, - 'core-js/modules/es.typed-array.to-string': 249, - 'core-js/modules/es.typed-array.uint8-array': 252 + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.typed-array.copy-within': 231, + 'core-js/modules/es.typed-array.every': 232, + 'core-js/modules/es.typed-array.fill': 233, + 'core-js/modules/es.typed-array.filter': 234, + 'core-js/modules/es.typed-array.find': 236, + 'core-js/modules/es.typed-array.find-index': 235, + 'core-js/modules/es.typed-array.for-each': 239, + 'core-js/modules/es.typed-array.includes': 240, + 'core-js/modules/es.typed-array.index-of': 241, + 'core-js/modules/es.typed-array.int32-array': 243, + 'core-js/modules/es.typed-array.iterator': 244, + 'core-js/modules/es.typed-array.join': 245, + 'core-js/modules/es.typed-array.last-index-of': 246, + 'core-js/modules/es.typed-array.map': 247, + 'core-js/modules/es.typed-array.reduce': 249, + 'core-js/modules/es.typed-array.reduce-right': 248, + 'core-js/modules/es.typed-array.reverse': 250, + 'core-js/modules/es.typed-array.set': 251, + 'core-js/modules/es.typed-array.slice': 252, + 'core-js/modules/es.typed-array.some': 253, + 'core-js/modules/es.typed-array.sort': 254, + 'core-js/modules/es.typed-array.subarray': 255, + 'core-js/modules/es.typed-array.to-locale-string': 256, + 'core-js/modules/es.typed-array.to-string': 257, + 'core-js/modules/es.typed-array.uint8-array': 260 } ], - 320: [ + 328: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -83355,10 +93396,9 @@ * for drawing images to the main display canvas. */ /** - * Creates a new p5.Image object. The new image is - * transparent by default. + * Creates a new p5.Image object. * - * `createImage()` uses the `width` and `height` paremeters to set the new + * `createImage()` uses the `width` and `height` parameters to set the new * p5.Image object's dimensions in pixels. The new * p5.Image can be modified by updating its * pixels array or by calling its @@ -83369,65 +93409,122 @@ * updatePixels() method must be called * for updates to take effect. * + * Note: The new p5.Image object is transparent by + * default. + * * @method createImage * @param {Integer} width width in pixels. * @param {Integer} height height in pixels. * @return {p5.Image} new p5.Image object. + * * @example *
* - * let img = createImage(66, 66); - * img.loadPixels(); - * for (let x = 0; x < img.width; x += 1) { - * for (let y = 0; y < img.height; y += 1) { - * img.set(x, y, 0); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.Image object. + * let img = createImage(66, 66); + * + * // Load the image's pixels into memory. + * img.loadPixels(); + * + * // Set all the image's pixels to black. + * for (let x = 0; x < img.width; x += 1) { + * for (let y = 0; y < img.height; y += 1) { + * img.set(x, y, 0); + * } * } - * } - * img.updatePixels(); - * image(img, 17, 17); * - * describe('A black square drawn in the middle of a gray square.'); + * // Update the image's pixel values. + * img.updatePixels(); + * + * // Draw the image. + * image(img, 17, 17); + * + * describe('A black square drawn in the middle of a gray square.'); + * } * *
* *
* - * let img = createImage(66, 66); - * img.loadPixels(); - * for (let x = 0; x < img.width; x += 1) { - * for (let y = 0; y < img.height; y += 1) { - * let a = map(x, 0, img.width, 0, 255); - * let c = color(0, a); - * img.set(x, y, c); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.Image object. + * let img = createImage(66, 66); + * + * // Load the image's pixels into memory. + * img.loadPixels(); + * + * // Create a color gradient. + * for (let x = 0; x < img.width; x += 1) { + * for (let y = 0; y < img.height; y += 1) { + * // Calculate the transparency. + * let a = map(x, 0, img.width, 0, 255); + * + * // Create a p5.Color object. + * let c = color(0, a); + * + * // Set the pixel's color. + * img.set(x, y, c); + * } * } - * } - * img.updatePixels(); - * image(img, 17, 17); * - * describe('A square with a horizontal color gradient that transitions from gray to black.'); + * // Update the image's pixels. + * img.updatePixels(); + * + * // Display the image. + * image(img, 17, 17); + * + * describe('A square with a horizontal color gradient that transitions from gray to black.'); + * } * *
* *
* - * let img = createImage(66, 66); - * img.loadPixels(); - * let d = pixelDensity(); - * let halfImage = 4 * (d * img.width) * (d * img.height / 2); - * for (let i = 0; i < halfImage; i += 4) { - * // Red. - * img.pixels[i] = 0; - * // Green. - * img.pixels[i + 1] = 0; - * // Blue. - * img.pixels[i + 2] = 0; - * // Alpha. - * img.pixels[i + 3] = 255; - * } - * img.updatePixels(); - * image(img, 17, 17); + * function setup() { + * createCanvas(100, 100); * - * describe('A black square drawn in the middle of a gray square.'); + * background(200); + * + * // Create a p5.Image object. + * let img = createImage(66, 66); + * + * // Load the pixels into memory. + * img.loadPixels(); + * // Get the current pixel density. + * let d = pixelDensity(); + * + * // Calculate the pixel that is halfway through the image's pixel array. + * let halfImage = 4 * (d * img.width) * (d * img.height / 2); + * + * // Set half of the image's pixels to black. + * for (let i = 0; i < halfImage; i += 4) { + * // Red. + * img.pixels[i] = 0; + * // Green. + * img.pixels[i + 1] = 0; + * // Blue. + * img.pixels[i + 2] = 0; + * // Alpha. + * img.pixels[i + 3] = 255; + * } + * + * // Update the image's pixels. + * img.updatePixels(); + * + * // Display the image. + * image(img, 17, 17); + * + * describe('A black square drawn in the middle of a gray square.'); + * } * *
*/ @@ -83437,14 +93534,28 @@ return new _main.default.Image(width, height); }; /** - * Saves the current canvas as an image. The browser will either save the - * file immediately or prompt the user with a dialogue window. + * Saves the current canvas as an image. + * + * By default, `saveCanvas()` saves the canvas as a PNG image called + * `untitled.png`. + * + * The first parameter, `filename`, is optional. It's a string that sets the + * file's name. If a file extension is included, as in + * `saveCanvas('drawing.png')`, then the image will be saved using that + * format. + * + * The second parameter, `extension`, is also optional. It sets the files format. + * Either `'png'`, `'webp'`, or `'jpg'` can be used. For example, `saveCanvas('drawing', 'jpg')` + * saves the canvas to a file called `drawing.jpg`. + * + * Note: The browser will either save the file immediately or prompt the user + * with a dialogue window. * * @method saveCanvas * @param {p5.Framebuffer|p5.Element|HTMLCanvasElement} selectedCanvas reference to a * specific HTML5 canvas element. * @param {String} [filename] file name. Defaults to 'untitled'. - * @param {String} [extension] file extension, either 'jpg' or 'png'. Defaults to 'png'. + * @param {String} [extension] file extension, either 'png', 'webp', or 'jpg'. Defaults to 'png'. * * @example *
@@ -83452,7 +93563,11 @@ * function setup() { * createCanvas(100, 100); * background(255); + * + * // Save the canvas to 'untitled.png'. * saveCanvas(); + * + * describe('A white square.'); * } * *
@@ -83461,8 +93576,13 @@ * * function setup() { * createCanvas(100, 100); + * * background(255); + * + * // Save the canvas to 'myCanvas.jpg'. * saveCanvas('myCanvas.jpg'); + * + * describe('A white square.'); * } * *
@@ -83471,8 +93591,13 @@ * * function setup() { * createCanvas(100, 100); + * * background(255); + * + * // Save the canvas to 'myCanvas.jpg'. * saveCanvas('myCanvas', 'jpg'); + * + * describe('A white square.'); * } * *
@@ -83481,8 +93606,13 @@ * * function setup() { * let cnv = createCanvas(100, 100); + * * background(255); + * + * // Save the canvas to 'untitled.png'. * saveCanvas(cnv); + * + * describe('A white square.'); * } * *
@@ -83491,8 +93621,13 @@ * * function setup() { * let cnv = createCanvas(100, 100); + * * background(255); + * + * // Save the canvas to 'myCanvas.jpg'. * saveCanvas(cnv, 'myCanvas.jpg'); + * + * describe('A white square.'); * } * *
@@ -83501,8 +93636,13 @@ * * function setup() { * let cnv = createCanvas(100, 100); + * * background(255); + * + * // Save the canvas to 'myCanvas.jpg'. * saveCanvas(cnv, 'myCanvas', 'jpg'); + * + * describe('A white square.'); * } * *
@@ -83513,22 +93653,23 @@ * @param {String} [extension] */ _main.default.prototype.saveCanvas = function () { - _main.default._validateParameters('saveCanvas', arguments); + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + _main.default._validateParameters('saveCanvas', args); // copy arguments to array - var args = [ - ].slice.call(arguments); var htmlCanvas, filename, extension, temporaryGraphics; - if (arguments[0] instanceof HTMLCanvasElement) { - htmlCanvas = arguments[0]; + if (args[0] instanceof HTMLCanvasElement) { + htmlCanvas = args[0]; args.shift(); - } else if (arguments[0] instanceof _main.default.Element) { - htmlCanvas = arguments[0].elt; + } else if (args[0] instanceof _main.default.Element) { + htmlCanvas = args[0].elt; args.shift(); - } else if (arguments[0] instanceof _main.default.Framebuffer) { - var framebuffer = arguments[0]; + } else if (args[0] instanceof _main.default.Framebuffer) { + var framebuffer = args[0]; temporaryGraphics = this.createGraphics(framebuffer.width, framebuffer.height); temporaryGraphics.pixelDensity(pixelDensity()); framebuffer.loadPixels(); @@ -83553,6 +93694,9 @@ //case 'png': mimeType = 'image/png'; break; + case 'webp': + mimeType = 'image/webp'; + break; case 'jpeg': case 'jpg': mimeType = 'image/jpeg'; @@ -83762,20 +93906,28 @@ _main.default.prototype.downloadFile(blob, filename, extension); }; /** - * Captures a sequence of frames from the canvas that can be used to create a - * movie. Frames are downloaded as individual image files by default. + * Captures a sequence of frames from the canvas that can be saved as images. + * + * `saveFrames()` creates an array of frame objects. Each frame is stored as + * an object with its file type, file name, and image data as a string. For + * example, the first saved frame might have the following properties: + * + * `{ ext: 'png', filenmame: 'frame0', imageData: 'data:image/octet-stream;base64, abc123' }`. * * The first parameter, `filename`, sets the prefix for the file names. For * example, setting the prefix to `'frame'` would generate the image files - * `frame0.png`, `frame1.png`, and so on. The second parameter, `extension`, - * sets the file type to either `'png'` or `'jpg'`. + * `frame0.png`, `frame1.png`, and so on. + * + * The second parameter, `extension`, sets the file type to either `'png'` or + * `'jpg'`. * * The third parameter, `duration`, sets the duration to record in seconds. - * The maximum duration is 15 seconds. The fourth parameter, `framerate`, sets - * the number of frames to record per second. The maximum frame rate value is - * 22. Limits are placed on `duration` and `framerate` to avoid using too much - * memory. Recording large canvases can easily crash sketches or even web - * browsers. + * The maximum duration is 15 seconds. + * + * The fourth parameter, `framerate`, sets the number of frames to record per + * second. The maximum frame rate value is 22. Limits are placed on `duration` + * and `framerate` to avoid using too much memory. Recording large canvases + * can easily crash sketches or even web browsers. * * The fifth parameter, `callback`, is optional. If a function is passed, * image files won't be saved by default. The callback function can be used @@ -83783,6 +93935,8 @@ * of image data contains a sequence of objects with three properties for each * frame: `imageData`, `filename`, and `extension`. * + * Note: Frames are downloaded as individual image files by default. + * * @method saveFrames * @param {String} filename prefix of file name. * @param {String} extension file extension, either 'jpg' or 'png'. @@ -83797,15 +93951,20 @@ * @example *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('A square repeatedly changes color from blue to pink.'); + * } + * * function draw() { * let r = frameCount % 255; * let g = 50; * let b = 100; * background(r, g, b); - * - * describe('A square repeatedly changes color from blue to pink.'); * } * + * // Save the frames when the user presses the 's' key. * function keyPressed() { * if (key === 's') { * saveFrames('frame', 'png', 1, 5); @@ -83816,21 +93975,29 @@ * *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('A square repeatedly changes color from blue to pink.'); + * } + * * function draw() { * let r = frameCount % 255; * let g = 50; * let b = 100; * background(r, g, b); - * - * describe('A square repeatedly changes color from blue to pink.'); * } * + * // Print 5 frames when the user presses the mouse. * function mousePressed() { - * saveFrames('frame', 'png', 1, 5, data => { - * // Prints an array of objects containing raw image data, - * // filenames, and extensions. - * print(data); - * }); + * saveFrames('frame', 'png', 1, 5, printFrames); + * } + * + * // Prints an array of objects containing raw image data, filenames, and extensions. + * function printFrames(frames) { + * for (let frame of frames) { + * print(frame); + * } * } * *
@@ -83906,56 +94073,56 @@ exports.default = _default; }, { - '../core/main': 298, - 'core-js/modules/es.array.concat': 169, - 'core-js/modules/es.array.filter': 173, - 'core-js/modules/es.array.for-each': 175, - 'core-js/modules/es.array.from': 176, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.map': 182, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.object.keys': 199, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.regexp.exec': 205, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.set': 207, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.string.replace': 214, - 'core-js/modules/es.string.split': 216, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.typed-array.copy-within': 223, - 'core-js/modules/es.typed-array.every': 224, - 'core-js/modules/es.typed-array.fill': 225, - 'core-js/modules/es.typed-array.filter': 226, - 'core-js/modules/es.typed-array.find': 228, - 'core-js/modules/es.typed-array.find-index': 227, - 'core-js/modules/es.typed-array.for-each': 231, - 'core-js/modules/es.typed-array.includes': 232, - 'core-js/modules/es.typed-array.index-of': 233, - 'core-js/modules/es.typed-array.iterator': 236, - 'core-js/modules/es.typed-array.join': 237, - 'core-js/modules/es.typed-array.last-index-of': 238, - 'core-js/modules/es.typed-array.map': 239, - 'core-js/modules/es.typed-array.reduce': 241, - 'core-js/modules/es.typed-array.reduce-right': 240, - 'core-js/modules/es.typed-array.reverse': 242, - 'core-js/modules/es.typed-array.set': 243, - 'core-js/modules/es.typed-array.slice': 244, - 'core-js/modules/es.typed-array.some': 245, - 'core-js/modules/es.typed-array.sort': 246, - 'core-js/modules/es.typed-array.subarray': 247, - 'core-js/modules/es.typed-array.to-locale-string': 248, - 'core-js/modules/es.typed-array.to-string': 249, - 'core-js/modules/es.typed-array.uint32-array': 251, - 'core-js/modules/es.typed-array.uint8-array': 252, - 'core-js/modules/web.dom-collections.for-each': 255, - 'core-js/modules/web.dom-collections.iterator': 256, - 'omggif': 270 + '../core/main': 306, + 'core-js/modules/es.array.concat': 171, + 'core-js/modules/es.array.filter': 175, + 'core-js/modules/es.array.for-each': 179, + 'core-js/modules/es.array.from': 180, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.map': 186, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.object.keys': 207, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.regexp.exec': 213, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.set': 215, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.string.replace': 222, + 'core-js/modules/es.string.split': 224, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.typed-array.copy-within': 231, + 'core-js/modules/es.typed-array.every': 232, + 'core-js/modules/es.typed-array.fill': 233, + 'core-js/modules/es.typed-array.filter': 234, + 'core-js/modules/es.typed-array.find': 236, + 'core-js/modules/es.typed-array.find-index': 235, + 'core-js/modules/es.typed-array.for-each': 239, + 'core-js/modules/es.typed-array.includes': 240, + 'core-js/modules/es.typed-array.index-of': 241, + 'core-js/modules/es.typed-array.iterator': 244, + 'core-js/modules/es.typed-array.join': 245, + 'core-js/modules/es.typed-array.last-index-of': 246, + 'core-js/modules/es.typed-array.map': 247, + 'core-js/modules/es.typed-array.reduce': 249, + 'core-js/modules/es.typed-array.reduce-right': 248, + 'core-js/modules/es.typed-array.reverse': 250, + 'core-js/modules/es.typed-array.set': 251, + 'core-js/modules/es.typed-array.slice': 252, + 'core-js/modules/es.typed-array.some': 253, + 'core-js/modules/es.typed-array.sort': 254, + 'core-js/modules/es.typed-array.subarray': 255, + 'core-js/modules/es.typed-array.to-locale-string': 256, + 'core-js/modules/es.typed-array.to-string': 257, + 'core-js/modules/es.typed-array.uint32-array': 259, + 'core-js/modules/es.typed-array.uint8-array': 260, + 'core-js/modules/web.dom-collections.for-each': 263, + 'core-js/modules/web.dom-collections.iterator': 264, + 'omggif': 278 } ], - 321: [ + 329: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -84182,17 +94349,23 @@ * @param {function(Event)} [failureCallback] function called with event * error if the image fails to load. * @return {p5.Image} the p5.Image object. + * * @example *
* * let img; * + * // Load the image and create a p5.Image object. * function preload() { * img = loadImage('assets/laDefense.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Draw the image. * image(img, 0, 0); + * * describe('Image of the underside of a white umbrella and a gridded ceiling.'); * } * @@ -84201,26 +94374,36 @@ *
* * function setup() { - * loadImage('assets/laDefense.jpg', img => { - * image(img, 0, 0); - * }); + * // Call handleImage() once the image loads. + * loadImage('assets/laDefense.jpg', handleImage); + * * describe('Image of the underside of a white umbrella and a gridded ceiling.'); * } + * + * // Display the image. + * function handleImage(img) { + * image(img, 0, 0); + * } * *
* *
* * function setup() { - * loadImage('assets/laDefense.jpg', success, failure); + * // Call handleImage() once the image loads or + * // call handleError() if an error occurs. + * loadImage('assets/laDefense.jpg', handleImage, handleError); * } * - * function success(img) { + * // Display the image. + * function handleImage(img) { * image(img, 0, 0); + * * describe('Image of the underside of a white umbrella and a gridded ceiling.'); * } * - * function failure(event) { + * // Log the error. + * function handleError(event) { * console.error('Oops!', event); * } * @@ -84304,12 +94487,14 @@ return pImg; }; /** - * Generates a gif from a sketch and saves it to a file. `saveGif()` may be - * called in setup() or at any point while a sketch - * is running. + * Generates a gif from a sketch and saves it to a file. + * + * `saveGif()` may be called in setup() or at any + * point while a sketch is running. * - * The first parameter, `fileName`, sets the gif's file name. The second - * parameter, `duration`, sets the gif's duration in seconds. + * The first parameter, `fileName`, sets the gif's file name. + * + * The second parameter, `duration`, sets the gif's duration in seconds. * * The third parameter, `options`, is optional. If an object is passed, * `saveGif()` will use its properties to customize the gif. `saveGif()` @@ -84330,18 +94515,56 @@ * @example *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('A circle drawn in the middle of a gray square. The circle changes color from black to white, then repeats.'); + * } + * * function draw() { * background(200); + * + * // Style the circle. * let c = frameCount % 255; * fill(c); + * + * // Display the circle. * circle(50, 50, 25); + * } + * + * // Save a 5-second gif when the user presses the 's' key. + * function keyPressed() { + * if (key === 's') { + * saveGif('mySketch', 5); + * } + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); * * describe('A circle drawn in the middle of a gray square. The circle changes color from black to white, then repeats.'); * } * + * function draw() { + * background(200); + * + * // Style the circle. + * let c = frameCount % 255; + * fill(c); + * + * // Display the circle. + * circle(50, 50, 25); + * } + * + * // Save a 5-second gif when the user presses the 's' key. + * // Wait 1 second after the key press before recording. * function keyPressed() { * if (key === 's') { - * saveGif('mySketch', 5); + * saveGif('mySketch', 5, { delay: 1 }); * } * } * @@ -84511,7 +94734,7 @@ if (this._renderer instanceof _main.default.RendererGL) { pixels = new Uint8Array(gl.drawingBufferWidth * gl.drawingBufferHeight * 4); gl.readPixels(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight, gl.RGBA, gl.UNSIGNED_BYTE, pixels); - data = _flipPixels(pixels); + data = _flipPixels(pixels, this.width, this.height); } else { data = this.drawingContext.getImageData(0, 0, this.width, this.height).data; } @@ -84633,7 +94856,7 @@ return _ref.apply(this, arguments); }; }(); - function _flipPixels(pixels) { + function _flipPixels(pixels, width, height) { // extracting the pixels using readPixels returns // an upside down image. we have to flip it back // first. this solution is proposed by gman on @@ -84921,12 +95144,19 @@ return iVal; } } /** - * Draws a source image to the canvas. + * Draws an image to the canvas. + * + * The first parameter, `img`, is the source image to be drawn. `img` can be + * any of the following objects: + * - p5.Image + * - p5.Element + * - p5.Texture + * - p5.Framebuffer + * - p5.FramebufferTexture * - * The first parameter, `img`, is the source image to be drawn. The second and - * third parameters, `dx` and `dy`, set the coordinates of the destination - * image's top left corner. See imageMode() for - * other ways to position images. + * The second and third parameters, `dx` and `dy`, set the coordinates of the + * destination image's top left corner. See + * imageMode() for other ways to position images. * * Here's a diagram that explains how optional parameters work in `image()`: * @@ -84943,7 +95173,7 @@ * The eighth and ninth parameters, `sw` and `sh`, are also optional. * They define the width and height of a subsection to draw from the source * image. By default, `image()` draws the full subsection that begins at - * (`sx`, `sy`) and extends to the edges of the source image. + * `(sx, sy)` and extends to the edges of the source image. * * The ninth parameter, `fit`, is also optional. It enables a subsection of * the source image to be drawn without affecting its aspect ratio. If @@ -84964,17 +95194,23 @@ * @param {Number} y y-coordinate of the top-left corner of the image. * @param {Number} [width] width to draw the image. * @param {Number} [height] height to draw the image. + * * @example *
* * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/laDefense.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * * background(50); + * + * // Draw the image. * image(img, 0, 0); * * describe('An image of the underside of a white umbrella with a gridded ceiling above.'); @@ -84986,12 +95222,17 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/laDefense.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * * background(50); + * + * // Draw the image. * image(img, 10, 10); * * describe('An image of the underside of a white umbrella with a gridded ceiling above. The image has dark gray borders on its left and top.'); @@ -85003,12 +95244,17 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/laDefense.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * * background(50); + * + * // Draw the image 50x50. * image(img, 0, 0, 50, 50); * * describe('An image of the underside of a white umbrella with a gridded ceiling above. The image is drawn in the top left corner of a dark gray square.'); @@ -85020,12 +95266,17 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/laDefense.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * * background(50); + * + * // Draw the center of the image. * image(img, 25, 25, 50, 50, 25, 25, 50, 50); * * describe('An image of a gridded ceiling drawn in the center of a dark gray square.'); @@ -85037,12 +95288,17 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/moonwalk.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * * background(50); + * + * // Draw the image and scale it to fit within the canvas. * image(img, 0, 0, width, height, 0, 0, img.width, img.height, CONTAIN); * * describe('An image of an astronaut on the moon. The top and bottom borders of the image are dark gray.'); @@ -85054,13 +95310,18 @@ * * let img; * + * // Load the image. * function preload() { * // Image is 50 x 50 pixels. * img = loadImage('assets/laDefense50.png'); * } * * function setup() { + * createCanvas(100, 100); + * * background(50); + * + * // Draw the image and scale it to cover the canvas. * image(img, 0, 0, width, height, 0, 0, img.width, img.height, COVER); * * describe('A pixelated image of the underside of a white umbrella with a gridded ceiling above.'); @@ -85142,7 +95403,7 @@ this._renderer.image(img, vals.sx, vals.sy, vals.sw, vals.sh, vals.dx, vals.dy, vals.dw, vals.dh); }; /** - * Tints images using a specified color. + * Tints images using a color. * * The version of `tint()` with one parameter interprets it one of four ways. * If the parameter is a number, it's interpreted as a grayscale value. If the @@ -85171,12 +95432,19 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/laDefense.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Left image. * image(img, 0, 0); + * + * // Right image. + * // Tint with a CSS color string. * tint('red'); * image(img, 50, 0); * @@ -85189,12 +95457,19 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/laDefense.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Left image. * image(img, 0, 0); + * + * // Right image. + * // Tint with RGB values. * tint(255, 0, 0); * image(img, 50, 0); * @@ -85207,12 +95482,19 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/laDefense.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Left. * image(img, 0, 0); + * + * // Right. + * // Tint with RGBA values. * tint(255, 0, 0, 100); * image(img, 50, 0); * @@ -85225,12 +95507,19 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/laDefense.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Left. * image(img, 0, 0); + * + * // Right. + * // Tint with grayscale and alpha values. * tint(255, 180); * image(img, 50, 0); * @@ -85266,21 +95555,32 @@ this._renderer._tint = c.levels; }; /** - * Removes the current tint set by tint() and restores - * images to their original colors. + * Removes the current tint set by tint(). + * + * `noTint()` restores images to their original colors. * * @method noTint + * * @example *
* * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/laDefense.jpg'); * } + * * function setup() { + * createCanvas(100, 100); + * + * // Left. + * // Tint with a CSS color string. * tint('red'); * image(img, 0, 0); + * + * // Right. + * // Remove the tint. * noTint(); * image(img, 50, 0); * @@ -85321,19 +95621,27 @@ * * @method imageMode * @param {Constant} mode either CORNER, CORNERS, or CENTER. + * * @example * *
* * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/bricks.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * * background(200); + * + * // Use CORNER mode. * imageMode(CORNER); + * + * // Display the image. * image(img, 10, 10, 50, 50); * * describe('A square image of a brick wall is drawn at the top left of a gray square.'); @@ -85345,13 +95653,20 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/bricks.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * * background(200); + * + * // Use CORNERS mode. * imageMode(CORNERS); + * + * // Display the image. * image(img, 10, 10, 90, 40); * * describe('An image of a brick wall is drawn on a gray square. The image is squeezed into a small rectangular area.'); @@ -85363,13 +95678,20 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/bricks.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * * background(200); + * + * // Use CENTER mode. * imageMode(CENTER); + * + * // Display the image. * image(img, 50, 50, 80, 80); * * describe('A square image of a brick wall is drawn on a gray square.'); @@ -85387,59 +95709,59 @@ exports.default = _default; }, { - '../core/constants': 286, - '../core/friendly_errors/fes_core': 289, - '../core/friendly_errors/file_errors': 290, - '../core/friendly_errors/validate_params': 293, - '../core/helpers': 294, - '../core/main': 298, - 'core-js/modules/es.array.copy-within': 170, - 'core-js/modules/es.array.includes': 177, - 'core-js/modules/es.array.index-of': 178, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.promise': 201, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.string.includes': 209, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.typed-array.copy-within': 223, - 'core-js/modules/es.typed-array.every': 224, - 'core-js/modules/es.typed-array.fill': 225, - 'core-js/modules/es.typed-array.filter': 226, - 'core-js/modules/es.typed-array.find': 228, - 'core-js/modules/es.typed-array.find-index': 227, - 'core-js/modules/es.typed-array.for-each': 231, - 'core-js/modules/es.typed-array.includes': 232, - 'core-js/modules/es.typed-array.index-of': 233, - 'core-js/modules/es.typed-array.iterator': 236, - 'core-js/modules/es.typed-array.join': 237, - 'core-js/modules/es.typed-array.last-index-of': 238, - 'core-js/modules/es.typed-array.map': 239, - 'core-js/modules/es.typed-array.reduce': 241, - 'core-js/modules/es.typed-array.reduce-right': 240, - 'core-js/modules/es.typed-array.reverse': 242, - 'core-js/modules/es.typed-array.set': 243, - 'core-js/modules/es.typed-array.slice': 244, - 'core-js/modules/es.typed-array.some': 245, - 'core-js/modules/es.typed-array.sort': 246, - 'core-js/modules/es.typed-array.subarray': 247, - 'core-js/modules/es.typed-array.to-locale-string': 248, - 'core-js/modules/es.typed-array.to-string': 249, - 'core-js/modules/es.typed-array.uint8-array': 252, - 'core-js/modules/es.typed-array.uint8-clamped-array': 253, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256, - 'gifenc': 263, - 'omggif': 270, - 'regenerator-runtime/runtime': 274 + '../core/constants': 294, + '../core/friendly_errors/fes_core': 297, + '../core/friendly_errors/file_errors': 298, + '../core/friendly_errors/validate_params': 301, + '../core/helpers': 302, + '../core/main': 306, + 'core-js/modules/es.array.copy-within': 172, + 'core-js/modules/es.array.includes': 181, + 'core-js/modules/es.array.index-of': 182, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.promise': 209, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.string.includes': 217, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.typed-array.copy-within': 231, + 'core-js/modules/es.typed-array.every': 232, + 'core-js/modules/es.typed-array.fill': 233, + 'core-js/modules/es.typed-array.filter': 234, + 'core-js/modules/es.typed-array.find': 236, + 'core-js/modules/es.typed-array.find-index': 235, + 'core-js/modules/es.typed-array.for-each': 239, + 'core-js/modules/es.typed-array.includes': 240, + 'core-js/modules/es.typed-array.index-of': 241, + 'core-js/modules/es.typed-array.iterator': 244, + 'core-js/modules/es.typed-array.join': 245, + 'core-js/modules/es.typed-array.last-index-of': 246, + 'core-js/modules/es.typed-array.map': 247, + 'core-js/modules/es.typed-array.reduce': 249, + 'core-js/modules/es.typed-array.reduce-right': 248, + 'core-js/modules/es.typed-array.reverse': 250, + 'core-js/modules/es.typed-array.set': 251, + 'core-js/modules/es.typed-array.slice': 252, + 'core-js/modules/es.typed-array.some': 253, + 'core-js/modules/es.typed-array.sort': 254, + 'core-js/modules/es.typed-array.subarray': 255, + 'core-js/modules/es.typed-array.to-locale-string': 256, + 'core-js/modules/es.typed-array.to-string': 257, + 'core-js/modules/es.typed-array.uint8-array': 260, + 'core-js/modules/es.typed-array.uint8-clamped-array': 261, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264, + 'gifenc': 271, + 'omggif': 278, + 'regenerator-runtime/runtime': 282 } ], - 322: [ + 330: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -85501,8 +95823,9 @@ * Class methods */ /** - * A class to describe an image. Images are rectangular grids of pixels that - * can be displayed and modified. + * A class to describe an image. + * + * Images are rectangular grids of pixels that can be displayed and modified. * * Existing images can be loaded by calling * loadImage(). Blank images can be created by @@ -85515,11 +95838,15 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/bricks.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Display the image. * image(img, 0, 0); * * describe('An image of a brick wall.'); @@ -85531,12 +95858,18 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/bricks.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Apply the GRAY filter. * img.filter(GRAY); + * + * // Display the image. * image(img, 0, 0); * * describe('A grayscale image of a brick wall.'); @@ -85546,18 +95879,32 @@ * *
* - * background(200); - * let img = createImage(66, 66); - * img.loadPixels(); - * for (let x = 0; x < img.width; x += 1) { - * for (let y = 0; y < img.height; y += 1) { - * img.set(x, y, 0); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.Image object. + * let img = createImage(66, 66); + * + * // Load the image's pixels. + * img.loadPixels(); + * + * // Set the pixels to black. + * for (let x = 0; x < img.width; x += 1) { + * for (let y = 0; y < img.height; y += 1) { + * img.set(x, y, 0); + * } * } - * } - * img.updatePixels(); - * image(img, 17, 17); * - * describe('A black square drawn in the middle of a gray square.'); + * // Update the image. + * img.updatePixels(); + * + * // Display the image. + * image(img, 17, 17); + * + * describe('A black square drawn in the middle of a gray square.'); + * } * *
* @@ -85571,26 +95918,35 @@ function _class(width, height) { _classCallCheck(this, _class); /** - * Image width. + * The image's width in pixels. + * * @type {Number} * @property {Number} width * @name width * @readOnly + * * @example *
* * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/rockies.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Display the image. * image(img, 0, 0); + * + * // Calculate the center coordinates. * let x = img.width / 2; * let y = img.height / 2; - * let d = 20; - * circle(x, y, d); + * + * // Draw a circle at the image's center. + * circle(x, y, 20); * * describe('An image of a mountain landscape with a white circle drawn in the middle.'); * } @@ -85599,26 +95955,35 @@ */ this.width = width; /** - * Image height. + * The image's height in pixels. + * * @type {Number} * @property height * @name height * @readOnly + * * @example *
* * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/rockies.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Display the image. * image(img, 0, 0); + * + * // Calculate the center coordinates. * let x = img.width / 2; * let y = img.height / 2; - * let d = 20; - * circle(x, y, d); + * + * // Draw a circle at the image's center. + * circle(x, y, 20); * * describe('An image of a mountain landscape with a white circle drawn in the middle.'); * } @@ -85637,10 +96002,11 @@ //For WebGL Texturing only: used to determine whether to reupload texture to GPU this._modified = false; /** - * An array containing the color of each pixel in the - * p5.Image object. Colors are stored as numbers - * representing red, green, blue, and alpha (RGBA) values. `img.pixels` is a - * one-dimensional array for performance reasons. + * An array containing the color of each pixel in the image. + * + * Colors are stored as numbers representing red, green, blue, and alpha + * (RGBA) values. `img.pixels` is a one-dimensional array for performance + * reasons. * * Each pixel occupies four elements in the pixels array, one for each * RGBA value. For example, the pixel at coordinates (0, 0) stores its @@ -85651,65 +96017,94 @@ * for a 100×100 p5.Image object has * 100 × 100 × 4 = 40,000 elements. * - * Accessing the RGBA values for a pixel in the - * p5.Image object requires a little math as - * shown below. The img.loadPixels() + * Accessing the RGBA values for a pixel in the image requires a little + * math as shown in the examples below. The + * img.loadPixels() * method must be called before accessing the `img.pixels` array. The * img.updatePixels() method must be * called after any changes are made. * * @property {Number[]} pixels * @name pixels + * * @example *
* - * let img = createImage(66, 66); - * img.loadPixels(); - * let numPixels = 4 * img.width * img.height; - * for (let i = 0; i < numPixels; i += 4) { - * // Red. - * img.pixels[i] = 0; - * // Green. - * img.pixels[i + 1] = 0; - * // Blue. - * img.pixels[i + 2] = 0; - * // Alpha. - * img.pixels[i + 3] = 255; - * } - * img.updatePixels(); - * image(img, 17, 17); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.Image object. + * let img = createImage(66, 66); + * + * // Load the image's pixels. + * img.loadPixels(); + * + * for (let i = 0; i < img.pixels.length; i += 4) { + * // Red. + * img.pixels[i] = 0; + * // Green. + * img.pixels[i + 1] = 0; + * // Blue. + * img.pixels[i + 2] = 0; + * // Alpha. + * img.pixels[i + 3] = 255; + * } + * + * // Update the image. + * img.updatePixels(); + * + * // Display the image. + * image(img, 17, 17); * - * describe('A black square drawn in the middle of a gray square.'); + * describe('A black square drawn in the middle of a gray square.'); + * } * *
* *
* - * let img = createImage(66, 66); - * img.loadPixels(); - * let numPixels = 4 * img.width * img.height; - * for (let i = 0; i < numPixels; i += 4) { - * // Red. - * img.pixels[i] = 255; - * // Green. - * img.pixels[i + 1] = 0; - * // Blue. - * img.pixels[i + 2] = 0; - * // Alpha. - * img.pixels[i + 3] = 255; - * } - * img.updatePixels(); - * image(img, 17, 17); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.Image object. + * let img = createImage(66, 66); * - * describe('A red square drawn in the middle of a gray square.'); + * // Load the image's pixels. + * img.loadPixels(); + * + * // Set the pixels to red. + * for (let i = 0; i < img.pixels.length; i += 4) { + * // Red. + * img.pixels[i] = 255; + * // Green. + * img.pixels[i + 1] = 0; + * // Blue. + * img.pixels[i + 2] = 0; + * // Alpha. + * img.pixels[i + 3] = 255; + * } + * + * // Update the image. + * img.updatePixels(); + * + * // Display the image. + * image(img, 17, 17); + * + * describe('A red square drawn in the middle of a gray square.'); + * } * *
*/ this.pixels = [ ]; } /** - * Gets or sets the pixel density for high pixel density displays. By default, - * the density will be set to 1. + * Gets or sets the pixel density for high pixel density displays. + * + * By default, the density will be set to 1. * * Call this method with no arguments to get the default density, or pass * in a number to set the density. If a non-positive number is provided, @@ -85759,7 +96154,7 @@ key: '_animateGif', value: function _animateGif(pInst) { var props = this.gifProperties; - var curTime = pInst._lastRealFrameTime; + var curTime = pInst._lastRealFrameTime || window.performance.now(); if (props.lastChangeTime === 0) { props.lastChangeTime = curTime; } @@ -85794,47 +96189,78 @@ this[prop] = value; this.setModified(true); } /** - * Loads the current value of each pixel in the - * p5.Image object into the `img.pixels` array. - * This method must be called before reading or modifying pixel values. + * Loads the current value of each pixel in the image into the `img.pixels` + * array. + * + * `img.loadPixels()` must be called before reading or modifying pixel + * values. * * @method loadPixels + * * @example *
* - * let img = createImage(66, 66); - * img.loadPixels(); - * for (let x = 0; x < img.width; x += 1) { - * for (let y = 0; y < img.height; y += 1) { - * img.set(x, y, 0); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.Image object. + * let img = createImage(66, 66); + * + * // Load the image's pixels. + * img.loadPixels(); + * + * // Set the pixels to black. + * for (let x = 0; x < img.width; x += 1) { + * for (let y = 0; y < img.height; y += 1) { + * img.set(x, y, 0); + * } * } - * } - * img.updatePixels(); - * image(img, 17, 17); * - * describe('A black square drawn in the middle of a gray square.'); + * // Update the image. + * img.updatePixels(); + * + * // Display the image. + * image(img, 17, 17); + * + * describe('A black square drawn in the middle of a gray square.'); + * } * *
* *
* - * let img = createImage(66, 66); - * img.loadPixels(); - * let numPixels = 4 * img.width * img.height; - * for (let i = 0; i < numPixels; i += 4) { - * // Red. - * img.pixels[i] = 0; - * // Green. - * img.pixels[i + 1] = 0; - * // Blue. - * img.pixels[i + 2] = 0; - * // Alpha. - * img.pixels[i + 3] = 255; - * } - * img.updatePixels(); - * image(img, 17, 17); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.Image object. + * let img = createImage(66, 66); + * + * // Load the image's pixels. + * img.loadPixels(); + * + * for (let i = 0; i < img.pixels.length; i += 4) { + * // Red. + * img.pixels[i] = 0; + * // Green. + * img.pixels[i + 1] = 0; + * // Blue. + * img.pixels[i + 2] = 0; + * // Alpha. + * img.pixels[i + 3] = 255; + * } + * + * // Update the image. + * img.updatePixels(); * - * describe('A black square drawn in the middle of a gray square.'); + * // Display the image. + * image(img, 17, 17); + * + * describe('A black square drawn in the middle of a gray square.'); + * } * *
*/ @@ -85856,12 +96282,11 @@ * img.set(). * * The optional parameters `x`, `y`, `width`, and `height` define a - * subsection of the p5.Image object to update. - * Doing so can improve performance in some cases. + * subsection of the image to update. Doing so can improve performance in + * some cases. * - * If the p5.Image object was loaded from a GIF, - * then calling `img.updatePixels()` will update the pixels in current - * frame. + * If the image was loaded from a GIF, then calling `img.updatePixels()` + * will update the pixels in current frame. * * @method updatePixels * @param {Integer} x x-coordinate of the upper-left corner @@ -85870,42 +96295,72 @@ * of the subsection to update. * @param {Integer} w width of the subsection to update. * @param {Integer} h height of the subsection to update. + * * @example *
* - * let img = createImage(66, 66); - * img.loadPixels(); - * for (let x = 0; x < img.width; x += 1) { - * for (let y = 0; y < img.height; y += 1) { - * img.set(x, y, 0); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.Image object. + * let img = createImage(66, 66); + * + * // Load the image's pixels. + * img.loadPixels(); + * + * // Set the pixels to black. + * for (let x = 0; x < img.width; x += 1) { + * for (let y = 0; y < img.height; y += 1) { + * img.set(x, y, 0); + * } * } - * } - * img.updatePixels(); - * image(img, 17, 17); * - * describe('A black square drawn in the middle of a gray square.'); + * // Update the image. + * img.updatePixels(); + * + * // Display the image. + * image(img, 17, 17); + * + * describe('A black square drawn in the middle of a gray square.'); + * } * *
* *
* - * let img = createImage(66, 66); - * img.loadPixels(); - * let numPixels = 4 * img.width * img.height; - * for (let i = 0; i < numPixels; i += 4) { - * // Red. - * img.pixels[i] = 0; - * // Green. - * img.pixels[i + 1] = 0; - * // Blue. - * img.pixels[i + 2] = 0; - * // Alpha. - * img.pixels[i + 3] = 255; - * } - * img.updatePixels(); - * image(img, 17, 17); + * function setup() { + * createCanvas(100, 100); * - * describe('A black square drawn in the middle of a gray square.'); + * background(200); + * + * // Create a p5.Image object. + * let img = createImage(66, 66); + * + * // Load the image's pixels. + * img.loadPixels(); + * + * // Set the pixels to black. + * for (let i = 0; i < img.pixels.length; i += 4) { + * // Red. + * img.pixels[i] = 0; + * // Green. + * img.pixels[i + 1] = 0; + * // Blue. + * img.pixels[i + 2] = 0; + * // Alpha. + * img.pixels[i + 3] = 255; + * } + * + * // Update the image. + * img.updatePixels(); + * + * // Display the image. + * image(img, 17, 17); + * + * describe('A black square drawn in the middle of a gray square.'); + * } * *
*/ @@ -85920,8 +96375,7 @@ _main.default.Renderer2D.prototype.updatePixels.call(this, x, y, w, h); this.setModified(true); } /** - * Gets a pixel or a region of pixels from a - * p5.Image object. + * Gets a pixel or a region of pixels from the image. * * `img.get()` is easy to use but it's not as fast as * img.pixels. Use @@ -85929,18 +96383,19 @@ * * The version of `img.get()` with no parameters returns the entire image. * - * The version of `img.get()` with two parameters interprets them as - * coordinates. It returns an array with the `[R, G, B, A]` values of the - * pixel at the given point. + * The version of `img.get()` with two parameters, as in `img.get(10, 20)`, + * interprets them as coordinates. It returns an array with the + * `[R, G, B, A]` values of the pixel at the given point. * - * The version of `img.get()` with four parameters interprets them as - * coordinates and dimensions. It returns a subsection of the canvas as a - * p5.Image object. The first two parameters are - * the coordinates for the upper-left corner of the subsection. The last two - * parameters are the width and height of the subsection. + * The version of `img.get()` with four parameters, as in + * `img,get(10, 20, 50, 90)`, interprets them as + * coordinates and dimensions. The first two parameters are the coordinates + * of the upper-left corner of the subsection. The last two parameters are + * the width and height of the subsection. It returns a subsection of the + * canvas in a new p5.Image object. * - * Use img.get() to work directly with - * p5.Image objects. + * Use `img.get()` instead of get() to work directly + * with images. * * @method get * @param {Number} x x-coordinate of the pixel. @@ -85948,19 +96403,30 @@ * @param {Number} w width of the subsection to be returned. * @param {Number} h height of the subsection to be returned. * @return {p5.Image} subsection as a p5.Image object. + * * @example *
* * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/rockies.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Display the image. * image(img, 0, 0); + * + * // Copy the image. * let img2 = get(); - * image(img2, width / 2, 0); + * + * // Display the copied image on the right. + * image(img2, 50, 0); * * describe('Two identical mountain landscapes shown side-by-side.'); * } @@ -85971,15 +96437,25 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/rockies.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Display the image. * image(img, 0, 0); + * + * // Get a pixel's color. * let c = img.get(50, 90); + * + * // Style the square using the pixel's color. * fill(c); * noStroke(); + * + * // Draw the square. * square(25, 25, 50); * * describe('A mountain landscape with an olive green square in its center.'); @@ -85991,14 +96467,22 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/rockies.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Display the image. * image(img, 0, 0); + * + * // Copy half of the image. * let img2 = img.get(0, 0, img.width / 2, img.height / 2); - * image(img2, width / 2, height / 2); + * + * // Display half of the image. + * image(img2, 50, 50); * * describe('A mountain landscape drawn on top of another mountain landscape.'); * } @@ -86032,8 +96516,7 @@ } return _main.default.Renderer2D.prototype._getPixel.apply(this, args); } /** - * Sets the color of one or more pixels within a - * p5.Image object. + * Sets the color of one or more pixels within an image. * * `img.set()` is easy to use but it's not as fast as * img.pixels. Use @@ -86053,49 +96536,91 @@ * @param {Number|Number[]|Object} a grayscale value | pixel array | * p5.Color object | * p5.Image to copy. + * * @example *
* - * let img = createImage(100, 100); - * img.set(30, 20, 0); - * img.set(85, 20, 0); - * img.set(85, 75, 0); - * img.set(30, 75, 0); - * img.updatePixels(); - * image(img, 0, 0); - * - * describe('Four black dots arranged in a square drawn on a gray background.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.Image object. + * let img = createImage(100, 100); + * + * // Set four pixels to black. + * img.set(30, 20, 0); + * img.set(85, 20, 0); + * img.set(85, 75, 0); + * img.set(30, 75, 0); + * + * // Update the image. + * img.updatePixels(); + * + * // Display the image. + * image(img, 0, 0); + * + * describe('Four black dots arranged in a square drawn on a gray background.'); + * } * *
* *
* - * let img = createImage(100, 100); - * let black = color(0); - * img.set(30, 20, black); - * img.set(85, 20, black); - * img.set(85, 75, black); - * img.set(30, 75, black); - * img.updatePixels(); - * image(img, 0, 0); - * - * describe('Four black dots arranged in a square drawn on a gray background.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.Image object. + * let img = createImage(100, 100); + * + * // Create a p5.Color object. + * let black = color(0); + * + * // Set four pixels to black. + * img.set(30, 20, black); + * img.set(85, 20, black); + * img.set(85, 75, black); + * img.set(30, 75, black); + * + * // Update the image. + * img.updatePixels(); + * + * // Display the image. + * image(img, 0, 0); + * + * describe('Four black dots arranged in a square drawn on a gray background.'); + * } * *
* *
* - * let img = createImage(66, 66); - * for (let x = 0; x < img.width; x += 1) { - * for (let y = 0; y < img.height; y += 1) { - * let c = map(x, 0, img.width, 0, 255); - * img.set(x, y, c); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.Image object. + * let img = createImage(66, 66); + * + * // Draw a color gradient. + * for (let x = 0; x < img.width; x += 1) { + * for (let y = 0; y < img.height; y += 1) { + * let c = map(x, 0, img.width, 0, 255); + * img.set(x, y, c); + * } * } - * } - * img.updatePixels(); - * image(img, 17, 17); * - * describe('A square with a horiztonal color gradient from black to white drawn on a gray background.'); + * // Update the image. + * img.updatePixels(); + * + * // Display the image. + * image(img, 17, 17); + * + * describe('A square with a horiztonal color gradient from black to white drawn on a gray background.'); + * } * *
* @@ -86103,13 +96628,21 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/rockies.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Create a p5.Image object. * let img2 = createImage(100, 100); + * + * // Set the blank image's pixels using the landscape. * img2.set(0, 0, img); + * + * // Display the second image. * image(img2, 0, 0); * * describe('An image of a mountain landscape.'); @@ -86125,26 +96658,36 @@ _main.default.Renderer2D.prototype.set.call(this, x, y, imgOrCol); this.setModified(true); } /** - * Resizes the p5.Image object to a given `width` - * and `height`. The image's original aspect ratio can be kept by passing 0 - * for either `width` or `height`. For example, calling `img.resize(50, 0)` - * on an image that was 500 × 300 pixels will resize it to - * 50 × 30 pixels. + * Resizes the image to a given width and height. + * + * The image's original aspect ratio can be kept by passing 0 for either + * `width` or `height`. For example, calling `img.resize(50, 0)` on an image + * that was 500 × 300 pixels will resize it to 50 × 30 pixels. * * @method resize * @param {Number} width resized image width. * @param {Number} height resized image height. + * * @example *
* * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/rockies.jpg'); * } - * function setup() { + * + * function setup() { + * createCanvas(100, 100); + * + * // Display the image. * image(img, 0, 0); + * + * // Resize the image. * img.resize(50, 100); + * + * // Display the resized image. * image(img, 0, 0); * * describe('Two images of a mountain landscape. One copy of the image is squeezed horizontally.'); @@ -86156,12 +96699,21 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/rockies.jpg'); * } - * function setup() { + * + * function setup() { + * createCanvas(100, 100); + * + * // Display the image. * image(img, 0, 0); + * + * // Resize the image, keeping the aspect ratio. * img.resize(0, 30); + * + * // Display the resized image. * image(img, 0, 0); * * describe('Two images of a mountain landscape. The small copy of the image covers the top-left corner of the larger image.'); @@ -86173,12 +96725,21 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/rockies.jpg'); * } - * function setup() { + * + * function setup() { + * createCanvas(100, 100); + * + * // Display the image. * image(img, 0, 0); + * + * // Resize the image, keeping the aspect ratio. * img.resize(60, 0); + * + * // Display the image. * image(img, 0, 0); * * describe('Two images of a mountain landscape. The small copy of the image covers the top-left corner of the larger image.'); @@ -86248,10 +96809,23 @@ } this.setModified(true); } /** + * Copies pixels from a source image to this image. * - * Copies pixels from a source p5.Image - * to this one. Calling `img.copy()` will scale pixels from the source - * region if it isn't the same size as the destination region. + * The first parameter, `srcImage`, is an optional + * p5.Image object to copy. If a source image isn't + * passed, then `img.copy()` can copy a region of this image to another + * region. + * + * The next four parameters, `sx`, `sy`, `sw`, and `sh` determine the region + * to copy from the source image. `(sx, sy)` is the top-left corner of the + * region. `sw` and `sh` are the region's width and height. + * + * The next four parameters, `dx`, `dy`, `dw`, and `dh` determine the region + * of this image to copy into. `(dx, dy)` is the top-left corner of the + * region. `dw` and `dh` are the region's width and height. + * + * Calling `img.copy()` will scale pixels from the source region if it isn't + * the same size as the destination region. * * @method copy * @param {p5.Image|p5.Element} srcImage source image. @@ -86269,14 +96843,21 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/rockies.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Copy one region of the image to another. * img.copy(7, 22, 10, 10, 35, 25, 50, 50); + * + * // Display the image. * image(img, 0, 0); - * // Outline copied region. + * + * // Outline the copied region. * stroke(255); * noFill(); * square(7, 22, 10); @@ -86291,15 +96872,23 @@ * let mountains; * let bricks; * + * // Load the images. * function preload() { * mountains = loadImage('assets/rockies.jpg'); * bricks = loadImage('assets/bricks.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Calculate the center of the bricks image. * let x = bricks.width / 2; * let y = bricks.height / 2; + * + * // Copy the bricks to the mountains image. * mountains.copy(bricks, 0, 0, x, y, 0, 0, x, y); + * + * // Display the mountains image. * image(mountains, 0, 0); * * describe('An image of a brick wall drawn at the top-left of an image of a mountain landscape.'); @@ -86328,10 +96917,12 @@ } _main.default.prototype.copy.apply(this, args); } /** - * Masks part of an image from displaying by loading another - * image and using its alpha channel as an alpha channel for - * this image. Masks are cumulative, once applied to an image - * object, they cannot be removed. + * Masks part of the image with another. + * + * `img.mask()` uses another p5.Image object's + * alpha channel as the alpha channel for this image. Masks are cumulative + * and can't be removed once applied. If the mask has a different + * pixel density from this image, the mask will be scaled. * * @method mask * @param {p5.Image} srcImage source image. @@ -86342,13 +96933,19 @@ * let photo; * let maskImage; * + * // Load the images. * function preload() { * photo = loadImage('assets/rockies.jpg'); * maskImage = loadImage('assets/mask2.png'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Apply the mask. * photo.mask(maskImage); + * + * // Display the image. * image(photo, 0, 0); * * describe('An image of a mountain landscape. The right side of the image has a faded patch of white.'); @@ -86366,27 +96963,28 @@ p5Image = this; } var currBlend = this.drawingContext.globalCompositeOperation; - var scaleFactor = 1; + var imgScaleFactor = this._pixelDensity; + var maskScaleFactor = 1; if (p5Image instanceof _main.default.Renderer) { - scaleFactor = p5Image._pInst._pixelDensity; + maskScaleFactor = p5Image._pInst._pixelDensity; } var copyArgs = [ p5Image, 0, 0, - scaleFactor * p5Image.width, - scaleFactor * p5Image.height, + maskScaleFactor * p5Image.width, + maskScaleFactor * p5Image.height, 0, 0, - this.width, - this.height + imgScaleFactor * this.width, + imgScaleFactor * this.height ]; this.drawingContext.globalCompositeOperation = 'destination-in'; if (this.gifProperties) { for (var i = 0; i < this.gifProperties.frames.length; i++) { this.drawingContext.putImageData(this.gifProperties.frames[i].image, 0, 0); this.copy.apply(this, copyArgs); - this.gifProperties.frames[i].image = this.drawingContext.getImageData(0, 0, this.width, this.height); + this.gifProperties.frames[i].image = this.drawingContext.getImageData(0, 0, imgScaleFactor * this.width, imgScaleFactor * this.height); } this.drawingContext.putImageData(this.gifProperties.frames[this.gifProperties.displayIndex].image, 0, 0); } else { @@ -86395,7 +96993,8 @@ this.drawingContext.globalCompositeOperation = currBlend; this.setModified(true); } /** - * Applies an image filter to the p5.Image object. + * Applies an image filter to the image. + * * The preset options are: * * `INVERT` @@ -86433,17 +97032,24 @@ * @param {Constant} filterType either THRESHOLD, GRAY, OPAQUE, INVERT, * POSTERIZE, ERODE, DILATE or BLUR. * @param {Number} [filterParam] parameter unique to each filter. + * * @example *
* * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/bricks.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Apply the INVERT filter. * img.filter(INVERT); + * + * // Display the image. * image(img, 0, 0); * * describe('A blue brick wall.'); @@ -86455,12 +97061,18 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/bricks.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Apply the GRAY filter. * img.filter(GRAY); + * + * // Display the image. * image(img, 0, 0); * * describe('A brick wall drawn in grayscale.'); @@ -86472,12 +97084,18 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/bricks.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Apply the THRESHOLD filter. * img.filter(THRESHOLD); + * + * // Display the image. * image(img, 0, 0); * * describe('A brick wall drawn in black and white.'); @@ -86489,12 +97107,18 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/bricks.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Apply the OPAQUE filter. * img.filter(OPAQUE); + * + * // Display the image. * image(img, 0, 0); * * describe('A red brick wall.'); @@ -86506,12 +97130,18 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/bricks.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Apply the POSTERIZE filter. * img.filter(POSTERIZE, 3); + * + * // Display the image. * image(img, 0, 0); * * describe('An image of a red brick wall drawn with a limited color palette.'); @@ -86523,12 +97153,18 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/bricks.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Apply the BLUR filter. * img.filter(BLUR, 3); + * + * // Display the image. * image(img, 0, 0); * * describe('A blurry image of a red brick wall.'); @@ -86540,12 +97176,18 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/bricks.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Apply the DILATE filter. * img.filter(DILATE); + * + * // Display the image. * image(img, 0, 0); * * describe('A red brick wall with bright lines between each brick.'); @@ -86557,12 +97199,18 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/bricks.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Apply the ERODE filter. * img.filter(ERODE); + * + * // Display the image. * image(img, 0, 0); * * describe('A red brick wall with faint lines between each brick.'); @@ -86578,9 +97226,23 @@ _filters.default.apply(this.canvas, _filters.default[operation], value); this.setModified(true); } /** - * Copies a region of pixels from another - * p5.Image object into this one. The `blendMode` - * parameter blends the images' colors to create different effects. + * Copies a region of pixels from another image into this one. + * + * The first parameter, `srcImage`, is the + * p5.Image object to blend. + * + * The next four parameters, `sx`, `sy`, `sw`, and `sh` determine the region + * to blend from the source image. `(sx, sy)` is the top-left corner of the + * region. `sw` and `sh` are the regions width and height. + * + * The next four parameters, `dx`, `dy`, `dw`, and `dh` determine the region + * of the canvas to blend into. `(dx, dy)` is the top-left corner of the + * region. `dw` and `dh` are the regions width and height. + * + * The tenth parameter, `blendMode`, sets the effect used to blend the images' + * colors. The options are `BLEND`, `DARKEST`, `LIGHTEST`, `DIFFERENCE`, + * `MULTIPLY`, `EXCLUSION`, `SCREEN`, `REPLACE`, `OVERLAY`, `HARD_LIGHT`, + * `SOFT_LIGHT`, `DODGE`, `BURN`, `ADD`, or `NORMAL`. * * @method blend * @param {p5.Image} srcImage source image @@ -86603,20 +97265,29 @@ * color | luminosity * * http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/ + * * @example *
* * let mountains; * let bricks; * + * // Load the images. * function preload() { * mountains = loadImage('assets/rockies.jpg'); * bricks = loadImage('assets/bricks_third.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Blend the bricks image into the mountains. * mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, ADD); + * + * // Display the mountains image. * image(mountains, 0, 0); + * + * // Display the bricks image. * image(bricks, 0, 0); * * describe('A wall of bricks in front of a mountain landscape. The same wall of bricks appears faded on the right of the image.'); @@ -86629,14 +97300,22 @@ * let mountains; * let bricks; * + * // Load the images. * function preload() { * mountains = loadImage('assets/rockies.jpg'); * bricks = loadImage('assets/bricks_third.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Blend the bricks image into the mountains. * mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, DARKEST); + * + * // Display the mountains image. * image(mountains, 0, 0); + * + * // Display the bricks image. * image(bricks, 0, 0); * * describe('A wall of bricks in front of a mountain landscape. The same wall of bricks appears transparent on the right of the image.'); @@ -86649,14 +97328,22 @@ * let mountains; * let bricks; * + * // Load the images. * function preload() { * mountains = loadImage('assets/rockies.jpg'); * bricks = loadImage('assets/bricks_third.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Blend the bricks image into the mountains. * mountains.blend(bricks, 0, 0, 33, 100, 67, 0, 33, 100, LIGHTEST); + * + * // Display the mountains image. * image(mountains, 0, 0); + * + * // Display the bricks image. * image(bricks, 0, 0); * * describe('A wall of bricks in front of a mountain landscape. The same wall of bricks appears washed out on the right of the image.'); @@ -86718,41 +97405,52 @@ value: function isModified() { return this._modified; } /** - * Saves the p5.Image object to a file. - * The browser will either save the file immediately or prompt the user - * with a dialogue window. + * Saves the image to a file. * - * By default, calling `img.save()` will save the image as `untitled.png`. + * By default, `img.save()` saves the image as a PNG image called + * `untitled.png`. * - * Calling `img.save()` with one argument, as in `img.save('photo.png')`, - * will set the image's filename and type together. + * The first parameter, `filename`, is optional. It's a string that sets the + * file's name. If a file extension is included, as in + * `img.save('drawing.png')`, then the image will be saved using that + * format. * - * Calling `img.save()` with two arguments, as in - * `image.save('photo', 'png')`, will set the image's filename and type - * separately. + * The second parameter, `extension`, is also optional. It sets the files format. + * Either `'png'` or `'jpg'` can be used. For example, `img.save('drawing', 'jpg')` + * saves the canvas to a file called `drawing.jpg`. + * + * Note: The browser will either save the file immediately or prompt the user + * with a dialogue window. + * + * The image will only be downloaded as an animated GIF if it was loaded + * from a GIF file. See saveGif() to create new + * GIFs. * - * The image will only be downloaded as an animated GIF if the - * p5.Image object was loaded from a GIF file. - * See saveGif() to create new GIFs. * @method save * @param {String} filename filename. Defaults to 'untitled'. * @param {String} [extension] file extension, either 'png' or 'jpg'. * Defaults to 'png'. + * * @example *
* * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/rockies.jpg'); * } * - * function draw() { + * function setup() { + * createCanvas(100, 100); + * + * // Display the image. * image(img, 0, 0); * - * describe('An image of a mountain landscape.'); + * describe('An image of a mountain landscape. The image is downloaded when the user presses the "s", "j", or "p" key.'); * } * + * // Save the image with different options when the user presses a key. * function keyPressed() { * if (key === 's') { * img.save(); @@ -86780,22 +97478,31 @@ * Restarts an animated GIF at its first frame. * * @method reset + * * @example *
* * let gif; * + * // Load the image. * function preload() { * gif = loadImage('assets/arnott-wallace-wink-loop-once.gif'); * } * + * function setup() { + * createCanvas(100, 100); + * + * describe('A cartoon face winks once and then freezes. Clicking resets the face and makes it wink again.'); + * } + * * function draw() { * background(255); - * image(gif, 0, 0); * - * describe('A cartoon face winks once and then freezes. Clicking resets the face and makes it wink again.'); + * // Display the image. + * image(gif, 0, 0); * } * + * // Reset the GIF when the user presses the mouse. * function mousePressed() { * gif.reset(); * } @@ -86822,21 +97529,32 @@ * * @method getCurrentFrame * @return {Number} index of the GIF's current frame. + * * @example *
* * let gif; * + * // Load the image. * function preload() { * gif = loadImage('assets/arnott-wallace-eye-loop-forever.gif'); * } * + * function setup() { + * createCanvas(100, 100); + * + * describe('A cartoon eye repeatedly looks around, then outwards. A number displayed in the bottom-left corner increases from 0 to 124, then repeats.'); + * } + * * function draw() { + * // Get the index of the current GIF frame. * let index = gif.getCurrentFrame(); + * + * // Display the image. * image(gif, 0, 0); - * text(index, 10, 90); * - * describe('A cartoon eye repeatedly looks around, then outwards. A number displayed in the bottom-left corner increases from 0 to 124, then repeats.'); + * // Display the current frame. + * text(index, 10, 90); * } * *
@@ -86855,29 +97573,41 @@ * * @method setFrame * @param {Number} index index of the frame to display. + * * @example *
* * let gif; * let frameSlider; * + * // Load the image. * function preload() { * gif = loadImage('assets/arnott-wallace-eye-loop-forever.gif'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Get the index of the last frame. * let maxFrame = gif.numFrames() - 1; + * + * // Create a slider to control which frame is drawn. * frameSlider = createSlider(0, maxFrame); * frameSlider.position(10, 80); * frameSlider.size(80); + * + * describe('A cartoon eye looks around when a slider is moved.'); * } * * function draw() { + * // Get the slider's value. * let index = frameSlider.value(); + * + * // Set the GIF's frame. * gif.setFrame(index); - * image(gif, 0, 0); * - * describe('A cartoon eye looks around when a slider is moved.'); + * // Display the image. + * image(gif, 0, 0); * } * *
@@ -86909,17 +97639,25 @@ * * let gif; * + * // Load the image. * function preload() { * gif = loadImage('assets/arnott-wallace-eye-loop-forever.gif'); * } * + * function setup() { + * createCanvas(100, 100); + * + * describe('A cartoon eye looks around. The text "n / 125" is shown at the bottom of the canvas.'); + * } + * * function draw() { + * // Display the image. * image(gif, 0, 0); + * + * // Display the current state of playback. * let total = gif.numFrames(); * let index = gif.getCurrentFrame(); * text(`${index} / ${total}`, 30, 90); - * - * describe('A cartoon eye looks around. The text "n / 125" is shown at the bottom of the canvas.'); * } * *
@@ -86943,21 +97681,28 @@ * * let gif; * + * // Load the image. * function preload() { * gif = loadImage('assets/nancy-liang-wind-loop-forever.gif'); * } * + * function setup() { + * createCanvas(100, 100); + * + * describe('A drawing of a child with hair blowing in the wind. The animation freezes when clicked and resumes when released.'); + * } + * * function draw() { * background(255); * image(gif, 0, 0); - * - * describe('A drawing of a child with hair blowing in the wind. The animation freezes when clicked and resumes when released.'); * } * + * // Pause the GIF when the user presses the mouse. * function mousePressed() { * gif.pause(); * } * + * // Play the GIF when the user releases the mouse. * function mouseReleased() { * gif.play(); * } @@ -86973,7 +97718,9 @@ this.gifProperties.playing = true; } } /** - * Pauses an animated GIF. The GIF can be resumed by calling + * Pauses an animated GIF. + * + * The GIF can be resumed by calling * img.play(). * * @method pause @@ -86983,21 +97730,30 @@ * * let gif; * + * // Load the image. * function preload() { * gif = loadImage('assets/nancy-liang-wind-loop-forever.gif'); * } * + * function setup() { + * createCanvas(100, 100); + * + * describe('A drawing of a child with hair blowing in the wind. The animation freezes when clicked and resumes when released.'); + * } + * * function draw() { * background(255); - * image(gif, 0, 0); * - * describe('A drawing of a child with hair blowing in the wind. The animation freezes when clicked and resumes when released.'); + * // Display the image. + * image(gif, 0, 0); * } * + * // Pause the GIF when the user presses the mouse. * function mousePressed() { * gif.pause(); * } * + * // Play the GIF when the user presses the mouse. * function mouseReleased() { * gif.play(); * } @@ -87015,6 +97771,8 @@ } /** * Changes the delay between frames in an animated GIF. * + * The first parameter, `delay`, is the length of the delay in milliseconds. + * * The second parameter, `index`, is optional. If provided, only the frame * at `index` will have its delay modified. All other frames will keep * their default delay. @@ -87029,23 +97787,32 @@ * let gifFast; * let gifSlow; * + * // Load the images. * function preload() { * gifFast = loadImage('assets/arnott-wallace-eye-loop-forever.gif'); * gifSlow = loadImage('assets/arnott-wallace-eye-loop-forever.gif'); * } * * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Resize the images. * gifFast.resize(50, 50); * gifSlow.resize(50, 50); + * + * // Set the delay lengths. * gifFast.delay(10); * gifSlow.delay(100); + * + * describe('Two animated eyes looking around. The eye on the left moves faster than the eye on the right.'); * } * * function draw() { + * // Display the images. * image(gifFast, 0, 0); * image(gifSlow, 50, 0); - * - * describe('Two animated eyes looking around. The eye on the left moves faster than the eye on the right.'); * } * *
@@ -87054,18 +97821,23 @@ * * let gif; * + * // Load the image. * function preload() { * gif = loadImage('assets/arnott-wallace-eye-loop-forever.gif'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Set the delay of frame 67. * gif.delay(3000, 67); + * + * describe('An animated eye looking around. It pauses for three seconds while it looks down.'); * } * * function draw() { + * // Display the image. * image(gif, 0, 0); - * - * describe('An animated eye looking around. It pauses for three seconds while it looks down.'); * } * *
@@ -87114,18 +97886,18 @@ exports.default = _default; }, { - '../core/main': 298, - './filters': 319, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/main': 306, + './filters': 327, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 323: [ + 331: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.array.filter'); @@ -87149,9 +97921,10 @@ * @requires core */ /** - * An array containing the color of each pixel on the canvas. Colors are - * stored as numbers representing red, green, blue, and alpha (RGBA) values. - * `pixels` is a one-dimensional array for performance reasons. + * An array containing the color of each pixel on the canvas. + * + * Colors are stored as numbers representing red, green, blue, and alpha + * (RGBA) values. `pixels` is a one-dimensional array for performance reasons. * * Each pixel occupies four elements in the `pixels` array, one for each RGBA * value. For example, the pixel at coordinates (0, 0) stores its RGBA values @@ -87178,65 +97951,106 @@ * @example *
* - * loadPixels(); - * let x = 50; - * let y = 50; - * let d = pixelDensity(); - * for (let i = 0; i < d; i += 1) { - * for (let j = 0; j < d; j += 1) { - * let index = 4 * ((y * d + j) * width * d + (x * d + i)); - * // Red. - * pixels[index] = 0; - * // Green. - * pixels[index + 1] = 0; - * // Blue. - * pixels[index + 2] = 0; - * // Alpha. - * pixels[index + 3] = 255; + * function setup() { + * createCanvas(100, 100); + * + * // Load the pixels array. + * loadPixels(); + * + * // Set the dot's coordinates. + * let x = 50; + * let y = 50; + * + * // Get the pixel density. + * let d = pixelDensity(); + * + * // Set the pixel(s) at the center of the canvas black. + * for (let i = 0; i < d; i += 1) { + * for (let j = 0; j < d; j += 1) { + * let index = 4 * ((y * d + j) * width * d + (x * d + i)); + * // Red. + * pixels[index] = 0; + * // Green. + * pixels[index + 1] = 0; + * // Blue. + * pixels[index + 2] = 0; + * // Alpha. + * pixels[index + 3] = 255; + * } * } - * } - * updatePixels(); * - * describe('A black dot in the middle of a gray rectangle.'); + * // Update the canvas. + * updatePixels(); + * + * describe('A black dot in the middle of a gray rectangle.'); + * } * *
* *
* - * loadPixels(); - * let d = pixelDensity(); - * let halfImage = 4 * (d * width) * (d * height / 2); - * for (let i = 0; i < halfImage; i += 4) { - * // Red. - * pixels[i] = 255; - * // Green. - * pixels[i + 1] = 0; - * // Blue. - * pixels[i + 2] = 0; - * // Alpha. - * pixels[i + 3] = 255; - * } - * updatePixels(); + * function setup() { + * createCanvas(100, 100); + * + * // Load the pixels array. + * loadPixels(); + * + * // Get the pixel density. + * let d = pixelDensity(); + * + * // Calculate the halfway index in the pixels array. + * let halfImage = 4 * (d * width) * (d * height / 2); + * + * // Make the top half of the canvas red. + * for (let i = 0; i < halfImage; i += 4) { + * // Red. + * pixels[i] = 255; + * // Green. + * pixels[i + 1] = 0; + * // Blue. + * pixels[i + 2] = 0; + * // Alpha. + * pixels[i + 3] = 255; + * } + * + * // Update the canvas. + * updatePixels(); * - * describe('A red rectangle drawn above a gray rectangle.'); + * describe('A red rectangle drawn above a gray rectangle.'); + * } * *
* *
* - * let pink = color(255, 102, 204); - * loadPixels(); - * let d = pixelDensity(); - * let halfImage = 4 * (d * width) * (d * height / 2); - * for (let i = 0; i < halfImage; i += 4) { - * pixels[i] = red(pink); - * pixels[i + 1] = green(pink); - * pixels[i + 2] = blue(pink); - * pixels[i + 3] = alpha(pink); - * } - * updatePixels(); + * function setup() { + * createCanvas(100, 100); + * + * // Create a p5.Color object. + * let pink = color(255, 102, 204); + * + * // Load the pixels array. + * loadPixels(); + * + * // Get the pixel density. + * let d = pixelDensity(); + * + * // Calculate the halfway index in the pixels array. + * let halfImage = 4 * (d * width) * (d * height / 2); + * + * // Make the top half of the canvas red. + * for (let i = 0; i < halfImage; i += 4) { + * pixels[i] = red(pink); + * pixels[i + 1] = green(pink); + * pixels[i + 2] = blue(pink); + * pixels[i + 3] = alpha(pink); + * } + * + * // Update the canvas. + * updatePixels(); * - * describe('A pink rectangle drawn above a gray rectangle.'); + * describe('A pink rectangle drawn above a gray rectangle.'); + * } * *
*/ @@ -87244,8 +98058,23 @@ _main.default.prototype.pixels = [ ]; /** - * Copies a region of pixels from one image to another. The `blendMode` - * parameter blends the images' colors to create different effects. + * Copies a region of pixels from one image to another. + * + * The first parameter, `srcImage`, is the + * p5.Image object to blend. + * + * The next four parameters, `sx`, `sy`, `sw`, and `sh` determine the region + * to blend from the source image. `(sx, sy)` is the top-left corner of the + * region. `sw` and `sh` are the regions width and height. + * + * The next four parameters, `dx`, `dy`, `dw`, and `dh` determine the region + * of the canvas to blend into. `(dx, dy)` is the top-left corner of the + * region. `dw` and `dh` are the regions width and height. + * + * The tenth parameter, `blendMode`, sets the effect used to blend the images' + * colors. The options are `BLEND`, `DARKEST`, `LIGHTEST`, `DIFFERENCE`, + * `MULTIPLY`, `EXCLUSION`, `SCREEN`, `REPLACE`, `OVERLAY`, `HARD_LIGHT`, + * `SOFT_LIGHT`, `DODGE`, `BURN`, `ADD`, or `NORMAL` * * @method blend * @param {p5.Image} srcImage source image. @@ -87268,14 +98097,22 @@ * let img0; * let img1; * + * // Load the images. * function preload() { * img0 = loadImage('assets/rockies.jpg'); * img1 = loadImage('assets/bricks_third.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Use the mountains as the background. * background(img0); + * + * // Display the bricks. * image(img1, 0, 0); + * + * // Display the bricks faded into the landscape. * blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, LIGHTEST); * * describe('A wall of bricks in front of a mountain landscape. The same wall of bricks appears faded on the right of the image.'); @@ -87288,14 +98125,22 @@ * let img0; * let img1; * + * // Load the images. * function preload() { * img0 = loadImage('assets/rockies.jpg'); * img1 = loadImage('assets/bricks_third.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Use the mountains as the background. * background(img0); + * + * // Display the bricks. * image(img1, 0, 0); + * + * // Display the bricks partially transparent. * blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, DARKEST); * * describe('A wall of bricks in front of a mountain landscape. The same wall of bricks appears transparent on the right of the image.'); @@ -87308,14 +98153,22 @@ * let img0; * let img1; * + * // Load the images. * function preload() { * img0 = loadImage('assets/rockies.jpg'); * img1 = loadImage('assets/bricks_third.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Use the mountains as the background. * background(img0); + * + * // Display the bricks. * image(img1, 0, 0); + * + * // Display the bricks washed out into the landscape. * blend(img1, 0, 0, 33, 100, 67, 0, 33, 100, ADD); * * describe('A wall of bricks in front of a mountain landscape. The same wall of bricks appears washed out on the right of the image.'); @@ -87348,10 +98201,21 @@ } }; /** - * Copies pixels from a source image to a region of the canvas. The source - * image can be the canvas itself or a p5.Image - * object. `copy()` will scale pixels from the source region if it isn't the - * same size as the destination region. + * Copies pixels from a source image to a region of the canvas. + * + * The first parameter, `srcImage`, is the + * p5.Image object to blend. The source image can be + * the canvas itself or a + * p5.Image object. `copy()` will scale pixels from + * the source region if it isn't the same size as the destination region. + * + * The next four parameters, `sx`, `sy`, `sw`, and `sh` determine the region + * to copy from the source image. `(sx, sy)` is the top-left corner of the + * region. `sw` and `sh` are the region's width and height. + * + * The next four parameters, `dx`, `dy`, `dw`, and `dh` determine the region + * of the canvas to copy into. `(dx, dy)` is the top-left corner of the + * region. `dw` and `dh` are the region's width and height. * * @method copy * @param {p5.Image|p5.Element} srcImage source image. @@ -87369,14 +98233,21 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/rockies.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Use the mountains as the background. * background(img); + * + * // Copy a region of pixels to another spot. * copy(img, 7, 22, 10, 10, 35, 25, 50, 50); - * // Show copied region. + * + * // Outline the copied region. * stroke(255); * noFill(); * square(7, 22, 10); @@ -87447,13 +98318,21 @@ syMod = srcImage.height / 2; } if (dstImage._renderer && dstImage._renderer.isP3D) { + dstImage.push(); + dstImage.resetMatrix(); + dstImage.noLights(); + dstImage.blendMode(dstImage.BLEND); + dstImage.imageMode(dstImage.CORNER); _main.default.RendererGL.prototype.image.call(dstImage._renderer, srcImage, sx + sxMod, sy + syMod, sw, sh, dx, dy, dw, dh); + dstImage.pop(); } else { dstImage.drawingContext.drawImage(srcImage.canvas, s * (sx + sxMod), s * (sy + syMod), s * sw, s * sh, dx, dy, dw, dh); } }; /** - * Applies an image filter to the canvas. The preset options are: + * Applies an image filter to the canvas. + * + * The preset options are: * * `INVERT` * Inverts the colors in the image. No parameter is used. @@ -87491,7 +98370,7 @@ * `filter(BLUR, false)`. This may be useful to keep computation off the GPU * or to work around a lack of WebGL support. * - * In `WEBGL` mode, `filter()` can also use custom shaders. See + * In WebgL mode, `filter()` can also use custom shaders. See * createFilterShader() for more * information. * @@ -87509,12 +98388,18 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/bricks.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Display the image. * image(img, 0, 0); + * + * // Apply the INVERT filter. * filter(INVERT); * * describe('A blue brick wall.'); @@ -87526,12 +98411,18 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/bricks.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Display the image. * image(img, 0, 0); + * + * // Apply the GRAY filter. * filter(GRAY); * * describe('A brick wall drawn in grayscale.'); @@ -87543,12 +98434,18 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/bricks.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Display the image. * image(img, 0, 0); + * + * // Apply the THRESHOLD filter. * filter(THRESHOLD); * * describe('A brick wall drawn in black and white.'); @@ -87560,12 +98457,18 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/bricks.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Display the image. * image(img, 0, 0); + * + * // Apply the OPAQUE filter. * filter(OPAQUE); * * describe('A red brick wall.'); @@ -87577,12 +98480,18 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/bricks.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Display the image. * image(img, 0, 0); + * + * // Apply the POSTERIZE filter. * filter(POSTERIZE, 3); * * describe('An image of a red brick wall drawn with limited color palette.'); @@ -87594,12 +98503,18 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/bricks.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Display the image. * image(img, 0, 0); + * + * // Apply the BLUR filter. * filter(BLUR, 3); * * describe('A blurry image of a red brick wall.'); @@ -87611,12 +98526,18 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/bricks.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Display the image. * image(img, 0, 0); + * + * // Apply the DILATE filter. * filter(DILATE); * * describe('A red brick wall with bright lines between each brick.'); @@ -87628,12 +98549,18 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/bricks.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Display the image. * image(img, 0, 0); + * + * // Apply the ERODE filter. * filter(ERODE); * * describe('A red brick wall with faint lines between each brick.'); @@ -87645,12 +98572,18 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/bricks.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Display the image. * image(img, 0, 0); + * + * // Apply the BLUR filter. * // Don't use WebGL. * filter(BLUR, 3, false); * @@ -87681,7 +98614,7 @@ for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { args[_key3] = arguments[_key3]; } - _main.default._validateParameters('filter', arguments); + _main.default._validateParameters('filter', args); var _parseFilterArgs = parseFilterArgs.apply(void 0, args), shader = _parseFilterArgs.shader, operation = _parseFilterArgs.operation, @@ -87721,7 +98654,10 @@ // filter it with shaders filterGraphicsLayer.filter.apply(filterGraphicsLayer, args); // copy secondary webgl renderer back to original p2d canvas - this._renderer._pInst.image(filterGraphicsLayer, 0, 0); + this.copy( // src + filterGraphicsLayer._renderer, // src coods + 0, 0, this.width, this.height, // dest coords + 0, 0, this.width, this.height); filterGraphicsLayer.clear(); // prevent feedback effects on p2d canvas } }; @@ -87783,14 +98719,22 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/rockies.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Display the image. * image(img, 0, 0); + * + * // Get the entire canvas. * let c = get(); - * image(c, width / 2, 0); + * + * // Display half the canvas. + * image(c, 50, 0); * * describe('Two identical mountain landscapes shown side-by-side.'); * } @@ -87801,15 +98745,25 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/rockies.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Display the image. * image(img, 0, 0); + * + * // Get the color of a pixel. * let c = get(50, 90); + * + * // Style the square with the pixel's color. * fill(c); * noStroke(); + * + * // Display the square. * square(25, 25, 50); * * describe('A mountain landscape with an olive green square in its center.'); @@ -87821,14 +98775,22 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/rockies.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Display the image. * image(img, 0, 0); - * let c = get(0, 0, width / 2, height / 2); - * image(c, width / 2, height / 2); + * + * // Get a region of the image. + * let c = get(0, 0, 50, 50); + * + * // Display the region. + * image(c, 50, 50); * * describe('A mountain landscape drawn on top of another mountain landscape.'); * } @@ -87853,8 +98815,9 @@ }; /** * Loads the current value of each pixel on the canvas into the - * pixels array. This - * function must be called before reading from or writing to + * pixels array. + * + * `loadPixels()` must be called before reading from or writing to * pixels. * * @method loadPixels @@ -87863,18 +98826,32 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/rockies.jpg'); * } * * function setup() { - * image(img, 0, 0, width, height); + * createCanvas(100, 100); + * + * // Display the image. + * image(img, 0, 0, 100, 100); + * + * // Get the pixel density. * let d = pixelDensity(); + * + * // Calculate the halfway index in the pixels array. * let halfImage = 4 * (d * width) * (d * height / 2); + * + * // Load the pixels array. * loadPixels(); + * + * // Copy the top half of the canvas to the bottom. * for (let i = 0; i < halfImage; i += 1) { * pixels[i + halfImage] = pixels[i]; * } + * + * // Update the canvas. * updatePixels(); * * describe('Two identical images of mountain landscapes, one on top of the other.'); @@ -87914,40 +98891,72 @@ * @example *
* - * set(30, 20, 0); - * set(85, 20, 0); - * set(85, 75, 0); - * set(30, 75, 0); - * updatePixels(); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Set four pixels to black. + * set(30, 20, 0); + * set(85, 20, 0); + * set(85, 75, 0); + * set(30, 75, 0); + * + * // Update the canvas. + * updatePixels(); * - * describe('Four black dots arranged in a square drawn on a gray background.'); + * describe('Four black dots arranged in a square drawn on a gray background.'); + * } * *
* *
* - * let black = color(0); - * set(30, 20, black); - * set(85, 20, black); - * set(85, 75, black); - * set(30, 75, black); - * updatePixels(); + * function setup() { + * createCanvas(100, 100); + * + * background(200); * - * describe('Four black dots arranged in a square drawn on a gray background.'); + * // Create a p5.Color object. + * let black = color(0); + * + * // Set four pixels to black. + * set(30, 20, black); + * set(85, 20, black); + * set(85, 75, black); + * set(30, 75, black); + * + * // Update the canvas. + * updatePixels(); + * + * describe('Four black dots arranged in a square drawn on a gray background.'); + * } * *
* *
* - * for (let x = 0; x < width; x += 1) { - * for (let y = 0; y < height; y += 1) { - * let c = map(x, 0, width, 0, 255); - * set(x, y, c); + * function setup() { + * createCanvas(100, 100); + * + * background(255); + * + * // Draw a horizontal color gradient. + * for (let x = 0; x < 100; x += 1) { + * for (let y = 0; y < 100; y += 1) { + * // Calculate the grayscale value. + * let c = map(x, 0, 100, 0, 255); + * + * // Set the pixel using the grayscale value. + * set(x, y, c); + * } * } - * } - * updatePixels(); * - * describe('A horiztonal color gradient from black to white.'); + * // Update the canvas. + * updatePixels(); + * + * describe('A horiztonal color gradient from black to white.'); + * } * *
* @@ -87955,12 +98964,18 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/rockies.jpg'); * } * * function setup() { + * createCanvas(100, 100); + * + * // Use the image to set all pixels. * set(0, 0, img); + * + * // Update the canvas. * updatePixels(); * * describe('An image of a mountain landscape.'); @@ -87992,18 +99007,32 @@ * * let img; * + * // Load the image. * function preload() { * img = loadImage('assets/rockies.jpg'); * } * * function setup() { - * image(img, 0, 0, width, height); + * createCanvas(100, 100); + * + * // Display the image. + * image(img, 0, 0, 100, 100); + * + * // Get the pixel density. * let d = pixelDensity(); + * + * // Calculate the halfway index in the pixels array. * let halfImage = 4 * (d * width) * (d * height / 2); + * + * // Load the pixels array. * loadPixels(); + * + * // Copy the top half of the canvas to the bottom. * for (let i = 0; i < halfImage; i += 1) { * pixels[i + halfImage] = pixels[i]; * } + * + * // Update the canvas. * updatePixels(); * * describe('Two identical images of mountain landscapes, one on top of the other.'); @@ -88024,13 +99053,13 @@ exports.default = _default; }, { - '../color/p5.Color': 284, - '../core/main': 298, - './filters': 319, - 'core-js/modules/es.array.filter': 173 + '../color/p5.Color': 292, + '../core/main': 306, + './filters': 327, + 'core-js/modules/es.array.filter': 175 } ], - 324: [ + 332: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -88038,7 +99067,6 @@ _dereq_('core-js/modules/es.symbol.iterator'); _dereq_('core-js/modules/es.array.concat'); _dereq_('core-js/modules/es.array.includes'); - _dereq_('core-js/modules/es.array.index-of'); _dereq_('core-js/modules/es.array.iterator'); _dereq_('core-js/modules/es.array.last-index-of'); _dereq_('core-js/modules/es.array.map'); @@ -88097,7 +99125,6 @@ _dereq_('core-js/modules/es.symbol.iterator'); _dereq_('core-js/modules/es.array.concat'); _dereq_('core-js/modules/es.array.includes'); - _dereq_('core-js/modules/es.array.index-of'); _dereq_('core-js/modules/es.array.iterator'); _dereq_('core-js/modules/es.array.last-index-of'); _dereq_('core-js/modules/es.array.map'); @@ -88175,103 +99202,232 @@ * @requires core */ /** - * Loads a JSON file from a file or a URL, and returns an Object. - * Note that even if the JSON file contains an Array, an Object will be - * returned with index numbers as keys. + * Loads a JSON file to create an `Object`. * - * This method is asynchronous, meaning it may not finish before the next - * line in your sketch is executed. JSONP is supported via a polyfill and you - * can pass in as the second argument an object with definitions of the json - * callback following the syntax specified here. + * JavaScript Object Notation + * (JSON) + * is a standard format for sending data between applications. The format is + * based on JavaScript objects which have keys and values. JSON files store + * data in an object with strings as keys. Values can be strings, numbers, + * Booleans, arrays, `null`, or other objects. + * + * The first parameter, `path`, is always a string with the path to the file. + * Paths to local files should be relative, as in + * `loadJSON('assets/data.json')`. URLs such as + * `'https://example.com/data.json'` may be blocked due to browser security. + * + * The second parameter, `successCallback`, is optional. If a function is + * passed, as in `loadJSON('assets/data.json', handleData)`, then the + * `handleData()` function will be called once the data loads. The object + * created from the JSON data will be passed to `handleData()` as its only argument. + * + * The third parameter, `failureCallback`, is also optional. If a function is + * passed, as in `loadJSON('assets/data.json', handleData, handleFailure)`, + * then the `handleFailure()` function will be called if an error occurs while + * loading. The `Error` object will be passed to `handleFailure()` as its only + * argument. + * + * Note: Data can take time to load. Calling `loadJSON()` within + * preload() ensures data loads before it's used in + * setup() or draw(). * - * This method is suitable for fetching files up to size of 64MB. * @method loadJSON - * @param {String} path name of the file or url to load - * @param {Object} [jsonpOptions] options object for jsonp related settings - * @param {String} [datatype] "json" or "jsonp" - * @param {function} [callback] function to be executed after - * loadJSON() completes, data is passed - * in as first argument - * @param {function} [errorCallback] function to be executed if - * there is an error, response is passed - * in as first argument - * @return {Object|Array} JSON data + * @param {String} path path of the JSON file to be loaded. + * @param {function} [successCallback] function to call once the data is loaded. Will be passed the object. + * @param {function} [errorCallback] function to call if the data fails to load. Will be passed an `Error` event object. + * @return {Object} object containing the loaded data. + * * @example * - * Calling loadJSON() inside preload() guarantees to complete the - * operation before setup() and draw() are called. + *
+ * + * let myData; * - *
- * // Examples use USGS Earthquake API: - * // https://earthquake.usgs.gov/fdsnws/event/1/#methods - * let earthquakes; + * // Load the JSON and create an object. * function preload() { - * // Get the most recent earthquake in the database - * let url = - 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/' + - * 'summary/all_day.geojson'; - * earthquakes = loadJSON(url); + * myData = loadJSON('assets/data.json'); * } * * function setup() { - * noLoop(); + * createCanvas(100, 100); + * + * background(200); + * + * // Style the circle. + * fill(myData.color); + * noStroke(); + * + * // Draw the circle. + * circle(myData.x, myData.y, myData.d); + * + * describe('A pink circle on a gray background.'); * } + * + *
+ * + *
+ * + * let myData; + * + * // Load the JSON and create an object. + * function preload() { + * myData = loadJSON('assets/data.json'); + * } + * + * function setup() { + * createCanvas(100, 100); * - * function draw() { * background(200); - * // Get the magnitude and name of the earthquake out of the loaded JSON - * let earthquakeMag = earthquakes.features[0].properties.mag; - * let earthquakeName = earthquakes.features[0].properties.place; - * ellipse(width / 2, height / 2, earthquakeMag * 10, earthquakeMag * 10); - * textAlign(CENTER); - * text(earthquakeName, 0, height - 30, width, 30); - * describe(`50×50 ellipse that changes from black to white - * depending on the current humidity`); + * + * // Create a p5.Color object and make it transparent. + * let c = color(myData.color); + * c.setAlpha(80); + * + * // Style the circles. + * fill(c); + * noStroke(); + * + * // Iterate over the myData.bubbles array. + * for (let b of myData.bubbles) { + * // Draw a circle for each bubble. + * circle(b.x, b.y, b.d); + * } + * + * describe('Several pink bubbles floating in a blue sky.'); + * } + * + *
+ * + *
+ * + * let myData; + * + * // Load the GeoJSON and create an object. + * function preload() { + * myData = loadJSON('https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson'); * } - *
* - * Outside of preload(), you may supply a callback function to handle the - * object: - *
* function setup() { - * noLoop(); - * let url = - 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/' + - * 'summary/all_day.geojson'; - * loadJSON(url, drawEarthquake); + * createCanvas(100, 100); + * + * background(200); + * + * // Get data about the most recent earthquake. + * let quake = myData.features[0].properties; + * + * // Draw a circle based on the earthquake's magnitude. + * circle(50, 50, quake.mag * 10); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(11); + * + * // Display the earthquake's location. + * text(quake.place, 5, 80, 100); + * + * describe(`A white circle on a gray background. The text "${quake.place}" is written beneath the circle.`); * } + * + *
+ * + *
+ * + * let bigQuake; + * + * // Load the GeoJSON and preprocess it. + * function preload() { + * loadJSON( + * 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson', + * handleData + * ); + * } + * + * function setup() { + * createCanvas(100, 100); * - * function draw() { * background(200); - * describe(`50×50 ellipse that changes from black to white - * depending on the current humidity`); + * + * // Draw a circle based on the earthquake's magnitude. + * circle(50, 50, bigQuake.mag * 10); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(11); + * + * // Display the earthquake's location. + * text(bigQuake.place, 5, 80, 100); + * + * describe(`A white circle on a gray background. The text "${bigQuake.place}" is written beneath the circle.`); * } * - * function drawEarthquake(earthquakes) { - * // Get the magnitude and name of the earthquake out of the loaded JSON - * let earthquakeMag = earthquakes.features[0].properties.mag; - * let earthquakeName = earthquakes.features[0].properties.place; - * ellipse(width / 2, height / 2, earthquakeMag * 10, earthquakeMag * 10); - * textAlign(CENTER); - * text(earthquakeName, 0, height - 30, width, 30); + * // Find the biggest recent earthquake. + * function handleData(data) { + * let maxMag = 0; + * // Iterate over the earthquakes array. + * for (let quake of data.features) { + * // Reassign bigQuake if a larger + * // magnitude quake is found. + * if (quake.properties.mag > maxMag) { + * bigQuake = quake.properties; + * } + * } * } - *
- */ - /** - * @method loadJSON - * @param {String} path - * @param {String} datatype - * @param {function} [callback] - * @param {function} [errorCallback] - * @return {Object|Array} - */ - /** - * @method loadJSON - * @param {String} path - * @param {function} callback - * @param {function} [errorCallback] - * @return {Object|Array} + *
+ *
+ * + *
+ * + * let bigQuake; + * + * // Load the GeoJSON and preprocess it. + * function preload() { + * loadJSON( + * 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson', + * handleData, + * handleError + * ); + * } + * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Draw a circle based on the earthquake's magnitude. + * circle(50, 50, bigQuake.mag * 10); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(11); + * + * // Display the earthquake's location. + * text(bigQuake.place, 5, 80, 100); + * + * describe(`A white circle on a gray background. The text "${bigQuake.place}" is written beneath the circle.`); + * } + * + * // Find the biggest recent earthquake. + * function handleData(data) { + * let maxMag = 0; + * // Iterate over the earthquakes array. + * for (let quake of data.features) { + * // Reassign bigQuake if a larger + * // magnitude quake is found. + * if (quake.properties.mag > maxMag) { + * bigQuake = quake.properties; + * } + * } + * } + * + * // Log any errors to the console. + * function handleError(error) { + * console.log('Oops!', error); + * } + * + *
*/ _main.default.prototype.loadJSON = function () { @@ -88325,62 +99481,138 @@ return ret; }; /** - * Reads the contents of a file and creates a String array of its individual - * lines. If the name of the file is used as the parameter, as in the above - * example, the file must be located in the sketch directory/folder. + * Loads a text file to create an `Array`. * - * Alternatively, the file may be loaded from anywhere on the local - * computer using an absolute path (something that starts with / on Unix and - * Linux, or a drive letter on Windows), or the filename parameter can be a - * URL for a file found on a network. + * The first parameter, `path`, is always a string with the path to the file. + * Paths to local files should be relative, as in + * `loadStrings('assets/data.txt')`. URLs such as + * `'https://example.com/data.txt'` may be blocked due to browser security. * - * This method is asynchronous, meaning it may not finish before the next - * line in your sketch is executed. + * The second parameter, `successCallback`, is optional. If a function is + * passed, as in `loadStrings('assets/data.txt', handleData)`, then the + * `handleData()` function will be called once the data loads. The array + * created from the text data will be passed to `handleData()` as its only + * argument. + * + * The third parameter, `failureCallback`, is also optional. If a function is + * passed, as in `loadStrings('assets/data.txt', handleData, handleFailure)`, + * then the `handleFailure()` function will be called if an error occurs while + * loading. The `Error` object will be passed to `handleFailure()` as its only + * argument. + * + * Note: Data can take time to load. Calling `loadStrings()` within + * preload() ensures data loads before it's used in + * setup() or draw(). * - * This method is suitable for fetching files up to size of 64MB. * @method loadStrings - * @param {String} filename name of the file or url to load - * @param {function} [callback] function to be executed after loadStrings() - * completes, Array is passed in as first - * argument - * @param {function} [errorCallback] function to be executed if - * there is an error, response is passed - * in as first argument - * @return {String[]} Array of Strings + * @param {String} path path of the text file to be loaded. + * @param {function} [successCallback] function to call once the data is + * loaded. Will be passed the array. + * @param {function} [errorCallback] function to call if the data fails to + * load. Will be passed an `Error` event + * object. + * @return {String[]} new array containing the loaded text. + * * @example * - * Calling loadStrings() inside preload() guarantees to complete the - * operation before setup() and draw() are called. + *
+ * + * let myData; * - *
- * let result; + * // Load the text and create an array. * function preload() { - * result = loadStrings('assets/test.txt'); + * myData = loadStrings('assets/test.txt'); * } - + * * function setup() { + * createCanvas(100, 100); + * * background(200); - * text(random(result), 10, 10, 80, 80); - * describe(`randomly generated text from a file, - * for example "i smell like butter"`); + * + * // Select a random line from the text. + * let phrase = random(myData); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(12); + * + * // Display the text. + * text(phrase, 10, 50, 90); + * + * describe(`The text "${phrase}" written in black on a gray background.`); * } - *
+ *
+ *
* - * Outside of preload(), you may supply a callback function to handle the - * object: + *
+ * + * let lastLine; + * + * // Load the text and preprocess it. + * function preload() { + * loadStrings('assets/test.txt', handleData); + * } * - *
* function setup() { - * loadStrings('assets/test.txt', pickString); - * describe(`randomly generated text from a file, - * for example "i have three feet"`); + * createCanvas(100, 100); + * + * background(200); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(12); + * + * // Display the text. + * text(lastLine, 10, 50, 90); + * + * describe('The text "I talk like an orange" written in black on a gray background.'); * } * - * function pickString(result) { + * // Select the last line from the text. + * function handleData(data) { + * lastLine = data[data.length - 1]; + * } + * + *
+ * + *
+ * + * let lastLine; + * + * // Load the text and preprocess it. + * function preload() { + * loadStrings('assets/test.txt', handleData, handleError); + * } + * + * function setup() { + * createCanvas(100, 100); + * * background(200); - * text(random(result), 10, 10, 80, 80); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(12); + * + * // Display the text. + * text(lastLine, 10, 50, 90); + * + * describe('The text "I talk like an orange" written in black on a gray background.'); * } - *
+ * + * // Select the last line from the text. + * function handleData(data) { + * lastLine = data[data.length - 1]; + * } + * + * // Log any errors to the console. + * function handleError(error) { + * console.error('Oops!', error); + * } + *
+ *
*/ _main.default.prototype.loadStrings = function () { for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { @@ -88679,67 +99911,165 @@ row[i]]; })); } /** - * Reads the contents of a file and creates an XML object with its values. - * If the name of the file is used as the parameter, as in the above example, - * the file must be located in the sketch directory/folder. + * Loads an XML file to create a p5.XML object. * - * Alternatively, the file maybe be loaded from anywhere on the local - * computer using an absolute path (something that starts with / on Unix and - * Linux, or a drive letter on Windows), or the filename parameter can be a - * URL for a file found on a network. + * Extensible Markup Language + * (XML) + * is a standard format for sending data between applications. Like HTML, the + * XML format is based on tags and attributes, as in + * `<time units="s">1234</time>`. * - * This method is asynchronous, meaning it may not finish before the next - * line in your sketch is executed. Calling loadXML() inside preload() - * guarantees to complete the operation before setup() and draw() are called. + * The first parameter, `path`, is always a string with the path to the file. + * Paths to local files should be relative, as in + * `loadXML('assets/data.xml')`. URLs such as `'https://example.com/data.xml'` + * may be blocked due to browser security. * - * Outside of preload(), you may supply a callback function to handle the - * object. + * The second parameter, `successCallback`, is optional. If a function is + * passed, as in `loadXML('assets/data.xml', handleData)`, then the + * `handleData()` function will be called once the data loads. The + * p5.XML object created from the data will be passed + * to `handleData()` as its only argument. + * + * The third parameter, `failureCallback`, is also optional. If a function is + * passed, as in `loadXML('assets/data.xml', handleData, handleFailure)`, then + * the `handleFailure()` function will be called if an error occurs while + * loading. The `Error` object will be passed to `handleFailure()` as its only + * argument. + * + * Note: Data can take time to load. Calling `loadXML()` within + * preload() ensures data loads before it's used in + * setup() or draw(). * - * This method is suitable for fetching files up to size of 64MB. * @method loadXML - * @param {String} filename name of the file or URL to load - * @param {function} [callback] function to be executed after loadXML() - * completes, XML object is passed in as - * first argument - * @param {function} [errorCallback] function to be executed if - * there is an error, response is passed - * in as first argument - * @return {Object} XML object containing data - * @example - *
- * // The following short XML file called "mammals.xml" is parsed - * // in the code below. - * // - * // - * // <mammals> - * // <animal id="0" species="Capra hircus">Goat</animal> - * // <animal id="1" species="Panthera pardus">Leopard</animal> - * // <animal id="2" species="Equus zebra">Zebra</animal> - * // </mammals> + * @param {String} path path of the XML file to be loaded. + * @param {function} [successCallback] function to call once the data is + * loaded. Will be passed the + * p5.XML object. + * @param {function} [errorCallback] function to call if the data fails to + * load. Will be passed an `Error` event + * object. + * @return {p5.XML} XML data loaded into a p5.XML + * object. * - * let xml; + * @example + *
+ * + * let myXML; * + * // Load the XML and create a p5.XML object. * function preload() { - * xml = loadXML('assets/mammals.xml'); + * myXML = loadXML('assets/animals.xml'); * } * * function setup() { - * let children = xml.getChildren('animal'); + * createCanvas(100, 100); + * + * background(200); + * + * // Get an array with all mammal tags. + * let mammals = myXML.getChildren('mammal'); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(14); * - * for (let i = 0; i < children.length; i++) { - * let id = children[i].getNum('id'); - * let coloring = children[i].getString('species'); - * let name = children[i].getContent(); - * print(id + ', ' + coloring + ', ' + name); + * // Iterate over the mammals array. + * for (let i = 0; i < mammals.length; i += 1) { + * + * // Calculate the y-coordinate. + * let y = (i + 1) * 25; + * + * // Get the mammal's common name. + * let name = mammals[i].getContent(); + * + * // Display the mammal's name. + * text(name, 20, y); * } - * describe('no image displayed'); + * + * describe( + * 'The words "Goat", "Leopard", and "Zebra" written on three separate lines. The text is black on a gray background.' + * ); * } + * + *
* - * // Sketch prints: - * // 0, Capra hircus, Goat - * // 1, Panthera pardus, Leopard - * // 2, Equus zebra, Zebra - *
+ *
+ * + * let lastMammal; + * + * // Load the XML and create a p5.XML object. + * function preload() { + * loadXML('assets/animals.xml', handleData); + * } + * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textFont('Courier New'); + * textSize(16); + * + * // Display the content of the last mammal element. + * text(lastMammal, 50, 50); + * + * describe('The word "Zebra" written in black on a gray background.'); + * } + * + * // Get the content of the last mammal element. + * function handleData(data) { + * // Get an array with all mammal elements. + * let mammals = data.getChildren('mammal'); + * + * // Get the content of the last mammal. + * lastMammal = mammals[mammals.length - 1].getContent(); + * } + * + *
+ * + *
+ * + * let lastMammal; + * + * // Load the XML and preprocess it. + * function preload() { + * loadXML('assets/animals.xml', handleData, handleError); + * } + * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textFont('Courier New'); + * textSize(16); + * + * // Display the content of the last mammal element. + * text(lastMammal, 50, 50); + * + * describe('The word "Zebra" written in black on a gray background.'); + * } + * + * // Get the content of the last mammal element. + * function handleData(data) { + * // Get an array with all mammal elements. + * let mammals = data.getChildren('mammal'); + * + * // Get the content of the last mammal. + * lastMammal = mammals[mammals.length - 1].getContent(); + * } + * + * // Log any errors to the console. + * function handleError(error) { + * console.error('Oops!', error); + * } + * + *
*/ _main.default.prototype.loadXML = function () { @@ -88896,8 +100226,10 @@ * @return {Promise} */ _main.default.prototype.httpGet = function () { - _main.default._validateParameters('httpGet', arguments); - var args = Array.prototype.slice.call(arguments); + for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { + args[_key4] = arguments[_key4]; + } + _main.default._validateParameters('httpGet', args); args.splice(1, 0, 'GET'); return _main.default.prototype.httpDo.apply(this, args); }; @@ -88984,8 +100316,10 @@ * @return {Promise} */ _main.default.prototype.httpPost = function () { - _main.default._validateParameters('httpPost', arguments); - var args = Array.prototype.slice.call(arguments); + for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) { + args[_key5] = arguments[_key5]; + } + _main.default._validateParameters('httpPost', args); args.splice(1, 0, 'POST'); return _main.default.prototype.httpDo.apply(this, args); }; @@ -89205,27 +100539,103 @@ _main.default.prototype._pWriters = [ ]; /** + * Creates a new p5.PrintWriter object. + * + * p5.PrintWriter objects provide a way to + * save a sequence of text data, called the *print stream*, to the user's + * computer. They're low-level objects that enable precise control of text + * output. Functions such as + * saveStrings() and + * saveJSON() are easier to use for simple file + * saving. + * + * The first parameter, `filename`, is the name of the file to be written. If + * a string is passed, as in `createWriter('words.txt')`, a new + * p5.PrintWriter object will be created that + * writes to a file named `words.txt`. + * + * The second parameter, `extension`, is optional. If a string is passed, as + * in `createWriter('words', 'csv')`, the first parameter will be interpreted + * as the file name and the second parameter as the extension. + * * @method createWriter - * @param {String} name name of the file to be created - * @param {String} [extension] - * @return {p5.PrintWriter} + * @param {String} name name of the file to create. + * @param {String} [extension] format to use for the file. + * @return {p5.PrintWriter} stream for writing data. + * * @example *
* * function setup() { * createCanvas(100, 100); + * * background(200); - * text('click here to save', 10, 10, 70, 80); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(12); + * + * // Display instructions. + * text('Double-click to save', 5, 50, 90); + * + * describe('The text "Double-click to save" written in black on a gray background.'); * } * - * function mousePressed() { - * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { - * const writer = createWriter('squares.txt'); - * for (let i = 0; i < 10; i++) { - * writer.print(i * i); - * } - * writer.close(); - * writer.clear(); + * // Save the file when the user double-clicks. + * function doubleClicked() { + * if (mouseX > 0 && mouseX < 100 && mouseY > 0 && mouseY < 100) { + * // Create a p5.PrintWriter object. + * let myWriter = createWriter('xo.txt'); + * + * // Add some lines to the print stream. + * myWriter.print('XOO'); + * myWriter.print('OXO'); + * myWriter.print('OOX'); + * + * // Save the file and close the print stream. + * myWriter.close(); + * } + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(12); + * + * // Display instructions. + * text('Double-click to save', 5, 50, 90); + * + * describe('The text "Double-click to save" written in black on a gray background.'); + * } + * + * // Save the file when the user double-clicks. + * function doubleClicked() { + * if (mouseX > 0 && mouseX < 100 && mouseY > 0 && mouseY < 100) { + * // Create a p5.PrintWriter object. + * // Use the file format .csv. + * let myWriter = createWriter('mauna_loa_co2', 'csv'); + * + * // Add some lines to the print stream. + * myWriter.print('date,ppm_co2'); + * myWriter.print('1960-01-01,316.43'); + * myWriter.print('1970-01-01,325.06'); + * myWriter.print('1980-01-01,337.9'); + * myWriter.print('1990-01-01,353.86'); + * myWriter.print('2000-01-01,369.45'); + * myWriter.print('2020-01-01,413.61'); + * + * // Save the file and close the print stream. + * myWriter.close(); * } * } * @@ -89249,67 +100659,103 @@ return newPW; }; /** - * @class p5.PrintWriter - * @param {String} filename - * @param {String} [extension] + * A class to describe a print stream. + * + * Each `p5.PrintWriter` object provides a way to save a sequence of text + * data, called the *print stream*, to the user's computer. It's a low-level + * object that enables precise control of text output. Functions such as + * saveStrings() and + * saveJSON() are easier to use for simple file + * saving. + * + * Note: createWriter() is the recommended way + * to make an instance of this class. + * + * @class p5.PrintWriter + * @param {String} filename name of the file to create. + * @param {String} [extension] format to use for the file. + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(12); + * + * // Display instructions. + * text('Double-click to save', 5, 50, 90); + * + * describe('The text "Double-click to save" written in black on a gray background.'); + * } + * + * // Save the file when the user double-clicks. + * function doubleClicked() { + * // Create a p5.PrintWriter object. + * let myWriter = createWriter('xo.txt'); + * + * // Add some lines to the print stream. + * myWriter.print('XOO'); + * myWriter.print('OXO'); + * myWriter.print('OOX'); + * + * // Save the file and close the print stream. + * myWriter.close(); + * } + * + *
*/ _main.default.PrintWriter = function (filename, extension) { var self = this; this.name = filename; this.content = ''; - //Changed to write because it was being overloaded by function below. /** - * Writes data to the PrintWriter stream + * Writes data to the print stream without adding new lines. + * + * The parameter, `data`, is the data to write. `data` can be a number or + * string, as in `myWriter.write('hi')`, or an array of numbers and strings, + * as in `myWriter.write([1, 2, 3])`. A comma will be inserted between array + * array elements when they're added to the print stream. + * * @method write - * @param {Array} data all data to be written by the PrintWriter + * @param {String|Number|Array} data data to be written as a string, number, + * or array of strings and numbers. + * * @example - *
- * - * // creates a file called 'newFile.txt' - * let writer = createWriter('newFile.txt'); - * // write 'Hello world!'' to the file - * writer.write(['Hello world!']); - * // close the PrintWriter and save the file - * writer.close(); - * - *
- *
- * - * // creates a file called 'newFile2.txt' - * let writer = createWriter('newFile2.txt'); - * // write 'apples,bananas,123' to the file - * writer.write(['apples', 'bananas', 123]); - * // close the PrintWriter and save the file - * writer.close(); - * - *
- *
- * - * // creates a file called 'newFile3.txt' - * let writer = createWriter('newFile3.txt'); - * // write 'My name is: Teddy' to the file - * writer.write('My name is:'); - * writer.write(' Teddy'); - * // close the PrintWriter and save the file - * writer.close(); - * - *
*
* * function setup() { * createCanvas(100, 100); - * button = createButton('SAVE FILE'); - * button.position(21, 40); - * button.mousePressed(createFile); + * + * background(200); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(12); + * + * // Display instructions. + * text('Double-click to save', 5, 50, 90); + * + * describe('The text "Double-click to save" written in black on a gray background.'); * } * - * function createFile() { - * // creates a file called 'newFile.txt' - * let writer = createWriter('newFile.txt'); - * // write 'Hello world!'' to the file - * writer.write(['Hello world!']); - * // close the PrintWriter and save the file - * writer.close(); + * // Save the file when the user double-clicks. + * function doubleClicked() { + * // Create a p5.PrintWriter object. + * let myWriter = createWriter('numbers.txt'); + * + * // Add some data to the print stream. + * myWriter.write('1,2,3,'); + * myWriter.write(['4', '5', '6']); + * + * // Save the file and close the print stream. + * myWriter.close(); * } * *
@@ -89318,39 +100764,47 @@ this.content += data; }; /** - * Writes data to the PrintWriter stream, and adds a new line at the end + * Writes data to the print stream with new lines added. + * + * The parameter, `data`, is the data to write. `data` can be a number or + * string, as in `myWriter.print('hi')`, or an array of numbers and strings, + * as in `myWriter.print([1, 2, 3])`. A comma will be inserted between array + * array elements when they're added to the print stream. + * * @method print - * @param {Array} data all data to be printed by the PrintWriter + * @param {String|Number|Array} data data to be written as a string, number, + * or array of strings and numbers. + * * @example - *
- * - * // creates a file called 'newFile.txt' - * let writer = createWriter('newFile.txt'); - * // creates a file containing - * // My name is: - * // Teddy - * writer.print('My name is:'); - * writer.print('Teddy'); - * // close the PrintWriter and save the file - * writer.close(); - * - *
- *
+ *
* - * let writer; - * * function setup() { - * createCanvas(400, 400); - * // create a PrintWriter - * writer = createWriter('newFile.txt'); - * } + * createCanvas(100, 100); * - * function draw() { - * writer.print([mouseX, mouseY]); + * background(200); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(12); + * + * // Display instructions. + * text('Double-click to save', 5, 50, 90); + * + * describe('The text "Double-click to save" written in black on a gray background.'); * } * - * function mouseClicked() { - * writer.close(); + * // Save the file when the user double-clicks. + * function doubleClicked() { + * // Create a p5.PrintWriter object. + * let myWriter = createWriter('numbers.txt'); + * + * // Add some data to the print stream. + * myWriter.print('1,2,3,'); + * myWriter.print(['4', '5', '6']); + * + * // Save the file and close the print stream. + * myWriter.close(); * } * *
@@ -89359,59 +100813,88 @@ this.content += ''.concat(data, '\n'); }; /** - * Clears the data already written to the PrintWriter object + * Clears all data from the print stream. + * * @method clear + * * @example - *
- * // create writer object - * let writer = createWriter('newFile.txt'); - * writer.write(['clear me']); - * // clear writer object here - * writer.clear(); - * // close writer - * writer.close(); - *
*
* * function setup() { - * button = createButton('CLEAR ME'); - * button.position(21, 40); - * button.mousePressed(createFile); + * createCanvas(100, 100); + * + * background(200); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(12); + * + * // Display instructions. + * text('Double-click to save', 5, 50, 90); + * + * describe('The text "Double-click to save" written in black on a gray background.'); * } * - * function createFile() { - * let writer = createWriter('newFile.txt'); - * writer.write(['clear me']); - * writer.clear(); - * writer.close(); + * // Save the file when the user double-clicks. + * function doubleClicked() { + * // Create a p5.PrintWriter object. + * let myWriter = createWriter('numbers.txt'); + * + * // Add some data to the print stream. + * myWriter.print('Hello p5*js!'); + * + * // Clear the print stream. + * myWriter.clear(); + * + * // Save the file and close the print stream. + * myWriter.close(); * } * *
- * */ this.clear = function () { this.content = ''; }; /** - * Closes the PrintWriter + * Saves the file and closes the print stream. + * * @method close + * * @example - *
- * - * // create a file called 'newFile.txt' - * let writer = createWriter('newFile.txt'); - * // close the PrintWriter and save the file - * writer.close(); - * - *
- *
+ *
* - * // create a file called 'newFile2.txt' - * let writer = createWriter('newFile2.txt'); - * // write some data to the file - * writer.write([100, 101, 102]); - * // close the PrintWriter and save the file - * writer.close(); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(12); + * + * // Display instructions. + * text('Double-click to save', 5, 50, 90); + * + * describe('The text "Double-click to save" written in black on a gray background.'); + * } + * + * // Save the file when the user double-clicks. + * function doubleClicked() { + * // Create a p5.PrintWriter object. + * let myWriter = createWriter('cat.txt'); + * + * // Add some data to the print stream. + * // ASCII art courtesy Wikipedia: + * // https://en.wikipedia.org/wiki/ASCII_art + * myWriter.print(' (\\_/) '); + * myWriter.print("(='.'=)"); + * myWriter.print('(")_(")'); + * + * // Save the file and close the print stream. + * myWriter.close(); + * } * *
*/ @@ -89581,45 +101064,129 @@ } }; /** - * Writes the contents of an Array or a JSON object to a .json file. - * The file saving process and location of the saved file will - * vary between web browsers. + * Saves an `Object` or `Array` to a JSON file. * - * @method saveJSON - * @param {Array|Object} json - * @param {String} filename - * @param {Boolean} [optimize] If true, removes line breaks - * and spaces from the output - * file to optimize filesize - * (but not readability). - * @example - *
- * let json = {}; // new JSON Object + * JavaScript Object Notation + * (JSON) + * is a standard format for sending data between applications. The format is + * based on JavaScript objects which have keys and values. JSON files store + * data in an object with strings as keys. Values can be strings, numbers, + * Booleans, arrays, `null`, or other objects. + * + * The first parameter, `json`, is the data to save. The data can be an array, + * as in `[1, 2, 3]`, or an object, as in + * `{ x: 50, y: 50, color: 'deeppink' }`. + * + * The second parameter, `filename`, is a string that sets the file's name. + * For example, calling `saveJSON([1, 2, 3], 'data.json')` saves the array + * `[1, 2, 3]` to a file called `data.json` on the user's computer. * - * json.id = 0; - * json.species = 'Panthera leo'; - * json.name = 'Lion'; + * The third parameter, `optimize`, is optional. If `true` is passed, as in + * `saveJSON([1, 2, 3], 'data.json', true)`, then all unneeded whitespace will + * be removed to reduce the file size. * + * Note: The browser will either save the file immediately or prompt the user + * with a dialogue window. + * + * @method saveJSON + * @param {Array|Object} json data to save. + * @param {String} filename name of the file to be saved. + * @param {Boolean} [optimize] whether to trim unneeded whitespace. Defaults + * to `true`. + * + * @example + *
+ * * function setup() { * createCanvas(100, 100); + * * background(200); - * text('click here to save', 10, 10, 70, 80); - * describe('no image displayed'); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(12); + * + * // Display instructions. + * text('Double-click to save', 5, 50, 90); + * + * describe('The text "Double-click to save" written in black on a gray background.'); * } * - * function mousePressed() { - * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { - * saveJSON(json, 'lion.json'); + * // Save the file when the user double-clicks. + * function doubleClicked() { + * if (mouseX > 0 && mouseX < 100 && mouseY > 0 && mouseY < 100) { + * // Create an array. + * let data = [1, 2, 3]; + * + * // Save the JSON file. + * saveJSON(data, 'numbers.json'); * } * } + * + *
* - * // saves the following to a file called "lion.json": - * // { - * // "id": 0, - * // "species": "Panthera leo", - * // "name": "Lion" - * // } - *
+ *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(12); + * + * // Display instructions. + * text('Double-click to save', 5, 50, 90); + * + * describe('The text "Double-click to save" written in black on a gray background.'); + * } + * + * // Save the file when the user double-clicks. + * function doubleClicked() { + * if (mouseX > 0 && mouseX < 100 && mouseY > 0 && mouseY < 100) { + * // Create an object. + * let data = { x: mouseX, y: mouseY }; + * + * // Save the JSON file. + * saveJSON(data, 'state.json'); + * } + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(12); + * + * // Display instructions. + * text('Double-click to save', 5, 50, 90); + * + * describe('The text "Double-click to save" written in black on a gray background.'); + * } + * + * // Save the file when the user double-clicks. + * function doubleClicked() { + * if (mouseX > 0 && mouseX < 100 && mouseY > 0 && mouseY < 100) { + * // Create an object. + * let data = { x: mouseX, y: mouseY }; + * + * // Save the JSON file and reduce its size. + * saveJSON(data, 'state.json', true); + * } + * } + * + *
*/ _main.default.prototype.saveJSON = function (json, filename, opt) { _main.default._validateParameters('saveJSON', arguments); @@ -89634,42 +101201,137 @@ _main.default.prototype.saveJSONObject = _main.default.prototype.saveJSON; _main.default.prototype.saveJSONArray = _main.default.prototype.saveJSON; /** - * Writes an array of Strings to a text file, one line per String. - * The file saving process and location of the saved file will - * vary between web browsers. + * Saves an `Array` of `String`s to a file, one per line. + * + * The first parameter, `list`, is an array with the strings to save. + * + * The second parameter, `filename`, is a string that sets the file's name. + * For example, calling `saveStrings(['0', '01', '011'], 'data.txt')` saves + * the array `['0', '01', '011']` to a file called `data.txt` on the user's + * computer. + * + * The third parameter, `extension`, is optional. If a string is passed, as in + * `saveStrings(['0', '01', '0`1'], 'data', 'txt')`, the second parameter will + * be interpreted as the file name and the third parameter as the extension. + * + * The fourth parameter, `isCRLF`, is also optional, If `true` is passed, as + * in `saveStrings(['0', '01', '011'], 'data', 'txt', true)`, then two + * characters, `\r\n` , will be added to the end of each string to create new + * lines in the saved file. `\r` is a carriage return (CR) and `\n` is a line + * feed (LF). By default, only `\n` (line feed) is added to each string in + * order to create new lines. + * + * Note: The browser will either save the file immediately or prompt the user + * with a dialogue window. * * @method saveStrings - * @param {String[]} list string array to be written - * @param {String} filename filename for output - * @param {String} [extension] the filename's extension - * @param {Boolean} [isCRLF] if true, change line-break to CRLF - * @example - *
- * let words = 'apple bear cat dog'; + * @param {String[]} list data to save. + * @param {String} filename name of file to be saved. + * @param {String} [extension] format to use for the file. + * @param {Boolean} [isCRLF] whether to add `\r\n` to the end of each + * string. Defaults to `false`. * - * // .split() outputs an Array - * let list = split(words, ' '); + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(12); + * + * // Display instructions. + * text('Double-click to save', 5, 50, 90); + * + * describe('The text "Double-click to save" written in black on a gray background.'); + * } + * + * // Save the file when the user double-clicks. + * function doubleClicked() { + * if (mouseX > 0 && mouseX < 100 && mouseY > 0 && mouseY < 100) { + * // Create an array. + * let data = ['0', '01', '011']; + * + * // Save the text file. + * saveStrings(data, 'data.txt'); + * } + * } + * + *
+ * + *
+ * * function setup() { * createCanvas(100, 100); + * * background(200); - * text('click here to save', 10, 10, 70, 80); - * describe('no image displayed'); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(12); + * + * // Display instructions. + * text('Double-click to save', 5, 50, 90); + * + * describe('The text "Double-click to save" written in black on a gray background.'); * } * - * function mousePressed() { - * if (mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height) { - * saveStrings(list, 'nouns.txt'); + * // Save the file when the user double-clicks. + * function doubleClicked() { + * if (mouseX > 0 && mouseX < 100 && mouseY > 0 && mouseY < 100) { + * // Create an array. + * // ASCII art courtesy Wikipedia: + * // https://en.wikipedia.org/wiki/ASCII_art + * let data = [' (\\_/) ', "(='.'=)", '(")_(")']; + * + * // Save the text file. + * saveStrings(data, 'cat', 'txt'); * } * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(12); + * + * // Display instructions. + * text('Double-click to save', 5, 50, 90); + * + * describe('The text "Double-click to save" written in black on a gray background.'); + * } * - * // Saves the following to a file called 'nouns.txt': - * // - * // apple - * // bear - * // cat - * // dog - *
+ * // Save the file when the user double-clicks. + * function doubleClicked() { + * if (mouseX > 0 && mouseX < 100 && mouseY > 0 && mouseY < 100) { + * // Create an array. + * // +--+ + * // / /| + * // +--+ + + * // | |/ + * // +--+ + * let data = [' +--+', ' / /|', '+--+ +', '| |/', '+--+']; + * + * // Save the text file. + * // Use CRLF for line endings. + * saveStrings(data, 'box', 'txt', true); + * } + * } + *
+ *
*/ _main.default.prototype.saveStrings = function (list, filename, extension, isCRLF) { _main.default._validateParameters('saveStrings', arguments); @@ -89914,8 +101576,7 @@ * @private */ _main.default.prototype._isSafari = function () { - var x = Object.prototype.toString.call(window.HTMLElement); - return x.indexOf('Constructor') > 0; + return window.HTMLElement.toString().includes('Constructor'); }; /** * Helper function, a callback for download that deletes @@ -89931,64 +101592,63 @@ exports.default = _default; }, { - '../core/friendly_errors/fes_core': 289, - '../core/friendly_errors/file_errors': 290, - '../core/friendly_errors/validate_params': 293, - '../core/main': 298, - 'core-js/modules/es.array.concat': 169, - 'core-js/modules/es.array.includes': 177, - 'core-js/modules/es.array.index-of': 178, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.last-index-of': 181, - 'core-js/modules/es.array.map': 182, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.array.splice': 185, - 'core-js/modules/es.function.name': 186, - 'core-js/modules/es.object.from-entries': 195, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.promise': 201, - 'core-js/modules/es.regexp.exec': 205, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.string.includes': 209, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.string.replace': 214, - 'core-js/modules/es.string.split': 216, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.typed-array.copy-within': 223, - 'core-js/modules/es.typed-array.every': 224, - 'core-js/modules/es.typed-array.fill': 225, - 'core-js/modules/es.typed-array.filter': 226, - 'core-js/modules/es.typed-array.find': 228, - 'core-js/modules/es.typed-array.find-index': 227, - 'core-js/modules/es.typed-array.for-each': 231, - 'core-js/modules/es.typed-array.includes': 232, - 'core-js/modules/es.typed-array.index-of': 233, - 'core-js/modules/es.typed-array.iterator': 236, - 'core-js/modules/es.typed-array.join': 237, - 'core-js/modules/es.typed-array.last-index-of': 238, - 'core-js/modules/es.typed-array.map': 239, - 'core-js/modules/es.typed-array.reduce': 241, - 'core-js/modules/es.typed-array.reduce-right': 240, - 'core-js/modules/es.typed-array.reverse': 242, - 'core-js/modules/es.typed-array.set': 243, - 'core-js/modules/es.typed-array.slice': 244, - 'core-js/modules/es.typed-array.some': 245, - 'core-js/modules/es.typed-array.sort': 246, - 'core-js/modules/es.typed-array.subarray': 247, - 'core-js/modules/es.typed-array.to-locale-string': 248, - 'core-js/modules/es.typed-array.to-string': 249, - 'core-js/modules/es.typed-array.uint8-array': 252, - 'core-js/modules/web.dom-collections.iterator': 256, - 'core-js/modules/web.url': 258, - 'es6-promise/auto': 259, - 'fetch-jsonp': 261, - 'file-saver': 262, - 'whatwg-fetch': 275 + '../core/friendly_errors/fes_core': 297, + '../core/friendly_errors/file_errors': 298, + '../core/friendly_errors/validate_params': 301, + '../core/main': 306, + 'core-js/modules/es.array.concat': 171, + 'core-js/modules/es.array.includes': 181, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.last-index-of': 185, + 'core-js/modules/es.array.map': 186, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.array.splice': 189, + 'core-js/modules/es.function.name': 192, + 'core-js/modules/es.object.from-entries': 203, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.promise': 209, + 'core-js/modules/es.regexp.exec': 213, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.string.includes': 217, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.string.replace': 222, + 'core-js/modules/es.string.split': 224, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.typed-array.copy-within': 231, + 'core-js/modules/es.typed-array.every': 232, + 'core-js/modules/es.typed-array.fill': 233, + 'core-js/modules/es.typed-array.filter': 234, + 'core-js/modules/es.typed-array.find': 236, + 'core-js/modules/es.typed-array.find-index': 235, + 'core-js/modules/es.typed-array.for-each': 239, + 'core-js/modules/es.typed-array.includes': 240, + 'core-js/modules/es.typed-array.index-of': 241, + 'core-js/modules/es.typed-array.iterator': 244, + 'core-js/modules/es.typed-array.join': 245, + 'core-js/modules/es.typed-array.last-index-of': 246, + 'core-js/modules/es.typed-array.map': 247, + 'core-js/modules/es.typed-array.reduce': 249, + 'core-js/modules/es.typed-array.reduce-right': 248, + 'core-js/modules/es.typed-array.reverse': 250, + 'core-js/modules/es.typed-array.set': 251, + 'core-js/modules/es.typed-array.slice': 252, + 'core-js/modules/es.typed-array.some': 253, + 'core-js/modules/es.typed-array.sort': 254, + 'core-js/modules/es.typed-array.subarray': 255, + 'core-js/modules/es.typed-array.to-locale-string': 256, + 'core-js/modules/es.typed-array.to-string': 257, + 'core-js/modules/es.typed-array.uint8-array': 260, + 'core-js/modules/web.dom-collections.iterator': 264, + 'core-js/modules/web.url': 266, + 'es6-promise/auto': 267, + 'fetch-jsonp': 269, + 'file-saver': 270, + 'whatwg-fetch': 283 } ], - 325: [ + 333: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.array.concat'); @@ -90111,7 +101771,9 @@ *
*
*/ - function _class(rows) { + function _class() { + var rows = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [ + ]; _classCallCheck(this, _class); this.columns = [ ]; @@ -90122,8 +101784,7 @@ * @property rows * @name rows */ - this.rows = [ - ]; + this.rows = rows; } /** * Use addRow() to add a new row of data to a p5.Table object. By default, * an empty row is created. Typically, you would store a reference to @@ -91422,19 +103083,19 @@ exports.default = _default; }, { - '../core/main': 298, - 'core-js/modules/es.array.concat': 169, - 'core-js/modules/es.array.index-of': 178, - 'core-js/modules/es.array.join': 180, - 'core-js/modules/es.array.splice': 185, - 'core-js/modules/es.regexp.constructor': 204, - 'core-js/modules/es.regexp.exec': 205, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.string.match': 211, - 'core-js/modules/es.string.replace': 214 + '../core/main': 306, + 'core-js/modules/es.array.concat': 171, + 'core-js/modules/es.array.index-of': 182, + 'core-js/modules/es.array.join': 184, + 'core-js/modules/es.array.splice': 189, + 'core-js/modules/es.regexp.constructor': 212, + 'core-js/modules/es.regexp.exec': 213, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.string.match': 219, + 'core-js/modules/es.string.replace': 222 } ], - 326: [ + 334: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.array.index-of'); @@ -91833,18 +103494,18 @@ exports.default = _default; }, { - '../core/main': 298, - 'core-js/modules/es.array.index-of': 178, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.object.from-entries': 195, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.regexp.exec': 205, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.string.split': 216, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/main': 306, + 'core-js/modules/es.array.index-of': 182, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.object.from-entries': 203, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.regexp.exec': 213, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.string.split': 224, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 327: [ + 335: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -91902,47 +103563,62 @@ * @requires core */ /** - * XML is a representation of an XML object, able to parse XML code. Use - * loadXML() to load external XML files and create XML objects. + * A class to describe an XML object. + * + * Each `p5.XML` object provides an easy way to interact with XML data. + * Extensible Markup Language + * (XML) + * is a standard format for sending data between applications. Like HTML, the + * XML format is based on tags and attributes, as in + * `<time units="s">1234</time>`. + * + * Note: Use loadXML() to load external XML files. * * @class p5.XML * @constructor - * @example - *
- * // The following short XML file called "mammals.xml" is parsed - * // in the code below. - * // - * // - * // <mammals> - * // <animal id="0" species="Capra hircus">Goat</animal> - * // <animal id="1" species="Panthera pardus">Leopard</animal> - * // <animal id="2" species="Equus zebra">Zebra</animal> - * // </mammals> * - * let xml; + * @example + *
+ * + * let myXML; * + * // Load the XML and create a p5.XML object. * function preload() { - * xml = loadXML('assets/mammals.xml'); + * myXML = loadXML('assets/animals.xml'); * } * * function setup() { - * let children = xml.getChildren('animal'); + * createCanvas(100, 100); + * + * background(200); + * + * // Get an array with all mammal tags. + * let mammals = myXML.getChildren('mammal'); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(14); + * + * // Iterate over the mammals array. + * for (let i = 0; i < mammals.length; i += 1) { + * + * // Calculate the y-coordinate. + * let y = (i + 1) * 25; * - * for (let i = 0; i < children.length; i++) { - * let id = children[i].getNum('id'); - * let coloring = children[i].getString('species'); - * let name = children[i].getContent(); - * print(id + ', ' + coloring + ', ' + name); + * // Get the mammal's common name. + * let name = mammals[i].getContent(); + * + * // Display the mammal's name. + * text(name, 20, y); * } * - * describe('no image displayed'); + * describe( + * 'The words "Goat", "Leopard", and "Zebra" written on three separate lines. The text is black on a gray background.' + * ); * } - * - * // Sketch prints: - * // 0, Capra hircus, Goat - * // 1, Panthera pardus, Leopard - * // 2, Equus zebra, Zebra - *
+ *
+ *
*/ _main.default.XML = /*#__PURE__*/ function () { @@ -91955,38 +103631,51 @@ this.DOM = DOM; } } /** - * Gets a copy of the element's parent. Returns the parent as another - * p5.XML object. + * Returns the element's parent element as a new p5.XML + * object. * * @method getParent - * @return {p5.XML} element parent - * @example - *
- * // The following short XML file called "mammals.xml" is parsed - * // in the code below. - * // - * // - * // <mammals> - * // <animal id="0" species="Capra hircus">Goat</animal> - * // <animal id="1" species="Panthera pardus">Leopard</animal> - * // <animal id="2" species="Equus zebra">Zebra</animal> - * // </mammals> + * @return {p5.XML} parent element. * - * let xml; + * @example + *
+ * + * let myXML; * + * // Load the XML and create a p5.XML object. * function preload() { - * xml = loadXML('assets/mammals.xml'); + * myXML = loadXML('assets/animals.xml'); * } * * function setup() { - * let children = xml.getChildren('animal'); - * let parent = children[1].getParent(); - * print(parent.getName()); - * } + * createCanvas(100, 100); * - * // Sketch prints: - * // mammals - *
+ * background(200); + * + * // Get an array with all mammal elements. + * let mammals = myXML.getChildren('mammal'); + * + * // Get the first mammal element. + * let firstMammal = mammals[0]; + * + * // Get the parent element. + * let parent = firstMammal.getParent(); + * + * // Get the parent element's name. + * let name = parent.getName(); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textFont('Courier New'); + * textSize(14); + * + * // Display the parent element's name. + * text(name, 50, 50); + * + * describe('The word "animals" written in black on a gray background.'); + * } + *
+ *
*/ _createClass(_class, [ @@ -91995,35 +103684,50 @@ value: function getParent() { return new _main.default.XML(this.DOM.parentElement); } /** - * Gets the element's full name, which is returned as a String. + * Returns the element's name as a `String`. + * + * An XML element's name is given by its tag. For example, the element + * `<language>JavaScript</language>` has the name `language`. * * @method getName - * @return {String} the name of the node - * @example<animal - *
- * // The following short XML file called "mammals.xml" is parsed - * // in the code below. - * // - * // - * // <mammals> - * // <animal id="0" species="Capra hircus">Goat</animal> - * // <animal id="1" species="Panthera pardus">Leopard</animal> - * // <animal id="2" species="Equus zebra">Zebra</animal> - * // </mammals> + * @return {String} name of the element. * - * let xml; + * @example + *
+ * + * let myXML; * + * // Load the XML and create a p5.XML object. * function preload() { - * xml = loadXML('assets/mammals.xml'); + * myXML = loadXML('assets/animals.xml'); * } * * function setup() { - * print(xml.getName()); - * } + * createCanvas(100, 100); * - * // Sketch prints: - * // mammals - *
+ * background(200); + * + * // Get an array with all mammal elements. + * let mammals = myXML.getChildren('mammal'); + * + * // Get the first mammal element. + * let firstMammal = mammals[0]; + * + * // Get the mammal element's name. + * let name = firstMammal.getName(); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textFont('Courier New'); + * textSize(14); + * + * // Display the element's name. + * text(name, 50, 50); + * + * describe('The word "mammal" written in black on a gray background.'); + * } + *
+
*/ }, @@ -92032,37 +103736,55 @@ value: function getName() { return this.DOM.tagName; } /** - * Sets the element's name, which is specified as a String. + * Sets the element's tag name. + * + * An XML element's name is given by its tag. For example, the element + * `<language>JavaScript</language>` has the name `language`. + * + * The parameter, `name`, is the element's new name as a string. For example, + * calling `myXML.setName('planet')` will make the element's new tag name + * `<planet></planet>`. * * @method setName - * @param {String} the new name of the node - * @example<animal - *
- * // The following short XML file called "mammals.xml" is parsed - * // in the code below. - * // - * // - * // <mammals> - * // <animal id="0" species="Capra hircus">Goat</animal> - * // <animal id="1" species="Panthera pardus">Leopard</animal> - * // <animal id="2" species="Equus zebra">Zebra</animal> - * // </mammals> + * @param {String} name new tag name of the element. * - * let xml; + * @example + *
+ * + * let myXML; * + * // Load the XML and create a p5.XML object. * function preload() { - * xml = loadXML('assets/mammals.xml'); + * myXML = loadXML('assets/animals.xml'); * } * * function setup() { - * print(xml.getName()); - * xml.setName('fish'); - * print(xml.getName()); - * } + * createCanvas(100, 100); * - * // Sketch prints: - * // mammals - * // fish + * background(200); + * + * // Get the element's original name. + * let oldName = myXML.getName(); + * + * // Set the element's name. + * myXML.setName('monsters'); + * + * // Get the element's new name. + * let newName = myXML.getName(); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textFont('Courier New'); + * textSize(14); + * + * // Display the element's names. + * text(oldName, 50, 33); + * text(newName, 50, 67); + * + * describe( + * 'The words "animals" and "monsters" written on separate lines. The text is black on a gray background.' + * ); + * } *
*/ @@ -92076,40 +103798,49 @@ var newDOM = xmlDoc.createElement(name); newDOM.innerHTML = content; for (var i = 0; i < attributes.length; i++) { - newDOM.setAttribute(attributes[i].nodeName, attributes.nodeValue); + newDOM.setAttribute(attributes[i].nodeName, attributes[i].nodeValue); } this.DOM = newDOM; } /** - * Checks whether or not the element has any children, and returns the result - * as a boolean. + * Returns `true` if the element has child elements and `false` if not. * * @method hasChildren - * @return {boolean} - * @example<animal - *
- * // The following short XML file called "mammals.xml" is parsed - * // in the code below. - * // - * // - * // <mammals> - * // <animal id="0" species="Capra hircus">Goat</animal> - * // <animal id="1" species="Panthera pardus">Leopard</animal> - * // <animal id="2" species="Equus zebra">Zebra</animal> - * // </mammals> + * @return {boolean} whether the element has children. * - * let xml; + * @example + *
+ * + * let myXML; * + * // Load the XML and create a p5.XML object. * function preload() { - * xml = loadXML('assets/mammals.xml'); + * myXML = loadXML('assets/animals.xml'); * } * * function setup() { - * print(xml.hasChildren()); - * } + * createCanvas(100, 100); * - * // Sketch prints: - * // true - *
+ * background(200); + * + * // Check whether the element has child elements. + * let isParent = myXML.hasChildren(); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textFont('Courier New'); + * textSize(14); + * + * // Style the text. + * if (isParent === true) { + * text('Parent', 50, 50); + * } else { + * text('Not Parent', 50, 50); + * } + * + * describe('The word "Parent" written in black on a gray background.'); + * } + *
+ *
*/ }, @@ -92118,37 +103849,51 @@ value: function hasChildren() { return this.DOM.children.length > 0; } /** - * Get the names of all of the element's children, and returns the names as an - * array of Strings. This is the same as looping through and calling getName() - * on each child element individually. + * Returns an array with the names of the element's child elements as + * `String`s. * * @method listChildren - * @return {String[]} names of the children of the element - * @example<animal - *
- * // The following short XML file called "mammals.xml" is parsed - * // in the code below. - * // - * // - * // <mammals> - * // <animal id="0" species="Capra hircus">Goat</animal> - * // <animal id="1" species="Panthera pardus">Leopard</animal> - * // <animal id="2" species="Equus zebra">Zebra</animal> - * // </mammals> + * @return {String[]} names of the child elements. * - * let xml; + * @example + *
+ * + * let myXML; * + * // Load the XML and create a p5.XML object. * function preload() { - * xml = loadXML('assets/mammals.xml'); + * myXML = loadXML('assets/animals.xml'); * } * * function setup() { - * print(xml.listChildren()); - * } + * createCanvas(100, 100); * - * // Sketch prints: - * // ["animal", "animal", "animal"] - *
+ * background(200); + * + * // Get the names of the element's children as an array. + * let children = myXML.listChildren(); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(14); + * + * // Iterate over the array. + * for (let i = 0; i < children.length; i += 1) { + * + * // Calculate the y-coordinate. + * let y = (i + 1) * 25; + * + * // Display the child element's name. + * text(children[i], 10, y); + * } + * + * describe( + * 'The words "mammal", "mammal", "mammal", and "reptile" written on separate lines. The text is black on a gray background.' + * ); + * } + *
+ *
*/ }, @@ -92162,44 +103907,102 @@ } return arr; } /** - * Returns all of the element's children as an array of p5.XML objects. When - * the name parameter is specified, then it will return all children that match - * that name. + * Returns an array with the element's child elements as new + * p5.XML objects. + * + * The parameter, `name`, is optional. If a string is passed, as in + * `myXML.getChildren('cat')`, then the method will only return child elements + * with the tag `<cat>`. * * @method getChildren - * @param {String} [name] element name - * @return {p5.XML[]} children of the element - * @example<animal - *
- * // The following short XML file called "mammals.xml" is parsed - * // in the code below. - * // - * // - * // <mammals> - * // <animal id="0" species="Capra hircus">Goat</animal> - * // <animal id="1" species="Panthera pardus">Leopard</animal> - * // <animal id="2" species="Equus zebra">Zebra</animal> - * // </mammals> + * @param {String} [name] name of the elements to return. + * @return {p5.XML[]} child elements. * - * let xml; + * @example + *
+ * + * let myXML; * + * // Load the XML and create a p5.XML object. * function preload() { - * xml = loadXML('assets/mammals.xml'); + * myXML = loadXML('assets/animals.xml'); * } * * function setup() { - * let animals = xml.getChildren('animal'); + * createCanvas(100, 100); + * + * background(200); + * + * // Get an array of the child elements. + * let children = myXML.getChildren(); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(14); + * + * // Iterate over the array. + * for (let i = 0; i < children.length; i += 1) { + * + * // Calculate the y-coordinate. + * let y = (i + 1) * 20; * - * for (let i = 0; i < animals.length; i++) { - * print(animals[i].getContent()); + * // Get the child element's content. + * let content = children[i].getContent(); + * + * // Display the child element's content. + * text(content, 10, y); * } + * + * describe( + * 'The words "Goat", "Leopard", "Zebra", and "Turtle" written on separate lines. The text is black on a gray background.' + * ); * } + * + *
* - * // Sketch prints: - * // "Goat" - * // "Leopard" - * // "Zebra" - *
+ *
+ * + * let myXML; + * + * // Load the XML and create a p5.XML object. + * function preload() { + * myXML = loadXML('assets/animals.xml'); + * } + * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Get an array of the child elements + * // that are mammals. + * let children = myXML.getChildren('mammal'); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(14); + * + * // Iterate over the array. + * for (let i = 0; i < children.length; i += 1) { + * + * // Calculate the y-coordinate. + * let y = (i + 1) * 20; + * + * // Get the child element's content. + * let content = children[i].getContent(); + * + * // Display the child element's content. + * text(content, 10, y); + * } + * + * describe( + * 'The words "Goat", "Leopard", and "Zebra" written on separate lines. The text is black on a gray background.' + * ); + * } + * + *
*/ }, @@ -92212,54 +104015,84 @@ return elementsToP5XML(this.DOM.children); } } /** - * Returns the first of the element's children that matches the name parameter - * or the child of the given index.It returns undefined if no matching - * child is found. + * Returns the first matching child element as a new + * p5.XML object. + * + * The parameter, `name`, is optional. If a string is passed, as in + * `myXML.getChild('cat')`, then the first child element with the tag + * `<cat>` will be returned. If a number is passed, as in + * `myXML.getChild(1)`, then the child element at that index will be returned. * * @method getChild - * @param {String|Integer} name element name or index - * @return {p5.XML} - * @example<animal - *
- * // The following short XML file called "mammals.xml" is parsed - * // in the code below. - * // - * // - * // <mammals> - * // <animal id="0" species="Capra hircus">Goat</animal> - * // <animal id="1" species="Panthera pardus">Leopard</animal> - * // <animal id="2" species="Equus zebra">Zebra</animal> - * // </mammals> + * @param {String|Integer} name element name or index. + * @return {p5.XML} child element. * - * let xml; + * @example + *
+ * + * let myXML; * + * // Load the XML and create a p5.XML object. * function preload() { - * xml = loadXML('assets/mammals.xml'); + * myXML = loadXML('assets/animals.xml'); * } * * function setup() { - * let firstChild = xml.getChild('animal'); - * print(firstChild.getContent()); + * createCanvas(100, 100); + * + * background(200); + * + * // Get the first child element that is a mammal. + * let goat = myXML.getChild('mammal'); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textFont('Courier New'); + * textSize(14); + * + * // Get the child element's content. + * let content = goat.getContent(); + * + * // Display the child element's content. + * text(content, 50, 50); + * + * describe('The word "Goat" written in black on a gray background.'); * } + * + *
* - * // Sketch prints: - * // "Goat" - *
- *
- * let xml; + *
+ * + * let myXML; * + * // Load the XML and create a p5.XML object. * function preload() { - * xml = loadXML('assets/mammals.xml'); + * myXML = loadXML('assets/animals.xml'); * } * * function setup() { - * let secondChild = xml.getChild(1); - * print(secondChild.getContent()); - * } + * createCanvas(100, 100); * - * // Sketch prints: - * // "Leopard" - *
+ * background(200); + * + * // Get the child element at index 1. + * let leopard = myXML.getChild(1); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textFont('Courier New'); + * textSize(14); + * + * // Get the child element's content. + * let content = leopard.getContent(); + * + * // Display the child element's content. + * text(content, 50, 50); + * + * describe('The word "Leopard" written in black on a gray background.'); + * } + *
+ *
*/ }, @@ -92293,48 +104126,61 @@ return new _main.default.XML(this.DOM.children[param]); } } /** - * Appends a new child to the element. The child can be specified with - * either a String, which will be used as the new tag's name, or as a - * reference to an existing p5.XML object. - * A reference to the newly created child is returned as an p5.XML object. + * Adds a new child element and returns a reference to it. + * + * The parameter, `child`, is the p5.XML object to add + * as a child element. For example, calling `myXML.addChild(otherXML)` inserts + * `otherXML` as a child element of `myXML`. * * @method addChild - * @param {p5.XML} node a p5.XML Object which will be the child to be added - * @example - *
- * // The following short XML file called "mammals.xml" is parsed - * // in the code below. - * // - * // - * // <mammals> - * // <animal id="0" species="Capra hircus">Goat</animal> - * // <animal id="1" species="Panthera pardus">Leopard</animal> - * // <animal id="2" species="Equus zebra">Zebra</animal> - * // </mammals> + * @param {p5.XML} child child element to add. + * @return {p5.XML} added child element. * - * let xml; + * @example + *
+ * + * let myXML; * + * // Load the XML and create a p5.XML object. * function preload() { - * xml = loadXML('assets/mammals.xml'); + * myXML = loadXML('assets/animals.xml'); * } * * function setup() { - * let child = new p5.XML(); - * child.setName('animal'); - * child.setAttribute('id', '3'); - * child.setAttribute('species', 'Ornithorhynchus anatinus'); - * child.setContent('Platypus'); - * xml.addChild(child); - * - * let animals = xml.getChildren('animal'); - * print(animals[animals.length - 1].getContent()); - * } + * createCanvas(100, 100); * - * // Sketch prints: - * // "Goat" - * // "Leopard" - * // "Zebra" - *
+ * background(200); + * + * // Create a new p5.XML object. + * let newAnimal = new p5.XML(); + * + * // Set its properties. + * newAnimal.setName('hydrozoa'); + * newAnimal.setAttribute('id', 4); + * newAnimal.setAttribute('species', 'Physalia physalis'); + * newAnimal.setContent('Bluebottle'); + * + * // Add the child element. + * myXML.addChild(newAnimal); + * + * // Get the first child element that is a hydrozoa. + * let blueBottle = myXML.getChild('hydrozoa'); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textFont('Courier New'); + * textSize(14); + * + * // Get the child element's content. + * let content = blueBottle.getContent(); + * + * // Display the child element's content. + * text(content, 50, 50); + * + * describe('The word "Bluebottle" written in black on a gray background.'); + * } + *
+ *
*/ }, @@ -92347,59 +104193,107 @@ // PEND } } /** - * Removes the element specified by name or index. + * Removes the first matching child element. + * + * The parameter, `name`, is the child element to remove. If a string is + * passed, as in `myXML.removeChild('cat')`, then the first child element + * with the tag `<cat>` will be removed. If a number is passed, as in + * `myXML.removeChild(1)`, then the child element at that index will be + * removed. * * @method removeChild - * @param {String|Integer} name element name or index - * @example - *
- * // The following short XML file called "mammals.xml" is parsed - * // in the code below. - * // - * // - * // <mammals> - * // <animal id="0" species="Capra hircus">Goat</animal> - * // <animal id="1" species="Panthera pardus">Leopard</animal> - * // <animal id="2" species="Equus zebra">Zebra</animal> - * // </mammals> + * @param {String|Integer} name name or index of the child element to remove. * - * let xml; + * @example + *
+ * + * let myXML; * + * // Load the XML and create a p5.XML object. * function preload() { - * xml = loadXML('assets/mammals.xml'); + * myXML = loadXML('assets/animals.xml'); * } * * function setup() { - * xml.removeChild('animal'); - * let children = xml.getChildren(); - * for (let i = 0; i < children.length; i++) { - * print(children[i].getContent()); + * createCanvas(100, 100); + * + * background(200); + * + * // Remove the first mammal element. + * myXML.removeChild('mammal'); + * + * // Get an array of child elements. + * let children = myXML.getChildren(); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(14); + * + * // Iterate over the array. + * for (let i = 0; i < children.length; i += 1) { + * + * // Calculate the y-coordinate. + * let y = (i + 1) * 25; + * + * // Get the child element's content. + * let content = children[i].getContent(); + * + * // Display the child element's content. + * text(content, 10, y); * } + * + * describe( + * 'The words "Leopard", "Zebra", and "Turtle" written on separate lines. The text is black on a gray background.' + * ); * } + * + *
* - * // Sketch prints: - * // "Leopard" - * // "Zebra" - *
- *
- * let xml; + *
+ * + * let myXML; * + * // Load the XML and create a p5.XML object. * function preload() { - * xml = loadXML('assets/mammals.xml'); + * myXML = loadXML('assets/animals.xml'); * } * * function setup() { - * xml.removeChild(1); - * let children = xml.getChildren(); - * for (let i = 0; i < children.length; i++) { - * print(children[i].getContent()); + * createCanvas(100, 100); + * + * background(200); + * + * // Remove the element at index 2. + * myXML.removeChild(2); + * + * // Get an array of child elements. + * let children = myXML.getChildren(); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(14); + * + * // Iterate over the array. + * for (let i = 0; i < children.length; i += 1) { + * + * // Calculate the y-coordinate. + * let y = (i + 1) * 25; + * + * // Get the child element's content. + * let content = children[i].getContent(); + * + * // Display the child element's content. + * text(content, 10, y); * } - * } * - * // Sketch prints: - * // "Goat" - * // "Zebra" - *
+ * describe( + * 'The words "Goat", "Leopard", and "Turtle" written on separate lines. The text is black on a gray background.' + * ); + * } + *
+ *
*/ }, @@ -92421,36 +104315,44 @@ this.DOM.removeChild(this.DOM.children[ind]); } } /** - * Counts the specified element's number of attributes, returned as an Number. + * Returns the number of attributes the element has. * * @method getAttributeCount - * @return {Integer} - * @example - *
- * // The following short XML file called "mammals.xml" is parsed - * // in the code below. - * // - * // - * // <mammals> - * // <animal id="0" species="Capra hircus">Goat</animal> - * // <animal id="1" species="Panthera pardus">Leopard</animal> - * // <animal id="2" species="Equus zebra">Zebra</animal> - * // </mammals> + * @return {Integer} number of attributes. * - * let xml; + * @example + *
+ * + * let myXML; * + * // Load the XML and create a p5.XML object. * function preload() { - * xml = loadXML('assets/mammals.xml'); + * myXML = loadXML('assets/animals.xml'); * } * * function setup() { - * let firstChild = xml.getChild('animal'); - * print(firstChild.getAttributeCount()); - * } + * createCanvas(100, 100); * - * // Sketch prints: - * // 2 - *
+ * background(200); + * + * // Get the first child element. + * let first = myXML.getChild(0); + * + * // Get the number of attributes. + * let numAttributes = first.getAttributeCount(); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textFont('Courier New'); + * textSize(14); + * + * // Display the number of attributes. + * text(numAttributes, 50, 50); + * + * describe('The number "2" written in black on a gray background.'); + * } + *
+ *
*/ }, @@ -92459,37 +104361,48 @@ value: function getAttributeCount() { return this.DOM.attributes.length; } /** - * Gets all of the specified element's attributes, and returns them as an - * array of Strings. + * Returns an `Array` with the names of the element's attributes. + * + * Note: Use + * myXML.getString() or + * myXML.getNum() to return an attribute's value. * * @method listAttributes - * @return {String[]} an array of strings containing the names of attributes - * @example - *
- * // The following short XML file called "mammals.xml" is parsed - * // in the code below. - * // - * // - * // <mammals> - * // <animal id="0" species="Capra hircus">Goat</animal> - * // <animal id="1" species="Panthera pardus">Leopard</animal> - * // <animal id="2" species="Equus zebra">Zebra</animal> - * // </mammals> + * @return {String[]} attribute names. * - * let xml; + * @example + *
+ * + * let myXML; * + * // Load the XML and create a p5.XML object. * function preload() { - * xml = loadXML('assets/mammals.xml'); + * myXML = loadXML('assets/animals.xml'); * } * * function setup() { - * let firstChild = xml.getChild('animal'); - * print(firstChild.listAttributes()); - * } + * createCanvas(100, 100); * - * // Sketch prints: - * // ["id", "species"] - *
+ * background(200); + * + * // Get the first child element. + * let first = myXML.getChild(0); + * + * // Get the number of attributes. + * let attributes = first.listAttributes(); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textFont('Courier New'); + * textSize(14); + * + * // Display the element's attributes. + * text(attributes, 50, 50); + * + * describe('The text "id,species" written in black on a gray background.'); + * } + *
+ *
*/ }, @@ -92522,39 +104435,57 @@ } return arr; } /** - * Checks whether or not an element has the specified attribute. + * Returns `true` if the element has a given attribute and `false` if not. + * + * The parameter, `name`, is a string with the name of the attribute being + * checked. + * + * Note: Use + * myXML.getString() or + * myXML.getNum() to return an attribute's value. * * @method hasAttribute - * @param {String} the attribute to be checked - * @return {boolean} true if attribute found else false - * @example - *
- * // The following short XML file called "mammals.xml" is parsed - * // in the code below. - * // - * // - * // <mammals> - * // <animal id="0" species="Capra hircus">Goat</animal> - * // <animal id="1" species="Panthera pardus">Leopard</animal> - * // <animal id="2" species="Equus zebra">Zebra</animal> - * // </mammals> + * @param {String} name name of the attribute to be checked. + * @return {boolean} whether the element has the attribute. * - * let xml; + * @example + *
+ * + * let myXML; * + * // Load the XML and create a p5.XML object. * function preload() { - * xml = loadXML('assets/mammals.xml'); + * myXML = loadXML('assets/animals.xml'); * } * * function setup() { - * let firstChild = xml.getChild('animal'); - * print(firstChild.hasAttribute('species')); - * print(firstChild.hasAttribute('color')); - * } + * createCanvas(100, 100); * - * // Sketch prints: - * // true - * // false - *
+ * background(200); + * + * // Get the first mammal child element. + * let mammal = myXML.getChild('mammal'); + * + * // Check whether the element has an + * // species attribute. + * let hasSpecies = mammal.hasAttribute('species'); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textFont('Courier New'); + * textSize(14); + * + * // Display whether the element has a species attribute. + * if (hasSpecies === true) { + * text('Species', 50, 50); + * } else { + * text('No species', 50, 50); + * } + * + * describe('The text "Species" written in black on a gray background.'); + * } + *
+ *
*/ }, @@ -92587,41 +104518,99 @@ } return obj[name] ? true : false; } /** - * Returns an attribute value of the element as an Number. If the defaultValue - * parameter is specified and the attribute doesn't exist, then defaultValue - * is returned. If no defaultValue is specified and the attribute doesn't - * exist, the value 0 is returned. + * Return an attribute's value as a `Number`. + * + * The first parameter, `name`, is a string with the name of the attribute + * being checked. For example, calling `myXML.getNum('id')` returns the + * element's `id` attribute as a number. + * + * The second parameter, `defaultValue`, is optional. If a number is passed, + * as in `myXML.getNum('id', -1)`, it will be returned if the attribute + * doesn't exist or can't be converted to a number. + * + * Note: Use + * myXML.getString() or + * myXML.getNum() to return an attribute's value. * * @method getNum - * @param {String} name the non-null full name of the attribute - * @param {Number} [defaultValue] the default value of the attribute - * @return {Number} - * @example - *
- * // The following short XML file called "mammals.xml" is parsed - * // in the code below. - * // - * // - * // <mammals> - * // <animal id="0" species="Capra hircus">Goat</animal> - * // <animal id="1" species="Panthera pardus">Leopard</animal> - * // <animal id="2" species="Equus zebra">Zebra</animal> - * // </mammals> + * @param {String} name name of the attribute to be checked. + * @param {Number} [defaultValue] value to return if the attribute doesn't exist. + * @return {Number} attribute value as a number. * - * let xml; + * @example + *
+ * + * let myXML; * + * // Load the XML and create a p5.XML object. * function preload() { - * xml = loadXML('assets/mammals.xml'); + * myXML = loadXML('assets/animals.xml'); * } * * function setup() { - * let firstChild = xml.getChild('animal'); - * print(firstChild.getNum('id')); + * createCanvas(100, 100); + * + * background(200); + * + * // Get the first reptile child element. + * let reptile = myXML.getChild('reptile'); + * + * // Get the reptile's content. + * let content = reptile.getContent(); + * + * // Get the reptile's ID. + * let id = reptile.getNum('id'); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(14); + * + * // Display the ID attribute. + * text(`${content} is ${id + 1}th`, 5, 50, 90); + * + * describe(`The text "${content} is ${id + 1}th" written in black on a gray background.`); * } + * + *
* - * // Sketch prints: - * // 0 - *
+ *
+ * + * let myXML; + * + * // Load the XML and create a p5.XML object. + * function preload() { + * myXML = loadXML('assets/animals.xml'); + * } + * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Get the first reptile child element. + * let reptile = myXML.getChild('reptile'); + * + * // Get the reptile's content. + * let content = reptile.getContent(); + * + * // Get the reptile's size. + * let weight = reptile.getNum('weight', 135); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(14); + * + * // Display the ID attribute. + * text(`${content} is ${weight}kg`, 5, 50, 90); + * + * describe( + * `The text "${content} is ${weight}kg" written in black on a gray background.` + * ); + * } + * + *
*/ }, @@ -92654,41 +104643,98 @@ } return Number(obj[name]) || defaultValue || 0; } /** - * Returns an attribute value of the element as an String. If the defaultValue - * parameter is specified and the attribute doesn't exist, then defaultValue - * is returned. If no defaultValue is specified and the attribute doesn't - * exist, null is returned. + * Return an attribute's value as a string. + * + * The first parameter, `name`, is a string with the name of the attribute + * being checked. For example, calling `myXML.getString('color')` returns the + * element's `id` attribute as a string. + * + * The second parameter, `defaultValue`, is optional. If a string is passed, + * as in `myXML.getString('color', 'deeppink')`, it will be returned if the + * attribute doesn't exist. + * + * Note: Use + * myXML.getString() or + * myXML.getNum() to return an attribute's value. * * @method getString - * @param {String} name the non-null full name of the attribute - * @param {Number} [defaultValue] the default value of the attribute - * @return {String} - * @example - *
- * // The following short XML file called "mammals.xml" is parsed - * // in the code below. - * // - * // - * // <mammals> - * // <animal id="0" species="Capra hircus">Goat</animal> - * // <animal id="1" species="Panthera pardus">Leopard</animal> - * // <animal id="2" species="Equus zebra">Zebra</animal> - * // </mammals> + * @param {String} name name of the attribute to be checked. + * @param {Number} [defaultValue] value to return if the attribute doesn't exist. + * @return {String} attribute value as a string. * - * let xml; + * @example + *
+ * + * let myXML; * + * // Load the XML and create a p5.XML object. * function preload() { - * xml = loadXML('assets/mammals.xml'); + * myXML = loadXML('assets/animals.xml'); * } * * function setup() { - * let firstChild = xml.getChild('animal'); - * print(firstChild.getString('species')); + * createCanvas(100, 100); + * + * background(200); + * + * // Get the first reptile child element. + * let reptile = myXML.getChild('reptile'); + * + * // Get the reptile's content. + * let content = reptile.getContent(); + * + * // Get the reptile's species. + * let species = reptile.getString('species'); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(14); + * + * // Display the species attribute. + * text(`${content}: ${species}`, 5, 50, 90); + * + * describe(`The text "${content}: ${species}" written in black on a gray background.`); + * } + * + *
+ * + *
+ * + * let myXML; + * + * // Load the XML and create a p5.XML object. + * function preload() { + * myXML = loadXML('assets/animals.xml'); * } * - * // Sketch prints: - * // "Capra hircus" - *
+ * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Get the first reptile child element. + * let reptile = myXML.getChild('reptile'); + * + * // Get the reptile's content. + * let content = reptile.getContent(); + * + * // Get the reptile's color. + * let attribute = reptile.getString('color', 'green'); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textFont('Courier New'); + * textSize(14); + * fill(attribute); + * + * // Display the element's content. + * text(content, 50, 50); + * + * describe(`The text "${content}" written in green on a gray background.`); + * } + *
+ *
*/ }, @@ -92721,41 +104767,60 @@ } return obj[name] ? String(obj[name]) : defaultValue || null; } /** - * Sets the content of an element's attribute. The first parameter specifies - * the attribute name, while the second specifies the new content. + * Sets an attribute to a given value. + * + * The first parameter, `name`, is a string with the name of the attribute + * being set. + * + * The second parameter, `value`, is the attribute's new value. For example, + * calling `myXML.setAttribute('id', 123)` sets the `id` attribute to the + * value 123. * * @method setAttribute - * @param {String} name the full name of the attribute - * @param {Number|String|Boolean} value the value of the attribute - * @example - *
- * // The following short XML file called "mammals.xml" is parsed - * // in the code below. - * // - * // - * // <mammals> - * // <animal id="0" species="Capra hircus">Goat</animal> - * // <animal id="1" species="Panthera pardus">Leopard</animal> - * // <animal id="2" species="Equus zebra">Zebra</animal> - * // </mammals> + * @param {String} name name of the attribute to be set. + * @param {Number|String|Boolean} value attribute's new value. * - * let xml; + * @example + *
+ * + * let myXML; * + * // Load the XML and create a p5.XML object. * function preload() { - * xml = loadXML('assets/mammals.xml'); + * myXML = loadXML('assets/animals.xml'); * } * * function setup() { - * let firstChild = xml.getChild('animal'); - * print(firstChild.getString('species')); - * firstChild.setAttribute('species', 'Jamides zebra'); - * print(firstChild.getString('species')); - * } + * createCanvas(100, 100); * - * // Sketch prints: - * // "Capra hircus" - * // "Jamides zebra" - *
+ * background(200); + * + * // Get the first reptile child element. + * let reptile = myXML.getChild('reptile'); + * + * // Set the reptile's color. + * reptile.setAttribute('color', 'green'); + * + * // Get the reptile's content. + * let content = reptile.getContent(); + * + * // Get the reptile's color. + * let attribute = reptile.getString('color'); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(14); + * + * // Display the element's content. + * text(`${content} is ${attribute}`, 5, 50, 90); + * + * describe( + * `The text "${content} is ${attribute}" written in green on a gray background.` + * ); + * } + *
+ *
*/ }, @@ -92764,38 +104829,76 @@ value: function setAttribute(name, value) { this.DOM.setAttribute(name, value); } /** - * Returns the content of an element. If there is no such content, - * defaultValue is returned if specified, otherwise null is returned. + * Returns the element's content as a `String`. + * + * The parameter, `defaultValue`, is optional. If a string is passed, as in + * `myXML.getContent('???')`, it will be returned if the element has no + * content. * * @method getContent - * @param {String} [defaultValue] value returned if no content is found - * @return {String} - * @example - *
- * // The following short XML file called "mammals.xml" is parsed - * // in the code below. - * // - * // - * // <mammals> - * // <animal id="0" species="Capra hircus">Goat</animal> - * // <animal id="1" species="Panthera pardus">Leopard</animal> - * // <animal id="2" species="Equus zebra">Zebra</animal> - * // </mammals> + * @param {String} [defaultValue] value to return if the element has no + * content. + * @return {String} element's content as a string. * - * let xml; + * @example + *
+ * + * let myXML; * + * // Load the XML and create a p5.XML object. * function preload() { - * xml = loadXML('assets/mammals.xml'); + * myXML = loadXML('assets/animals.xml'); * } * * function setup() { - * let firstChild = xml.getChild('animal'); - * print(firstChild.getContent()); + * createCanvas(100, 100); + * + * background(200); + * + * // Get the first reptile child element. + * let reptile = myXML.getChild('reptile'); + * + * // Get the reptile's content. + * let content = reptile.getContent(); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textFont('Courier New'); + * textSize(14); + * + * // Display the element's content. + * text(content, 5, 50, 90); + * + * describe(`The text "${content}" written in green on a gray background.`); * } + * + *
* - * // Sketch prints: - * // "Goat" - *
+ *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.XML object. + * let blankSpace = new p5.XML(); + * + * // Get the element's content and use a default value. + * let content = blankSpace.getContent('Your name'); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textFont('Courier New'); + * textSize(14); + * + * // Display the element's content. + * text(content, 5, 50, 90); + * + * describe(`The text "${content}" written in green on a gray background.`); + * } + * + *
*/ }, @@ -92809,37 +104912,55 @@ } /** * Sets the element's content. * + * An element's content is the text between its tags. For example, the element + * `<language>JavaScript</language>` has the content `JavaScript`. + * + * The parameter, `content`, is a string with the element's new content. + * * @method setContent - * @param {String} text the new content - * @example - *
- * // The following short XML file called "mammals.xml" is parsed - * // in the code below. - * // - * // - * // <mammals> - * // <animal id="0" species="Capra hircus">Goat</animal> - * // <animal id="1" species="Panthera pardus">Leopard</animal> - * // <animal id="2" species="Equus zebra">Zebra</animal> - * // </mammals> + * @param {String} content new content for the element. * - * let xml; + * @example + *
+ * + * let myXML; * + * // Load the XML and create a p5.XML object. * function preload() { - * xml = loadXML('assets/mammals.xml'); + * myXML = loadXML('assets/animals.xml'); * } * * function setup() { - * let firstChild = xml.getChild('animal'); - * print(firstChild.getContent()); - * firstChild.setContent('Mountain Goat'); - * print(firstChild.getContent()); - * } + * createCanvas(100, 100); * - * // Sketch prints: - * // "Goat" - * // "Mountain Goat" - *
+ * background(200); + * + * // Get the first reptile child element. + * let reptile = myXML.getChild('reptile'); + * + * // Get the reptile's original content. + * let oldContent = reptile.getContent(); + * + * // Set the reptile's content. + * reptile.setContent('Loggerhead'); + * + * // Get the reptile's new content. + * let newContent = reptile.getContent(); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textFont('Courier New'); + * textSize(14); + * + * // Display the element's old and new content. + * text(`${oldContent}: ${newContent}`, 5, 50, 90); + * + * describe( + * `The text "${oldContent}: ${newContent}" written in green on a gray background.` + * ); + * } + *
+ *
*/ }, @@ -92850,30 +104971,57 @@ this.DOM.textContent = content; } } /** - * Serializes the element into a string. This function is useful for preparing - * the content to be sent over a http request or saved to file. + * Returns the element as a `String`. + * + * `myXML.serialize()` is useful for sending the element over the network or + * saving it to a file. * * @method serialize - * @return {String} Serialized string of the element + * @return {String} element as a string. + * * @example - *
- * let xml; + *
+ * + * let myXML; * + * // Load the XML and create a p5.XML object. * function preload() { - * xml = loadXML('assets/mammals.xml'); + * myXML = loadXML('assets/animals.xml'); * } * * function setup() { - * print(xml.serialize()); + * createCanvas(100, 100); + * + * background(200); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(12); + * + * // Display instructions. + * text('Double-click to save', 5, 50, 90); + * + * describe('The text "Double-click to save" written in black on a gray background.'); * } * - * // Sketch prints: - * // - * // Goat - * // Leopard - * // Zebra - * // - *
+ * // Save the file when the user double-clicks. + * function doubleClicked() { + * // Create a p5.PrintWriter object. + * // Use the file format .xml. + * let myWriter = createWriter('animals', 'xml'); + * + * // Serialize the XML data to a string. + * let data = myXML.serialize(); + * + * // Write the data to the print stream. + * myWriter.write(data); + * + * // Save the file and close the print stream. + * myWriter.close(); + * } + *
+ *
*/ }, @@ -92899,25 +105047,26 @@ exports.default = _default; }, { - '../core/main': 298, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.number.constructor': 191, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.regexp.exec': 205, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.string.replace': 214, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/main': 306, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.number.constructor': 197, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.regexp.exec': 213, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.string.replace': 222, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 328: [ + 336: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); _dereq_('core-js/modules/es.symbol.description'); _dereq_('core-js/modules/es.symbol.iterator'); + _dereq_('core-js/modules/es.array.from'); _dereq_('core-js/modules/es.array.includes'); _dereq_('core-js/modules/es.array.index-of'); _dereq_('core-js/modules/es.array.iterator'); @@ -92926,23 +105075,17 @@ _dereq_('core-js/modules/es.math.hypot'); _dereq_('core-js/modules/es.number.constructor'); _dereq_('core-js/modules/es.object.to-string'); + _dereq_('core-js/modules/es.regexp.to-string'); _dereq_('core-js/modules/es.string.includes'); _dereq_('core-js/modules/es.string.iterator'); _dereq_('core-js/modules/web.dom-collections.iterator'); - _dereq_('core-js/modules/es.symbol'); - _dereq_('core-js/modules/es.symbol.description'); - _dereq_('core-js/modules/es.symbol.iterator'); _dereq_('core-js/modules/es.array.includes'); _dereq_('core-js/modules/es.array.index-of'); - _dereq_('core-js/modules/es.array.iterator'); _dereq_('core-js/modules/es.array.map'); _dereq_('core-js/modules/es.array.slice'); _dereq_('core-js/modules/es.math.hypot'); _dereq_('core-js/modules/es.number.constructor'); - _dereq_('core-js/modules/es.object.to-string'); _dereq_('core-js/modules/es.string.includes'); - _dereq_('core-js/modules/es.string.iterator'); - _dereq_('core-js/modules/web.dom-collections.iterator'); Object.defineProperty(exports, '__esModule', { value: true }); @@ -92953,35 +105096,61 @@ default: obj }; - } /** - * @module Math - * @submodule Calculation - * @for p5 - * @requires core - */ + } + function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); + } + function _nonIterableSpread() { + throw new TypeError('Invalid attempt to spread non-iterable instance'); + } + function _iterableToArray(iter) { + if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === '[object Arguments]') return Array.from(iter); + } + function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) { + for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { + arr2[i] = arr[i]; + } + return arr2; + } + } /** + * @module Math + * @submodule Calculation + * @for p5 + * @requires core + */ /** - * Calculates the absolute value of a number. A number's absolute value is its - * distance from zero on the number line. -5 and 5 are both five units away - * from zero, so calling `abs(-5)` and `abs(5)` both return 5. The absolute - * value of a number is always positive. + * Calculates the absolute value of a number. + * + * A number's absolute value is its distance from zero on the number line. + * -5 and 5 are both five units away from zero, so calling `abs(-5)` and + * `abs(5)` both return 5. The absolute value of a number is always positive. * * @method abs * @param {Number} n number to compute. * @return {Number} absolute value of given number. + * * @example *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('A gray square with a vertical black line that divides it in half. A white rectangle gets taller when the user moves the mouse away from the line.'); + * } + * * function draw() { - * // Invert the y-axis. - * scale(1, -1); - * translate(0, -height); + * background(200); * - * let centerX = width / 2; - * let x = frameCount; - * let y = abs(x - centerX); - * point(x, y); + * // Divide the canvas. + * line(50, 0, 50, 100); * - * describe('A series of black dots that form a "V" shape.'); + * // Calculate the mouse's distance from the middle. + * let h = abs(mouseX - 50); + * + * // Draw a rectangle based on the mouse's distance + * // from the middle. + * rect(0, 100 - h, 100, h); * } * *
@@ -92989,30 +105158,43 @@ _main.default.prototype.abs = Math.abs; /** - * Calculates the closest integer value that is greater than or equal to the - * parameter's value. For example, calling `ceil(9.03)` returns the value + * Calculates the closest integer value that is greater than or equal to a + * number. + * + * For example, calling `ceil(9.03)` and `ceil(9.97)` both return the value * 10. * * @method ceil * @param {Number} n number to round up. * @return {Integer} rounded up number. + * * @example *
* - * // Set the range for RGB values from 0 to 1. - * colorMode(RGB, 1); - * noStroke(); + * function setup() { + * createCanvas(100, 100); + * + * background(200); * - * let r = 0.3; - * fill(r, 0, 0); - * rect(0, 0, width / 2, height); + * // Use RGB color with values from 0 to 1. + * colorMode(RGB, 1); + * + * noStroke(); + * + * // Draw the left rectangle. + * let r = 0.3; + * fill(r, 0, 0); + * rect(0, 0, 50, 100); * - * // Round r up to 1. - * r = ceil(r); - * fill(r, 0, 0); - * rect(width / 2, 0, width / 2, height); + * // Round r up to 1. + * r = ceil(r); * - * describe('Two rectangles. The one on the left is dark red and the one on the right is bright red.'); + * // Draw the right rectangle. + * fill(r, 0, 0); + * rect(50, 0, 50, 100); + * + * describe('Two rectangles. The one on the left is dark red and the one on the right is bright red.'); + * } * *
*/ @@ -93025,9 +105207,16 @@ * @param {Number} low minimum limit. * @param {Number} high maximum limit. * @return {Number} constrained number. + * * @example *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('A black dot drawn on a gray square follows the mouse from left to right. Its movement is constrained to the middle third of the square.'); + * } + * * function draw() { * background(200); * @@ -93036,33 +105225,35 @@ * * strokeWeight(5); * point(x, y); - * - * describe('A black dot drawn on a gray square follows the mouse from left to right. Its movement is constrained to the middle third of the square.'); * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('Two vertical lines. Two circles move horizontally with the mouse. One circle stops at the vertical lines.'); + * } + * * function draw() { * background(200); * * // Set boundaries and draw them. - * let leftWall = width * 0.25; - * let rightWall = width * 0.75; - * line(leftWall, 0, leftWall, height); - * line(rightWall, 0, rightWall, height); + * let leftWall = 25; + * let rightWall = 75; + * line(leftWall, 0, leftWall, 100); + * line(rightWall, 0, rightWall, 100); * * // Draw a circle that follows the mouse freely. * fill(255); - * circle(mouseX, height / 3, 9); + * circle(mouseX, 33, 9); * * // Draw a circle that's constrained. * let xc = constrain(mouseX, leftWall, rightWall); * fill(0); - * circle(xc, 2 * height / 3, 9); - * - * describe('Two vertical lines. Two circles move horizontally with the mouse. One circle stops at the vertical lines.'); + * circle(xc, 67, 9); * } * *
@@ -93093,20 +105284,35 @@ * @example *
* - * let x1 = 10; - * let y1 = 50; - * let x2 = 90; - * let y2 = 50; + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Set the coordinates. + * let x1 = 10; + * let y1 = 50; + * let x2 = 90; + * let y2 = 50; * - * line(x1, y1, x2, y2); - * strokeWeight(5); - * point(x1, y1); - * point(x2, y2); + * // Draw the points and a line connecting them. + * line(x1, y1, x2, y2); + * strokeWeight(5); + * point(x1, y1); + * point(x2, y2); + * + * // Calculate the distance. + * let d = dist(x1, y1, x2, y2); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); * - * let d = dist(x1, y1, x2, y2); - * text(d, 43, 40); + * // Display the distance. + * text(d, 43, 40); * - * describe('Two dots connected by a horizontal line. The number 80 is written above the center of the line.'); + * describe('Two dots connected by a horizontal line. The number 80 is written above the center of the line.'); + * } * *
*/ @@ -93134,25 +105340,63 @@ } }; /** - * Returns Euler's number e (2.71828...) raised to the power of the `n` - * parameter. + * Calculates the value of Euler's number e (2.71828...) raised to the power + * of a number. * * @method exp * @param {Number} n exponent to raise. * @return {Number} e^n + * * @example *
* + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Top-left. + * let d = exp(1); + * circle(10, 10, d); + * + * // Left-center. + * d = exp(2); + * circle(20, 20, d); + * + * // Right-center. + * d = exp(3); + * circle(40, 40, d); + * + * // Bottom-right. + * d = exp(4); + * circle(80, 80, d); + * + * describe('A series of circles that grow exponentially from top left to bottom right.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * describe('A series of black dots that grow exponentially from left to right.'); + * } + * * function draw() { * // Invert the y-axis. * scale(1, -1); - * translate(0, -height); + * translate(0, -100); * + * // Calculate the coordinates. * let x = frameCount; * let y = 0.005 * exp(x * 0.1); - * point(x, y); * - * describe('A series of black dots that grow exponentially from left to right.'); + * // Draw a point. + * point(x, y); * } * *
@@ -93160,36 +105404,46 @@ _main.default.prototype.exp = Math.exp; /** * Calculates the closest integer value that is less than or equal to the - * value of the `n` parameter. + * value of a number. * * @method floor * @param {Number} n number to round down. * @return {Integer} rounded down number. + * * @example *
* - * // Set the range for RGB values from 0 to 1. - * colorMode(RGB, 1); - * noStroke(); + * function setup() { + * createCanvas(100, 100); + * + * // Use RGB color with values from 0 to 1. + * colorMode(RGB, 1); * - * let r = 0.8; - * fill(r, 0, 0); - * rect(0, 0, width / 2, height); + * noStroke(); + * + * // Draw the left rectangle. + * let r = 0.8; + * fill(r, 0, 0); + * rect(0, 0, 50, 100); * - * // Round r down to 0. - * r = floor(r); - * fill(r, 0, 0); - * rect(width / 2, 0, width / 2, height); + * // Round r down to 0. + * r = floor(r); * - * describe('Two rectangles. The one on the left is bright red and the one on the right is black.'); + * // Draw the right rectangle. + * fill(r, 0, 0); + * rect(50, 0, 50, 100); + * + * describe('Two rectangles. The one on the left is bright red and the one on the right is black.'); + * } * *
*/ _main.default.prototype.floor = Math.floor; /** - * Calculates a number between two numbers at a specific increment. The `amt` - * parameter is the amount to interpolate between the two numbers. 0.0 is - * equal to the first number, 0.1 is very near the first number, 0.5 is + * Calculates a number between two numbers at a specific increment. + * + * The `amt` parameter is the amount to interpolate between the two numbers. + * 0.0 is equal to the first number, 0.1 is very near the first number, 0.5 is * half-way in between, and 1.0 is equal to the second number. The `lerp()` * function is convenient for creating motion along a straight path and for * drawing dotted lines. @@ -93203,31 +105457,71 @@ * @param {Number} stop second value. * @param {Number} amt number. * @return {Number} lerped value. + * * @example *
* - * let a = 20; - * let b = 80; - * let c = lerp(a, b, 0.2); - * let d = lerp(a, b, 0.5); - * let e = lerp(a, b, 0.8); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Declare variables for coordinates. + * let a = 20; + * let b = 80; + * let c = lerp(a, b, 0.2); + * let d = lerp(a, b, 0.5); + * let e = lerp(a, b, 0.8); + * + * strokeWeight(5); + * + * // Draw the original points in black. + * stroke(0); + * point(a, 50); + * point(b, 50); + * + * // Draw the lerped points in gray. + * stroke(100); + * point(c, 50); + * point(d, 50); + * point(e, 50); + * + * describe('Five points in a horizontal line. The outer points are black and the inner points are gray.'); + * } + * + *
* + *
+ * + * let x = 50; * let y = 50; + * let targetX = 50; + * let targetY = 50; + * + * function setup() { + * createCanvas(100, 100); + * + * background(200); * - * strokeWeight(5); + * describe('A white circle at the center of a gray canvas. The circle moves to where the user clicks, then moves smoothly back to the center.'); + * } + * + * function draw() { + * background(220); * - * // Draw the original points in black. - * stroke(0); - * point(a, y); - * point(b, y); + * // Move x and y toward the target. + * x = lerp(x, targetX, 0.05); + * y = lerp(y, targetY, 0.05); * - * // Draw the lerped points in gray. - * stroke(100); - * point(c, y); - * point(d, y); - * point(e, y); + * // Draw the circle. + * circle(x, y, 20); + * } * - * describe('Five points in a horizontal line. The outer points are black and the inner points are gray.'); + * // Set x and y when the user clicks the mouse. + * function mouseClicked() { + * x = mouseX; + * y = mouseY; + * } * *
*/ @@ -93236,54 +105530,107 @@ return amt * (stop - start) + start; }; /** - * Calculates the natural logarithm (the base-e logarithm) of a number. This - * function expects the `n` parameter to be a value greater than 0.0. + * Calculates the natural logarithm (the base-e logarithm) of a number. + * + * `log()` expects the `n` parameter to be a value greater than 0 because + * the natural logarithm is defined that way. * * @method log * @param {Number} n number greater than 0. * @return {Number} natural logarithm of n. + * * @example *
* + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Top-left. + * let d = log(50); + * circle(33, 33, d); + * + * // Bottom-right. + * d = log(500000000); + * circle(67, 67, d); + * + * describe('Two white circles. The circle at the top-left is small. The circle at the bottom-right is about five times larger.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * describe('A series of black dots that get higher slowly from left to right.'); + * } + * * function draw() { * // Invert the y-axis. * scale(1, -1); - * translate(0, -height); + * translate(0, -100); * + * // Calculate coordinates. * let x = frameCount; * let y = 15 * log(x); - * point(x, y); * - * describe('A series of black dots that get higher slowly from left to right.'); + * // Draw a point. + * point(x, y); * } * *
*/ _main.default.prototype.log = Math.log; /** - * Calculates the magnitude, or length, of a vector. A vector is like an arrow - * pointing in space. Vectors are commonly used for programming motion. + * Calculates the magnitude, or length, of a vector. * - * Vectors don't have a "start" position because the same arrow can be drawn - * anywhere. A vector's magnitude can be thought of as the distance from the - * origin (0, 0) to its tip at (x, y). `mag(x, y)` is a shortcut for calling + * A vector can be thought of in different ways. In one view, a vector is a + * point in space. The vector's components, `x` and `y`, are the point's + * coordinates `(x, y)`. A vector's magnitude is the distance from the origin + * `(0, 0)` to `(x, y)`. `mag(x, y)` is a shortcut for calling * `dist(0, 0, x, y)`. * + * A vector can also be thought of as an arrow pointing in space. This view is + * helpful for programming motion. See p5.Vector for + * more details. + * + * Use p5.Vector.mag() to calculate the + * magnitude of a p5.Vector object. + * * @method mag * @param {Number} x first component. * @param {Number} y second component. - * @return {Number} magnitude of vector from (0,0) to (x,y). + * @return {Number} magnitude of vector. + * * @example *
* - * let x = 30; - * let y = 40; - * let m = mag(x, y); + * function setup() { + * createCanvas(100, 100); * - * line(0, 0, x, y); - * text(m, x, y); + * background(200); + * + * // Set the vector's components. + * let x = 30; + * let y = 40; + * + * // Calculate the magnitude. + * let m = mag(x, y); + * + * // Style the text. + * textSize(16); + * + * // Display the vector and its magnitude. + * line(0, 0, x, y); + * text(m, x, y); * - * describe('A diagonal line is drawn from the top left of the canvas. The number 50 is written at the end of the line.'); + * describe('A diagonal line is drawn from the top left of the canvas. The number 50 is written at the end of the line.'); + * } * *
*/ @@ -93300,43 +105647,64 @@ * in the target range [0, 100] is proportional to 2's position in the * original range [0, 10]. * + * The sixth parameter, `withinBounds`, is optional. By default, `map()` can + * return values outside of the target range. For example, + * `map(11, 0, 10, 0, 100)` returns 110. Passing `true` as the sixth parameter + * constrains the remapped value to the target range. For example, + * `map(11, 0, 10, 0, 100, true)` returns 100. + * * @method map - * @param {Number} value the incoming value to be converted. + * @param {Number} value the value to be remapped. * @param {Number} start1 lower bound of the value's current range. * @param {Number} stop1 upper bound of the value's current range. * @param {Number} start2 lower bound of the value's target range. * @param {Number} stop2 upper bound of the value's target range. * @param {Boolean} [withinBounds] constrain the value to the newly mapped range. * @return {Number} remapped number. + * * @example *
* - * let n = map(7, 0, 10, 0, 100); - * text(n, 50, 50); + * function setup() { + * createCanvas(100, 100); * - * describe('The number 70 written in the middle of a gray square.'); - * - *
+ * describe('Two horizontal lines. The top line grows horizontally as the mouse moves to the right. The bottom line also grows horizontally but is scaled to stay on the left half of the canvas.'); + * } * - *
- * - * let x = map(2, 0, 10, 0, width); - * circle(x, 50, 10); + * function draw() { + * background(200); + * + * // Draw the top line. + * line(0, 25, mouseX, 25); + * + * // Remap mouseX from [0, 100] to [0, 50]. + * let x = map(mouseX, 0, 100, 0, 50); * - * describe('A white circle drawn on the left side of a gray square.'); + * // Draw the bottom line. + * line(0, 75, x, 75); + * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('A circle changes color from black to white as the mouse moves from left to right.'); + * } + * * function draw() { * background(200); * - * let c = map(mouseX, 0, width, 0, 255); + * // Remap mouseX from [0, 100] to [0, 255] + * let c = map(mouseX, 0, 100, 0, 255); + * + * // Style the circle. * fill(c); - * circle(50, 50, 20); * - * describe('A circle changes color from black to white as the mouse moves from left to right.'); + * // Draw the circle. + * circle(50, 50, 20); * } * *
@@ -93366,47 +105734,52 @@ * @param {Number} n0 first number to compare. * @param {Number} n1 second number to compare. * @return {Number} maximum number. + * * @example *
* - * let m = max(10, 20); - * text(m, 50, 50); + * function setup() { + * createCanvas(100, 100); * - * describe('The number 20 written in the middle of a gray square.'); - * - *
+ * background(200); * - *
- * - * let m = max([10, 20]); - * text(m, 50, 50); + * // Calculate the maximum of 10, 5, and 20. + * let m = max(10, 5, 20); * - * describe('The number 20 written in the middle of a gray square.'); + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * + * // Display the max. + * text(m, 50, 50); + * + * describe('The number 20 written in the middle of a gray square.'); + * } * *
* *
* - * let numbers = [2, 1, 5, 4, 8, 9]; + * function setup() { + * createCanvas(100, 100); * - * // Draw all of the numbers in the array. - * noStroke(); - * let spacing = 15; - * numbers.forEach((n, index) => { - * let x = index * spacing; - * let y = 25; - * text(n, x, y); - * }); + * background(200); + * + * // Create an array of numbers. + * let numbers = [10, 5, 20]; + * + * // Calculate the maximum of the array. + * let m = max(numbers); * - * // Draw the maximum value in the array. - * let m = max(numbers); - * let maxX = 33; - * let maxY = 80; + * // Style the text. + * textAlign(CENTER); + * textSize(16); * - * textSize(32); - * text(m, maxX, maxY); + * // Display the max. + * text(m, 50, 50); * - * describe('The numbers 2 1 5 4 8 9 are written in small text at the top of a gray square. The number 9 is written in large text at the center of the square.'); + * describe('The number 20 written in the middle of a gray square.'); + * } * *
*/ @@ -93417,35 +105790,12 @@ */ _main.default.prototype.max = function () { var findMax = function findMax(arr) { - var max = - Infinity; - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - try { - for (var _iterator = arr[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var x = _step.value; - max = x > max ? x : max; - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return != null) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } - return max; + return Math.max.apply(Math, _toConsumableArray(arr)); }; for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } - if (args[0] instanceof Array) { + if (Array.isArray(args[0])) { return findMax(args[0]); } else { return findMax(args); @@ -93464,47 +105814,52 @@ * @param {Number} n0 first number to compare. * @param {Number} n1 second number to compare. * @return {Number} minimum number. + * * @example *
* - * let m = min(10, 20); - * text(m, 50, 50); + * function setup() { + * createCanvas(100, 100); * - * describe('The number 10 written in the middle of a gray square.'); - * - *
+ * background(200); * - *
- * - * let m = min([10, 20]); - * text(m, 50, 50); + * // Calculate the minimum of 10, 5, and 20. + * let m = min(10, 5, 20); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); * - * describe('The number 10 written in the middle of a gray square.'); + * // Display the min. + * text(m, 50, 50); + * + * describe('The number 5 written in the middle of a gray square.'); + * } * *
* *
* - * let numbers = [2, 1, 5, 4, 8, 9]; + * function setup() { + * createCanvas(100, 100); * - * // Draw all of the numbers in the array. - * noStroke(); - * let spacing = 15; - * numbers.forEach((n, index) => { - * let x = index * spacing; - * let y = 25; - * text(n, x, y); - * }); + * background(200); + * + * // Create an array of numbers. + * let numbers = [10, 5, 20]; * - * // Draw the minimum value in the array. - * let m = min(numbers); - * let minX = 33; - * let minY = 80; + * // Calculate the minimum of the array. + * let m = min(numbers); * - * textSize(32); - * text(m, minX, minY); + * // Style the text. + * textAlign(CENTER); + * textSize(16); * - * describe('The numbers 2 1 5 4 8 9 are written in small text at the top of a gray square. The number 1 is written in large text at the center of the square.'); + * // Display the min. + * text(m, 50, 50); + * + * describe('The number 5 written in the middle of a gray square.'); + * } * *
*/ @@ -93515,35 +105870,12 @@ */ _main.default.prototype.min = function () { var findMin = function findMin(arr) { - var min = Infinity; - var _iteratorNormalCompletion2 = true; - var _didIteratorError2 = false; - var _iteratorError2 = undefined; - try { - for (var _iterator2 = arr[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { - var x = _step2.value; - min = x < min ? x : min; - } - } catch (err) { - _didIteratorError2 = true; - _iteratorError2 = err; - } finally { - try { - if (!_iteratorNormalCompletion2 && _iterator2.return != null) { - _iterator2.return(); - } - } finally { - if (_didIteratorError2) { - throw _iteratorError2; - } - } - } - return min; + return Math.min.apply(Math, _toConsumableArray(arr)); }; for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { args[_key3] = arguments[_key3]; } - if (args[0] instanceof Array) { + if (Array.isArray(args[0])) { return findMin(args[0]); } else { return findMin(args); @@ -93554,7 +105886,7 @@ * * For example, `norm(2, 0, 10)` returns 0.2. 2's position in the original * range [0, 10] is proportional to 0.2's position in the range [0, 1]. This - * is equivalent to calling `map(2, 0, 10, 0, 1)`. + * is the same as calling `map(2, 0, 10, 0, 1)`. * * Numbers outside of the original range are not constrained between 0 and 1. * Out-of-range values are often intentional and useful. @@ -93564,18 +105896,26 @@ * @param {Number} start lower bound of the value's current range. * @param {Number} stop upper bound of the value's current range. * @return {Number} normalized number. + * * @example *
* - * function draw() { - * // Set the range for RGB values from 0 to 1. - * colorMode(RGB, 1); + * function setup() { + * createCanvas(100, 100); * - * let r = norm(mouseX, 0, width); - * background(r, 0, 0); + * // Use RGB color with values from 0 to 1. + * colorMode(RGB, 1); * * describe('A square changes color from black to red as the mouse moves from left to right.'); * } + * + * function draw() { + * // Calculate the redValue. + * let redValue = norm(mouseX, 0, 100); + * + * // Paint the background. + * background(redValue, 0, 0); + * } * *
*/ @@ -93584,62 +105924,106 @@ return this.map(n, start, stop, 0, 1); }; /** - * Calculates exponential expressions such as 2^3. + * Calculates exponential expressions such as 23. * - * For example, `pow(2, 3)` is equivalent to the expression - * 2 × 2 × 2. `pow(2, -3)` is equivalent to 1 ÷ + * For example, `pow(2, 3)` evaluates the expression + * 2 × 2 × 2. `pow(2, -3)` evaluates 1 ÷ * (2 × 2 × 2). * * @method pow * @param {Number} n base of the exponential expression. * @param {Number} e power by which to raise the base. * @return {Number} n^e. + * * @example *
* - * let base = 3; + * function setup() { + * createCanvas(100, 100); * - * let d = pow(base, 1); - * circle(10, 10, d); + * background(200); + * + * // Set the base of the exponent. + * let base = 3; * - * d = pow(base, 2); - * circle(20, 20, d); + * // Top-left. + * let d = pow(base, 1); + * circle(10, 10, d); * - * d = pow(base, 3); - * circle(40, 40, d); + * // Left-center. + * d = pow(base, 2); + * circle(20, 20, d); * - * d = pow(base, 4); - * circle(80, 80, d); + * // Right-center. + * d = pow(base, 3); + * circle(40, 40, d); * - * describe('A series of circles that grow exponentially from top left to bottom right.'); + * // Bottom-right. + * d = pow(base, 4); + * circle(80, 80, d); + * + * describe('A series of circles that grow exponentially from top left to bottom right.'); + * } * *
*/ _main.default.prototype.pow = Math.pow; /** - * Calculates the integer closest to the `n` parameter. For example, - * `round(133.8)` returns the value 134. + * Calculates the integer closest to a number. + * + * For example, `round(133.8)` returns the value 134. + * + * The second parameter, `decimals`, is optional. It sets the number of + * decimal places to use when rounding. For example, `round(12.34, 1)` returns + * 12.3. `decimals` is 0 by default. * * @method round * @param {Number} n number to round. * @param {Number} [decimals] number of decimal places to round to, default is 0. * @return {Integer} rounded number. + * * @example *
* - * let x = round(3.7); - * text(x, width / 2, height / 2); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Round a number. + * let x = round(4.2); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * + * // Display the rounded number. + * text(x, 50, 50); * - * describe('The number 4 written in middle of canvas.'); + * describe('The number 4 written in middle of the canvas.'); + * } * *
* *
* - * let x = round(12.782383, 2); - * text(x, width / 2, height / 2); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Round a number to 2 decimal places. + * let x = round(12.782383, 2); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); * - * describe('The number 12.78 written in middle of canvas.'); + * // Display the rounded number. + * text(x, 50, 50); + * + * describe('The number 12.78 written in middle of canvas.'); + * } * *
*/ @@ -93651,29 +106035,59 @@ return Math.round(n * multiplier) / multiplier; }; /** - * Squares a number, which means multiplying the number by itself. The value - * returned is always a positive number. + * Calculates the square of a number. * - * For example, `sq(3)` evaluates 3 × 3 which is 9. `sq(-3)` evaluates - * -3 × -3 which is also 9. Multiplying two negative numbers produces - * a positive number. + * Squaring a number means multiplying the number by itself. For example, + * `sq(3)` evaluates 3 × 3 which is 9. `sq(-3)` evaluates -3 × -3 + * which is also 9. Multiplying two negative numbers produces a positive + * number. The value returned by `sq()` is always positive. * * @method sq * @param {Number} n number to square. * @return {Number} squared number. + * * @example *
* + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Top-left. + * let d = sq(3); + * circle(33, 33, d); + * + * // Bottom-right. + * d = sq(6); + * circle(67, 67, d); + * + * describe('Two white circles. The circle at the top-left is small. The circle at the bottom-right is four times larger.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * describe('A series of black dots that get higher quickly from left to right.'); + * } + * * function draw() { * // Invert the y-axis. * scale(1, -1); - * translate(0, -height); + * translate(0, -100); * + * // Calculate the coordinates. * let x = frameCount; * let y = 0.01 * sq(x); - * point(x, y); * - * describe('A series of black dots that get higher quickly from left to right.'); + * // Draw the point. + * point(x, y); * } * *
@@ -93682,50 +106096,96 @@ return n * n; }; /** - * Calculates the square root of a number. A number's square root can be - * multiplied by itself to produce the original number. + * Calculates the square root of a number. * - * For example, `sqrt(9)` returns 3 because 3 × 3 = 9. `sqrt()` always - * returns a positive value. `sqrt()` doesn't work with negative arguments + * A number's square root can be multiplied by itself to produce the original + * number. For example, `sqrt(9)` returns 3 because 3 × 3 = 9. `sqrt()` + * always returns a positive value. `sqrt()` doesn't work with negative arguments * such as `sqrt(-9)`. * * @method sqrt * @param {Number} n non-negative number to square root. * @return {Number} square root of number. + * * @example *
* + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Top-left. + * let d = sqrt(16); + * circle(33, 33, d); + * + * // Bottom-right. + * d = sqrt(1600); + * circle(67, 67, d); + * + * describe('Two white circles. The circle at the top-left is small. The circle at the bottom-right is ten times larger.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * describe('A series of black dots that get higher slowly from left to right.'); + * } + * * function draw() { * // Invert the y-axis. * scale(1, -1); - * translate(0, -height); + * translate(0, -100); * + * // Calculate the coordinates. * let x = frameCount; * let y = 5 * sqrt(x); - * point(x, y); * - * describe('A series of black dots that get higher slowly from left to right.'); + * // Draw the point. + * point(x, y); * } * *
*/ _main.default.prototype.sqrt = Math.sqrt; /** - * Calculates the fractional part of a number. For example, + * Calculates the fractional part of a number. + * + * A number's fractional part includes its decimal values. For example, * `fract(12.34)` returns 0.34. * * @method fract * @param {Number} n number whose fractional part will be found. * @returns {Number} fractional part of n. + * * @example *
* - * let n = 56.78; - * text(n, 20, 33); - * let f = fract(n); - * text(f, 20, 66); + * function setup() { + * createCanvas(100, 100); * - * describe('The number 56.78 written above the number 0.78.'); + * background(200); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * + * // Original number. + * let n = 56.78; + * text(n, 50, 33); + * + * // Fractional part. + * let f = fract(n); + * text(f, 50, 67); + * + * describe('The number 56.78 written above the number 0.78.'); + * } * *
*/ @@ -93753,24 +106213,26 @@ exports.default = _default; }, { - '../core/main': 298, - 'core-js/modules/es.array.includes': 177, - 'core-js/modules/es.array.index-of': 178, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.map': 182, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.math.hypot': 188, - 'core-js/modules/es.number.constructor': 191, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.string.includes': 209, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/main': 306, + 'core-js/modules/es.array.from': 180, + 'core-js/modules/es.array.includes': 181, + 'core-js/modules/es.array.index-of': 182, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.map': 186, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.math.hypot': 194, + 'core-js/modules/es.number.constructor': 197, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.string.includes': 217, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 329: [ + 337: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.array.concat'); @@ -93834,10 +106296,17 @@ * @requires core */ /** - * Creates a new p5.Vector object. A vector is like - * an arrow pointing in space. Vectors have both magnitude (length) - * and direction. Calling `createVector()` without arguments sets the new - * vector's components to 0. + * Creates a new p5.Vector object. + * + * A vector can be thought of in different ways. In one view, a vector is like + * an arrow pointing in space. Vectors have both magnitude (length) and + * direction. This view is helpful for programming motion. + * + * A vector's components determine its magnitude and direction. For example, + * calling `createVector(3, 4)` creates a new + * p5.Vector object with an x-component of 3 and a + * y-component of 4. From the origin, this vector's tip is 3 units to the + * right and 4 units down. * * p5.Vector objects are often used to program * motion because they simplify the math. For example, a moving ball has a @@ -93854,19 +106323,28 @@ * @param {Number} [y] y component of the vector. * @param {Number} [z] z component of the vector. * @return {p5.Vector} new p5.Vector object. + * * @example *
* - * let p1 = createVector(25, 25); - * let p2 = createVector(50, 50); - * let p3 = createVector(75, 75); + * function setup() { + * createCanvas(100, 100); + * + * background(200); * - * strokeWeight(5); - * point(p1); - * point(p2); - * point(p3); + * // Create p5.Vector objects. + * let p1 = createVector(25, 25); + * let p2 = createVector(50, 50); + * let p3 = createVector(75, 75); * - * describe('Three black dots form a diagonal line from top left to bottom right.'); + * // Draw the dots. + * strokeWeight(5); + * point(p1); + * point(p2); + * point(p3); + * + * describe('Three black dots form a diagonal line from top left to bottom right.'); + * } * *
* @@ -93877,23 +106355,29 @@ * * function setup() { * createCanvas(100, 100); - * pos = createVector(width / 2, height); + * + * // Create p5.Vector objects. + * pos = createVector(50, 100); * vel = createVector(0, -1); + * + * describe('A black dot moves from bottom to top on a gray square. The dot reappears at the bottom when it reaches the top.'); * } * * function draw() { * background(200); * + * // Add velocity to position. * pos.add(vel); * + * // If the dot reaches the top of the canvas, + * // restart from the bottom. * if (pos.y < 0) { - * pos.y = height; + * pos.y = 100; * } * + * // Draw the dot. * strokeWeight(5); * point(pos); - * - * describe('A black dot moves from bottom to top on a gray square. The dot reappears at the bottom when it reaches the top.'); * } *
*
@@ -93913,15 +106397,15 @@ exports.default = _default; }, { - '../core/main': 298, - 'core-js/modules/es.array.concat': 169, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.reflect.construct': 202, - 'core-js/modules/es.regexp.to-string': 206 + '../core/main': 306, + 'core-js/modules/es.array.concat': 171, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.reflect.construct': 210, + 'core-js/modules/es.regexp.to-string': 214 } ], - 330: [ + 338: [ function (_dereq_, module, exports) { 'use strict'; Object.defineProperty(exports, '__esModule', { @@ -93963,8 +106447,7 @@ }; var perlin; // will be initialized lazily by noise() or noiseSeed() /** - * Returns random numbers that can be tuned to feel more organic. The values - * returned will always be between 0 and 1. + * Returns random numbers that can be tuned to feel organic. * * Values returned by random() and * randomGaussian() can change by large @@ -93974,8 +106457,9 @@ * terrains, and so on. Ken Perlin invented `noise()` while animating the * original Tron film in the 1980s. * - * `noise()` returns the same value for a given input while a sketch is - * running. It produces different results each time a sketch runs. The + * `noise()` always returns values between 0 and 1. It returns the same value + * for a given input while a sketch is running. `noise()` produces different + * results each time a sketch runs. The * noiseSeed() function can be used to generate * the same sequence of Perlin noise values each time a sketch runs. * @@ -94002,125 +106486,179 @@ * @param {Number} [y] y-coordinate in noise space. * @param {Number} [z] z-coordinate in noise space. * @return {Number} Perlin noise value at specified coordinates. + * * @example *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('A black dot moves randomly on a gray square.'); + * } + * * function draw() { * background(200); * + * // Calculate the coordinates. * let x = 100 * noise(0.005 * frameCount); * let y = 100 * noise(0.005 * frameCount + 10000); * + * // Draw the point. * strokeWeight(5); * point(x, y); - * - * describe('A black dot moves randomly on a gray square.'); * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('A black dot moves randomly on a gray square.'); + * } + * * function draw() { * background(200); * + * // Set the noise level and scale. * let noiseLevel = 100; * let noiseScale = 0.005; - * // Scale input coordinate. + * + * // Scale the input coordinate. * let nt = noiseScale * frameCount; - * // Compute noise value. + * + * // Compute the noise values. * let x = noiseLevel * noise(nt); * let y = noiseLevel * noise(nt + 10000); - * // Render. + * + * // Draw the point. * strokeWeight(5); * point(x, y); - * - * describe('A black dot moves randomly on a gray square.'); * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('A hilly terrain drawn in gray against a black sky.'); + * } + * * function draw() { + * // Set the noise level and scale. * let noiseLevel = 100; * let noiseScale = 0.02; - * // Scale input coordinate. + * + * // Scale the input coordinate. * let x = frameCount; * let nx = noiseScale * x; - * // Compute noise value. + * + * // Compute the noise value. * let y = noiseLevel * noise(nx); - * // Render. - * line(x, 0, x, y); * - * describe('A hilly terrain drawn in gray against a black sky.'); + * // Draw the line. + * line(x, 0, x, y); * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('A calm sea drawn in gray against a black sky.'); + * } + * * function draw() { * background(200); * + * // Set the noise level and scale. * let noiseLevel = 100; * let noiseScale = 0.002; - * for (let x = 0; x < width; x += 1) { - * // Scale input coordinates. + * + * // Iterate from left to right. + * for (let x = 0; x < 100; x += 1) { + * // Scale the input coordinates. * let nx = noiseScale * x; * let nt = noiseScale * frameCount; - * // Compute noise value. + * + * // Compute the noise value. * let y = noiseLevel * noise(nx, nt); - * // Render. + * + * // Draw the line. * line(x, 0, x, y); * } - * - * describe('A calm sea drawn in gray against a black sky.'); * } * *
* *
* - * let noiseLevel = 255; - * let noiseScale = 0.01; - * for (let y = 0; y < height; y += 1) { - * for (let x = 0; x < width; x += 1) { - * // Scale input coordinates. - * let nx = noiseScale * x; - * let ny = noiseScale * y; - * // Compute noise value. - * let c = noiseLevel * noise(nx, ny); - * // Render. - * stroke(c); - * point(x, y); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Set the noise level and scale. + * let noiseLevel = 255; + * let noiseScale = 0.01; + * + * // Iterate from top to bottom. + * for (let y = 0; y < 100; y += 1) { + * // Iterate from left to right. + * for (let x = 0; x < 100; x += 1) { + * // Scale the input coordinates. + * let nx = noiseScale * x; + * let ny = noiseScale * y; + * + * // Compute the noise value. + * let c = noiseLevel * noise(nx, ny); + * + * // Draw the point. + * stroke(c); + * point(x, y); + * } * } - * } * - * describe('A gray cloudy pattern.'); + * describe('A gray cloudy pattern.'); + * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('A gray cloudy pattern that changes.'); + * } + * * function draw() { + * // Set the noise level and scale. * let noiseLevel = 255; * let noiseScale = 0.009; - * for (let y = 0; y < height; y += 1) { + * + * // Iterate from top to bottom. + * for (let y = 0; y < 100; y += 1) { + * // Iterate from left to right. * for (let x = 0; x < width; x += 1) { - * // Scale input coordinates. + * // Scale the input coordinates. * let nx = noiseScale * x; * let ny = noiseScale * y; * let nt = noiseScale * frameCount; - * // Compute noise value. + * + * // Compute the noise value. * let c = noiseLevel * noise(nx, ny, nt); - * // Render. + * + * // Draw the point. * stroke(c); * point(x, y); * } * } - * - * describe('A gray cloudy pattern that changes.'); * } * *
@@ -94216,34 +106754,47 @@ * @method noiseDetail * @param {Number} lod number of octaves to be used by the noise. * @param {Number} falloff falloff factor for each octave. + * * @example *
* - * let noiseLevel = 255; - * let noiseScale = 0.02; - * for (let y = 0; y < height; y += 1) { - * for (let x = 0; x < width / 2; x += 1) { - * // Scale input coordinates. - * let nx = noiseScale * x; - * let ny = noiseScale * y; - * - * // Compute noise value. - * noiseDetail(6, 0.25); - * let c = noiseLevel * noise(nx, ny); - * // Render left side. - * stroke(c); - * point(x, y); - * - * // Compute noise value. - * noiseDetail(4, 0.5); - * c = noiseLevel * noise(nx, ny); - * // Render right side. - * stroke(c); - * point(x + width / 2, y); + * function setup() { + * createCanvas(100, 100); + * + * // Set the noise level and scale. + * let noiseLevel = 255; + * let noiseScale = 0.02; + * + * // Iterate from top to bottom. + * for (let y = 0; y < 100; y += 1) { + * // Iterate from left to right. + * for (let x = 0; x < 50; x += 1) { + * // Scale the input coordinates. + * let nx = noiseScale * x; + * let ny = noiseScale * y; + * + * // Compute the noise value with six octaves + * // and a low falloff factor. + * noiseDetail(6, 0.25); + * let c = noiseLevel * noise(nx, ny); + * + * // Draw the left side. + * stroke(c); + * point(x, y); + * + * // Compute the noise value with four octaves + * // and a high falloff factor. + * noiseDetail(4, 0.5); + * c = noiseLevel * noise(nx, ny); + * + * // Draw the right side. + * stroke(c); + * point(x + 50, y); + * } * } - * } * - * describe('Two gray cloudy patterns. The pattern on the right is cloudier than the pattern on the left.'); + * describe('Two gray cloudy patterns. The pattern on the right is cloudier than the pattern on the left.'); + * } * *
*/ @@ -94256,33 +106807,43 @@ } }; /** - * Sets the seed value for noise(). By default, - * noise() produces different results each time - * a sketch is run. Calling `noiseSeed()` with a constant - * argument, such as `noiseSeed(99)`, makes noise() - * produce the same results each time a sketch is run. + * Sets the seed value for the noise() function. + * + * By default, noise() produces different results + * each time a sketch is run. Calling `noiseSeed()` with a constant argument, + * such as `noiseSeed(99)`, makes noise() produce the + * same results each time a sketch is run. * * @method noiseSeed * @param {Number} seed seed value. + * * @example *
* * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Set the noise seed for consistent results. * noiseSeed(99); - * background(255); + * + * describe('A black rectangle that grows randomly, first to the right and then to the left.'); * } * * function draw() { + * // Set the noise level and scale. * let noiseLevel = 100; * let noiseScale = 0.005; - * // Scale input coordinate. + * + * // Scale the input coordinate. * let nt = noiseScale * frameCount; - * // Compute noise value. + * + * // Compute the noise value. * let x = noiseLevel * noise(nt); - * // Render. - * line(x, 0, x, height); * - * describe('A black rectangle that grows randomly, first to the right and then to the left.'); + * // Draw the line. + * line(x, 0, x, height); * } * *
@@ -94329,10 +106890,10 @@ exports.default = _default; }, { - '../core/main': 298 + '../core/main': 306 } ], - 331: [ + 339: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -94341,10 +106902,10 @@ _dereq_('core-js/modules/es.array.concat'); _dereq_('core-js/modules/es.array.every'); _dereq_('core-js/modules/es.array.iterator'); - _dereq_('core-js/modules/es.array.slice'); _dereq_('core-js/modules/es.array.some'); _dereq_('core-js/modules/es.math.sign'); _dereq_('core-js/modules/es.number.constructor'); + _dereq_('core-js/modules/es.number.epsilon'); _dereq_('core-js/modules/es.number.is-finite'); _dereq_('core-js/modules/es.object.get-own-property-descriptor'); _dereq_('core-js/modules/es.object.to-string'); @@ -94378,10 +106939,10 @@ } _dereq_('core-js/modules/es.array.concat'); _dereq_('core-js/modules/es.array.every'); - _dereq_('core-js/modules/es.array.slice'); _dereq_('core-js/modules/es.array.some'); _dereq_('core-js/modules/es.math.sign'); _dereq_('core-js/modules/es.number.constructor'); + _dereq_('core-js/modules/es.number.epsilon'); _dereq_('core-js/modules/es.number.is-finite'); _dereq_('core-js/modules/es.string.sub'); Object.defineProperty(exports, '__esModule', { @@ -94460,32 +107021,11 @@ * @submodule Vector * @requires constants */ - /// HELPERS FOR REMAINDER METHOD - - var calculateRemainder2D = function calculateRemainder2D(xComponent, yComponent) { - if (xComponent !== 0) { - this.x = this.x % xComponent; - } - if (yComponent !== 0) { - this.y = this.y % yComponent; - } - return this; - }; - var calculateRemainder3D = function calculateRemainder3D(xComponent, yComponent, zComponent) { - if (xComponent !== 0) { - this.x = this.x % xComponent; - } - if (yComponent !== 0) { - this.y = this.y % yComponent; - } - if (zComponent !== 0) { - this.z = this.z % zComponent; - } - return this; - }; /** - * A class to describe a two or three-dimensional vector. A vector is like an - * arrow pointing in space. Vectors have both magnitude (length) and + * A class to describe a two or three-dimensional vector. + * + * A vector can be thought of in different ways. In one view, a vector is like + * an arrow pointing in space. Vectors have both magnitude (length) and * direction. * * `p5.Vector` objects are often used to program motion because they simplify @@ -94497,6 +107037,9 @@ * its position vector moves it, as in `pos.add(vel)`. Vector math relies on * methods inside the `p5.Vector` class. * + * Note: createVector() is the recommended way + * to make an instance of this class. + * * @class p5.Vector * @constructor * @param {Number} [x] x component of the vector. @@ -94505,14 +107048,26 @@ * @example *
* - * let p1 = createVector(25, 25); - * let p2 = createVector(75, 75); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create p5.Vector objects. + * let p1 = createVector(25, 25); + * let p2 = createVector(75, 75); * - * strokeWeight(5); - * point(p1); - * point(p2.x, p2.y); + * // Style the points. + * strokeWeight(5); + * + * // Draw the first point using a p5.Vector. + * point(p1); * - * describe('Two black dots on a gray square, one at the top left and the other at the bottom right.'); + * // Draw the second point using a p5.Vector's components. + * point(p2.x, p2.y); + * + * describe('Two black dots on a gray square, one at the top left and the other at the bottom right.'); + * } * *
* @@ -94523,27 +107078,34 @@ * * function setup() { * createCanvas(100, 100); - * pos = createVector(width / 2, height); + * + * // Create p5.Vector objects. + * pos = createVector(50, 100); * vel = createVector(0, -1); + * + * describe('A black dot moves from bottom to top on a gray square. The dot reappears at the bottom when it reaches the top.'); * } * * function draw() { * background(200); * + * // Add velocity to position. * pos.add(vel); * + * // If the dot reaches the top of the canvas, + * // restart from the bottom. * if (pos.y < 0) { - * pos.y = height; + * pos.y = 100; * } * + * // Draw the dot. * strokeWeight(5); * point(pos); - * - * describe('A black dot moves from bottom to top on a gray square. The dot reappears at the bottom when it reaches the top.'); * } * *
*/ + _main.default.Vector = /*#__PURE__*/ function () { // This is how it comes in with createVector() // This check if the first argument is a function @@ -94587,15 +107149,20 @@ */ this.z = z; } /** - * Returns a string representation of a vector. This method is useful for - * printing vectors to the console while debugging. + * Returns a string representation of a vector. + * + * Calling `toString()` is useful for printing vectors to the console while + * debugging. + * * @method toString * @return {String} string representation of the vector. + * * @example *
* * function setup() { * let v = createVector(20, 30); + * * // Prints 'p5.Vector Object : [20, 30, 0]'. * print(v.toString()); * } @@ -94609,9 +107176,16 @@ value: function toString() { return 'p5.Vector Object : ['.concat(this.x, ', ').concat(this.y, ', ').concat(this.z, ']'); } /** - * Sets the `x`, `y`, and `z` components of the vector using separate numbers, - * a p5.Vector object, or an array of numbers. - * Calling `set()` with no arguments sets the vector's components to 0. + * Sets the vector's `x`, `y`, and `z` components. + * + * `set()` can use separate numbers, as in `v.set(1, 2, 3)`, a + * p5.Vector object, as in `v.set(v2)`, or an + * array of numbers, as in `v.set([1, 2, 3])`. + * + * If a value isn't provided for a component, it will be set to 0. For + * example, `v.set(4, 5)` sets `v.x` to 4, `v.y` to 5, and `v.z` to 0. + * Calling `set()` with no arguments, as in `v.set()`, sets all the vector's + * components to 0. * * @method set * @param {Number} [x] x component of the vector. @@ -94621,27 +107195,37 @@ * @example *
* - * strokeWeight(5); + * function setup() { + * createCanvas(100, 100); + * + * background(200); * - * // Top left. - * let pos = createVector(25, 25); - * point(pos); + * // Style the points. + * strokeWeight(5); * - * // Top right. - * pos.set(75, 25); - * point(pos); + * // Top left. + * let pos = createVector(25, 25); + * point(pos); * - * // Bottom right. - * let p2 = createVector(75, 75); - * pos.set(p2); - * point(pos); + * // Top right. + * // set() with numbers. + * pos.set(75, 25); + * point(pos); * - * // Bottom left. - * let arr = [25, 75]; - * pos.set(arr); - * point(pos); + * // Bottom right. + * // set() with a p5.Vector. + * let p2 = createVector(75, 75); + * pos.set(p2); + * point(pos); * - * describe('Four black dots arranged in a square on a gray background.'); + * // Bottom left. + * // set() with an array. + * let arr = [25, 75]; + * pos.set(arr); + * point(pos); + * + * describe('Four black dots arranged in a square on a gray background.'); + * } * *
*/ @@ -94676,16 +107260,27 @@ * * @method copy * @return {p5.Vector} copy of the p5.Vector object. + * * @example *
* - * let pos = createVector(50, 50); - * let pc = pos.copy(); + * function setup() { + * createCanvas(100 ,100); + * + * background(200); + * + * // Create a p5.Vector object. + * let pos = createVector(50, 50); + * + * // Make a copy. + * let pc = pos.copy(); * - * strokeWeight(5); - * point(pc); + * // Draw the point. + * strokeWeight(5); + * point(pc); * - * describe('A black point drawn in the middle of a gray square.'); + * describe('A black point drawn in the middle of a gray square.'); + * } * *
*/ @@ -94700,9 +107295,15 @@ return new _main.default.Vector(this.x, this.y, this.z); } } /** - * Adds to a vector's `x`, `y`, and `z` components using separate numbers, - * another p5.Vector object, or an array of numbers. - * Calling `add()` with no arguments has no effect. + * Adds to a vector's `x`, `y`, and `z` components. + * + * `add()` can use separate numbers, as in `v.add(1, 2, 3)`, + * another p5.Vector object, as in `v.add(v2)`, or + * an array of numbers, as in `v.add([1, 2, 3])`. + * + * If a value isn't provided for a component, it won't change. For + * example, `v.add(4, 5)` adds 4 to `v.x`, 5 to `v.y`, and 0 to `v.z`. + * Calling `add()` with no arguments, as in `v.add()`, has no effect. * * The static version of `add()`, as in `p5.Vector.add(v2, v1)`, returns a new * p5.Vector object and doesn't change the @@ -94713,71 +107314,99 @@ * @param {Number} [y] y component of the vector to be added. * @param {Number} [z] z component of the vector to be added. * @chainable + * * @example *
* - * strokeWeight(5); + * function setup() { + * createCanvas(100, 100); + * + * background(200); * - * // Top left. - * let pos = createVector(25, 25); - * point(pos); + * // Style the points. + * strokeWeight(5); * - * // Top right. - * pos.add(50, 0); - * point(pos); + * // Top left. + * let pos = createVector(25, 25); + * point(pos); * - * // Bottom right. - * let p2 = createVector(0, 50); - * pos.add(p2); - * point(pos); + * // Top right. + * // Add numbers. + * pos.add(50, 0); + * point(pos); * - * // Bottom left. - * let arr = [-50, 0]; - * pos.add(arr); - * point(pos); + * // Bottom right. + * // Add a p5.Vector. + * let p2 = createVector(0, 50); + * pos.add(p2); + * point(pos); * - * describe('Four black dots arranged in a square on a gray background.'); + * // Bottom left. + * // Add an array. + * let arr = [-50, 0]; + * pos.add(arr); + * point(pos); + * + * describe('Four black dots arranged in a square on a gray background.'); + * } * *
* *
* - * // Top left. - * let p1 = createVector(25, 25); + * function setup() { + * createCanvas(100, 100); * - * // Center. - * let p2 = createVector(50, 50); + * background(200); + * + * // Top left. + * let p1 = createVector(25, 25); * - * // Bottom right. - * let p3 = p5.Vector.add(p1, p2); + * // Center. + * let p2 = createVector(50, 50); * - * strokeWeight(5); - * point(p1); - * point(p2); - * point(p3); + * // Bottom right. + * // Add p1 and p2. + * let p3 = p5.Vector.add(p1, p2); * - * describe('Three black dots in a diagonal line from top left to bottom right.'); + * // Draw the points. + * strokeWeight(5); + * point(p1); + * point(p2); + * point(p3); + * + * describe('Three black dots in a diagonal line from top left to bottom right.'); + * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('Three arrows drawn on a gray square. A red arrow extends from the top left corner to the center. A blue arrow extends from the tip of the red arrow. A purple arrow extends from the origin to the tip of the blue arrow.'); + * } + * * function draw() { * background(200); * * let origin = createVector(0, 0); + * + * // Draw the red arrow. * let v1 = createVector(50, 50); * drawArrow(origin, v1, 'red'); * + * // Draw the blue arrow. * let v2 = createVector(-30, 20); * drawArrow(v1, v2, 'blue'); * + * // Purple arrow. * let v3 = p5.Vector.add(v1, v2); * drawArrow(origin, v3, 'purple'); - * - * describe('Three arrows drawn on a gray square. A red arrow extends from the top left corner to the center. A blue arrow extends from the tip of the red arrow. A purple arrow extends from the origin to the tip of the blue arrow.'); * } * + * // Draws an arrow between two vectors. * function drawArrow(base, vec, myColor) { * push(); * stroke(myColor); @@ -94821,72 +107450,173 @@ this.z += z || 0; return this; } /** - * Performs modulo (remainder) division with a vector's `x`, `y`, and `z` - * components using separate numbers, another - * p5.Vector object, or an array of numbers. - * - * The static version of `rem()` as in `p5.Vector.rem(v2, v1)`, returns a new - * p5.Vector object and doesn't change the - * originals. - * - * @method rem - * @param {Number} x x component of divisor vector. - * @param {Number} y y component of divisor vector. - * @param {Number} z z component of divisor vector. - * @chainable - * @example - *
- * - * let v = createVector(3, 4, 5); - * v.rem(2, 3, 4); - * // Prints 'p5.Vector Object : [1, 1, 1]'. - * print(v.toString()); - * - *
- * - *
- * - * let v1 = createVector(3, 4, 5); - * let v2 = createVector(2, 3, 4); - * v1.rem(v2); - * - * // Prints 'p5.Vector Object : [1, 1, 1]'. - * print(v1.toString()); - * - *
- * - *
- * - * let v = createVector(3, 4, 5); - * let arr = [2, 3, 4]; - * v.rem(arr); - * - * // Prints 'p5.Vector Object : [1, 1, 1]'. - * print(v.toString()); - * - *
- * - *
- * - * let v1 = createVector(3, 4, 5); - * let v2 = createVector(2, 3, 4); - * let v3 = p5.Vector.rem(v1, v2); - * - * // Prints 'p5.Vector Object : [1, 1, 1]'. - * print(v3.toString()); - * - *
- */ + * @private + * @chainable + */ + + }, + { + key: 'calculateRemainder2D', + value: function calculateRemainder2D(xComponent, yComponent) { + if (xComponent !== 0) { + this.x = this.x % xComponent; + } + if (yComponent !== 0) { + this.y = this.y % yComponent; + } + return this; + } /** + * @private + * @chainable + */ + + }, + { + key: 'calculateRemainder3D', + value: function calculateRemainder3D(xComponent, yComponent, zComponent) { + if (xComponent !== 0) { + this.x = this.x % xComponent; + } + if (yComponent !== 0) { + this.y = this.y % yComponent; + } + if (zComponent !== 0) { + this.z = this.z % zComponent; + } + return this; + } /** + * Performs modulo (remainder) division with a vector's `x`, `y`, and `z` + * components. + * + * `rem()` can use separate numbers, as in `v.rem(1, 2, 3)`, + * another p5.Vector object, as in `v.rem(v2)`, or + * an array of numbers, as in `v.rem([1, 2, 3])`. + * + * If only one value is provided, as in `v.rem(2)`, then all the components + * will be set to their values modulo 2. If two values are provided, as in + * `v.rem(2, 3)`, then `v.z` won't change. Calling `rem()` with no + * arguments, as in `v.rem()`, has no effect. + * + * The static version of `rem()`, as in `p5.Vector.rem(v2, v1)`, returns a + * new p5.Vector object and doesn't change the + * originals. + * + * @method rem + * @param {Number} x x component of divisor vector. + * @param {Number} y y component of divisor vector. + * @param {Number} z z component of divisor vector. + * @chainable + * + * @example + *
+ * + * function setup() { + * // Create a p5.Vector object. + * let v = createVector(3, 4, 5); + * + * // Divide numbers. + * v.rem(2); + * + * // Prints 'p5.Vector Object : [1, 0, 1]'. + * print(v.toString()); + * } + * + *
+ * + *
+ * + * function setup() { + * // Create a p5.Vector object. + * let v = createVector(3, 4, 5); + * + * // Divide numbers. + * v.rem(2, 3); + * + * // Prints 'p5.Vector Object : [1, 1, 5]'. + * print(v.toString()); + * } + * + *
+ * + *
+ * + * function setup() { + * // Create a p5.Vector object. + * let v = createVector(3, 4, 5); + * + * // Divide numbers. + * v.rem(2, 3, 4); + * + * // Prints 'p5.Vector Object : [1, 1, 1]'. + * print(v.toString()); + * } + * + *
+ * + *
+ * + * function setup() { + * // Create p5.Vector objects. + * let v1 = createVector(3, 4, 5); + * let v2 = createVector(2, 3, 4); + * + * // Divide a p5.Vector. + * v1.rem(v2); + * + * // Prints 'p5.Vector Object : [1, 1, 1]'. + * print(v1.toString()); + * } + * + *
+ * + *
+ * + * function setup() { + * // Create a p5.Vector object. + * let v = createVector(3, 4, 5); + * + * // Divide an array. + * let arr = [2, 3, 4]; + * v.rem(arr); + * + * // Prints 'p5.Vector Object : [1, 1, 1]'. + * print(v.toString()); + * } + * + *
+ * + *
+ * + * function setup() { + * // Create p5.Vector objects. + * let v1 = createVector(3, 4, 5); + * let v2 = createVector(2, 3, 4); + * + * // Divide without modifying the original vectors. + * let v3 = p5.Vector.rem(v1, v2); + * + * // Prints 'p5.Vector Object : [1, 1, 1]'. + * print(v3.toString()); + * } + * + *
+ */ /** - * @method rem - * @param {p5.Vector | Number[]} value divisor vector. - * @chainable - */ + * @method rem + * @param {p5.Vector | Number[]} value divisor vector. + * @chainable + */ }, { key: 'rem', - value: function rem(x, y, z) { + value: function rem() { + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + var x = args[0], + y = args[1], + z = args[2]; if (x instanceof _main.default.Vector) { if ([x.x, x.y, @@ -94894,49 +107624,43 @@ var xComponent = parseFloat(x.x); var yComponent = parseFloat(x.y); var zComponent = parseFloat(x.z); - return calculateRemainder3D.call(this, xComponent, yComponent, zComponent); + return this.calculateRemainder3D(xComponent, yComponent, zComponent); } } else if (Array.isArray(x)) { - if (x.every(function (element) { - return Number.isFinite(element); - })) { + if (x.every(Number.isFinite)) { if (x.length === 2) { - return calculateRemainder2D.call(this, x[0], x[1]); + return this.calculateRemainder2D(x[0], x[1]); } if (x.length === 3) { - return calculateRemainder3D.call(this, x[0], x[1], x[2]); + return this.calculateRemainder3D(x[0], x[1], x[2]); } } - } else if (arguments.length === 1) { - if (Number.isFinite(arguments[0]) && arguments[0] !== 0) { - this.x = this.x % arguments[0]; - this.y = this.y % arguments[0]; - this.z = this.z % arguments[0]; + } else if (args.length === 1) { + if (Number.isFinite(x) && x !== 0) { + this.x = this.x % x; + this.y = this.y % x; + this.z = this.z % x; return this; } - } else if (arguments.length === 2) { - var vectorComponents = Array.prototype.slice.call(arguments); - if (vectorComponents.every(function (element) { - return Number.isFinite(element); - })) { - if (vectorComponents.length === 2) { - return calculateRemainder2D.call(this, vectorComponents[0], vectorComponents[1]); - } + } else if (args.length === 2) { + if (args.every(Number.isFinite)) { + return this.calculateRemainder2D(x, y); } - } else if (arguments.length === 3) { - var _vectorComponents = Array.prototype.slice.call(arguments); - if (_vectorComponents.every(function (element) { - return Number.isFinite(element); - })) { - if (_vectorComponents.length === 3) { - return calculateRemainder3D.call(this, _vectorComponents[0], _vectorComponents[1], _vectorComponents[2]); - } + } else if (args.length === 3) { + if (args.every(Number.isFinite)) { + return this.calculateRemainder3D(x, y, z); } } } /** - * Subtracts from a vector's `x`, `y`, and `z` components using separate - * numbers, another p5.Vector object, or an array of - * numbers. Calling `sub()` with no arguments has no effect. + * Subtracts from a vector's `x`, `y`, and `z` components. + * + * `sub()` can use separate numbers, as in `v.sub(1, 2, 3)`, another + * p5.Vector object, as in `v.sub(v2)`, or an array + * of numbers, as in `v.sub([1, 2, 3])`. + * + * If a value isn't provided for a component, it won't change. For + * example, `v.sub(4, 5)` subtracts 4 from `v.x`, 5 from `v.y`, and 0 from `v.z`. + * Calling `sub()` with no arguments, as in `v.sub()`, has no effect. * * The static version of `sub()`, as in `p5.Vector.sub(v2, v1)`, returns a new * p5.Vector object and doesn't change the @@ -94947,71 +107671,96 @@ * @param {Number} [y] y component of the vector to subtract. * @param {Number} [z] z component of the vector to subtract. * @chainable + * * @example *
* - * strokeWeight(5); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the points. + * strokeWeight(5); * - * // Bottom right. - * let pos = createVector(75, 75); - * point(pos); + * // Bottom right. + * let pos = createVector(75, 75); + * point(pos); * - * // Top right. - * pos.sub(0, 50); - * point(pos); + * // Top right. + * // Subtract numbers. + * pos.sub(0, 50); + * point(pos); * - * // Top left. - * let p2 = createVector(50, 0); - * pos.sub(p2); - * point(pos); + * // Top left. + * // Subtract a p5.Vector. + * let p2 = createVector(50, 0); + * pos.sub(p2); + * point(pos); * - * // Bottom left. - * let arr = [0, -50]; - * pos.sub(arr); - * point(pos); + * // Bottom left. + * // Subtract an array. + * let arr = [0, -50]; + * pos.sub(arr); + * point(pos); * - * describe('Four black dots arranged in a square on a gray background.'); + * describe('Four black dots arranged in a square on a gray background.'); + * } * *
* *
* - * // Bottom right. - * let p1 = createVector(75, 75); + * function setup() { + * createCanvas(100, 100); + * + * background(200); * - * // Center. - * let p2 = createVector(50, 50); + * // Create p5.Vector objects. + * let p1 = createVector(75, 75); + * let p2 = createVector(50, 50); * - * // Top left. - * let p3 = p5.Vector.sub(p1, p2); + * // Subtract with modifying the original vectors. + * let p3 = p5.Vector.sub(p1, p2); * - * strokeWeight(5); - * point(p1); - * point(p2); - * point(p3); + * // Draw the points. + * strokeWeight(5); + * point(p1); + * point(p2); + * point(p3); * - * describe('Three black dots in a diagonal line from top left to bottom right.'); + * describe('Three black dots in a diagonal line from top left to bottom right.'); + * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('Three arrows drawn on a gray square. A red and a blue arrow extend from the top left. A purple arrow extends from the tip of the red arrow to the tip of the blue arrow.'); + * } + * * function draw() { * background(200); * * let origin = createVector(0, 0); + * + * // Draw the red arrow. * let v1 = createVector(50, 50); * drawArrow(origin, v1, 'red'); * + * // Draw the blue arrow. * let v2 = createVector(20, 70); * drawArrow(origin, v2, 'blue'); * + * // Purple arrow. * let v3 = p5.Vector.sub(v2, v1); * drawArrow(v1, v3, 'purple'); - * - * describe('Three arrows drawn on a gray square. A red and a blue arrow extend from the top left. A purple arrow extends from the tip of the red arrow to the tip of the blue arrow.'); * } * + * // Draws an arrow between two vectors. * function drawArrow(base, vec, myColor) { * push(); * stroke(myColor); @@ -95055,10 +107804,17 @@ this.z -= z || 0; return this; } /** - * Multiplies a vector's `x`, `y`, and `z` components by the same number, - * separate numbers, the components of another - * p5.Vector object, or an array of numbers. Calling - * `mult()` with no arguments has no effect. + * Multiplies a vector's `x`, `y`, and `z` components. + * + * `mult()` can use separate numbers, as in `v.mult(1, 2, 3)`, another + * p5.Vector object, as in `v.mult(v2)`, or an array + * of numbers, as in `v.mult([1, 2, 3])`. + * + * If only one value is provided, as in `v.mult(2)`, then all the components + * will be multiplied by 2. If a value isn't provided for a component, it + * won't change. For example, `v.mult(4, 5)` multiplies `v.x` by, `v.y` by 5, + * and `v.z` by 1. Calling `mult()` with no arguments, as in `v.mult()`, has + * no effect. * * The static version of `mult()`, as in `p5.Vector.mult(v, 2)`, returns a new * p5.Vector object and doesn't change the @@ -95070,92 +107826,146 @@ * @example *
* - * strokeWeight(5); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the points. + * strokeWeight(5); * - * let p = createVector(25, 25); - * point(p); + * // Top-left. + * let p = createVector(25, 25); + * point(p); * - * p.mult(2); - * point(p); + * // Center. + * // Multiply all components by 2. + * p.mult(2); + * point(p); * - * describe('Two black dots drawn on a gray square. One dot is in the top left corner and the other is in the center.'); + * describe('Two black dots drawn on a gray square. One dot is in the top left corner and the other is in the center.'); + * } * *
* *
* - * strokeWeight(5); + * function setup() { + * strokeWeight(5); * - * let p = createVector(25, 25); - * point(p); + * // Top-left. + * let p = createVector(25, 25); + * point(p); * - * p.mult(2, 3); - * point(p); + * // Bottom-right. + * // Multiply p.x * 2 and p.y * 3 + * p.mult(2, 3); + * point(p); * - * describe('Two black dots drawn on a gray square. One dot is in the top left corner and the other is in the bottom center.'); + * describe('Two black dots drawn on a gray square. One dot is in the top left corner and the other is in the bottom center.'); + * } * *
* *
* - * strokeWeight(5); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the points. + * strokeWeight(5); * - * let p = createVector(25, 25); - * point(p); + * // Top-left. + * let p = createVector(25, 25); + * point(p); * - * let arr = [2, 3]; - * p.mult(arr); - * point(p); + * // Bottom-right. + * // Multiply p.x * 2 and p.y * 3 + * let arr = [2, 3]; + * p.mult(arr); + * point(p); * - * describe('Two black dots drawn on a gray square. One dot is in the top left corner and the other is in the bottom center.'); + * describe('Two black dots drawn on a gray square. One dot is in the top left corner and the other is in the bottom center.'); + * } * *
* *
* - * strokeWeight(5); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the points. + * strokeWeight(5); * - * let p = createVector(25, 25); - * point(p); + * // Top-left. + * let p = createVector(25, 25); + * point(p); * - * let p2 = createVector(2, 3); - * p.mult(p2); - * point(p); + * // Bottom-right. + * // Multiply p.x * p2.x and p.y * p2.y + * let p2 = createVector(2, 3); + * p.mult(p2); + * point(p); * - * describe('Two black dots drawn on a gray square. One dot is in the top left corner and the other is in the bottom center.'); + * describe('Two black dots drawn on a gray square. One dot is in the top left corner and the other is in the bottom center.'); + * } * *
* *
* - * strokeWeight(5); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the points. + * strokeWeight(5); * - * let p = createVector(25, 25); - * point(p); + * // Top-left. + * let p = createVector(25, 25); + * point(p); * - * let p2 = createVector(2, 3); - * let p3 = p5.Vector.mult(p, p2); - * point(p3); + * // Bottom-right. + * // Create a new p5.Vector with + * // p3.x = p.x * p2.x + * // p3.y = p.y * p2.y + * let p2 = createVector(2, 3); + * let p3 = p5.Vector.mult(p, p2); + * point(p3); * - * describe('Two black dots drawn on a gray square. One dot is in the top left corner and the other is in the bottom center.'); + * describe('Two black dots drawn on a gray square. One dot is in the top left corner and the other is in the bottom center.'); + * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('Two arrows extending from the top left corner. The blue arrow is twice the length of the red arrow.'); + * } * function draw() { * background(200); * * let origin = createVector(0, 0); + * + * // Draw the red arrow. * let v1 = createVector(25, 25); * drawArrow(origin, v1, 'red'); * + * // Draw the blue arrow. * let v2 = p5.Vector.mult(v1, 2); * drawArrow(origin, v2, 'blue'); - * - * describe('Two arrows extending from the top left corner. The blue arrow is twice the length of the red arrow.'); * } * + * // Draws an arrow between two vectors. * function drawArrow(base, vec, myColor) { * push(); * stroke(myColor); @@ -95193,7 +108003,13 @@ }, { key: 'mult', - value: function mult(x, y, z) { + value: function mult() { + for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args[_key2] = arguments[_key2]; + } + var x = args[0], + y = args[1], + z = args[2]; if (x instanceof _main.default.Vector) { // new p5.Vector will check that values are valid upon construction but it's possible // that someone could change the value of a component after creation, which is why we still @@ -95230,22 +108046,22 @@ } return this; } - var vectorComponents = Array.prototype.slice.call(arguments); + var vectorComponents = args; if (vectorComponents.every(function (element) { return Number.isFinite(element); }) && vectorComponents.every(function (element) { return typeof element === 'number'; })) { - if (arguments.length === 1) { + if (args.length === 1) { this.x *= x; this.y *= x; this.z *= x; } - if (arguments.length === 2) { + if (args.length === 2) { this.x *= x; this.y *= y; } - if (arguments.length === 3) { + if (args.length === 3) { this.x *= x; this.y *= y; this.z *= z; @@ -95255,10 +108071,17 @@ } return this; } /** - * Divides a vector's `x`, `y`, and `z` components by the same number, - * separate numbers, the components of another - * p5.Vector object, or an array of numbers. Calling - * `div()` with no arguments has no effect. + * Divides a vector's `x`, `y`, and `z` components. + * + * `div()` can use separate numbers, as in `v.div(1, 2, 3)`, another + * p5.Vector object, as in `v.div(v2)`, or an array + * of numbers, as in `v.div([1, 2, 3])`. + * + * If only one value is provided, as in `v.div(2)`, then all the components + * will be divided by 2. If a value isn't provided for a component, it + * won't change. For example, `v.div(4, 5)` divides `v.x` by, `v.y` by 5, + * and `v.z` by 1. Calling `div()` with no arguments, as in `v.div()`, has + * no effect. * * The static version of `div()`, as in `p5.Vector.div(v, 2)`, returns a new * p5.Vector object and doesn't change the @@ -95270,74 +108093,126 @@ * @example *
* - * strokeWeight(5); + * function setup() { + * createCanvas(100, 100); * - * let p = createVector(50, 50); - * point(p); + * background(200); * - * p.div(2); - * point(p); + * // Style the points. + * strokeWeight(5); * - * describe('Two black dots drawn on a gray square. One dot is in the top left corner and the other is in the center.'); + * // Center. + * let p = createVector(50, 50); + * point(p); + * + * // Top-left. + * // Divide p.x / 2 and p.y / 2 + * p.div(2); + * point(p); + * + * describe('Two black dots drawn on a gray square. One dot is in the top left corner and the other is in the center.'); + * } * *
* *
* - * strokeWeight(5); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the points. + * strokeWeight(5); * - * let p = createVector(50, 75); - * point(p); + * // Bottom-right. + * let p = createVector(50, 75); + * point(p); * - * p.div(2, 3); - * point(p); + * // Top-left. + * // Divide p.x / 2 and p.y / 3 + * p.div(2, 3); + * point(p); * - * describe('Two black dots drawn on a gray square. One dot is in the top left corner and the other is in the bottom center.'); + * describe('Two black dots drawn on a gray square. One dot is in the top left corner and the other is in the bottom center.'); + * } * *
* *
* - * strokeWeight(5); + * function setup() { + * createCanvas(100, 100); * - * let p = createVector(50, 75); - * point(p); + * background(200); * - * let arr = [2, 3]; - * p.div(arr); - * point(p); + * // Style the points. + * strokeWeight(5); * - * describe('Two black dots drawn on a gray square. One dot is in the top left corner and the other is in the bottom center.'); + * // Bottom-right. + * let p = createVector(50, 75); + * point(p); + * + * // Top-left. + * // Divide p.x / 2 and p.y / 3 + * let arr = [2, 3]; + * p.div(arr); + * point(p); + * + * describe('Two black dots drawn on a gray square. One dot is in the top left corner and the other is in the bottom center.'); + * } * *
* *
* - * strokeWeight(5); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the points. + * strokeWeight(5); * - * let p = createVector(50, 75); - * point(p); + * // Bottom-right. + * let p = createVector(50, 75); + * point(p); * - * let p2 = createVector(2, 3); - * p.div(p2); - * point(p); + * // Top-left. + * // Divide p.x / 2 and p.y / 3 + * let p2 = createVector(2, 3); + * p.div(p2); + * point(p); * - * describe('Two black dots drawn on a gray square. One dot is in the top left corner and the other is in the bottom center.'); + * describe('Two black dots drawn on a gray square. One dot is in the top left corner and the other is in the bottom center.'); + * } * *
* *
* - * strokeWeight(5); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the points. + * strokeWeight(5); * - * let p = createVector(50, 75); - * point(p); + * // Bottom-right. + * let p = createVector(50, 75); + * point(p); * - * let p2 = createVector(2, 3); - * let p3 = p5.Vector.div(p, p2); - * point(p3); + * // Top-left. + * // Create a new p5.Vector with + * // p3.x = p.x / p2.x + * // p3.y = p.y / p2.y + * let p2 = createVector(2, 3); + * let p3 = p5.Vector.div(p, p2); + * point(p3); * - * describe('Two black dots drawn on a gray square. One dot is in the top left corner and the other is in the bottom center.'); + * describe('Two black dots drawn on a gray square. One dot is in the top left corner and the other is in the bottom center.'); + * } * *
* @@ -95347,15 +108222,19 @@ * background(200); * * let origin = createVector(0, 0); + * + * // Draw the red arrow. * let v1 = createVector(50, 50); * drawArrow(origin, v1, 'red'); * + * // Draw the blue arrow. * let v2 = p5.Vector.div(v1, 2); * drawArrow(origin, v2, 'blue'); * * describe('Two arrows extending from the top left corner. The blue arrow is half the length of the red arrow.'); * } * + * // Draws an arrow between two vectors. * function drawArrow(base, vec, myColor) { * push(); * stroke(myColor); @@ -95393,7 +108272,13 @@ }, { key: 'div', - value: function div(x, y, z) { + value: function div() { + for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { + args[_key3] = arguments[_key3]; + } + var x = args[0], + y = args[1], + z = args[2]; if (x instanceof _main.default.Vector) { // new p5.Vector will check that values are valid upon construction but it's possible // that someone could change the value of a component after creation, which is why we still @@ -95415,9 +108300,7 @@ return this; } if (Array.isArray(x)) { - if (x.every(function (element) { - return Number.isFinite(element); - }) && x.every(function (element) { + if (x.every(Number.isFinite) && x.every(function (element) { return typeof element === 'number'; })) { if (x.some(function (element) { @@ -95443,28 +108326,25 @@ } return this; } - var vectorComponents = Array.prototype.slice.call(arguments); - if (vectorComponents.every(function (element) { - return Number.isFinite(element); - }) && vectorComponents.every(function (element) { + if (args.every(Number.isFinite) && args.every(function (element) { return typeof element === 'number'; })) { - if (vectorComponents.some(function (element) { + if (args.some(function (element) { return element === 0; })) { console.warn('p5.Vector.prototype.div:', 'divide by 0'); return this; } - if (arguments.length === 1) { + if (args.length === 1) { this.x /= x; this.y /= x; this.z /= x; } - if (arguments.length === 2) { + if (args.length === 2) { this.x /= x; this.y /= y; } - if (arguments.length === 3) { + if (args.length === 3) { this.x /= x; this.y /= y; this.z /= z; @@ -95474,20 +108354,38 @@ } return this; } /** - * Returns the magnitude (length) of the vector. + * Calculates the magnitude (length) of the vector. + * + * Use mag() to calculate the magnitude of a 2D vector + * using components as in `mag(x, y)`. * * @method mag * @return {Number} magnitude of the vector. + * * @example *
* - * let p = createVector(30, 40); - * line(0, 0, p.x, p.y); + * function setup() { + * createCanvas(100, 100); * - * let m = p.mag(); - * text(m, p.x, p.y); + * background(200); + * + * // Create a p5.Vector object. + * let p = createVector(30, 40); * - * describe('A diagonal black line extends from the top left corner of a gray square. The number 50 is written at the end of the line.'); + * // Draw a line from the origin. + * line(0, 0, p.x, p.y); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * + * // Display the vector's magnitude. + * let m = p.mag(); + * text(m, p.x, p.y); + * + * describe('A diagonal black line extends from the top left corner of a gray square. The number 50 is written at the end of the line.'); + * } * *
*/ @@ -95498,20 +108396,34 @@ value: function mag() { return Math.sqrt(this.magSq()); } /** - * Returns the magnitude (length) of the vector squared. + * Calculates the magnitude (length) of the vector squared. * * @method magSq * @return {number} squared magnitude of the vector. * @example *
* - * let p = createVector(30, 40); - * line(0, 0, p.x, p.y); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.Vector object. + * let p = createVector(30, 40); * - * let m = p.magSq(); - * text(m, p.x, p.y); + * // Draw a line from the origin. + * line(0, 0, p.x, p.y); * - * describe('A diagonal black line extends from the top left corner of a gray square. The number 2500 is written at the end of the line.'); + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * + * // Display the vector's magnitude squared. + * let m = p.magSq(); + * text(m, p.x, p.y); + * + * describe('A diagonal black line extends from the top left corner of a gray square. The number 2500 is written at the end of the line.'); + * } * *
*/ @@ -95525,11 +108437,13 @@ var z = this.z; return x * x + y * y + z * z; } /** - * Returns the dot product of two vectors. The dot product is a number that - * describes the overlap between two vectors. Visually, the dot product can be - * thought of as the "shadow" one vector casts on another. The dot product's - * magnitude is largest when two vectors point in the same or opposite - * directions. Its magnitude is 0 when two vectors form a right angle. + * Calculates the dot product of two vectors. + * + * The dot product is a number that describes the overlap between two vectors. + * Visually, the dot product can be thought of as the "shadow" one vector + * casts on another. The dot product's magnitude is largest when two vectors + * point in the same or opposite directions. Its magnitude is 0 when two + * vectors form a right angle. * * The version of `dot()` with one parameter interprets it as another * p5.Vector object. @@ -95549,42 +108463,64 @@ * @example *
* - * let v1 = createVector(3, 4); - * let v2 = createVector(3, 0); - * let dp = v1.dot(v2); - * // Prints "9" to the console. - * print(dp); + * function setup() { + * // Create p5.Vector objects. + * let v1 = createVector(3, 4); + * let v2 = createVector(3, 0); + * + * // Calculate the dot product. + * let dp = v1.dot(v2); + * + * // Prints "9" to the console. + * print(dp); + * } * *
* *
* - * let v1 = createVector(1, 0); - * let v2 = createVector(0, 1); - * let dp = p5.Vector.dot(v1, v2); - * // Prints "0" to the console. - * print(dp); + * function setup() { + * // Create p5.Vector objects. + * let v1 = createVector(1, 0); + * let v2 = createVector(0, 1); + * + * // Calculate the dot product. + * let dp = p5.Vector.dot(v1, v2); + * + * // Prints "0" to the console. + * print(dp); + * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('Two arrows drawn on a gray square. A black arrow points to the right and a red arrow follows the mouse. The text "v1 • v2 = something" changes as the mouse moves.'); + * } + * * function draw() { * background(200); * - * let v0 = createVector(width / 2, height / 2); + * // Center. + * let v0 = createVector(50, 50); + * + * // Draw the black arrow. * let v1 = createVector(30, 0); * drawArrow(v0, v1, 'black'); * - * let v2 = createVector(mouseX - width / 2, mouseY - height / 2); + * // Draw the red arrow. + * let v2 = createVector(mouseX - 50, mouseY - 50); * drawArrow(v0, v2, 'red'); * + * // Display the dot product. * let dp = v2.dot(v1); - * text(`v2 • v1 = ${dp}`, 15, 20); - * - * describe('Two arrows drawn on a gray square. A black arrow points to the right and a red arrow follows the mouse. The text "v1 • v2 = something" changes as the mouse moves.'); + * text(`v2 • v1 = ${dp}`, 10, 20); * } * + * // Draws an arrow between two vectors. * function drawArrow(base, vec, myColor) { * push(); * stroke(myColor); @@ -95616,10 +108552,11 @@ } return this.x * (x || 0) + this.y * (y || 0) + this.z * (z || 0); } /** - * Returns the cross product of two vectors. The cross product is a vector - * that points straight out of the plane created by two vectors. The cross - * product's magnitude is the area of the parallelogram formed by the original - * two vectors. + * Calculates the cross product of two vectors. + * + * The cross product is a vector that points straight out of the plane created + * by two vectors. The cross product's magnitude is the area of the parallelogram + * formed by the original two vectors. * * The static version of `cross()`, as in `p5.Vector.cross(v1, v2)`, is the same * as calling `v1.cross(v2)`. @@ -95627,24 +108564,37 @@ * @method cross * @param {p5.Vector} v p5.Vector to be crossed. * @return {p5.Vector} cross product as a p5.Vector. + * * @example *
* - * let v1 = createVector(1, 0); - * let v2 = createVector(3, 4); - * let cp = v1.cross(v2); - * // Prints "p5.Vector Object : [0, 0, 4]" to the console. - * print(cp.toString()); + * function setup() { + * // Create p5.Vector objects. + * let v1 = createVector(1, 0); + * let v2 = createVector(3, 4); + * + * // Calculate the cross product. + * let cp = v1.cross(v2); + * + * // Prints "p5.Vector Object : [0, 0, 4]" to the console. + * print(cp.toString()); + * } * *
* *
* - * let v1 = createVector(1, 0); - * let v2 = createVector(3, 4); - * let cp = p5.Vector.cross(v1, v2); - * // Prints "p5.Vector Object : [0, 0, 4]" to the console. - * print(cp.toString()); + * function setup() { + * // Create p5.Vector objects. + * let v1 = createVector(1, 0); + * let v2 = createVector(3, 4); + * + * // Calculate the cross product. + * let cp = p5.Vector.cross(v1, v2); + * + * // Prints "p5.Vector Object : [0, 0, 4]" to the console. + * print(cp.toString()); + * } * *
*/ @@ -95662,8 +108612,10 @@ return new _main.default.Vector(x, y, z); } } /** - * Returns the distance between two points represented by vectors. A point's - * coordinates can be thought of as a vector's components. + * Calculates the distance between two points represented by vectors. + * + * A point's coordinates can be represented by the components of a vector + * that extends from the origin to the point. * * The static version of `dist()`, as in `p5.Vector.dist(v1, v2)`, is the same * as calling `v1.dist(v2)`. @@ -95674,48 +108626,82 @@ * @method dist * @param {p5.Vector} v x, y, and z coordinates of a p5.Vector. * @return {Number} distance. + * * @example *
* - * let v1 = createVector(1, 0); - * let v2 = createVector(0, 1); - * let d = v1.dist(v2); - * // Prints "1.414..." to the console. - * print(d); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create p5.Vector objects. + * let v1 = createVector(1, 0); + * let v2 = createVector(0, 1); + * + * // Calculate the distance between them. + * let d = v1.dist(v2); + * + * // Prints "1.414..." to the console. + * print(d); + * } * *
* *
* - * let v1 = createVector(1, 0); - * let v2 = createVector(0, 1); - * let d = p5.Vector.dist(v1, v2); - * // Prints "1.414..." to the console. - * print(d); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create p5.Vector objects. + * let v1 = createVector(1, 0); + * let v2 = createVector(0, 1); + * + * // Calculate the distance between them. + * let d = p5.Vector.dist(v1, v2); + * + * // Prints "1.414..." to the console. + * print(d); + * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('Three arrows drawn on a gray square. A red and a blue arrow extend from the top left. A purple arrow extends from the tip of the red arrow to the tip of the blue arrow. The number 36 is written in black near the purple arrow.'); + * } + * * function draw() { * background(200); * * let origin = createVector(0, 0); + * + * // Draw the red arrow. * let v1 = createVector(50, 50); * drawArrow(origin, v1, 'red'); * + * // Draw the blue arrow. * let v2 = createVector(20, 70); * drawArrow(origin, v2, 'blue'); * + * // Purple arrow. * let v3 = p5.Vector.sub(v2, v1); * drawArrow(v1, v3, 'purple'); * + * // Style the text. + * textAlign(CENTER); + * + * // Display the magnitude. * let m = floor(v3.mag()); * text(m, 50, 75); - * - * describe('Three arrows drawn on a gray square. A red and a blue arrow extend from the top left. A purple arrow extends from the tip of the red arrow to the tip of the blue arrow. The number 36 is written in black near the purple arrow.'); * } * + * // Draws an arrow between two vectors. * function drawArrow(base, vec, myColor) { * push(); * stroke(myColor); @@ -95748,46 +108734,81 @@ * * @method normalize * @return {p5.Vector} normalized p5.Vector. + * * @example *
* - * let v = createVector(10, 20, 2); - * v.normalize(); - * // Prints "p5.Vector Object : [0.445..., 0.890..., 0.089...]" to the console. - * print(v.toString()); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.Vector. + * let v = createVector(10, 20, 2); + * + * // Normalize. + * v.normalize(); + * + * // Prints "p5.Vector Object : [0.445..., 0.890..., 0.089...]" to the console. + * print(v.toString()); + * } * *
* *
* - * let v0 = createVector(10, 20, 2); - * let v1 = p5.Vector.normalize(v0); - * // Prints "p5.Vector Object : [10, 20, 2]" to the console. - * print(v0.toString()); - * // Prints "p5.Vector Object : [0.445..., 0.890..., 0.089...]" to the console. - * print(v1.toString()); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a p5.Vector. + * let v0 = createVector(10, 20, 2); + * + * // Create a normalized copy. + * let v1 = p5.Vector.normalize(v0); + * + * // Prints "p5.Vector Object : [10, 20, 2]" to the console. + * print(v0.toString()); + * // Prints "p5.Vector Object : [0.445..., 0.890..., 0.089...]" to the console. + * print(v1.toString()); + * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * describe("A red and blue arrow extend from the center of a circle. Both arrows follow the mouse, but the blue arrow's length is fixed to the circle's radius."); + * } + * * function draw() { * background(240); * + * // Vector to the center. * let v0 = createVector(50, 50); + * + * // Vector from the center to the mouse. * let v1 = createVector(mouseX - 50, mouseY - 50); * + * // Circle's radius. * let r = 25; + * + * // Draw the red arrow. * drawArrow(v0, v1, 'red'); + * + * // Draw the blue arrow. * v1.normalize(); * drawArrow(v0, v1.mult(r), 'blue'); * + * // Draw the circle. * noFill(); * circle(50, 50, r * 2); - * - * describe("A red and blue arrow extend from the center of a circle. Both arrows follow the mouse, but the blue arrow's length is fixed to the circle's radius."); * } * + * // Draws an arrow between two vectors. * function drawArrow(base, vec, myColor) { * push(); * stroke(myColor); @@ -95824,43 +108845,69 @@ * @method limit * @param {Number} max maximum magnitude for the vector. * @chainable + * * @example *
* - * let v = createVector(10, 20, 2); - * v.limit(5); - * // Prints "p5.Vector Object : [2.227..., 4.454..., 0.445...]" to the console. - * print(v.toString()); + * function setup() { + * // Create a p5.Vector object. + * let v = createVector(10, 20, 2); + * + * // Limit its magnitude. + * v.limit(5); + * + * // Prints "p5.Vector Object : [2.227..., 4.454..., 0.445...]" to the console. + * print(v.toString()); + * } * *
* *
* - * let v0 = createVector(10, 20, 2); - * let v1 = p5.Vector.limit(v0, 5); - * // Prints "p5.Vector Object : [2.227..., 4.454..., 0.445...]" to the console. - * print(v1.toString()); + * function setup() { + * // Create a p5.Vector object. + * let v0 = createVector(10, 20, 2); + * + * // Create a copy an limit its magintude. + * let v1 = p5.Vector.limit(v0, 5); + * + * // Prints "p5.Vector Object : [2.227..., 4.454..., 0.445...]" to the console. + * print(v1.toString()); + * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * describe("A red and blue arrow extend from the center of a circle. Both arrows follow the mouse, but the blue arrow never crosses the circle's edge."); + * } * function draw() { * background(240); * + * // Vector to the center. * let v0 = createVector(50, 50); + * + * // Vector from the center to the mouse. * let v1 = createVector(mouseX - 50, mouseY - 50); * + * // Circle's radius. * let r = 25; + * + * // Draw the red arrow. * drawArrow(v0, v1, 'red'); + * + * // Draw the blue arrow. * drawArrow(v0, v1.limit(r), 'blue'); * + * // Draw the circle. * noFill(); * circle(50, 50, r * 2); - * - * describe("A red and blue arrow extend from the center of a circle. Both arrows follow the mouse, but the blue arrow never crosses the circle's edge."); * } * + * // Draws an arrow between two vectors. * function drawArrow(base, vec, myColor) { * push(); * stroke(myColor); @@ -95898,46 +108945,69 @@ * @method setMag * @param {number} len new length for this vector. * @chainable + * * @example *
* - * let v = createVector(3, 4, 0); - * // Prints "5" to the console. - * print(v.mag()); + * function setup() { + * // Create a p5.Vector object. + * let v = createVector(3, 4, 0); + * + * // Prints "5" to the console. + * print(v.mag()); + * + * // Set its magnitude to 10. + * v.setMag(10); * - * v.setMag(10); - * // Prints "p5.Vector Object : [6, 8, 0]" to the console. - * print(v.toString()); + * // Prints "p5.Vector Object : [6, 8, 0]" to the console. + * print(v.toString()); + * } * *
* *
* - * let v0 = createVector(3, 4, 0); - * let v1 = p5.Vector.setMag(v0, 10); - * // Prints "5" to the console. - * print(v0.mag()); - * // Prints "p5.Vector Object : [6, 8, 0]" to the console. - * print(v1.toString()); + * function setup() { + * // Create a p5.Vector object. + * let v0 = createVector(3, 4, 0); + * + * // Create a copy with a magnitude of 10. + * let v1 = p5.Vector.setMag(v0, 10); + * + * // Prints "5" to the console. + * print(v0.mag()); + * + * // Prints "p5.Vector Object : [6, 8, 0]" to the console. + * print(v1.toString()); + * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('Two arrows extend from the top left corner of a square toward its center. The red arrow reaches the center and the blue arrow only extends part of the way.'); + * } + * * function draw() { * background(240); * * let origin = createVector(0, 0); * let v = createVector(50, 50); * + * // Draw the red arrow. * drawArrow(origin, v, 'red'); * + * // Set v's magnitude to 30. * v.setMag(30); - * drawArrow(origin, v, 'blue'); * - * describe('Two arrows extend from the top left corner of a square toward its center. The red arrow reaches the center and the blue arrow only extends part of the way.'); + * // Draw the blue arrow. + * drawArrow(origin, v, 'blue'); * } * + * // Draws an arrow between two vectors. * function drawArrow(base, vec, myColor) { * push(); * stroke(myColor); @@ -95961,8 +109031,10 @@ value: function setMag(n) { return this.normalize().mult(n); } /** - * Calculates the angle a 2D vector makes with the positive x-axis. Angles - * increase in the clockwise direction. + * Calculates the angle a 2D vector makes with the positive x-axis. + * + * By convention, the positive x-axis has an angle of 0. Angles increase in + * the clockwise direction. * * If the vector was created with * createVector(), `heading()` returns angles @@ -95973,51 +109045,77 @@ * * @method heading * @return {Number} angle of rotation. + * * @example *
* - * let v = createVector(1, 1); - * // Prints "0.785..." to the console. - * print(v.heading()); + * function setup() { + * // Create a p5.Vector object. + * let v = createVector(1, 1); * - * angleMode(DEGREES); - * // Prints "45" to the console. - * print(v.heading()); + * // Prints "0.785..." to the console. + * print(v.heading()); + * + * // Use degrees. + * angleMode(DEGREES); + * + * // Prints "45" to the console. + * print(v.heading()); + * } * *
* *
* - * let v = createVector(1, 1); - * // Prints "0.785..." to the console. - * print(p5.Vector.heading(v)); + * function setup() { + * // Create a p5.Vector object. + * let v = createVector(1, 1); + * + * // Prints "0.785..." to the console. + * print(p5.Vector.heading(v)); * - * angleMode(DEGREES); - * // Prints "45" to the console. - * print(p5.Vector.heading(v)); + * // Use degrees. + * angleMode(DEGREES); + * + * // Prints "45" to the console. + * print(p5.Vector.heading(v)); + * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('A black arrow extends from the top left of a square to its center. The text "Radians: 0.79" and "Degrees: 45" is written near the tip of the arrow.'); + * } + * * function draw() { * background(200); * * let origin = createVector(0, 0); * let v = createVector(50, 50); * + * // Draw the black arrow. * drawArrow(origin, v, 'black'); * + * // Use radians. * angleMode(RADIANS); + * + * // Display the heading in radians. * let h = round(v.heading(), 2); * text(`Radians: ${h}`, 20, 70); + * + * // Use degrees. * angleMode(DEGREES); + * + * // Display the heading in degrees. * h = v.heading(); * text(`Degrees: ${h}`, 20, 85); - * - * describe('A black arrow extends from the top left of a square to its center. The text "Radians: 0.79" and "Degrees: 45" is written near the tip of the arrow.'); * } * + * // Draws an arrow between two vectors. * function drawArrow(base, vec, myColor) { * push(); * stroke(myColor); @@ -96044,6 +109142,7 @@ return h; } /** * Rotates a 2D vector to a specific angle without changing its magnitude. + * * By convention, the positive x-axis has an angle of 0. Angles increase in * the clockwise direction. * @@ -96057,45 +109156,69 @@ * @example *
* - * let v = createVector(0, 1); - * // Prints "1.570..." to the console. - * print(v.heading()); + * function setup() { + * // Create a p5.Vector object. + * let v = createVector(0, 1); + * + * // Prints "1.570..." to the console. + * print(v.heading()); * - * v.setHeading(PI); - * // Prints "3.141..." to the console. - * print(v.heading()); + * // Point to the left. + * v.setHeading(PI); + * + * // Prints "3.141..." to the console. + * print(v.heading()); + * } * *
* *
* - * angleMode(DEGREES); - * let v = createVector(0, 1); - * // Prints "90" to the console. - * print(v.heading()); - * - * v.setHeading(180); - * // Prints "180" to the console. - * print(v.heading()); + * function setup() { + * // Use degrees. + * angleMode(DEGREES); + * + * // Create a p5.Vector object. + * let v = createVector(0, 1); + * + * // Prints "90" to the console. + * print(v.heading()); + * + * // Point to the left. + * v.setHeading(180); + * + * // Prints "180" to the console. + * print(v.heading()); + * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('Two arrows extend from the center of a gray square. The red arrow points to the right and the blue arrow points down.'); + * } + * * function draw() { * background(200); * + * // Create p5.Vector objects. * let v0 = createVector(50, 50); * let v1 = createVector(30, 0); * + * // Draw the red arrow. * drawArrow(v0, v1, 'red'); * + * // Point down. * v1.setHeading(HALF_PI); - * drawArrow(v0, v1, 'blue'); * - * describe('Two arrows extend from the center of a gray square. The red arrow points to the right and the blue arrow points down.'); + * // Draw the blue arrow. + * drawArrow(v0, v1, 'blue'); * } * + * // Draws an arrow between two vectors. * function drawArrow(base, vec, myColor) { * push(); * stroke(myColor); @@ -96124,6 +109247,7 @@ return this; } /** * Rotates a 2D vector by an angle without changing its magnitude. + * * By convention, the positive x-axis has an angle of 0. Angles increase in * the clockwise direction. * @@ -96141,47 +109265,78 @@ * @example *
* - * let v = createVector(1, 0); - * // Prints "p5.Vector Object : [1, 0, 0]" to the console. - * print(v.toString()); - * v.rotate(HALF_PI); - * // Prints "p5.Vector Object : [0, 1, 0]" to the console. - * print(v.toString()); + * function setup() { + * // Create a p5.Vector object. + * let v = createVector(1, 0); + * + * // Prints "p5.Vector Object : [1, 0, 0]" to the console. + * print(v.toString()); + * + * // Rotate a quarter turn. + * v.rotate(HALF_PI); + * + * // Prints "p5.Vector Object : [0, 1, 0]" to the console. + * print(v.toString()); + * } * *
* *
* - * angleMode(DEGREES); - * let v = createVector(1, 0); - * // Prints "p5.Vector Object : [1, 0, 0]" to the console. - * print(v.toString()); - * v.rotate(90); - * // Prints "p5.Vector Object : [0, 1, 0]" to the console. - * print(v.toString()); + * function setup() { + * // Use degrees. + * angleMode(DEGREES); + * + * // Create a p5.Vector object. + * let v = createVector(1, 0); + * + * // Prints "p5.Vector Object : [1, 0, 0]" to the console. + * print(v.toString()); + * + * // Rotate a quarter turn. + * v.rotate(90); + * + * // Prints "p5.Vector Object : [0, 1, 0]" to the console. + * print(v.toString()); + * } * *
* *
* - * let v0 = createVector(1, 0); - * let v1 = p5.Vector.rotate(v0, HALF_PI); - * // Prints "p5.Vector Object : [1, 0, 0]" to the console. - * print(v0.toString()); - * // Prints "p5.Vector Object : [0, 1, 0]" to the console. - * print(v1.toString()); + * function setup() { + * // Create a p5.Vector object. + * let v0 = createVector(1, 0); + * + * // Create a rotated copy. + * let v1 = p5.Vector.rotate(v0, HALF_PI); + * + * // Prints "p5.Vector Object : [1, 0, 0]" to the console. + * print(v0.toString()); + * // Prints "p5.Vector Object : [0, 1, 0]" to the console. + * print(v1.toString()); + * } * *
* *
* - * angleMode(DEGREES); - * let v0 = createVector(1, 0); - * let v1 = p5.Vector.rotate(v0, 90); - * // Prints "p5.Vector Object : [1, 0, 0]" to the console. - * print(v0.toString()); - * // Prints "p5.Vector Object : [0, 1, 0]" to the console. - * print(v1.toString()); + * function setup() { + * // Use degrees. + * angleMode(DEGREES); + * + * // Create a p5.Vector object. + * let v0 = createVector(1, 0); + * + * // Create a rotated copy. + * let v1 = p5.Vector.rotate(v0, 90); + * + * // Prints "p5.Vector Object : [1, 0, 0]" to the console. + * print(v0.toString()); + * + * // Prints "p5.Vector Object : [0, 1, 0]" to the console. + * print(v1.toString()); + * } * *
* @@ -96191,20 +109346,26 @@ * let v1; * * function setup() { + * createCanvas(100, 100); + * + * // Create p5.Vector objects. * v0 = createVector(50, 50); * v1 = createVector(30, 0); + * + * describe('A black arrow extends from the center of a gray square. The arrow rotates clockwise.'); * } * * function draw() { * background(240); * + * // Rotate v1. * v1.rotate(0.01); * + * // Draw the black arrow. * drawArrow(v0, v1, 'black'); - * - * describe('A black arrow extends from the center of a gray square. The arrow rotates counterclockwise.'); * } * + * // Draws an arrow between two vectors. * function drawArrow(base, vec, myColor) { * push(); * stroke(myColor); @@ -96233,8 +109394,10 @@ this.y = Math.sin(newHeading) * mag; return this; } /** - * Returns the angle between two vectors. The angles returned are signed, - * which means that `v1.angleBetween(v2) === -v2.angleBetween(v1)`. + * Calculates the angle between two vectors. + * + * The angles returned are signed, which means that + * `v1.angleBetween(v2) === -v2.angleBetween(v1)`. * * If the vector was created with * createVector(), `angleBetween()` returns @@ -96247,72 +109410,110 @@ * @example *
* - * let v0 = createVector(1, 0); - * let v1 = createVector(0, 1); - * // Prints "1.570..." to the console. - * print(v0.angleBetween(v1)); - * // Prints "-1.570..." to the console. - * print(v1.angleBetween(v0)); + * function setup() { + * // Create p5.Vector objects. + * let v0 = createVector(1, 0); + * let v1 = createVector(0, 1); + * + * // Prints "1.570..." to the console. + * print(v0.angleBetween(v1)); + * + * // Prints "-1.570..." to the console. + * print(v1.angleBetween(v0)); + * } * *
* *
* - * angleMode(DEGREES); - * let v0 = createVector(1, 0); - * let v1 = createVector(0, 1); - * // Prints "90" to the console. - * print(v0.angleBetween(v1)); - * // Prints "-90" to the console. - * print(v1.angleBetween(v0)); + * function setup() { + * // Use degrees. + * angleMode(DEGREES); + * // Create p5.Vector objects. + * let v0 = createVector(1, 0); + * let v1 = createVector(0, 1); + * + * // Prints "90" to the console. + * print(v0.angleBetween(v1)); + * + * // Prints "-90" to the console. + * print(v1.angleBetween(v0)); + * } * *
* *
* - * let v0 = createVector(1, 0); - * let v1 = createVector(0, 1); - * // Prints "1.570..." to the console. - * print(p5.Vector.angleBetween(v0, v1)); - * // Prints "-1.570..." to the console. - * print(p5.Vector.angleBetween(v1, v0)); + * function setup() { + * // Create p5.Vector objects. + * let v0 = createVector(1, 0); + * let v1 = createVector(0, 1); + * + * // Prints "1.570..." to the console. + * print(p5.Vector.angleBetween(v0, v1)); + * + * // Prints "-1.570..." to the console. + * print(p5.Vector.angleBetween(v1, v0)); + * } * *
* *
* - * angleMode(DEGREES); - * let v0 = createVector(1, 0); - * let v1 = createVector(0, 1); - * // Prints "90" to the console. - * print(p5.Vector.angleBetween(v0, v1)); - * // Prints "-90" to the console. - * print(p5.Vector.angleBetween(v1, v0)); + * function setup() { + * // Use degrees. + * angleMode(DEGREES); + * + * // Create p5.Vector objects. + * let v0 = createVector(1, 0); + * let v1 = createVector(0, 1); + * + * // Prints "90" to the console. + * print(p5.Vector.angleBetween(v0, v1)); + * + * // Prints "-90" to the console. + * print(p5.Vector.angleBetween(v1, v0)); + * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('Two arrows extend from the center of a gray square. A red arrow points to the right and a blue arrow points down. The text "Radians: 1.57" and "Degrees: 90" is written above the arrows.'); + * } * function draw() { * background(200); * + * // Create p5.Vector objects. * let v0 = createVector(50, 50); * let v1 = createVector(30, 0); * let v2 = createVector(0, 30); * + * // Draw the red arrow. * drawArrow(v0, v1, 'red'); + * + * // Draw the blue arrow. * drawArrow(v0, v2, 'blue'); * + * // Use radians. * angleMode(RADIANS); + * + * // Display the angle in radians. * let angle = round(v1.angleBetween(v2), 2); * text(`Radians: ${angle}`, 20, 20); + * + * // Use degrees. * angleMode(DEGREES); + * + * // Display the angle in degrees. * angle = round(v1.angleBetween(v2), 2); * text(`Degrees: ${angle}`, 20, 35); - * - * describe('Two arrows extend from the center of a gray square. A red arrow points to the right and a blue arrow points down. The text "Radians: 1.57" and "Degrees: 90" is written above the arrows.'); * } * + * // Draws an arrow between two vectors. * function drawArrow(base, vec, myColor) { * push(); * stroke(myColor); @@ -96350,10 +109551,11 @@ return angle; } /** * Calculates new `x`, `y`, and `z` components that are proportionally the - * same distance between two vectors. The `amt` parameter is the amount to - * interpolate between the old vector and the new vector. 0.0 keeps all - * components equal to the old vector's, 0.5 is halfway between, and 1.0 sets - * all components equal to the new vector's. + * same distance between two vectors. + * + * The `amt` parameter is the amount to interpolate between the old vector and + * the new vector. 0.0 keeps all components equal to the old vector's, 0.5 is + * halfway between, and 1.0 sets all components equal to the new vector's. * * The static version of `lerp()`, as in `p5.Vector.lerp(v0, v1, 0.5)`, * returns a new p5.Vector object and doesn't change @@ -96370,50 +109572,80 @@ * @example *
* - * let v0 = createVector(1, 1, 1); - * let v1 = createVector(3, 3, 3); - * v0.lerp(v1, 0.5); - * // Prints "p5.Vector Object : [2, 2, 2]" to the console. - * print(v0.toString()); + * function setup() { + * // Create a p5.Vector object. + * let v0 = createVector(1, 1, 1); + * let v1 = createVector(3, 3, 3); + * + * // Interpolate. + * v0.lerp(v1, 0.5); + * + * // Prints "p5.Vector Object : [2, 2, 2]" to the console. + * print(v0.toString()); + * } * *
* *
* - * let v = createVector(1, 1, 1); - * v.lerp(3, 3, 3, 0.5); - * // Prints "p5.Vector Object : [2, 2, 2]" to the console. - * print(v.toString()); + * function setup() { + * // Create a p5.Vector object. + * let v = createVector(1, 1, 1); + * + * // Interpolate. + * v.lerp(3, 3, 3, 0.5); + * + * // Prints "p5.Vector Object : [2, 2, 2]" to the console. + * print(v.toString()); + * } * *
* *
* - * let v0 = createVector(1, 1, 1); - * let v1 = createVector(3, 3, 3); - * let v2 = p5.Vector.lerp(v0, v1, 0.5); - * // Prints "p5.Vector Object : [2, 2, 2]" to the console. - * print(v2.toString()); + * function setup() { + * // Create p5.Vector objects. + * let v0 = createVector(1, 1, 1); + * let v1 = createVector(3, 3, 3); + * + * // Interpolate. + * let v2 = p5.Vector.lerp(v0, v1, 0.5); + * + * // Prints "p5.Vector Object : [2, 2, 2]" to the console. + * print(v2.toString()); + * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('Three arrows extend from the center of a gray square. A red arrow points to the right, a blue arrow points down, and a purple arrow points to the bottom right.'); + * } * function draw() { * background(200); * + * // Create p5.Vector objects. * let v0 = createVector(50, 50); * let v1 = createVector(30, 0); * let v2 = createVector(0, 30); + * + * // Interpolate. * let v3 = p5.Vector.lerp(v1, v2, 0.5); * + * // Draw the red arrow. * drawArrow(v0, v1, 'red'); + * + * // Draw the blue arrow. * drawArrow(v0, v2, 'blue'); - * drawArrow(v0, v3, 'purple'); * - * describe('Three arrows extend from the center of a gray square. A red arrow points to the right, a blue arrow points down, and a purple arrow points to the bottom right.'); + * // Draw the purple arrow. + * drawArrow(v0, v3, 'purple'); * } * + * // Draws an arrow between two vectors. * function drawArrow(base, vec, myColor) { * push(); * stroke(myColor); @@ -96449,8 +109681,9 @@ this.z += (z - this.z) * amt || 0; return this; } /** - * Calculates a new heading and magnitude that are between two vectors. The - * `amt` parameter is the amount to interpolate between the old vector and + * Calculates a new heading and magnitude that are between two vectors. + * + * The `amt` parameter is the amount to interpolate between the old vector and * the new vector. 0.0 keeps the heading and magnitude equal to the old * vector's, 0.5 sets them halfway between, and 1.0 sets the heading and * magnitude equal to the new vector's. @@ -96473,65 +109706,100 @@ * @example *
* - * let v0 = createVector(3, 0); - * // Prints "3" to the console. - * print(v0.mag()); - * // Prints "0" to the console. - * print(v0.heading()); - * - * let v1 = createVector(0, 1); - * // Prints "1" to the console. - * print(v1.mag()); - * // Prints "1.570..." to the console. - * print(v1.heading()); - * - * v0.slerp(v1, 0.5); - * // Prints "2" to the console. - * print(v0.mag()); - * // Prints "0.785..." to the console. - * print(v0.heading()); + * function setup() { + * // Create a p5.Vector object. + * let v0 = createVector(3, 0); + * + * // Prints "3" to the console. + * print(v0.mag()); + * + * // Prints "0" to the console. + * print(v0.heading()); + * + * // Create a p5.Vector object. + * let v1 = createVector(0, 1); + * + * // Prints "1" to the console. + * print(v1.mag()); + * + * // Prints "1.570..." to the console. + * print(v1.heading()); + * + * // Interpolate halfway between v0 and v1. + * v0.slerp(v1, 0.5); + * + * // Prints "2" to the console. + * print(v0.mag()); + * + * // Prints "0.785..." to the console. + * print(v0.heading()); + * } * *
* *
* - * let v0 = createVector(3, 0); - * // Prints "3" to the console. - * print(v0.mag()); - * // Prints "0" to the console. - * print(v0.heading()); - * - * let v1 = createVector(0, 1); - * // Prints "1" to the console. - * print(v1.mag()); - * // Prints "1.570..." to the console. - * print(v1.heading()); - * - * let v3 = p5.Vector.slerp(v0, v1, 0.5); - * // Prints "2" to the console. - * print(v3.mag()); - * // Prints "0.785..." to the console. - * print(v3.heading()); + * function setup() { + * // Create a p5.Vector object. + * let v0 = createVector(3, 0); + * + * // Prints "3" to the console. + * print(v0.mag()); + * + * // Prints "0" to the console. + * print(v0.heading()); + * + * // Create a p5.Vector object. + * let v1 = createVector(0, 1); + * + * // Prints "1" to the console. + * print(v1.mag()); + * + * // Prints "1.570..." to the console. + * print(v1.heading()); + * + * // Create a p5.Vector that's halfway between v0 and v1. + * let v3 = p5.Vector.slerp(v0, v1, 0.5); + * + * // Prints "2" to the console. + * print(v3.mag()); + * + * // Prints "0.785..." to the console. + * print(v3.heading()); + * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('Three arrows extend from the center of a gray square. A red arrow points to the right, a blue arrow points to the left, and a purple arrow points down.'); + * } + * * function draw() { * background(200); * + * // Create p5.Vector objects. * let v0 = createVector(50, 50); * let v1 = createVector(20, 0); * let v2 = createVector(-40, 0); + * + * // Create a p5.Vector that's halfway between v1 and v2. * let v3 = p5.Vector.slerp(v1, v2, 0.5); * + * // Draw the red arrow. * drawArrow(v0, v1, 'red'); + * + * // Draw the blue arrow. * drawArrow(v0, v2, 'blue'); - * drawArrow(v0, v3, 'purple'); * - * describe('Three arrows extend from the center of a gray square. A red arrow points to the right, a blue arrow points to the left, and a purple arrow points down.'); + * // Draw the purple arrow. + * drawArrow(v0, v3, 'purple'); * } * + * // Draws an arrow between two vectors. * function drawArrow(base, vec, myColor) { * push(); * stroke(myColor); @@ -96617,9 +109885,10 @@ this.z = this.z * cosMultiplier + ey.z * sinMultiplier; return this; } /** - * Reflects a vector about a line in 2D or a plane in 3D. The orientation of - * the line or plane is described by a normal vector that points away from the - * shape. + * Reflects a vector about a line in 2D or a plane in 3D. + * + * The orientation of the line or plane is described by a normal vector that + * points away from the shape. * * The static version of `reflect()`, as in `p5.Vector.reflect(v, n)`, * returns a new p5.Vector object and doesn't change @@ -96632,44 +109901,78 @@ * @example *
* - * let n = createVector(0, 1); - * let v = createVector(4, 6); - * v.reflect(n); - * // Prints "p5.Vector Object : [4, -6, 0]" to the console. - * print(v.toString()); + * function setup() { + * // Create a normal vector. + * let n = createVector(0, 1); + * // Create a vector to reflect. + * let v = createVector(4, 6); + * + * // Reflect v about n. + * v.reflect(n); + * + * // Prints "p5.Vector Object : [4, -6, 0]" to the console. + * print(v.toString()); + * } * *
* *
* - * let n = createVector(0, 1); - * let v0 = createVector(4, 6); - * let v1 = p5.Vector.reflect(v0, n); - * // Prints "p5.Vector Object : [4, -6, 0]" to the console. - * print(v1.toString()); + * function setup() { + * // Create a normal vector. + * let n = createVector(0, 1); + * + * // Create a vector to reflect. + * let v0 = createVector(4, 6); + * + * // Create a reflected vector. + * let v1 = p5.Vector.reflect(v0, n); + * + * // Prints "p5.Vector Object : [4, -6, 0]" to the console. + * print(v1.toString()); + * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('Three arrows extend from the center of a gray square with a vertical line down its middle. A black arrow points to the right, a blue arrow points to the bottom left, and a red arrow points to the bottom right.'); + * } * function draw() { * background(200); * + * // Draw a vertical line. * line(50, 0, 50, 100); + * + * // Create a normal vector. * let n = createVector(1, 0); * + * // Center. * let v0 = createVector(50, 50); + * + * // Create a vector to reflect. * let v1 = createVector(30, 40); + * + * // Create a reflected vector. * let v2 = p5.Vector.reflect(v1, n); * + * // Scale the normal vector for drawing. * n.setMag(30); + * + * // Draw the black arrow. * drawArrow(v0, n, 'black'); + * + * // Draw the red arrow. * drawArrow(v0, v1, 'red'); - * drawArrow(v0, v2, 'blue'); * - * describe('Three arrows extend from the center of a gray square with a vertical line down its middle. A black arrow points to the right, a blue arrow points to the bottom left, and a red arrow points to the bottom right.'); + * // Draw the blue arrow. + * drawArrow(v0, v2, 'blue'); * } * + * // Draws an arrow between two vectors. * function drawArrow(base, vec, myColor) { * push(); * stroke(myColor); @@ -96691,8 +109994,8 @@ { key: 'reflect', value: function reflect(surfaceNormal) { - surfaceNormal.normalize(); - return this.sub(surfaceNormal.mult(2 * this.dot(surfaceNormal))); + var surfaceNormalCopy = _main.default.Vector.normalize(surfaceNormal); + return this.sub(surfaceNormalCopy.mult(2 * this.dot(surfaceNormalCopy))); } /** * Returns the vector's components as an array of numbers. * @@ -96701,9 +110004,13 @@ * @example *
* - * let v = createVector(20, 30); - * // Prints "[20, 30, 0]" to the console. - * print(v.array()); + * function setup() { + * // Create a p5.Vector object. + * let v = createVector(20, 30); + * + * // Prints "[20, 30, 0]" to the console. + * print(v.array()); + * } * *
*/ @@ -96716,7 +110023,9 @@ this.y || 0, this.z || 0]; } /** - * Returns `true` if the vector's components are all the same as another + * Checks whether all the vector's components are equal to another vector's. + * + * `equals()` returns `true` if the vector's components are all the same as another * vector's and `false` if not. * * The version of `equals()` with one parameter interprets it as another @@ -96737,40 +110046,52 @@ * @example *
* - * let v0 = createVector(10, 20, 30); - * let v1 = createVector(10, 20, 30); - * let v2 = createVector(0, 0, 0); - * - * // Prints "true" to the console. - * print(v0.equals(v1)); - * // Prints "false" to the console. - * print(v0.equals(v2)); + * function setup() { + * // Create p5.Vector objects. + * let v0 = createVector(10, 20, 30); + * let v1 = createVector(10, 20, 30); + * let v2 = createVector(0, 0, 0); + * + * // Prints "true" to the console. + * print(v0.equals(v1)); + * + * // Prints "false" to the console. + * print(v0.equals(v2)); + * } * *
* *
* - * let v0 = createVector(5, 10, 20); - * let v1 = createVector(5, 10, 20); - * let v2 = createVector(13, 10, 19); - * - * // Prints "true" to the console. - * print(v0.equals(v1.x, v1.y, v1.z)); - * // Prints "false" to the console. - * print(v0.equals(v2.x, v2.y, v2.z)); + * function setup() { + * // Create p5.Vector objects. + * let v0 = createVector(5, 10, 20); + * let v1 = createVector(5, 10, 20); + * let v2 = createVector(13, 10, 19); + * + * // Prints "true" to the console. + * print(v0.equals(v1.x, v1.y, v1.z)); + * + * // Prints "false" to the console. + * print(v0.equals(v2.x, v2.y, v2.z)); + * } * *
* *
* - * let v0 = createVector(10, 20, 30); - * let v1 = createVector(10, 20, 30); - * let v2 = createVector(0, 0, 0); - * - * // Prints "true" to the console. - * print(p5.Vector.equals(v0, v1)); - * // Prints "false" to the console. - * print(p5.Vector.equals(v0, v2)); + * function setup() { + * // Create p5.Vector objects. + * let v0 = createVector(10, 20, 30); + * let v1 = createVector(10, 20, 30); + * let v2 = createVector(0, 0, 0); + * + * // Prints "true" to the console. + * print(p5.Vector.equals(v0, v1)); + * + * // Prints "false" to the console. + * print(p5.Vector.equals(v0, v2)); + * } * *
*/ @@ -96803,35 +110124,60 @@ return this.x === a && this.y === b && this.z === c; } // Static Methods /** - * Make a new 2D vector from an angle. + * Creates a new 2D vector from an angle. * * @method fromAngle * @static * @param {Number} angle desired angle, in radians. Unaffected by angleMode(). * @param {Number} [length] length of the new vector (defaults to 1). * @return {p5.Vector} new p5.Vector object. + * * @example *
* - * let v = p5.Vector.fromAngle(0); - * // Prints "p5.Vector Object : [1, 0, 0]" to the console. - * print(v.toString()); + * function setup() { + * // Create a p5.Vector object. + * let v = p5.Vector.fromAngle(0); + * + * // Prints "p5.Vector Object : [1, 0, 0]" to the console. + * print(v.toString()); + * } + * + *
+ * + *
+ * + * function setup() { + * // Create a p5.Vector object. + * let v = p5.Vector.fromAngle(0, 30); + * + * // Prints "p5.Vector Object : [30, 0, 0]" to the console. + * print(v.toString()); + * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('A black arrow extends from the center of a gray square. It points to the right.'); + * } * function draw() { * background(200); * + * // Create a p5.Vector to the center. * let v0 = createVector(50, 50); + * + * // Create a p5.Vector with an angle 0 and magnitude 30. * let v1 = p5.Vector.fromAngle(0, 30); * + * // Draw the black arrow. * drawArrow(v0, v1, 'black'); - * - * describe('A black arrow extends from the center of a gray square. It points to the right.'); * } * + * // Draws an arrow between two vectors. * function drawArrow(base, vec, myColor) { * push(); * stroke(myColor); @@ -96849,17 +110195,47 @@ *
*/ + }, + { + key: 'clampToZero', + /** + * Replaces the components of a p5.Vector that are very close to zero with zero. + * + * In computers, handling numbers with decimals can give slightly imprecise answers due to the way those numbers are represented. + * This can make it hard to check if a number is zero, as it may be close but not exactly zero. + * This method rounds very close numbers to zero to make those checks easier + * + * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON + * + * @method clampToZero + * @return {p5.Vector} with components very close to zero replaced with zero. + * @chainable + */ + value: function clampToZero() { + this.x = this._clampToZero(this.x); + this.y = this._clampToZero(this.y); + this.z = this._clampToZero(this.z); + return this; + } /** + * Helper function for clampToZero + * @private + */ + + }, + { + key: '_clampToZero', + value: function _clampToZero(val) { + return Math.abs((val || 0) - 0) <= Number.EPSILON ? 0 : val; + } } ], [ { key: 'fromAngle', - value: function fromAngle(angle, length) { - if (typeof length === 'undefined') { - length = 1; - } + value: function fromAngle(angle) { + var length = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; return new _main.default.Vector(length * Math.cos(angle), length * Math.sin(angle), 0); } /** - * Make a new 3D vector from a pair of ISO spherical angles. + * Creates a new 3D vector from a pair of ISO spherical angles. * * @method fromAngles * @static @@ -96868,12 +110244,17 @@ * (zero is out of the screen). * @param {Number} [length] length of the new vector (defaults to 1). * @return {p5.Vector} new p5.Vector object. + * * @example *
* - * let v = p5.Vector.fromAngles(0, 0); - * // Prints "p5.Vector Object : [0, -1, 0]" to the console. - * print(v.toString()); + * function setup() { + * // Create a p5.Vector object. + * let v = p5.Vector.fromAngles(0, 0); + * + * // Prints "p5.Vector Object : [0, -1, 0]" to the console. + * print(v.toString()); + * } * *
* @@ -96881,23 +110262,30 @@ * * function setup() { * createCanvas(100, 100, WEBGL); + * + * describe('A light shines on a pink sphere as it orbits.'); * } * * function draw() { * background(0); * - * fill(255); - * noStroke(); - * + * // Calculate the ISO angles. * let theta = frameCount * 0.05; * let phi = 0; + * + * // Create a p5.Vector object. * let v = p5.Vector.fromAngles(theta, phi, 100); + * + * // Create a point light using the p5.Vector. * let c = color('deeppink'); * pointLight(c, v); * - * sphere(35); + * // Style the sphere. + * fill(255); + * noStroke(); * - * describe('A light shines on a pink sphere as it orbits.'); + * // Draw the sphere. + * sphere(35); * } * *
@@ -96906,17 +110294,15 @@ }, { key: 'fromAngles', - value: function fromAngles(theta, phi, length) { - if (typeof length === 'undefined') { - length = 1; - } + value: function fromAngles(theta, phi) { + var length = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1; var cosPhi = Math.cos(phi); var sinPhi = Math.sin(phi); var cosTheta = Math.cos(theta); var sinTheta = Math.sin(theta); return new _main.default.Vector(length * sinTheta * sinPhi, - length * cosTheta, length * sinTheta * cosPhi); } /** - * Make a new 2D unit vector with a random heading. + * Creates a new 2D unit vector with a random heading. * * @method random2D * @static @@ -96924,28 +110310,45 @@ * @example *
* - * let v = p5.Vector.random2D(); - * // Prints "p5.Vector Object : [x, y, 0]" to the console - * // where x and y are small random numbers. - * print(v.toString()); + * function setup() { + * // Create a p5.Vector object. + * let v = p5.Vector.random2D(); + * + * // Prints "p5.Vector Object : [x, y, 0]" to the console + * // where x and y are small random numbers. + * print(v.toString()); + * } * *
* *
* - * function draw() { - * background(200); + * function setup() { + * createCanvas(100, 100); * + * // Slow the frame rate. * frameRate(1); * + * describe('A black arrow in extends from the center of a gray square. It changes direction once per second.'); + * } + * + * function draw() { + * background(200); + * + * // Create a p5.Vector to the center. * let v0 = createVector(50, 50); + * + * // Create a random p5.Vector. * let v1 = p5.Vector.random2D(); + * + * // Scale v1 for drawing. * v1.mult(30); - * drawArrow(v0, v1, 'black'); * - * describe('A black arrow in extends from the center of a gray square. It changes direction once per second.'); + * // Draw the black arrow. + * drawArrow(v0, v1, 'black'); * } * + * // Draws an arrow between two vectors. * function drawArrow(base, vec, myColor) { * push(); * stroke(myColor); @@ -96969,7 +110372,7 @@ value: function random2D() { return this.fromAngle(Math.random() * constants.TWO_PI); } /** - * Make a new 3D unit vector with a random heading. + * Creates a new 3D unit vector with a random heading. * * @method random3D * @static @@ -96977,10 +110380,14 @@ * @example *
* - * let v = p5.Vector.random3D(); - * // Prints "p5.Vector Object : [x, y, z]" to the console - * // where x, y, and z are small random numbers. - * print(v.toString()); + * function setup() { + * // Create a p5.Vector object. + * let v = p5.Vector.random3D(); + * + * // Prints "p5.Vector Object : [x, y, z]" to the console + * // where x, y, and z are small random numbers. + * print(v.toString()); + * } * *
*/ @@ -97021,10 +110428,16 @@ }, { key: 'add', - value: function add(v1, v2, target) { + value: function add() { + for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { + args[_key4] = arguments[_key4]; + } + var v1 = args[0], + v2 = args[1], + target = args[2]; if (!target) { target = v1.copy(); - if (arguments.length === 3) { + if (args.length === 3) { _main.default._friendlyError('The target parameter is undefined, it should be of type p5.Vector', 'p5.Vector.add'); } } else { @@ -97072,10 +110485,16 @@ }, { key: 'sub', - value: function sub(v1, v2, target) { + value: function sub() { + for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) { + args[_key5] = arguments[_key5]; + } + var v1 = args[0], + v2 = args[1], + target = args[2]; if (!target) { target = v1.copy(); - if (arguments.length === 3) { + if (args.length === 3) { _main.default._friendlyError('The target parameter is undefined, it should be of type p5.Vector', 'p5.Vector.sub'); } } else { @@ -97100,6 +110519,7 @@ * @param {p5.Vector} v * @param {Number} n * @param {p5.Vector} [target] vector to receive the result. + * @return {p5.Vector} The resulting new p5.Vector */ /** * @method mult @@ -97107,6 +110527,7 @@ * @param {p5.Vector} v0 * @param {p5.Vector} v1 * @param {p5.Vector} [target] + * @return {p5.Vector} The resulting new p5.Vector */ /** * @method mult @@ -97114,15 +110535,22 @@ * @param {p5.Vector} v0 * @param {Number[]} arr * @param {p5.Vector} [target] + * @return {p5.Vector} The resulting new p5.Vector */ }, { key: 'mult', - value: function mult(v, n, target) { + value: function mult() { + for (var _len6 = arguments.length, args = new Array(_len6), _key6 = 0; _key6 < _len6; _key6++) { + args[_key6] = arguments[_key6]; + } + var v = args[0], + n = args[1], + target = args[2]; if (!target) { target = v.copy(); - if (arguments.length === 3) { + if (args.length === 3) { _main.default._friendlyError('The target parameter is undefined, it should be of type p5.Vector', 'p5.Vector.mult'); } } else { @@ -97139,13 +110567,20 @@ * @param {p5.Vector} v * @param {Number} angle * @param {p5.Vector} [target] The vector to receive the result + * @return {p5.Vector} The resulting new p5.Vector */ }, { key: 'rotate', - value: function rotate(v, a, target) { - if (arguments.length === 2) { + value: function rotate() { + for (var _len7 = arguments.length, args = new Array(_len7), _key7 = 0; _key7 < _len7; _key7++) { + args[_key7] = arguments[_key7]; + } + var v = args[0], + a = args[1], + target = args[2]; + if (args.length === 2) { target = v.copy(); } else { if (!(target instanceof _main.default.Vector)) { @@ -97172,6 +110607,7 @@ * @param {p5.Vector} v * @param {Number} n * @param {p5.Vector} [target] The vector to receive the result + * @return {p5.Vector} The resulting new p5.Vector */ /** * @method div @@ -97179,6 +110615,7 @@ * @param {p5.Vector} v0 * @param {p5.Vector} v1 * @param {p5.Vector} [target] + * @return {p5.Vector} The resulting new p5.Vector */ /** * @method div @@ -97186,15 +110623,22 @@ * @param {p5.Vector} v0 * @param {Number[]} arr * @param {p5.Vector} [target] + * @return {p5.Vector} The resulting new p5.Vector */ }, { key: 'div', - value: function div(v, n, target) { + value: function div() { + for (var _len8 = arguments.length, args = new Array(_len8), _key8 = 0; _key8 < _len8; _key8++) { + args[_key8] = arguments[_key8]; + } + var v = args[0], + n = args[1], + target = args[2]; if (!target) { target = v.copy(); - if (arguments.length === 3) { + if (args.length === 3) { _main.default._friendlyError('The target parameter is undefined, it should be of type p5.Vector', 'p5.Vector.div'); } } else { @@ -97268,10 +110712,17 @@ }, { key: 'lerp', - value: function lerp(v1, v2, amt, target) { + value: function lerp() { + for (var _len9 = arguments.length, args = new Array(_len9), _key9 = 0; _key9 < _len9; _key9++) { + args[_key9] = arguments[_key9]; + } + var v1 = args[0], + v2 = args[1], + amt = args[2], + target = args[3]; if (!target) { target = v1.copy(); - if (arguments.length === 4) { + if (args.length === 4) { _main.default._friendlyError('The target parameter is undefined, it should be of type p5.Vector', 'p5.Vector.lerp'); } } else { @@ -97298,10 +110749,17 @@ }, { key: 'slerp', - value: function slerp(v1, v2, amt, target) { + value: function slerp() { + for (var _len10 = arguments.length, args = new Array(_len10), _key10 = 0; _key10 < _len10; _key10++) { + args[_key10] = arguments[_key10]; + } + var v1 = args[0], + v2 = args[1], + amt = args[2], + target = args[3]; if (!target) { target = v1.copy(); - if (arguments.length === 4) { + if (args.length === 4) { _main.default._friendlyError('The target parameter is undefined, it should be of type p5.Vector', 'p5.Vector.slerp'); } } else { @@ -97357,8 +110815,13 @@ }, { key: 'normalize', - value: function normalize(v, target) { - if (arguments.length < 2) { + value: function normalize() { + for (var _len11 = arguments.length, args = new Array(_len11), _key11 = 0; _key11 < _len11; _key11++) { + args[_key11] = arguments[_key11]; + } + var v = args[0], + target = args[1]; + if (args.length < 2) { target = v.copy(); } else { if (!(target instanceof _main.default.Vector)) { @@ -97383,8 +110846,14 @@ }, { key: 'limit', - value: function limit(v, max, target) { - if (arguments.length < 3) { + value: function limit() { + for (var _len12 = arguments.length, args = new Array(_len12), _key12 = 0; _key12 < _len12; _key12++) { + args[_key12] = arguments[_key12]; + } + var v = args[0], + max = args[1], + target = args[2]; + if (args.length < 3) { target = v.copy(); } else { if (!(target instanceof _main.default.Vector)) { @@ -97409,8 +110878,14 @@ }, { key: 'setMag', - value: function setMag(v, len, target) { - if (arguments.length < 3) { + value: function setMag() { + for (var _len13 = arguments.length, args = new Array(_len13), _key13 = 0; _key13 < _len13; _key13++) { + args[_key13] = arguments[_key13]; + } + var v = args[0], + len = args[1], + target = args[2]; + if (args.length < 3) { target = v.copy(); } else { if (!(target instanceof _main.default.Vector)) { @@ -97471,8 +110946,14 @@ }, { key: 'reflect', - value: function reflect(incidentVector, surfaceNormal, target) { - if (arguments.length < 3) { + value: function reflect() { + for (var _len14 = arguments.length, args = new Array(_len14), _key14 = 0; _key14 < _len14; _key14++) { + args[_key14] = arguments[_key14]; + } + var incidentVector = args[0], + surfaceNormal = args[1], + target = args[2]; + if (args.length < 3) { target = incidentVector.copy(); } else { if (!(target instanceof _main.default.Vector)) { @@ -97517,7 +110998,7 @@ var v; if (v1 instanceof _main.default.Vector) { v = v1; - } else if (v1 instanceof Array) { + } else if (Array.isArray(v1)) { v = new _main.default.Vector().set(v1); } else { _main.default._friendlyError('The v1 parameter should be of type Array or p5.Vector', 'p5.Vector.equals'); @@ -97532,28 +111013,28 @@ exports.default = _default; }, { - '../core/constants': 286, - '../core/main': 298, - 'core-js/modules/es.array.concat': 169, - 'core-js/modules/es.array.every': 171, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.array.some': 184, - 'core-js/modules/es.math.sign': 190, - 'core-js/modules/es.number.constructor': 191, - 'core-js/modules/es.number.is-finite': 192, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.string.sub': 218, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/constants': 294, + '../core/main': 306, + 'core-js/modules/es.array.concat': 171, + 'core-js/modules/es.array.every': 173, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.some': 188, + 'core-js/modules/es.math.sign': 196, + 'core-js/modules/es.number.constructor': 197, + 'core-js/modules/es.number.epsilon': 198, + 'core-js/modules/es.number.is-finite': 199, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.string.sub': 226, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 332: [ + 340: [ function (_dereq_, module, exports) { 'use strict'; Object.defineProperty(exports, '__esModule', { @@ -97598,9 +111079,10 @@ this[stateProperty] = (val == null ? Math.random() * m : val) >>> 0; }; /** - * Sets the seed value for random() and - * randomGaussian(). By default, - * random() and + * Sets the seed value for the random() and + * randomGaussian() functions. + * + * By default, random() and * randomGaussian() produce different * results each time a sketch is run. Calling `randomSeed()` with a constant * argument, such as `randomSeed(99)`, makes these functions produce the same @@ -97608,20 +111090,35 @@ * * @method randomSeed * @param {Number} seed seed value. + * * @example *
* - * let x = random(width); - * let y = random(height); - * circle(x, y, 10); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Get random coordinates. + * let x = random(0, 100); + * let y = random(0, 100); + * + * // Draw the white circle. + * circle(x, y, 10); * - * randomSeed(99); - * x = random(width); - * y = random(height); - * fill(0); - * circle(x, y, 10); + * // Set a random seed for consistency. + * randomSeed(99); * - * describe('A white circle appears at a random position. A black circle appears at (27.4, 25.8).'); + * // Get random coordinates. + * x = random(0, 100); + * y = random(0, 100); + * + * // Draw the black circle. + * fill(0); + * circle(x, y, 10); + * + * describe('A white circle appears at a random position. A black circle appears at (27.4, 25.8).'); + * } * *
*/ @@ -97661,59 +111158,143 @@ * @param {Number} [min] lower bound (inclusive). * @param {Number} [max] upper bound (exclusive). * @return {Number} random number. + * * @example *
* - * let x = random(width); - * let y = random(height); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Get random coordinates between 0 and 100. + * let x = random(0, 100); + * let y = random(0, 100); * - * strokeWeight(5); - * point(x, y); + * // Draw a point. + * strokeWeight(5); + * point(x, y); * - * describe('A black dot appears in a random posiiton on a gray square.'); + * describe('A black dot appears in a random position on a gray square.'); + * } * *
* *
* - * let animals = ['🦁', '🐯', '🐻']; - * let animal = random(animals); - * text(animal, 50, 50); + * function setup() { + * createCanvas(100, 100); * - * describe('An animal face is displayed at random. Either a lion, tiger, or bear.'); + * background(200); + * + * // Get random coordinates between 0 and 100. + * let x = random(100); + * let y = random(100); + * + * // Draw the point. + * strokeWeight(5); + * point(x, y); + * + * describe('A black dot appears in a random position on a gray square.'); + * } * *
* *
* - * function draw() { + * function setup() { + * createCanvas(100, 100); + * * background(200); * + * // Create an array of emoji strings. + * let animals = ['🦁', '🐯', '🐻']; + * + * // Choose a random element from the array. + * let choice = random(animals); + * + * // Style the text. + * textAlign(CENTER); + * textSize(20); + * + * // Display the emoji. + * text(choice, 50, 50); + * + * describe('An animal face is displayed at random. Either a lion, tiger, or bear.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * // Slow the frame rate. * frameRate(5); - * let x = random(width); - * let y = random(height); * + * describe('A black dot moves around randomly on a gray square.'); + * } + * + * function draw() { + * background(200); + * + * // Get random coordinates between 0 and 100. + * let x = random(100); + * let y = random(100); + * + * // Draw the point. * strokeWeight(5); * point(x, y); - * - * describe('A black dot moves around randomly on a gray square.'); * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * // Slow the frame rate. + * frameRate(5); + * + * describe('A black dot moves around randomly in the middle of a gray square.'); + * } + * * function draw() { * background(200); * - * frameRate(5); + * // Get random coordinates between 45 and 55. * let x = random(45, 55); * let y = random(45, 55); * + * // Draw the point. * strokeWeight(5); * point(x, y); + * } + * + *
* - * describe('A black dot moves around randomly in the middle of a gray square.'); + *
+ * + * let x = 50; + * let y = 50; + * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * describe('A black dot moves around randomly leaving a trail.'); + * } + * + * function draw() { + * // Update x and y randomly. + * x += random(-1, 1); + * y += random(-1, 1); + * + * // Draw the point. + * point(x, y); * } * *
@@ -97722,7 +111303,6 @@ * @method random * @param {Array} choices array to choose from. * @return {*} random element from the array. - * @example */ _main.default.prototype.random = function (min, max) { _main.default._validateParameters('random', arguments); @@ -97735,7 +111315,7 @@ if (typeof min === 'undefined') { return rand; } else if (typeof max === 'undefined') { - if (min instanceof Array) { + if (Array.isArray(min)) { return min[Math.floor(rand * min.length)]; } else { return rand * min; @@ -97750,10 +111330,11 @@ } }; /** - * Returns a random number fitting a Gaussian, or normal, distribution. Normal - * distributions look like bell curves when plotted. Values from a normal - * distribution cluster around a central value called the mean. The cluster's - * standard deviation describes its spread. + * Returns a random number fitting a Gaussian, or normal, distribution. + * + * Normal distributions look like bell curves when plotted. Values from a + * normal distribution cluster around a central value called the mean. The + * cluster's standard deviation describes its spread. * * By default, `randomGaussian()` produces different results each time a * sketch runs. The randomSeed() function can be @@ -97779,26 +111360,33 @@ * @example *
* + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * describe('Three horizontal black lines are filled in randomly. The top line spans entire canvas. The middle line is very short. The bottom line spans two-thirds of the canvas.'); + * } + * * function draw() { + * // Style the circles. * noStroke(); * fill(0, 10); * - * // Uniform distribution. - * let x = random(width); + * // Uniform distribution between 0 and 100. + * let x = random(100); * let y = 25; * circle(x, y, 5); * - * // Gaussian distribution with sd = 1. + * // Gaussian distribution with a mean of 50 and sd of 1. * x = randomGaussian(50); * y = 50; * circle(x, y, 5); * - * // Gaussian distribution with sd = 10. + * // Gaussian distribution with a mean of 50 and sd of 10. * x = randomGaussian(50, 10); * y = 75; * circle(x, y, 5); - * - * describe('Three horizontal black lines are filled in randomly. The top line spans entire canvas. The middle line is very short. The bottom line spans two-thirds of the canvas.'); * } * *
@@ -97830,10 +111418,10 @@ exports.default = _default; }, { - '../core/main': 298 + '../core/main': 306 } ], - 333: [ + 341: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -97935,9 +111523,11 @@ _main.default.prototype._angleMode = constants.RADIANS; /** - * The inverse of cos(), returns the arc cosine of a - * value. This function expects arguments in the range -1 to 1. By default, - * `acos()` returns values in the range 0 to π (about 3.14). If the + * Calculates the arc cosine of a number. + * + * `acos()` is the inverse of cos(). It expects + * arguments in the range -1 to 1. By default, `acos()` returns values in the + * range 0 to π (about 3.14). If the * angleMode() is `DEGREES`, then values are * returned in the range 0 to 180. * @@ -97948,27 +111538,45 @@ * @example *
* - * let a = PI; - * let c = cos(a); - * let ac = acos(c); - * text(`${round(a, 3)}`, 35, 25); - * text(`${round(c, 3)}`, 35, 50); - * text(`${round(ac, 3)}`, 35, 75); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Calculate cos() and acos() values. + * let a = PI; + * let c = cos(a); + * let ac = acos(c); + * + * // Display the values. + * text(`${round(a, 3)}`, 35, 25); + * text(`${round(c, 3)}`, 35, 50); + * text(`${round(ac, 3)}`, 35, 75); * - * describe('The numbers 3.142, -1, and 3.142 written on separate rows.'); + * describe('The numbers 3.142, -1, and 3.142 written on separate rows.'); + * } * *
* *
* - * let a = PI; - * let c = cos(a); - * let ac = acos(c); - * text(`${round(a, 3)}`, 35, 25); - * text(`${round(c, 3)}`, 35, 50); - * text(`${round(ac, 3)}`, 35, 75); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Calculate cos() and acos() values. + * let a = PI + QUARTER_PI; + * let c = cos(a); + * let ac = acos(c); * - * describe('The numbers 3.927, -0.707, and 2.356 written on separate rows.'); + * // Display the values. + * text(`${round(a, 3)}`, 35, 25); + * text(`${round(c, 3)}`, 35, 50); + * text(`${round(ac, 3)}`, 35, 75); + * + * describe('The numbers 3.927, -0.707, and 2.356 written on separate rows.'); + * } * *
*/ @@ -97976,11 +111584,12 @@ return this._fromRadians(Math.acos(ratio)); }; /** - * The inverse of sin(), returns the arc sine of a - * value. This function expects input values in the range of -1 to 1. By - * default, `asin()` returns values in the range -π ÷ 2 - * (about -1.57) to π ÷ 2 (about 1.57). If the - * angleMode() is `DEGREES` then values are + * Calculates the arc sine of a number. + * + * `asin()` is the inverse of sin(). It expects input + * values in the range of -1 to 1. By default, `asin()` returns values in the + * range -π ÷ 2 (about -1.57) to π ÷ 2 (about 1.57). If + * the angleMode() is `DEGREES` then values are * returned in the range -90 to 90. * * @method asin @@ -97990,27 +111599,45 @@ * @example *
* - * let a = PI / 3; - * let s = sin(a); - * let as = asin(s); - * text(`${round(a, 3)}`, 35, 25); - * text(`${round(s, 3)}`, 35, 50); - * text(`${round(as, 3)}`, 35, 75); + * function setup() { + * createCanvas(100, 100); + * + * background(200); * - * describe('The numbers 1.047, 0.866, and 1.047 written on separate rows.'); + * // Calculate sin() and asin() values. + * let a = PI / 3; + * let s = sin(a); + * let as = asin(s); + * + * // Display the values. + * text(`${round(a, 3)}`, 35, 25); + * text(`${round(s, 3)}`, 35, 50); + * text(`${round(as, 3)}`, 35, 75); + * + * describe('The numbers 1.047, 0.866, and 1.047 written on separate rows.'); + * } * *
* *
* - * let a = PI + PI / 3; - * let s = sin(a); - * let as = asin(s); - * text(`${round(a, 3)}`, 35, 25); - * text(`${round(s, 3)}`, 35, 50); - * text(`${round(as, 3)}`, 35, 75); + * function setup() { + * createCanvas(100, 100); * - * describe('The numbers 4.189, -0.866, and -1.047 written on separate rows.'); + * background(200); + * + * // Calculate sin() and asin() values. + * let a = PI + PI / 3; + * let s = sin(a); + * let as = asin(s); + * + * // Display the values. + * text(`${round(a, 3)}`, 35, 25); + * text(`${round(s, 3)}`, 35, 50); + * text(`${round(as, 3)}`, 35, 75); + * + * describe('The numbers 4.189, -0.866, and -1.047 written on separate rows.'); + * } * *
*/ @@ -98018,12 +111645,13 @@ return this._fromRadians(Math.asin(ratio)); }; /** - * The inverse of tan(), returns the arc tangent of a - * value. This function expects input values in the range of -Infinity to - * Infinity. By default, `atan()` returns values in the range -π ÷ 2 - * (about -1.57) to π ÷ 2 (about 1.57). If the - * angleMode() is `DEGREES` then values are - * returned in the range -90 to 90. + * Calculates the arc tangent of a number. + * + * `atan()` is the inverse of tan(). It expects input + * values in the range of -Infinity to Infinity. By default, `atan()` returns + * values in the range -π ÷ 2 (about -1.57) to π ÷ 2 + * (about 1.57). If the angleMode() is `DEGREES` + * then values are returned in the range -90 to 90. * * @method atan * @param {Number} value value whose arc tangent is to be returned. @@ -98032,27 +111660,45 @@ * @example *
* - * let a = PI / 3; - * let t = tan(a); - * let at = atan(t); - * text(`${round(a, 3)}`, 35, 25); - * text(`${round(t, 3)}`, 35, 50); - * text(`${round(at, 3)}`, 35, 75); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Calculate tan() and atan() values. + * let a = PI / 3; + * let t = tan(a); + * let at = atan(t); + * + * // Display the values. + * text(`${round(a, 3)}`, 35, 25); + * text(`${round(t, 3)}`, 35, 50); + * text(`${round(at, 3)}`, 35, 75); * - * describe('The numbers 1.047, 1.732, and 1.047 written on separate rows.'); + * describe('The numbers 1.047, 1.732, and 1.047 written on separate rows.'); + * } * *
* *
* - * let a = PI + PI / 3; - * let t = tan(a); - * let at = atan(t); - * text(`${round(a, 3)}`, 35, 25); - * text(`${round(t, 3)}`, 35, 50); - * text(`${round(at, 3)}`, 35, 75); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Calculate tan() and atan() values. + * let a = PI + PI / 3; + * let t = tan(a); + * let at = atan(t); + * + * // Display the values. + * text(`${round(a, 3)}`, 35, 25); + * text(`${round(t, 3)}`, 35, 50); + * text(`${round(at, 3)}`, 35, 75); * - * describe('The numbers 4.189, 1.732, and 1.047 written on separate rows.'); + * describe('The numbers 4.189, 1.732, and 1.047 written on separate rows.'); + * } * *
*/ @@ -98060,15 +111706,17 @@ return this._fromRadians(Math.atan(ratio)); }; /** - * Calculates the angle formed by a specified point, the origin, and the - * positive x-axis. By default, `atan2()` returns values in the range + * Calculates the angle formed by a point, the origin, and the positive + * x-axis. + * + * `atan2()` is most often used for orienting geometry to the mouse's + * position, as in `atan2(mouseY, mouseX)`. The first parameter is the point's + * y-coordinate and the second parameter is its x-coordinate. + * + * By default, `atan2()` returns values in the range * -π (about -3.14) to π (3.14). If the * angleMode() is `DEGREES`, then values are - * returned in the range -180 to 180. The `atan2()` function is most often - * used for orienting geometry to the mouse's position. - * - * Note: The y-coordinate of the point is the first parameter and the - * x-coordinate is the second parameter. + * returned in the range -180 to 180. * * @method atan2 * @param {Number} y y-coordinate of the point. @@ -98078,17 +111726,55 @@ * @example *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('A rectangle at the top-left of the canvas rotates with mouse movements.'); + * } + * * function draw() { * background(200); - * translate(width / 2, height / 2); - * let x = mouseX - width / 2; - * let y = mouseY - height / 2; - * let a = atan2(y, x); + * + * // Calculate the angle between the mouse + * // and the origin. + * let a = atan2(mouseY, mouseX); + * + * // Rotate. * rotate(a); - * rect(-30, -5, 60, 10); + * + * // Draw the shape. + * rect(0, 0, 60, 10); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); * * describe('A rectangle at the center of the canvas rotates with mouse movements.'); * } + * + * function draw() { + * background(200); + * + * // Translate the origin to the center. + * translate(50, 50); + * + * // Get the mouse's coordinates relative to the origin. + * let x = mouseX - 50; + * let y = mouseY - 50; + * + * // Calculate the angle between the mouse and the origin. + * let a = atan2(y, x); + * + * // Rotate. + * rotate(a); + * + * // Draw the shape. + * rect(-30, -5, 60, 10); + * } * *
*/ @@ -98096,10 +111782,11 @@ return this._fromRadians(Math.atan2(y, x)); }; /** - * Calculates the cosine of an angle. `cos()` is useful for many geometric - * tasks in creative coding. The values returned oscillate between -1 and 1 - * as the input angle increases. `cos()` takes into account the current - * angleMode. + * Calculates the cosine of an angle. + * + * `cos()` is useful for many geometric tasks in creative coding. The values + * returned oscillate between -1 and 1 as the input angle increases. `cos()` + * takes into account the current angleMode(). * * @method cos * @param {Number} angle the angle. @@ -98108,42 +111795,65 @@ * @example *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('A white ball on a string oscillates left and right.'); + * } + * * function draw() { * background(200); * - * let t = frameCount; - * let x = 30 * cos(t * 0.05) + 50; + * // Calculate the coordinates. + * let x = 30 * cos(frameCount * 0.05) + 50; * let y = 50; + * + * // Draw the oscillator. * line(50, y, x, y); * circle(x, y, 20); - * - * describe('A white ball on a string oscillates left and right.'); * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * describe('A series of black dots form a wave pattern.'); + * } + * * function draw() { + * // Calculate the coordinates. * let x = frameCount; * let y = 30 * cos(x * 0.1) + 50; - * point(x, y); * - * describe('A series of black dots form a wave pattern.'); + * // Draw the point. + * point(x, y); * } * *
* *
* - * function draw() { - * let t = frameCount; - * let x = 30 * cos(t * 0.1) + 50; - * let y = 10 * sin(t * 0.2) + 50; - * point(x, y); + * function setup() { + * createCanvas(100, 100); + * + * background(200); * * describe('A series of black dots form an infinity symbol.'); * } + * + * function draw() { + * // Calculate the coordinates. + * let x = 30 * cos(frameCount * 0.1) + 50; + * let y = 10 * sin(frameCount * 0.2) + 50; + * + * // Draw the point. + * point(x, y); + * } * *
*/ @@ -98151,10 +111861,11 @@ return Math.cos(this._toRadians(angle)); }; /** - * Calculates the sine of an angle. `sin()` is useful for many geometric tasks - * in creative coding. The values returned oscillate between -1 and 1 as the - * input angle increases. `sin()` takes into account the current - * angleMode. + * Calculates the sine of an angle. + * + * `sin()` is useful for many geometric tasks in creative coding. The values + * returned oscillate between -1 and 1 as the input angle increases. `sin()` + * takes into account the current angleMode(). * * @method sin * @param {Number} angle the angle. @@ -98163,42 +111874,65 @@ * @example *
* + * function setup() { + * createCanvas(100, 100); + * + * describe('A white ball on a string oscillates up and down.'); + * } + * * function draw() { * background(200); * - * let t = frameCount; + * // Calculate the coordinates. * let x = 50; - * let y = 30 * sin(t * 0.05) + 50; - * line(x, 50, x, y); - * circle(x, y, 20); + * let y = 30 * sin(frameCount * 0.05) + 50; * - * describe('A white ball on a string oscillates up and down.'); + * // Draw the oscillator. + * line(50, y, x, y); + * circle(x, y, 20); * } * *
* *
* + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * describe('A series of black dots form a wave pattern.'); + * } + * * function draw() { + * // Calculate the coordinates. * let x = frameCount; * let y = 30 * sin(x * 0.1) + 50; - * point(x, y); * - * describe('A series of black dots form a wave pattern.'); + * // Draw the point. + * point(x, y); * } * *
* *
* - * function draw() { - * let t = frameCount; - * let x = 30 * cos(t * 0.1) + 50; - * let y = 10 * sin(t * 0.2) + 50; - * point(x, y); + * function setup() { + * createCanvas(100, 100); + * + * background(200); * * describe('A series of black dots form an infinity symbol.'); * } + * + * function draw() { + * // Calculate the coordinates. + * let x = 30 * cos(frameCount * 0.1) + 50; + * let y = 10 * sin(frameCount * 0.2) + 50; + * + * // Draw the point. + * point(x, y); + * } * *
*/ @@ -98206,10 +111940,12 @@ return Math.sin(this._toRadians(angle)); }; /** - * Calculates the tangent of an angle. `tan()` is useful for many geometric - * tasks in creative coding. The values returned range from -Infinity - * to Infinity and repeat periodically as the input angle increases. `tan()` - * takes into account the current angleMode. + * Calculates the tangent of an angle. + * + * `tan()` is useful for many geometric tasks in creative coding. The values + * returned range from -Infinity to Infinity and repeat periodically as the + * input angle increases. `tan()` takes into account the current + * angleMode(). * * @method tan * @param {Number} angle the angle. @@ -98218,12 +111954,21 @@ * @example *
* + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * describe('A series of identical curves drawn with black dots. Each curve starts from the top of the canvas, continues down at a slight angle, flattens out at the middle of the canvas, then continues to the bottom.'); + * } + * * function draw() { + * // Calculate the coordinates. * let x = frameCount; * let y = 5 * tan(x * 0.1) + 50; - * point(x, y); * - * describe('A series of identical curves drawn with black dots. Each curve starts from the top of the canvas, continues down at a slight angle, flattens out at the middle of the canvas, then continues to the bottom.'); + * // Draw the point. + * point(x, y); * } * *
@@ -98232,12 +111977,14 @@ return Math.tan(this._toRadians(angle)); }; /** - * Converts an angle measurement in radians to its corresponding value in - * degrees. Degrees and radians are two ways of measuring the same thing. - * There are 360 degrees in a circle and 2 × π (about 6.28) - * radians in a circle. For example, 90° = π ÷ 2 (about 1.57) - * radians. This function doesn't take into account the current - * angleMode(). + * Converts an angle measured in radians to its value in degrees. + * + * Degrees and radians are both units for measuring angles. There are 360˚ in + * one full rotation. A full rotation is 2 × π (about 6.28) radians. + * + * The same angle can be expressed in with either unit. For example, 90° is a + * quarter of a full rotation. The same angle is 2 × π ÷ 4 + * (about 1.57) radians. * * @method degrees * @param {Number} radians radians value to convert to degrees. @@ -98246,11 +111993,20 @@ * @example *
* - * let rad = QUARTER_PI; - * let deg = degrees(rad); - * text(`${round(rad, 2)} rad = ${deg}˚`, 10, 50); + * function setup() { + * createCanvas(100, 100); * - * describe('The text "0.79 rad = 45˚".'); + * background(200); + * + * // Calculate the angle conversion. + * let rad = QUARTER_PI; + * let deg = degrees(rad); + * + * // Display the conversion. + * text(`${round(rad, 2)} rad = ${deg}˚`, 10, 50); + * + * describe('The text "0.79 rad = 45˚".'); + * } * *
*/ @@ -98258,12 +112014,14 @@ return angle * constants.RAD_TO_DEG; }; /** - * Converts an angle measurement in degrees to its corresponding value in - * radians. Degrees and radians are two ways of measuring the same thing. - * There are 360 degrees in a circle and 2 × π (about 6.28) - * radians in a circle. For example, 90° = π ÷ 2 (about 1.57) - * radians. This function doesn't take into account the current - * angleMode(). + * Converts an angle measured in degrees to its value in radians. + * + * Degrees and radians are both units for measuring angles. There are 360˚ in + * one full rotation. A full rotation is 2 × π (about 6.28) radians. + * + * The same angle can be expressed in with either unit. For example, 90° is a + * quarter of a full rotation. The same angle is 2 × π ÷ 4 + * (about 1.57) radians. * * @method radians * @param {Number} degrees degree value to convert to radians. @@ -98272,11 +112030,20 @@ * @example *
* - * let deg = 45; - * let rad = radians(deg); - * text(`${deg}˚ = ${round(rad, 3)} rad`, 10, 50); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Caclulate the angle conversion. + * let deg = 45; + * let rad = radians(deg); * - * describe('The text "45˚ = 0.785 rad".'); + * // Display the angle conversion. + * text(`${deg}˚ = ${round(rad, 3)} rad`, 10, 50); + * + * describe('The text "45˚ = 0.785 rad".'); + * } * *
*/ @@ -98284,33 +112051,190 @@ return angle * constants.DEG_TO_RAD; }; /** - * Changes the way trigonometric functions interpret angle values. By default, - * the mode is `RADIANS`. + * Changes the unit system used to measure angles. + * + * Degrees and radians are both units for measuring angles. There are 360˚ in + * one full rotation. A full rotation is 2 × π (about 6.28) radians. + * + * Functions such as rotate() and + * sin() expect angles measured radians by default. + * Calling `angleMode(DEGREES)` switches to degrees. Calling + * `angleMode(RADIANS)` switches back to radians. + * + * Calling `angleMode()` with no arguments returns current angle mode, which + * is either `RADIANS` or `DEGREES`. * - * Calling `angleMode()` with no arguments returns current angle mode. * @method angleMode * @param {Constant} mode either RADIANS or DEGREES. + * * @example *
* - * let r = 40; - * push(); - * rotate(PI / 6); - * line(0, 0, r, 0); - * text('0.524 rad', r, 0); - * pop(); + * function setup() { + * createCanvas(100, 100); * - * angleMode(DEGREES); - * push(); - * rotate(60); - * line(0, 0, r, 0); - * text('60˚', r, 0); - * pop(); + * background(200); + * + * // Rotate 1/8 turn. + * rotate(QUARTER_PI); + * + * // Draw a line. + * line(0, 0, 80, 0); + * + * describe('A diagonal line radiating from the top-left corner of a square.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Use degrees. + * angleMode(DEGREES); + * + * // Rotate 1/8 turn. + * rotate(45); * - * describe('Two diagonal lines radiating from the top left corner of a square. The lines are oriented 30 degrees from the edges of the square and 30 degrees apart from each other.'); + * // Draw a line. + * line(0, 0, 80, 0); + * + * describe('A diagonal line radiating from the top-left corner of a square.'); + * } * *
* + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(50); + * + * // Calculate the angle to rotate. + * let angle = TWO_PI / 7; + * + * // Move the origin to the center. + * translate(50, 50); + * + * // Style the flower. + * noStroke(); + * fill(255, 50); + * + * // Draw the flower. + * for (let i = 0; i < 7; i += 1) { + * ellipse(0, 0, 80, 20); + * rotate(angle); + * } + * + * describe('A translucent white flower on a dark background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(50); + * + * // Use degrees. + * angleMode(DEGREES); + * + * // Calculate the angle to rotate. + * let angle = 360 / 7; + * + * // Move the origin to the center. + * translate(50, 50); + * + * // Style the flower. + * noStroke(); + * fill(255, 50); + * + * // Draw the flower. + * for (let i = 0; i < 7; i += 1) { + * ellipse(0, 0, 80, 20); + * rotate(angle); + * } + * + * describe('A translucent white flower on a dark background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * describe('A white ball on a string oscillates left and right.'); + * } + * + * function draw() { + * background(200); + * + * // Calculate the coordinates. + * let x = 30 * cos(frameCount * 0.05) + 50; + * let y = 50; + * + * // Draw the oscillator. + * line(50, y, x, y); + * circle(x, y, 20); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * // Use degrees. + * angleMode(DEGREES); + * + * describe('A white ball on a string oscillates left and right.'); + * } + * + * function draw() { + * background(200); + * + * // Calculate the coordinates. + * let x = 30 * cos(frameCount * 2.86) + 50; + * let y = 50; + * + * // Draw the oscillator. + * line(50, y, x, y); + * circle(x, y, 20); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Draw the upper line. + * rotate(PI / 6); + * line(0, 0, 80, 0); + * + * // Use degrees. + * angleMode(DEGREES); + * + * // Draw the lower line. + * rotate(30); + * line(0, 0, 80, 0); + * + * describe('Two diagonal lines radiating from the top-left corner of a square. The lines are oriented 30 degrees from the edges of the square and 30 degrees apart from each other.'); + * } + * + *
*/ /** * @method angleMode @@ -98321,6 +112245,22 @@ if (typeof mode === 'undefined') { return this._angleMode; } else if (mode === constants.DEGREES || mode === constants.RADIANS) { + var prevMode = this._angleMode; + // No change + if (mode === prevMode) return; + // Otherwise adjust pRotation according to new mode + // This is necessary for acceleration events to work properly + if (mode === constants.RADIANS) { + // Change pRotation to radians + this._setProperty('pRotationX', this.pRotationX * constants.DEG_TO_RAD); + this._setProperty('pRotationY', this.pRotationY * constants.DEG_TO_RAD); + this._setProperty('pRotationZ', this.pRotationZ * constants.DEG_TO_RAD); + } else { + // Change pRotation to degrees + this._setProperty('pRotationX', this.pRotationX * constants.RAD_TO_DEG); + this._setProperty('pRotationY', this.pRotationY * constants.RAD_TO_DEG); + this._setProperty('pRotationZ', this.pRotationZ * constants.RAD_TO_DEG); + } this._angleMode = mode; } }; @@ -98366,24 +112306,38 @@ } return angle; }; + /** + * converts angles from DEGREES into the current angleMode + * + * @method _fromDegrees + * @private + * @param {Number} angle + * @returns {Number} + */ + _main.default.prototype._fromDegrees = function (angle) { + if (this._angleMode === constants.RADIANS) { + return angle * constants.DEG_TO_RAD; + } + return angle; + }; var _default = _main.default; exports.default = _default; }, { - '../core/constants': 286, - '../core/main': 298, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/constants': 294, + '../core/main': 306, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 334: [ + 342: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.regexp.exec'); @@ -98435,42 +112389,64 @@ * @example *
* - * strokeWeight(0.5); - * line(50, 0, 50, 100); + * function setup() { + * createCanvas(100, 100); * - * textSize(16); - * textAlign(RIGHT); - * text('ABCD', 50, 30); - * textAlign(CENTER); - * text('EFGH', 50, 50); - * textAlign(LEFT); - * text('IJKL', 50, 70); + * background(200); * - * describe('The letters ABCD displayed at top-left, EFGH at center, and IJKL at bottom-right. A vertical line divides the canvas in half.'); + * // Draw a vertical line. + * strokeWeight(0.5); + * line(50, 0, 50, 100); + * + * // Top line. + * textSize(16); + * textAlign(RIGHT); + * text('ABCD', 50, 30); + * + * // Middle line. + * textAlign(CENTER); + * text('EFGH', 50, 50); + * + * // Bottom line. + * textAlign(LEFT); + * text('IJKL', 50, 70); + * + * describe('The letters ABCD displayed at top-left, EFGH at center, and IJKL at bottom-right. A vertical line divides the canvas in half.'); + * } * *
* *
* - * strokeWeight(0.5); + * function setup() { + * createCanvas(100, 100); + * + * background(200); * - * line(0, 12, width, 12); - * textAlign(CENTER, TOP); - * text('TOP', 50, 12); + * strokeWeight(0.5); + * + * // First line. + * line(0, 12, width, 12); + * textAlign(CENTER, TOP); + * text('TOP', 50, 12); * - * line(0, 37, width, 37); - * textAlign(CENTER, CENTER); - * text('CENTER', 50, 37); + * // Second line. + * line(0, 37, width, 37); + * textAlign(CENTER, CENTER); + * text('CENTER', 50, 37); * - * line(0, 62, width, 62); - * textAlign(CENTER, BASELINE); - * text('BASELINE', 50, 62); + * // Third line. + * line(0, 62, width, 62); + * textAlign(CENTER, BASELINE); + * text('BASELINE', 50, 62); * - * line(0, 97, width, 97); - * textAlign(CENTER, BOTTOM); - * text('BOTTOM', 50, 97); + * // Fourth line. + * line(0, 97, width, 97); + * textAlign(CENTER, BOTTOM); + * text('BOTTOM', 50, 97); * - * describe('The words "TOP", "CENTER", "BASELINE", and "BOTTOM" each drawn relative to a horizontal line. Their positions demonstrate different vertical alignments.'); + * describe('The words "TOP", "CENTER", "BASELINE", and "BOTTOM" each drawn relative to a horizontal line. Their positions demonstrate different vertical alignments.'); + * } * *
*/ @@ -98486,7 +112462,9 @@ }; /** * Sets the spacing between lines of text when - * text() is called. Spacing is measured in pixels. + * text() is called. + * + * Note: Spacing is measured in pixels. * * Calling `textLeading()` without an argument returns the current spacing. * @@ -98497,15 +112475,23 @@ * @example *
* - * // "\n" starts a new line of text. - * let lines = 'one\ntwo'; + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // "\n" starts a new line of text. + * let lines = 'one\ntwo'; * - * text(lines, 10, 25); + * // Left. + * text(lines, 10, 25); * - * textLeading(30); - * text(lines, 70, 25); + * // Right. + * textLeading(30); + * text(lines, 70, 25); * - * describe('The words "one" and "two" written on separate lines twice. The words on the left have less vertical spacing than the words on the right.'); + * describe('The words "one" and "two" written on separate lines twice. The words on the left have less vertical spacing than the words on the right.'); + * } * *
*/ @@ -98520,25 +112506,38 @@ }; /** * Sets the font size when - * text() is called. Font size is measured in pixels. + * text() is called. + * + * Note: Font size is measured in pixels. * * Calling `textSize()` without an arugment returns the current size. * * @method textSize - * @param {Number} size size of the letters in units of pixels + * @param {Number} size size of the letters in units of pixels. * @chainable * * @example *
* - * textSize(12); - * text('Font Size 12', 10, 30); - * textSize(14); - * text('Font Size 14', 10, 60); - * textSize(16); - * text('Font Size 16', 10, 90); + * function setup() { + * createCanvas(100, 100); * - * describe('The text "Font Size 12" drawn small, "Font Size 14" drawn medium, and "Font Size 16" drawn large.'); + * background(200); + * + * // Top. + * textSize(12); + * text('Font Size 12', 10, 30); + * + * // Middle. + * textSize(14); + * text('Font Size 14', 10, 60); + * + * // Bottom. + * textSize(16); + * text('Font Size 16', 10, 90); + * + * describe('The text "Font Size 12" drawn small, "Font Size 14" drawn medium, and "Font Size 16" drawn large.'); + * } * *
*/ @@ -98553,32 +112552,48 @@ }; /** * Sets the style for system fonts when - * text() is called. `textStyle()` accepts the - * following values: `NORMAL`, `ITALIC`, `BOLD` or `BOLDITALIC`. + * text() is called. + * + * The parameter, `style`, can be either `NORMAL`, `ITALIC`, `BOLD`, or + * `BOLDITALIC`. * * `textStyle()` may be overridden by CSS styling. This function doesn't * affect fonts loaded with loadFont(). * * @method textStyle * @param {Constant} style styling for text, either NORMAL, - * ITALIC, BOLD or BOLDITALIC + * ITALIC, BOLD or BOLDITALIC. * @chainable * @example *
* - * textSize(12); - * textAlign(CENTER); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the text. + * textSize(12); + * textAlign(CENTER); + * + * // First row. + * textStyle(NORMAL); + * text('Normal', 50, 15); * - * textStyle(NORMAL); - * text('Normal', 50, 15); - * textStyle(ITALIC); - * text('Italic', 50, 40); - * textStyle(BOLD); - * text('Bold', 50, 65); - * textStyle(BOLDITALIC); - * text('Bold Italic', 50, 90); + * // Second row. + * textStyle(ITALIC); + * text('Italic', 50, 40); * - * describe('The words "Normal" displayed normally, "Italic" in italic, "Bold" in bold, and "Bold Italic" in bold italics.'); + * // Third row. + * textStyle(BOLD); + * text('Bold', 50, 65); + * + * // Fourth row. + * textStyle(BOLDITALIC); + * text('Bold Italic', 50, 90); + * + * describe('The words "Normal" displayed normally, "Italic" in italic, "Bold" in bold, and "Bold Italic" in bold italics.'); + * } * *
*/ @@ -98592,7 +112607,7 @@ return (_this$_renderer4 = this._renderer).textStyle.apply(_this$_renderer4, arguments); }; /** - * Returns the maximum width of a string of text drawn when + * Calculates the maximum width of a string of text drawn when * text() is called. * * @method textWidth @@ -98602,13 +112617,22 @@ *
* * function setup() { + * createCanvas(100, 100); + * * background(200); * + * // Style the text. * textSize(28); * strokeWeight(0.5); + * + * // Calculate the text width. * let s = 'yoyo'; * let w = textWidth(s); + * + * // Display the text. * text(s, 22, 55); + * + * // Underline the text. * line(22, 55, 22 + w, 55); * * describe('The word "yoyo" underlined.'); @@ -98619,14 +112643,23 @@ *
* * function setup() { + * createCanvas(100, 100); + * * background(200); * + * // Style the text. * textSize(28); * strokeWeight(0.5); + * + * // Calculate the text width. * // "\n" starts a new line. * let s = 'yo\nyo'; * let w = textWidth(s); + * + * // Display the text. * text(s, 22, 55); + * + * // Underline the text. * line(22, 55, 22 + w, 55); * * describe('The word "yo" written twice, one copy beneath the other. The words are divided by a horizontal line.'); @@ -98656,9 +112689,10 @@ return largestWidth; }; /** - * Returns the ascent of the current font at its current size. The ascent - * represents the distance, in pixels, of the tallest character above - * the baseline. + * Calculates the ascent of the current font at its current size. + * + * The ascent represents the distance, in pixels, of the tallest character + * above the baseline. * * @method textAscent * @return {Number} ascent measured in units of pixels. @@ -98672,7 +112706,11 @@ * } * * function setup() { + * createCanvas(100, 100); + * * background(200); + * + * // Style the text. * textFont(font); * * // Different for each font. @@ -98684,6 +112722,7 @@ * // Draw small text. * textSize(24); * text('dp', 0, baseY); + * * // Draw baseline and ascent. * let a = textAscent() * fontScale; * line(0, baseY, 23, baseY); @@ -98692,6 +112731,7 @@ * // Draw large text. * textSize(48); * text('dp', 45, baseY); + * * // Draw baseline and ascent. * a = textAscent() * fontScale; * line(45, baseY, 91, baseY); @@ -98710,9 +112750,10 @@ return this._renderer.textAscent(); }; /** - * Returns the descent of the current font at its current size. The descent - * represents the distance, in pixels, of the character with the longest - * descender below the baseline. + * Calculates the descent of the current font at its current size. + * + * The descent represents the distance, in pixels, of the character with the + * longest descender below the baseline. * * @method textDescent * @return {Number} descent measured in units of pixels. @@ -98726,7 +112767,11 @@ * } * * function setup() { + * createCanvas(100, 100); + * * background(200); + * + * // Style the font. * textFont(font); * * // Different for each font. @@ -98738,6 +112783,7 @@ * // Draw small text. * textSize(24); * text('dp', 0, baseY); + * * // Draw baseline and descent. * let d = textDescent() * fontScale; * line(0, baseY, 23, baseY); @@ -98746,6 +112792,7 @@ * // Draw large text. * textSize(48); * text('dp', 45, baseY); + * * // Draw baseline and descent. * d = textDescent() * fontScale; * line(45, baseY, 91, baseY); @@ -98771,8 +112818,9 @@ }; /** * Sets the style for wrapping text when - * text() is called. `textWrap()` accepts the - * following values: + * text() is called. + * + * The parameter, `style`, can be one of the following values: * * `WORD` starts new lines of text at spaces. If a string of text doesn't * have spaces, it may overflow the text box and the canvas. This is the @@ -98792,45 +112840,78 @@ * @example *
* - * textSize(20); - * textWrap(WORD); - * text('Have a wonderful day', 0, 10, 100); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the text. + * textSize(20); + * textWrap(WORD); + * + * // Display the text. + * text('Have a wonderful day', 0, 10, 100); + * + * describe('The text "Have a wonderful day" written across three lines.'); + * } * *
* *
* - * textSize(20); - * textWrap(CHAR); - * text('Have a wonderful day', 0, 10, 100); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the text. + * textSize(20); + * textWrap(CHAR); + * + * // Display the text. + * text('Have a wonderful day', 0, 10, 100); + * + * describe('The text "Have a wonderful day" written across two lines.'); + * } * *
* *
* - * textSize(20); - * textWrap(CHAR); - * text('祝你有美好的一天', 0, 10, 100); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Style the text. + * textSize(20); + * textWrap(CHAR); + * + * // Display the text. + * text('祝你有美好的一天', 0, 10, 100); + * + * describe('The text "祝你有美好的一天" written across two lines.'); + * } * *
*/ _main.default.prototype.textWrap = function (wrapStyle) { - if (wrapStyle !== 'WORD' && wrapStyle !== 'CHAR') { - throw 'Error: textWrap accepts only WORD or CHAR'; - } + _main.default._validateParameters('textWrap', [ + wrapStyle + ]); return this._renderer.textWrap(wrapStyle); }; var _default = _main.default; exports.default = _default; }, { - '../core/main': 298, - 'core-js/modules/es.regexp.exec': 205, - 'core-js/modules/es.string.replace': 214, - 'core-js/modules/es.string.split': 216 + '../core/main': 306, + 'core-js/modules/es.regexp.exec': 213, + 'core-js/modules/es.string.replace': 222, + 'core-js/modules/es.string.split': 224 } ], - 335: [ + 343: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -99356,30 +113437,30 @@ exports.default = _default; }, { - '../core/constants': 286, - '../core/friendly_errors/fes_core': 289, - '../core/friendly_errors/file_errors': 290, - '../core/friendly_errors/validate_params': 293, - '../core/main': 298, - 'core-js/modules/es.array.concat': 169, - 'core-js/modules/es.array.includes': 177, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.last-index-of': 181, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.regexp.exec': 205, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.string.split': 216, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256, - 'opentype.js': 271 + '../core/constants': 294, + '../core/friendly_errors/fes_core': 297, + '../core/friendly_errors/file_errors': 298, + '../core/friendly_errors/validate_params': 301, + '../core/main': 306, + 'core-js/modules/es.array.concat': 171, + 'core-js/modules/es.array.includes': 181, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.last-index-of': 185, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.regexp.exec': 213, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.string.split': 224, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264, + 'opentype.js': 279 } ], - 336: [ + 344: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -99523,6 +113604,7 @@ */ /** * A class to describe fonts. + * * @class p5.Font * @constructor * @param {p5} [pInst] pointer to p5 instance. @@ -99537,12 +113619,17 @@ * } * * function setup() { + * createCanvas(100, 100); + * + * // Style the text. * fill('deeppink'); * textFont(font); * textSize(36); + * + * // Display the text. * text('p5*js', 10, 50); * - * describe('The text "p5*js" written in pink on a white background.'); + * describe('The text "p5*js" written in pink on a gray background.'); * } *
*
@@ -99555,16 +113642,23 @@ this.cache = { }; /** - * Underlying + * The font's underlying * opentype.js * font object. + * * @property font * @name font */ this.font = undefined; } /** - * Returns the bounding box for a string of text written using this - * p5.Font. + * Returns the bounding box for a string of text written using the font. + * + * The bounding box is the smallest rectangle that can contain a string of + * text. `font.textBounds()` returns an object with the bounding box's + * location and size. For example, calling `font.textBounds('p5*js', 5, 20)` + * returns an object in the format + * `{ x: 5.7, y: 12.1 , w: 9.9, h: 28.6 }`. The `x` and `y` properties are + * always the coordinates of the bounding box's top-left corner. * * The first parameter, `str`, is a string of text. The second and third * parameters, `x` and `y`, are the text's position. By default, they set the @@ -99594,12 +113688,18 @@ * } * * function setup() { + * createCanvas(100, 100); + * * background(200); * + * // Display the bounding box. * let bbox = font.textBounds('p5*js', 35, 53); * rect(bbox.x, bbox.y, bbox.w, bbox.h); * + * // Style the text. * textFont(font); + * + * // Display the text. * text('p5*js', 35, 53); * * describe('The text "p5*js" written in black inside a white rectangle.'); @@ -99616,15 +113716,20 @@ * } * * function setup() { + * createCanvas(100, 100); + * * background(200); * + * // Style the text. * textFont(font); * textSize(15); * textAlign(CENTER, CENTER); * + * // Display the bounding box. * let bbox = font.textBounds('p5*js', 50, 50); * rect(bbox.x, bbox.y, bbox.w, bbox.h); * + * // Display the text. * text('p5*js', 50, 50); * * describe('The text "p5*js" written in black inside a white rectangle.'); @@ -99641,13 +113746,19 @@ * } * * function setup() { + * createCanvas(100, 100); + * * background(200); * + * // Display the bounding box. * let bbox = font.textBounds('p5*js', 31, 53, 15); * rect(bbox.x, bbox.y, bbox.w, bbox.h); * + * // Style the text. * textFont(font); * textSize(15); + * + * // Display the text. * text('p5*js', 31, 53); * * describe('The text "p5*js" written in black inside a white rectangle.'); @@ -99699,7 +113810,7 @@ var lineCount = 0; this.font.forEachGlyph(str, x, y, fontSize, opts, function (glyph, gX, gY, gFontSize) { var gm = glyph.getMetrics(); - if (glyph.index === 0 || glyph.index === 10) { + if (glyph.index === 0) { lineCount += 1; xCoords[lineCount] = [ ]; @@ -99743,8 +113854,12 @@ } return result; } /** - * Returns an array of points outlining a string of text written using this - * p5.Font. + * Returns an array of points outlining a string of text written using the + * font. + * + * Each point object in the array has three properties that describe the + * point's location and orientation, called its path angle. For example, + * `{ x: 10, y: 20, alpha: 450 }`. * * The first parameter, `str`, is a string of text. The second and third * parameters, `x` and `y`, are the text's position. By default, they set the @@ -99775,6 +113890,7 @@ * @param {Object} [options] object with sampleFactor and simplifyThreshold * properties. * @return {Array} array of point objects, each with x, y, and alpha (path angle) properties. + * * @example *
* @@ -99785,11 +113901,17 @@ * } * * function setup() { + * createCanvas(100, 100); + * * background(200); + * + * // Get the point array. * let points = font.textToPoints('p5*js', 6, 60, 35, { sampleFactor: 0.5 }); - * points.forEach(p => { + * + * // Draw a dot at each point. + * for (let p of points) { * point(p.x, p.y); - * }); + * } * * describe('A set of black dots outlining the text "p5*js" on a gray background.'); * } @@ -99978,7 +114100,7 @@ //pos = handleAlignment(p, ctx, line, x, y); pdata = this._getPath(line, x, y, options).commands; } - ctx.beginPath(); + if (!pg._clipping) ctx.beginPath(); var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; @@ -100310,8 +114432,8 @@ res.push(r = [ ]); pa = pathArray[i]; - if (pa[0] !== String.prototype.toUpperCase.call(pa[0])) { - r[0] = String.prototype.toUpperCase.call(pa[0]); + if (pa[0] !== pa[0].toUpperCase()) { + r[0] = pa[0].toUpperCase(); switch (r[0]) { case 'A': r[1] = pa[1]; @@ -100872,30 +114994,30 @@ exports.default = _default; }, { - '../core/constants': 286, - '../core/main': 298, - 'core-js/modules/es.array.concat': 169, - 'core-js/modules/es.array.fill': 172, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.join': 180, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.array.splice': 185, - 'core-js/modules/es.function.name': 186, - 'core-js/modules/es.number.to-fixed': 193, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.regexp.exec': 205, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.string.replace': 214, - 'core-js/modules/es.string.split': 216, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/constants': 294, + '../core/main': 306, + 'core-js/modules/es.array.concat': 171, + 'core-js/modules/es.array.fill': 174, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.join': 184, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.array.splice': 189, + 'core-js/modules/es.function.name': 192, + 'core-js/modules/es.number.to-fixed': 200, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.regexp.exec': 213, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.string.replace': 222, + 'core-js/modules/es.string.split': 224, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 337: [ + 345: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.array.concat'); @@ -101100,28 +115222,101 @@ return list; }; /** - * Randomizes the order of the elements of an array. Implements - * - * Fisher-Yates Shuffle Algorithm. + * Shuffles the elements of an array. + * + * The first parameter, `array`, is the array to be shuffled. For example, + * calling `shuffle(myArray)` will shuffle the elements of `myArray`. By + * default, the original array won’t be modified. Instead, a copy will be + * created, shuffled, and returned. + * + * The second parameter, `modify`, is optional. If `true` is passed, as in + * `shuffle(myArray, true)`, then the array will be shuffled in place without + * making a copy. * * @method shuffle - * @param {Array} array Array to shuffle - * @param {Boolean} [bool] modify passed array - * @return {Array} shuffled Array + * @param {Array} array array to shuffle. + * @param {Boolean} [bool] if `true`, shuffle the original array in place. Defaults to `false`. + * @return {Array} shuffled array. + * * @example - *
+ *
+ * * function setup() { - * let regularArr = ['ABC', 'def', createVector(), TAU, Math.E]; - * print(regularArr); - * shuffle(regularArr, true); // force modifications to passed array - * print(regularArr); + * createCanvas(100, 100); + * + * background(200); + * + * // Create an array of colors. + * let colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet']; + * + * // Create a shuffled copy of the array. + * let shuffledColors = shuffle(colors); + * + * // Draw a row of circles using the original array. + * for (let i = 0; i < colors.length; i += 1) { + * // Calculate the x-coordinate. + * let x = (i + 1) * 12.5; + * + * // Style the circle. + * let c = colors[i]; + * fill(c); + * + * // Draw the circle. + * circle(x, 33, 10); + * } + * + * // Draw a row of circles using the original array. + * for (let i = 0; i < shuffledColors.length; i += 1) { + * // Calculate the x-coordinate. + * let x = (i + 1) * 12.5; + * + * // Style the circle. + * let c = shuffledColors[i]; + * fill(c); + * + * // Draw the circle. + * circle(x, 67, 10); + * } * - * // By default shuffle() returns a shuffled cloned array: - * let newArr = shuffle(regularArr); - * print(regularArr); - * print(newArr); + * describe( + * 'Two rows of circles on a gray background. The top row follows the color sequence ROYGBIV. The bottom row has all the same colors but they are shuffled.' + * ); * } - *
+ *
+ *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create an array of colors. + * let colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet']; + * + * // Shuffle the array. + * shuffle(colors, true); + * + * // Draw a row of circles using the original array. + * for (let i = 0; i < colors.length; i += 1) { + * // Calculate the x-coordinate. + * let x = (i + 1) * 12.5; + * + * // Style the circle. + * let c = colors[i]; + * fill(c); + * + * // Draw the circle. + * circle(x, 50, 10); + * } + * + * describe( + * 'A row of colorful circles on a gray background. Their sequence changes each time the sketch runs.' + * ); + * } + * + *
*/ _main.default.prototype.shuffle = function (arr, bool) { var isView = ArrayBuffer && ArrayBuffer.isView && ArrayBuffer.isView(arr); @@ -101260,15 +115455,15 @@ exports.default = _default; }, { - '../core/main': 298, - 'core-js/modules/es.array-buffer.constructor': 168, - 'core-js/modules/es.array.concat': 169, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.array.splice': 185, - 'core-js/modules/es.object.to-string': 200 + '../core/main': 306, + 'core-js/modules/es.array-buffer.constructor': 170, + 'core-js/modules/es.array.concat': 171, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.array.splice': 189, + 'core-js/modules/es.object.to-string': 208 } ], - 338: [ + 346: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.array.map'); @@ -101298,29 +115493,79 @@ * @requires core */ /** - * Converts a string to its floating point representation. The contents of a - * string must resemble a number, or NaN (not a number) will be returned. - * For example, float("1234.56") evaluates to 1234.56, but float("giraffe") - * will return NaN. + * Converts a `String` to a floating point (decimal) `Number`. + * + * `float()` converts strings that resemble numbers, such as `'12.34'`, into + * numbers. * - * When an array of values is passed in, then an array of floats of the same - * length is returned. + * The parameter, `str`, is the string value to convert. For example, calling + * `float('12.34')` returns the number `12.34`. If an array of strings is + * passed, as in `float(['12.34', '56.78'])`, then an array of numbers will be + * returned. + * + * Note: If a string can't be converted to a number, as in `float('giraffe')`, + * then the value `NaN` (not a number) will be returned. * * @method float - * @param {String} str float string to parse - * @return {Number} floating point representation of string + * @param {String} str string to convert. + * @return {Number} converted number. + * * @example - *
- * let str = '20'; - * let diameter = float(str); - * ellipse(width / 2, height / 2, diameter, diameter); - * describe('20-by-20 white ellipse in the center of the canvas'); - *
- *
- * print(float('10.31')); // 10.31 - * print(float('Infinity')); // Infinity - * print(float('-Infinity')); // -Infinity - *
+ *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a string variable. + * let original = '12.3'; + * + * // Convert the string to a number. + * let converted = float(original); + * + * // Double the converted value. + * let twice = converted * 2; + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(12); + * + * // Display the original and converted values. + * text(`${original} × 2 = ${twice}`, 50, 50); + * + * describe('The text "12.3 × 2 = 24.6" written in black on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create an array of strings. + * let original = ['60', '30', '15']; + * + * // Convert the strings to numbers. + * let diameters = float(original); + * + * for (let d of diameters) { + * // Draw a circle. + * circle(50, 50, d); + * } + * + * describe('Three white, concentric circles on a gray background.'); + * } + * + *
+ */ + /** + * @method float + * @param {String[]} ns array of strings to convert. + * @return {Number[]} converted numbers. */ _main.default.prototype.float = function (str) { @@ -101330,32 +115575,128 @@ return parseFloat(str); }; /** - * Converts a boolean, string, or float to its integer representation. - * When an array of values is passed in, then an int array of the same length - * is returned. + * Converts a `Boolean`, `String`, or decimal `Number` to an integer. + * + * `int()` converts values to integers. Integers are positive or negative + * numbers without decimals. If the original value has decimals, as in -34.56, + * they're removed to produce an integer such as -34. + * + * The parameter, `n`, is the value to convert. If `n` is a Boolean, as in + * `int(false)` or `int(true)`, then the number 0 (`false`) or 1 (`true`) will + * be returned. If `n` is a string or number, as in `int('45')` or + * `int(67.89)`, then an integer will be returned. If an array is passed, as + * in `int([12.34, 56.78])`, then an array of integers will be returned. + * + * Note: If a value can't be converted to a number, as in `int('giraffe')`, + * then the value `NaN` (not a number) will be returned. * * @method int - * @param {String|Boolean|Number} n value to parse - * @param {Integer} [radix] the radix to convert to (default: 10) - * @return {Number} integer representation of value + * @param {String|Boolean|Number} n value to convert. + * @return {Number} converted number. * * @example - *
- * print(int('10')); // 10 - * print(int(10.31)); // 10 - * print(int(-10)); // -10 - * print(int(true)); // 1 - * print(int(false)); // 0 - * print(int([false, true, '10.3', 9.8])); // [0, 1, 10, 9] - * print(int(Infinity)); // Infinity - * print(int('-Infinity')); // -Infinity - *
+ *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a Boolean variable. + * let original = false; + * + * // Convert the Boolean to an integer. + * let converted = int(original); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(16); + * + * // Display the original and converted values. + * text(`${original} : ${converted}`, 50, 50); + * + * describe('The text "false : 0" written in black on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a string variable. + * let original = '12.34'; + * + * // Convert the string to an integer. + * let converted = int(original); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(14); + * + * // Display the original and converted values. + * text(`${original} ≈ ${converted}`, 50, 50); + * + * describe('The text "12.34 ≈ 12" written in black on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a decimal number variable. + * let original = 12.34; + * + * // Convert the decimal number to an integer. + * let converted = int(original); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(14); + * + * // Display the original and converted values. + * text(`${original} ≈ ${converted}`, 50, 50); + * + * describe('The text "12.34 ≈ 12" written in black on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create an array of strings. + * let original = ['60', '30', '15']; + * + * // Convert the strings to integers. + * let diameters = int(original); + * + * for (let d of diameters) { + * // Draw a circle. + * circle(50, 50, d); + * } + * + * describe('Three white, concentric circles on a gray background.'); + * } + * + *
*/ /** * @method int - * @param {Array} ns values to parse - * @param {Integer} [radix] - * @return {Number[]} integer representation of values + * @param {Array} ns values to convert. + * @return {Number[]} converted numbers. */ _main.default.prototype.int = function (n) { var radix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 10; @@ -101376,22 +115717,105 @@ } }; /** - * Converts a boolean, string or number to its string representation. - * When an array of values is passed in, then an array of strings of the same - * length is returned. + * Converts a `Boolean` or `Number` to `String`. + * + * `str()` converts values to strings. See the + * String reference page for guidance on using + * template literals instead. + * + * The parameter, `n`, is the value to convert. If `n` is a Boolean, as in + * `str(false)` or `str(true)`, then the value will be returned as a string, + * as in `'false'` or `'true'`. If `n` is a number, as in `str(123)`, then its + * value will be returned as a string, as in `'123'`. If an array is passed, + * as in `str([12.34, 56.78])`, then an array of strings will be returned. * * @method str - * @param {String|Boolean|Number|Array} n value to parse - * @return {String} string representation of value + * @param {String|Boolean|Number} n value to convert. + * @return {String} converted string. + * * @example - *
- * print(str('10')); // "10" - * print(str(10.31)); // "10.31" - * print(str(-10)); // "-10" - * print(str(true)); // "true" - * print(str(false)); // "false" - * print(str([true, '10.3', 9.8])); // [ "true", "10.3", "9.8" ] - *
+ *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a Boolean variable. + * let original = false; + * + * // Convert the Boolean to a string. + * let converted = str(original); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(16); + * + * // Display the original and converted values. + * text(`${original} : ${converted}`, 50, 50); + * + * describe('The text "false : false" written in black on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a number variable. + * let original = 123; + * + * // Convert the number to a string. + * let converted = str(original); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(16); + * + * // Display the original and converted values. + * text(`${original} = ${converted}`, 50, 50); + * + * describe('The text "123 = 123" written in black on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create an array of numbers. + * let original = [12, 34, 56]; + * + * // Convert the numbers to strings. + * let strings = str(original); + * + * // Create an empty string variable. + * let final = ''; + * + * // Concatenate all the strings. + * for (let s of strings) { + * final += s; + * } + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(16); + * + * // Display the concatenated string. + * text(final, 50, 50); + * + * describe('The text "123456" written in black on a gray background.'); + * } + * + *
*/ _main.default.prototype.str = function (n) { if (n instanceof Array) { @@ -101401,24 +115825,119 @@ } }; /** - * Converts a number or string to its boolean representation. - * For a number, any non-zero value (positive or negative) evaluates to true, - * while zero evaluates to false. For a string, the value "true" evaluates to - * true, while any other value evaluates to false. When an array of number or - * string values is passed in, then a array of booleans of the same length is - * returned. + * Converts a `String` or `Number` to a `Boolean`. + * + * `boolean()` converts values to `true` or `false`. + * + * The parameter, `n`, is the value to convert. If `n` is a string, then + * `boolean('true')` will return `true` and every other string value will + * return `false`. If `n` is a number, then `boolean(0)` will return `false` + * and every other numeric value will return `true`. If an array is passed, as + * `in boolean([0, 1, 'true', 'blue'])`, then an array of Boolean values will + * be returned. * * @method boolean - * @param {String|Boolean|Number|Array} n value to parse - * @return {Boolean} boolean representation of value + * @param {String|Boolean|Number} n value to convert. + * @return {Boolean} converted Boolean value. + * * @example - *
- * print(boolean(0)); // false - * print(boolean(1)); // true - * print(boolean('true')); // true - * print(boolean('abcd')); // false - * print(boolean([0, 12, 'true'])); // [false, true, true] - *
+ *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a number variable. + * let original = 0; + * + * // Convert the number to a Boolean value. + * let converted = boolean(original); + * + * // Style the circle based on the converted value. + * if (converted === true) { + * fill('blue'); + * } else { + * fill('red'); + * } + * + * // Draw the circle. + * circle(50, 50, 40); + * + * describe('A red circle on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a string variable. + * let original = 'true'; + * + * // Convert the string to a Boolean value. + * let converted = boolean(original); + * + * // Style the circle based on the converted value. + * if (converted === true) { + * fill('blue'); + * } else { + * fill('red'); + * } + * + * // Draw the circle. + * circle(50, 50, 40); + * + * describe('A blue circle on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create an array of values. + * let original = [0, 'hi', 123, 'true']; + * + * // Convert the array to a Boolean values. + * let converted = boolean(original); + * + * // Iterate over the array of converted Boolean values. + * for (let i = 0; i < converted.length; i += 1) { + * + * // Style the circle based on the converted value. + * if (converted[i] === true) { + * fill('blue'); + * } else { + * fill('red'); + * } + * + * // Calculate the x-coordinate. + * let x = (i + 1) * 20; + * + * // Draw the circle. + * circle(x, 50, 15); + * } + * + * describe( + * 'A row of circles on a gray background. The two circles on the left are red and the two on the right are blue.' + * ); + * } + * + *
+ */ + /** + * @method boolean + * @param {Array} ns values to convert. + * @return {Boolean[]} converted Boolean values. */ _main.default.prototype.boolean = function (n) { if (typeof n === 'number') { @@ -101432,31 +115951,139 @@ } }; /** - * Converts a number, string representation of a number, or boolean to its byte - * representation. A byte can be only a whole number between -128 and 127, so - * when a value outside of this range is converted, it wraps around to the - * corresponding byte representation. When an array of number, string or boolean - * values is passed in, then an array of bytes the same length is returned. + * Converts a `Boolean`, `String`, or `Number` to its byte value. + * + * `byte()` converts a value to an integer (whole number) between -128 and + * 127. Values greater than 127 wrap around while negative values are + * unchanged. For example, 128 becomes -128 and -129 remains the same. + * + * The parameter, `n`, is the value to convert. If `n` is a Boolean, as in + * `byte(false)` or `byte(true)`, the number 0 (`false`) or 1 (`true`) will be + * returned. If `n` is a string or number, as in `byte('256')` or `byte(256)`, + * then the byte value will be returned. Decimal values are ignored. If an + * array is passed, as in `byte([true, 123, '456'])`, then an array of byte + * values will be returned. + * + * Note: If a value can't be converted to a number, as in `byte('giraffe')`, + * then the value `NaN` (not a number) will be returned. * * @method byte - * @param {String|Boolean|Number} n value to parse - * @return {Number} byte representation of value + * @param {String|Boolean|Number} n value to convert. + * @return {Number} converted byte value. * * @example - *
- * print(byte(127)); // 127 - * print(byte(128)); // -128 - * print(byte(23.4)); // 23 - * print(byte('23.4')); // 23 - * print(byte('hello')); // NaN - * print(byte(true)); // 1 - * print(byte([0, 255, '100'])); // [0, -1, 100] - *
+ *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a Boolean variable. + * let original = true; + * + * // Convert the Boolean to its byte value. + * let converted = byte(original); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(16); + * + * // Display the original and converted values. + * text(`${original} : ${converted}`, 50, 50); + * + * describe('The text "true : 1" written in black on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a string variable. + * let original = '256'; + * + * // Convert the string to its byte value. + * let converted = byte(original); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(16); + * + * // Display the original and converted values. + * text(`${original} : ${converted}`, 50, 50); + * + * describe('The text "256 : 0" written in black on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a number variable. + * let original = 256; + * + * // Convert the number to its byte value. + * let converted = byte(original); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(16); + * + * // Display the original and converted values. + * text(`${original} : ${converted}`, 50, 50); + * + * describe('The text "256 : 0" written in black on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create an array of values. + * let original = [false, '64', 383]; + * + * // Convert the array elements to their byte values. + * let converted = byte(original); + * + * // Iterate over the converted array elements. + * for (let i = 0; i < converted.length; i += 1) { + * + * // Style the circle. + * fill(converted[i]); + * + * // Calculate the x-coordinate. + * let x = (i + 1) * 25; + * + * // Draw the circle. + * circle(x, 50, 20); + * } + * + * describe( + * 'Three gray circles on a gray background. The circles get lighter from left to right.' + * ); + * } + * + *
*/ /** * @method byte - * @param {Array} ns values to parse - * @return {Number[]} array of byte representation of values + * @param {Array} ns values to convert. + * @return {Number[]} converted byte values. */ _main.default.prototype.byte = function (n) { var nn = _main.default.prototype.int(n, 10); @@ -101467,28 +116094,113 @@ } }; /** - * Converts a number or string to its corresponding single-character - * string representation. If a string parameter is provided, it is first - * parsed as an integer and then translated into a single-character string. - * When an array of number or string values is passed in, then an array of - * single-character strings of the same length is returned. + * Converts a `Number` or `String` to a single-character `String`. + * + * `char()` converts numbers to their single-character string representations. + * + * The parameter, `n`, is the value to convert. If a number is passed, as in + * `char(65)`, the corresponding single-character string is returned. If a + * string is passed, as in `char('65')`, the string is converted to an integer + * (whole number) and the corresponding single-character string is returned. + * If an array is passed, as in `char([65, 66, 67])`, an array of + * single-character strings is returned. + * + * See MDN + * for more information about conversions. * * @method char - * @param {String|Number} n value to parse - * @return {String} string representation of value + * @param {String|Number} n value to convert. + * @return {String} converted single-character string. * * @example - *
- * print(char(65)); // "A" - * print(char('65')); // "A" - * print(char([65, 66, 67])); // [ "A", "B", "C" ] - * print(join(char([65, 66, 67]), '')); // "ABC" - *
+ *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a number variable. + * let original = 65; + * + * // Convert the number to a char. + * let converted = char(original); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(16); + * + * // Display the original and converted values. + * text(`${original} : ${converted}`, 50, 50); + * + * describe('The text "65 : A" written in black on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a string variable. + * let original = '65'; + * + * // Convert the string to a char. + * let converted = char(original); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(16); + * + * // Display the original and converted values. + * text(`${original} : ${converted}`, 50, 50); + * + * describe('The text "65 : A" written in black on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create an array of numbers. + * let original = ['65', 66, '67']; + * + * // Convert the string to a char. + * let converted = char(original); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(16); + * + * // Iterate over elements of the converted array. + * for (let i = 0; i < converted.length; i += 1) { + * + * // Calculate the y-coordinate. + * let y = (i + 1) * 25; + * + * // Display the original and converted values. + * text(`${original[i]} : ${converted[i]}`, 50, y); + * } + * + * describe( + * 'The text "65 : A", "66 : B", and "67 : C" written on three separate lines. The text is in black on a gray background.' + * ); + * } + * + *
*/ /** * @method char - * @param {Array} ns values to parse - * @return {String[]} array of string representation of values + * @param {Array} ns values to convert. + * @return {String[]} converted single-character strings. */ _main.default.prototype.char = function (n) { if (typeof n === 'number' && !isNaN(n)) { @@ -101500,62 +116212,208 @@ } }; /** - * Converts a single-character string to its corresponding integer - * representation. When an array of single-character string values is passed - * in, then an array of integers of the same length is returned. + * Converts a single-character `String` to a `Number`. + * + * `unchar()` converts single-character strings to their corresponding + * integer (whole number). + * + * The parameter, `n`, is the character to convert. For example, + * `unchar('A')`, returns the number 65. If an array is passed, as in + * `unchar(['A', 'B', 'C'])`, an array of integers is returned. * * @method unchar - * @param {String} n value to parse - * @return {Number} integer representation of value + * @param {String} n value to convert. + * @return {Number} converted number. * * @example - *
- * print(unchar('A')); // 65 - * print(unchar(['A', 'B', 'C'])); // [ 65, 66, 67 ] - * print(unchar(split('ABC', ''))); // [ 65, 66, 67 ] - *
- */ - /** - * @method unchar - * @param {Array} ns values to parse - * @return {Number[]} integer representation of values - */ - _main.default.prototype.unchar = function (n) { - if (typeof n === 'string' && n.length === 1) { - return n.charCodeAt(0); - } else if (n instanceof Array) { - return n.map(_main.default.prototype.unchar); - } - }; - /** - * Converts a number to a string in its equivalent hexadecimal notation. If a - * second parameter is passed, it is used to set the number of characters to - * generate in the hexadecimal notation. When an array is passed in, an - * array of strings in hexadecimal notation of the same length is returned. + *
+ * + * function setup() { + * createCanvas(100, 100); * - * @method hex - * @param {Number} n value to parse - * @param {Number} [digits] - * @return {String} hexadecimal string representation of value + * background(200); * - * @example - *
- * print(hex(255)); // "000000FF" - * print(hex(255, 6)); // "0000FF" - * print(hex([0, 127, 255], 6)); // [ "000000", "00007F", "0000FF" ] - * print(Infinity); // "FFFFFFFF" - * print(-Infinity); // "00000000" - *
- */ - /** - * @method hex - * @param {Number[]} ns array of values to parse - * @param {Number} [digits] - * @return {String[]} hexadecimal string representation of values - */ - _main.default.prototype.hex = function (n, digits) { - digits = digits === undefined || digits === null ? digits = 8 : digits; - if (n instanceof Array) { + * // Create a string variable. + * let original = 'A'; + * + * // Convert the string to a number. + * let converted = unchar(original); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(16); + * + * // Display the original and converted values. + * text(`${original} : ${converted}`, 50, 50); + * + * describe('The text "A : 65" written in black on a gray background.'); + * } + *
+ *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create an array of characters. + * let original = ['A', 'B', 'C']; + * + * // Convert the string to a number. + * let converted = unchar(original); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(16); + * + * // Iterate over elements of the converted array. + * for (let i = 0; i < converted.length; i += 1) { + * + * // Calculate the y-coordinate. + * let y = (i + 1) * 25; + * + * // Display the original and converted values. + * text(`${original[i]} : ${converted[i]}`, 50, y); + * } + * + * describe( + * 'The text "A : 65", "B : 66", and "C :67" written on three separate lines. The text is in black on a gray background.' + * ); + * } + * + *
+ */ + /** + * @method unchar + * @param {String[]} ns values to convert. + * @return {Number[]} converted numbers. + */ + _main.default.prototype.unchar = function (n) { + if (typeof n === 'string' && n.length === 1) { + return n.charCodeAt(0); + } else if (n instanceof Array) { + return n.map(_main.default.prototype.unchar); + } + }; + /** + * Converts a `Number` to a `String` with its hexadecimal value. + * + * `hex()` converts a number to a string with its hexadecimal number value. + * Hexadecimal (hex) numbers are base-16, which means there are 16 unique + * digits. Hex extends the numbers 0–9 with the letters A–F. For example, the + * number `11` (eleven) in base-10 is written as the letter `B` in hex. + * + * The first parameter, `n`, is the number to convert. For example, `hex(20)`, + * returns the string `'00000014'`. If an array is passed, as in + * `hex([1, 10, 100])`, an array of hexadecimal strings is returned. + * + * The second parameter, `digits`, is optional. If a number is passed, as in + * `hex(20, 2)`, it sets the number of hexadecimal digits to display. For + * example, calling `hex(20, 2)` returns the string `'14'`. + * + * @method hex + * @param {Number} n value to convert. + * @param {Number} [digits] number of digits to include. + * @return {String} converted hexadecimal value. + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a number variable. + * let original = 20; + * + * // Convert the number to a hex string. + * let converted = hex(original); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(14); + * + * // Display the original and converted values. + * text(`${original} = ${converted}`, 50, 50); + * + * describe('The text "20 = 00000014" written in black on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a number variable. + * let original = 20; + * + * // Convert the number to a hex string. + * // Only display two hex digits. + * let converted = hex(original, 2); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(16); + * + * // Display the original and converted values. + * text(`${original} = ${converted}`, 50, 50); + * + * describe('The text "20 = 14" written in black on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create an array of numbers. + * let original = [1, 10, 100]; + * + * // Convert the numbers to hex strings. + * // Only use two hex digits. + * let converted = hex(original, 2); + * + * // Style the text. + * textAlign(RIGHT, CENTER); + * textSize(16); + * + * // Iterate over the converted values. + * for (let i = 0; i < converted.length; i += 1) { + * + * // Calculate the y-coordinate. + * let y = (i + 1) * 25; + * + * // Display the original and converted values. + * text(`${ original[i]} = ${converted[i]}`, 75, y); + * } + * + * describe( + * 'The text "1 = 01", "10 = 0A", and "100 = 64" written on three separate lines. The text is in black on a gray background.' + * ); + * } + * + *
+ */ + /** + * @method hex + * @param {Number[]} ns values to convert. + * @param {Number} [digits] + * @return {String[]} converted hexadecimal values. + */ + _main.default.prototype.hex = function (n, digits) { + digits = digits === undefined || digits === null ? digits = 8 : digits; + if (n instanceof Array) { return n.map(function (n) { return _main.default.prototype.hex(n, digits); }); @@ -101577,25 +116435,86 @@ } }; /** - * Converts a string representation of a hexadecimal number to its equivalent - * integer value. When an array of strings in hexadecimal notation is passed - * in, an array of integers of the same length is returned. + * Converts a `String` with a hexadecimal value to a `Number`. + * + * `unhex()` converts a string with its hexadecimal number value to a number. + * Hexadecimal (hex) numbers are base-16, which means there are 16 unique + * digits. Hex extends the numbers 0–9 with the letters A–F. For example, the + * number `11` (eleven) in base-10 is written as the letter `B` in hex. + * + * The first parameter, `n`, is the hex string to convert. For example, + * `unhex('FF')`, returns the number 255. If an array is passed, as in + * `unhex(['00', '80', 'FF'])`, an array of numbers is returned. * * @method unhex - * @param {String} n value to parse - * @return {Number} integer representation of hexadecimal value + * @param {String} n value to convert. + * @return {Number} converted number. * * @example - *
- * print(unhex('A')); // 10 - * print(unhex('FF')); // 255 - * print(unhex(['FF', 'AA', '00'])); // [ 255, 170, 0 ] - *
+ *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a a hex string variable + * let original = 'FF'; + * + * // Convert the hex string to a number. + * let converted = unhex(original); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(16); + * + * // Display the original and converted values. + * text(`${original} = ${converted}`, 50, 50); + * + * describe('The text "FF = 255" written in black on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create an array of numbers. + * let original = ['00', '80', 'FF']; + * + * // Convert the numbers to hex strings. + * // Only use two hex digits. + * let converted = unhex(original, 2); + * + * // Style the text. + * textAlign(RIGHT, CENTER); + * textSize(16); + * + * // Iterate over the converted values. + * for (let i = 0; i < converted.length; i += 1) { + * + * // Calculate the y-coordinate. + * let y = (i + 1) * 25; + * + * // Display the original and converted values. + * text(`${ original[i]} = ${converted[i]}`, 80, y); + * } + * + * describe( + * 'The text "00 = 0", "80 = 128", and "FF = 255" written on three separate lines. The text is in black on a gray background.' + * ); + * } + * + *
*/ /** * @method unhex - * @param {Array} ns values to parse - * @return {Number[]} integer representations of hexadecimal value + * @param {String[]} ns values to convert. + * @return {Number[]} converted numbers. */ _main.default.prototype.unhex = function (n) { if (n instanceof Array) { @@ -101608,15 +116527,15 @@ exports.default = _default; }, { - '../core/main': 298, - 'core-js/modules/es.array.map': 182, - 'core-js/modules/es.number.constructor': 191, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.string.repeat': 213 + '../core/main': 306, + 'core-js/modules/es.array.map': 186, + 'core-js/modules/es.number.constructor': 197, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.string.repeat': 221 } ], - 339: [ + 347: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -101711,23 +116630,42 @@ */ //return p5; //LM is this a mistake? /** - * Combines an array of Strings into one String, each separated by the - * character(s) used for the separator parameter. To join arrays of ints or - * floats, it's necessary to first convert them to Strings using nf() or - * nfs(). + * Combines an array of strings into one string. + * + * The first parameter, `list`, is the array of strings to join. + * + * The second parameter, `separator`, is the character(s) that should be used + * to separate the combined strings. For example, calling + * `join(myWords, ' : ')` would return a string of words each separated by a + * colon and spaces. * * @method join - * @param {Array} list array of Strings to be joined - * @param {String} separator String to be placed between each item - * @return {String} joined String + * @param {Array} list array of strings to combine. + * @param {String} separator character(s) to place between strings when they're combined. + * @return {String} combined string. + * * @example *
* - * let array = ['Hello', 'world!']; - * let separator = ' '; - * let message = join(array, separator); - * text(message, 5, 50); - * describe('“Hello world!” displayed middle left of canvas.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create an array of strings. + * let myWords = ['one', 'two', 'three']; + * + * // Create a combined string + * let combined = join(myWords, ' : '); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * + * // Display the combined string. + * text(combined, 50, 50); + * + * describe('The text "one : two : three" written in black on a gray canvas.'); + * } * *
*/ @@ -101737,35 +116675,56 @@ return list.join(separator); }; /** - * This function is used to apply a regular expression to a piece of text, - * and return matching groups (elements found inside parentheses) as a - * String array. If there are no matches, a null value will be returned. - * If no groups are specified in the regular expression, but the sequence - * matches, an array of length 1 (with the matched text as the first element - * of the array) will be returned. + * Applies a regular expression to a string and returns an array with the + * first match. * - * To use the function, first check to see if the result is null. If the - * result is null, then the sequence did not match at all. If the sequence - * did match, an array is returned. + * `match()` uses regular expressions (regex) to match patterns in text. For + * example, the regex `abc` can be used to search a string for the exact + * sequence of characters `abc`. See + * MDN. + * for more information about regexes. * - * If there are groups (specified by sets of parentheses) in the regular - * expression, then the contents of each will be returned in the array. - * Element [0] of a regular expression match returns the entire matching - * string, and the match groups start at element [1] (the first group is [1], - * the second [2], and so on). + * The first parameter, `str`, is the string to search. + * + * The second parameter, `regex`, is a string with the regular expression to + * apply. For example, calling `match('Hello, p5*js!', '[a-z][0-9]')` would + * return the array `['p5']`. + * + * Note: If no matches are found, `null` is returned. * * @method match - * @param {String} str the String to be searched - * @param {String} regexp the regexp to be used for matching - * @return {String[]} Array of Strings found + * @param {String} str string to search. + * @param {String} regexp regular expression to match. + * @return {String[]} match if found. + * * @example *
* - * let string = 'Hello p5js*!'; - * let regexp = 'p5js\\*'; - * let m = match(string, regexp); - * text(m, 5, 50); - * describe('“p5js*” displayed middle left of canvas.'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a string variable. + * let string = 'Hello, p5*js!'; + * + * // Match the characters that are lowercase + * // letters followed by digits. + * let matches = match(string, '[a-z][0-9]'); + * + * // Print the matches array to the console: + * // ['p5'] + * print(matches); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(16); + * + * // Display the matches. + * text(matches, 50, 50); + * + * describe('The text "p5" written in black on a gray canvas.'); + * } * *
*/ @@ -101774,34 +116733,67 @@ return str.match(reg); }; /** - * This function is used to apply a regular expression to a piece of text, - * and return a list of matching groups (elements found inside parentheses) - * as a two-dimensional String array. If there are no matches, a null value - * will be returned. If no groups are specified in the regular expression, - * but the sequence matches, a two dimensional array is still returned, but - * the second dimension is only of length one. + * Applies a regular expression to a string and returns an array of matches. * - * To use the function, first check to see if the result is null. If the - * result is null, then the sequence did not match at all. If the sequence - * did match, a 2D array is returned. + * `match()` uses regular expressions (regex) to match patterns in text. For + * example, the regex `abc` can be used to search a string for the exact + * sequence of characters `abc`. See + * MDN. + * for more information about regexes. `matchAll()` is different from + * match() because it returns every match, not just + * the first. * - * If there are groups (specified by sets of parentheses) in the regular - * expression, then the contents of each will be returned in the array. - * Assuming a loop with counter variable i, element [i][0] of a regular - * expression match returns the entire matching string, and the match groups - * start at element [i][1] (the first group is [i][1], the second [i][2], - * and so on). + * The first parameter, `str`, is the string to search. + * + * The second parameter, `regex`, is a string with the regular expression to + * apply. For example, calling + * `matchAll('p5*js is easier than abc123', '[a-z][0-9]')` would return the + * 2D array `[['p5'], ['c1']]`. + * + * Note: If no matches are found, an empty array `[]` is returned. * * @method matchAll - * @param {String} str the String to be searched - * @param {String} regexp the regexp to be used for matching - * @return {String[]} 2d Array of Strings found + * @param {String} str string to search. + * @param {String} regexp regular expression to match. + * @return {String[]} matches found. + * * @example - *
+ *
* - * let string = 'Hello p5js*! Hello world!'; - * let regexp = 'Hello'; - * matchAll(string, regexp); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a string variable. + * let string = 'p5*js is easier than abc123'; + * + * // Match the character sequences that are + * // lowercase letters followed by digits. + * let matches = matchAll(string, '[a-z][0-9]'); + * + * // Print the matches array to the console: + * // [['p5'], ['c1']] + * print(matches); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(16); + * + * // Iterate over the matches array. + * for (let i = 0; i < matches.length; i += 1) { + * + * // Calculate the y-coordainate. + * let y = (i + 1) * 33; + * + * // Display the match. + * text(matches[i], 50, y); + * } + * + * describe( + * 'The text "p5" and "c1" written on separate lines. The text is black on a gray background.' + * ); + * } * *
*/ @@ -101821,56 +116813,82 @@ return matches; }; /** - * Utility function for formatting numbers into strings. There are two - * versions: one for formatting floats, and one for formatting ints. + * Converts a `Number` into a `String` with a given number of digits. + * + * `nf()` converts numbers such as `123.45` into strings formatted with a set + * number of digits, as in `'123.4500'`. * - * The values for the digits, left, and right parameters should always - * be positive integers. + * The first parameter, `num`, is the number to convert to a string. For + * example, calling `nf(123.45)` returns the string `'123.45'`. If an array of + * numbers is passed, as in `nf([123.45, 67.89])`, an array of formatted + * strings will be returned. * - * (NOTE): Be cautious when using left and right parameters as it prepends numbers of 0's if the parameter - * if greater than the current length of the number. + * The second parameter, `left`, is optional. If a number is passed, as in + * `nf(123.45, 4)`, it sets the minimum number of digits to include to the + * left of the decimal place. If `left` is larger than the number of digits in + * `num`, then unused digits will be set to 0. For example, calling + * `nf(123.45, 4)` returns the string `'0123.45'`. * - * For example if number is 123.2 and left parameter passed is 4 which is greater than length of 123 - * (integer part) i.e 3 than result will be 0123.2. Same case for right parameter i.e. if right is 3 than - * the result will be 123.200. + * The third parameter, `right`, is also optional. If a number is passed, as + * in `nf(123.45, 4, 1)`, it sets the minimum number of digits to include to + * the right of the decimal place. If `right` is smaller than the number of + * decimal places in `num`, then `num` will be rounded to the given number of + * decimal places. For example, calling `nf(123.45, 4, 1)` returns the string + * `'0123.5'`. If right is larger than the number of decimal places in `num`, + * then unused decimal places will be set to 0. For example, calling + * `nf(123.45, 4, 3)` returns the string `'0123.450'`. * * @method nf - * @param {Number|String} num the Number to format - * @param {Integer|String} [left] number of digits to the left of the - * decimal point - * @param {Integer|String} [right] number of digits to the right of the - * decimal point - * @return {String} formatted String + * @param {Number|String} num number to format. + * @param {Integer|String} [left] number of digits to include to the left of + * the decimal point. + * @param {Integer|String} [right] number of digits to include to the right + * of the decimal point. + * @return {String} formatted string. * * @example *
* * function setup() { + * createCanvas(100, 100); + * * background(200); - * let num1 = 321; - * let num2 = -1321; * - * noStroke(); - * fill(0); + * // Style the text. + * textAlign(LEFT, CENTER); * textSize(16); * - * text(nf(num1, 4, 2), 10, 30); - * text(nf(num2, 4, 2), 10, 80); - * // Draw dividing line - * stroke(120); - * line(0, 50, width, 50); + * // Create a number variable. + * let number = 123.45; * - * describe('“0321.00” middle top, “-1321.00” middle bottom canvas'); + * // Display the number as a string. + * let formatted = nf(number); + * text(formatted, 20, 25); + * + * // Display the number with four digits + * // to the left of the decimal. + * let left = nf(number, 4); + * text(left, 20, 50); + * + * // Display the number with four digits + * // to the left of the decimal and one + * // to the right. + * let right = nf(number, 4, 1); + * text(right, 20, 75); + * + * describe( + * 'The numbers "123.45", "0123.45", and "0123.5" written on three separate lines. The text is in black on a gray background.' + * ); * } * *
*/ /** * @method nf - * @param {Array} nums the Numbers to format - * @param {Integer|String} [left] - * @param {Integer|String} [right] - * @return {String[]} formatted Strings + * @param {Number[]} nums numbers to format. + * @param {Integer|String} [left] + * @param {Integer|String} [right] + * @return {String[]} formatted strings. */ _main.default.prototype.nf = function (nums, left, right) { _main.default._validateParameters('nf', arguments); @@ -101915,47 +116933,99 @@ } } } /** - * Utility function for formatting numbers into strings and placing - * appropriate commas to mark units of 1000. There are two versions: one - * for formatting ints, and one for formatting an array of ints. The value - * for the right parameter should always be a positive integer. + * Converts a `Number` into a `String` with commas to mark units of 1,000. + * + * `nfc()` converts numbers such as 12345 into strings formatted with commas + * to mark the thousands place, as in `'12,345'`. + * + * The first parameter, `num`, is the number to convert to a string. For + * example, calling `nfc(12345)` returns the string `'12,345'`. + * + * The second parameter, `right`, is optional. If a number is passed, as in + * `nfc(12345, 1)`, it sets the minimum number of digits to include to the + * right of the decimal place. If `right` is smaller than the number of + * decimal places in `num`, then `num` will be rounded to the given number of + * decimal places. For example, calling `nfc(12345.67, 1)` returns the string + * `'12,345.7'`. If `right` is larger than the number of decimal places in + * `num`, then unused decimal places will be set to 0. For example, calling + * `nfc(12345.67, 3)` returns the string `'12,345.670'`. * * @method nfc - * @param {Number|String} num the Number to format - * @param {Integer|String} [right] number of digits to the right of the - * decimal point - * @return {String} formatted String + * @param {Number|String} num number to format. + * @param {Integer|String} [right] number of digits to include to the right + * of the decimal point. + * @return {String} formatted string. * * @example *
* * function setup() { + * createCanvas(100, 100); + * * background(200); - * let num = 11253106.115; - * let numArr = [1, 1, 2]; * - * noStroke(); - * fill(0); - * textSize(12); + * // Style the text. + * textAlign(LEFT, CENTER); + * textSize(16); + * + * // Create a number variable. + * let number = 12345; + * + * // Display the number as a string. + * let commas = nfc(number); + * text(commas, 15, 33); + * + * // Display the number with four digits + * // to the left of the decimal. + * let decimals = nfc(number, 2); + * text(decimals, 15, 67); + * + * describe( + * 'The numbers "12,345" and "12,345.00" written on separate lines. The text is in black on a gray background.' + * ); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); * - * // Draw formatted numbers - * text(nfc(num, 4), 10, 30); - * text(nfc(numArr, 2), 10, 80); + * background(200); + * + * // Create an array of numbers. + * let numbers = [12345, 6789]; + * + * // Convert the numbers to formatted strings. + * let formatted = nfc(numbers); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(14); + * + * // Iterate over the array. + * for (let i = 0; i < formatted.length; i += 1) { * - * // Draw dividing line - * stroke(120); - * line(0, 50, width, 50); + * // Calculate the y-coordinate. + * let y = (i + 1) * 33; + * + * // Display the original and formatted numbers. + * text(`${numbers[i]} : ${formatted[i]}`, 50, y); + * } * - * describe('“11,253,106.115” top middle and “1.00,1.00,2.00” displayed bottom mid'); + * describe( + * 'The text "12345 : 12,345" and "6789 : 6,789" written on two separate lines. The text is in black on a gray background.' + * ); * } * *
*/ /** * @method nfc - * @param {Array} nums the Numbers to format - * @param {Integer|String} [right] - * @return {String[]} formatted Strings + * @param {Number[]} nums numbers to format. + * @param {Integer|String} [right] + * @return {String[]} formatted strings. */ _main.default.prototype.nfc = function (num, right) { @@ -101989,51 +117059,116 @@ } return n + rem; } /** - * Utility function for formatting numbers into strings. Similar to nf() but - * puts a "+" in front of positive numbers and a "-" in front of negative - * numbers. There are two versions: one for formatting floats, and one for - * formatting ints. The values for left, and right parameters - * should always be positive integers. + * Converts a `Number` into a `String` with a plus or minus sign. + * + * `nfp()` converts numbers such as 123 into strings formatted with a `+` or + * `-` symbol to mark whether they're positive or negative, as in `'+123'`. + * + * The first parameter, `num`, is the number to convert to a string. For + * example, calling `nfp(123.45)` returns the string `'+123.45'`. If an array + * of numbers is passed, as in `nfp([123.45, -6.78])`, an array of formatted + * strings will be returned. + * + * The second parameter, `left`, is optional. If a number is passed, as in + * `nfp(123.45, 4)`, it sets the minimum number of digits to include to the + * left of the decimal place. If `left` is larger than the number of digits in + * `num`, then unused digits will be set to 0. For example, calling + * `nfp(123.45, 4)` returns the string `'+0123.45'`. + * + * The third parameter, `right`, is also optional. If a number is passed, as + * in `nfp(123.45, 4, 1)`, it sets the minimum number of digits to include to + * the right of the decimal place. If `right` is smaller than the number of + * decimal places in `num`, then `num` will be rounded to the given number of + * decimal places. For example, calling `nfp(123.45, 4, 1)` returns the + * string `'+0123.5'`. If `right` is larger than the number of decimal places + * in `num`, then unused decimal places will be set to 0. For example, + * calling `nfp(123.45, 4, 3)` returns the string `'+0123.450'`. * * @method nfp - * @param {Number} num the Number to format - * @param {Integer} [left] number of digits to the left of the decimal - * point - * @param {Integer} [right] number of digits to the right of the - * decimal point - * @return {String} formatted String + * @param {Number} num number to format. + * @param {Integer} [left] number of digits to include to the left of the + * decimal point. + * @param {Integer} [right] number of digits to include to the right of the + * decimal point. + * @return {String} formatted string. * * @example *
* * function setup() { + * createCanvas(100, 100); + * * background(200); - * let num1 = 11253106.115; - * let num2 = -11253106.115; * - * noStroke(); - * fill(0); - * textSize(12); + * // Create number variables. + * let positive = 123; + * let negative = -123; + * + * // Convert the positive number to a formatted string. + * let p = nfp(positive); * - * // Draw formatted numbers - * text(nfp(num1, 4, 2), 10, 30); - * text(nfp(num2, 4, 2), 10, 80); + * // Convert the negative number to a formatted string + * // with four digits to the left of the decimal + * // and two digits to the right of the decimal. + * let n = nfp(negative, 4, 2); * - * // Draw dividing line - * stroke(120); - * line(0, 50, width, 50); + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(14); + * + * // Display the original and formatted numbers. + * text(`${positive} : ${p}`, 50, 33); + * text(`${negative} : ${n}`, 50, 67); + * + * describe( + * 'The text "123 : +123" and "-123 : -123.00" written on separate lines. The text is in black on a gray background.' + * ); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create number variables. + * let numbers = [123, -4.56]; * - * describe('“+11253106.11” top middle and “-11253106.11” displayed bottom middle'); + * // Convert the numbers to formatted strings + * // with four digits to the left of the decimal + * // and one digit to the right of the decimal. + * let formatted = nfp(numbers, 4, 1); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(14); + * + * // Iterate over the array. + * for (let i = 0; i < formatted.length; i += 1) { + * + * // Calculate the y-coordinate. + * let y = (i + 1) * 33; + * + * // Display the original and formatted numbers. + * text(`${numbers[i]} : ${formatted[i]}`, 50, y); + * } + * + * describe( + * 'The text "123 : +0123.0" and "-4.56 : 00-4.6" written on separate lines. The text is in black on a gray background.' + * ); * } * *
*/ /** * @method nfp - * @param {Number[]} nums the Numbers to format - * @param {Integer} [left] - * @param {Integer} [right] - * @return {String[]} formatted Strings + * @param {Number[]} nums numbers to format. + * @param {Integer} [left] + * @param {Integer} [right] + * @return {String[]} formatted strings. */ _main.default.prototype.nfp = function () { @@ -102051,67 +117186,107 @@ function addNfp(num) { return parseFloat(num) > 0 ? '+'.concat(num.toString()) : num.toString(); } /** - * Utility function for formatting numbers into strings. Similar to nf() but - * puts an additional "_" (space) in front of positive numbers just in case to align it with negative - * numbers which includes "-" (minus) sign. + * Converts a positive `Number` into a `String` with an extra space in front. + * + * `nfs()` converts positive numbers such as 123.45 into strings formatted + * with an extra space in front, as in ' 123.45'. Doing so can be helpful for + * aligning positive and negative numbers. + * + * The first parameter, `num`, is the number to convert to a string. For + * example, calling `nfs(123.45)` returns the string `' 123.45'`. + * + * The second parameter, `left`, is optional. If a number is passed, as in + * `nfs(123.45, 4)`, it sets the minimum number of digits to include to the + * left of the decimal place. If `left` is larger than the number of digits in + * `num`, then unused digits will be set to 0. For example, calling + * `nfs(123.45, 4)` returns the string `' 0123.45'`. + * + * The third parameter, `right`, is also optional. If a number is passed, as + * in `nfs(123.45, 4, 1)`, it sets the minimum number of digits to include to + * the right of the decimal place. If `right` is smaller than the number of + * decimal places in `num`, then `num` will be rounded to the given number of + * decimal places. For example, calling `nfs(123.45, 4, 1)` returns the + * string `' 0123.5'`. If `right` is larger than the number of decimal places + * in `num`, then unused decimal places will be set to 0. For example, + * calling `nfs(123.45, 4, 3)` returns the string `' 0123.450'`. + * + * @method nfs + * @param {Number} num number to format. + * @param {Integer} [left] number of digits to include to the left of the + * decimal point. + * @param {Integer} [right] number of digits to include to the right of the + * decimal point. + * @return {String} formatted string. + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); * - * The main usecase of nfs() can be seen when one wants to align the digits (place values) of a non-negative - * number with some negative number (See the example to get a clear picture). - * There are two versions: one for formatting float, and one for formatting int. + * background(200); * - * The values for the digits, left, and right parameters should always be positive integers. + * // Create number variables. + * let positive = 123; + * let negative = -123; * - * (IMP): The result on the canvas basically the expected alignment can vary based on the typeface you are using. + * // Convert the positive number to a formatted string. + * let formatted = nfs(positive); * - * (NOTE): Be cautious when using left and right parameters as it prepends numbers of 0's if the parameter - * if greater than the current length of the number. + * // Style the text. + * textAlign(CENTER, CENTER); + * textFont('Courier New'); + * textSize(16); * - * For example if number is 123.2 and left parameter passed is 4 which is greater than length of 123 - * (integer part) i.e 3 than result will be 0123.2. Same case for right parameter i.e. if right is 3 than - * the result will be 123.200. + * // Display the negative number and the formatted positive number. + * text(negative, 50, 33); + * text(formatted, 50, 67); * - * @method nfs - * @param {Number} num the Number to format - * @param {Integer} [left] number of digits to the left of the decimal - * point - * @param {Integer} [right] number of digits to the right of the - * decimal point - * @return {String} formatted String + * describe( + * 'The numbers -123 and 123 written on separate lines. The numbers align vertically. The text is in black on a gray background.' + * ); + * } + * + *
* - * @example *
* * function setup() { + * createCanvas(100, 100); + * * background(200); - * let num1 = 321; - * let num2 = -1321; * - * noStroke(); - * fill(0); + * // Create a number variable. + * let number = 123.45; + * + * // Convert the positive number to a formatted string. + * // Use four digits to the left of the decimal and + * // one digit to the right. + * let formatted = nfs(number, 4, 1); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textFont('Courier New'); * textSize(16); * - * // nfs() aligns num1 (positive number) with num2 (negative number) by - * // adding a blank space in front of the num1 (positive number) - * // [left = 4] in num1 add one 0 in front, to align the digits with num2 - * // [right = 2] in num1 and num2 adds two 0's after both numbers - * // To see the differences check the example of nf() too. - * text(nfs(num1, 4, 2), 10, 30); - * text(nfs(num2, 4, 2), 10, 80); - * // Draw dividing line - * stroke(120); - * line(0, 50, width, 50); + * // Display a negative version of the number and + * // the formatted positive version. + * text('-0123.5', 50, 33); + * text(formatted, 50, 67); * - * describe('“0321.00” top middle and “-1321.00” displayed bottom middle'); + * describe( + * 'The numbers "-0123.5" and "0123.5" written on separate lines. The numbers align vertically. The text is in black on a gray background.' + * ); * } * *
*/ /** * @method nfs - * @param {Array} nums the Numbers to format - * @param {Integer} [left] - * @param {Integer} [right] - * @return {String[]} formatted Strings + * @param {Array} nums numbers to format. + * @param {Integer} [left] + * @param {Integer} [right] + * @return {String[]} formatted strings. */ _main.default.prototype.nfs = function () { @@ -102129,28 +117304,58 @@ function addNfs(num) { return parseFloat(num) >= 0 ? ' '.concat(num.toString()) : num.toString(); } /** - * The split() function maps to String.split(), it breaks a String into - * pieces using a character or string as the delimiter. The delim parameter - * specifies the character or characters that mark the boundaries between - * each piece. A String[] array is returned that contains each of the pieces. + * Splits a `String` into pieces and returns an array containing the pieces. * - * The splitTokens() function works in a similar fashion, except that it - * splits using a range of characters instead of a specific character or - * sequence. + * The first parameter, `value`, is the string to split. + * + * The second parameter, `delim`, is the character(s) that should be used to + * split the string. For example, calling + * `split('rock...paper...scissors', '...')` would return the array + * `['rock', 'paper', 'scissors']` because there are three periods `...` + * between each word. * * @method split * @param {String} value the String to be split * @param {String} delim the String used to separate the data * @return {String[]} Array of Strings + * * @example *
* - * let names = 'Pat,Xio,Alex'; - * let splitString = split(names, ','); - * text(splitString[0], 5, 30); - * text(splitString[1], 5, 50); - * text(splitString[2], 5, 70); - * describe('“Pat” top left, “Xio” mid left, and “Alex” displayed bottom left'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a string variable. + * let string = 'rock...paper...scissors'; + * + * // Split the string at each ... + * let words = split(string, '...'); + * + * // Print the array to the console: + * // ["rock", "paper", "scissors"] + * print(words); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textFont('Courier New'); + * textSize(16); + * + * // Iterate over the words array. + * for (let i = 0; i < words.length; i += 1) { + * + * // Calculate the y-coordinate. + * let y = (i + 1) * 25; + * + * // Display the word. + * text(words[i], 50, y); + * } + * + * describe( + * 'The words "rock", "paper", and "scissors" written on separate lines. The text is black on a gray background.' + * ); + * } * *
*/ @@ -102160,27 +117365,139 @@ return str.split(delim); }; /** - * The splitTokens() function splits a String at one or many character - * delimiters or "tokens." The delim parameter specifies the character or - * characters to be used as a boundary. + * Splits a `String` into pieces and returns an array containing the pieces. + * + * `splitTokens()` is an enhanced version of + * split(). It can split a string when any characters + * from a list are detected. * - * If no delim characters are specified, any whitespace character is used to - * split. Whitespace characters include tab (\t), line feed (\n), carriage - * return (\r), form feed (\f), and space. + * The first parameter, `value`, is the string to split. + * + * The second parameter, `delim`, is optional. It sets the character(s) that + * should be used to split the string. `delim` can be a single string, as in + * `splitTokens('rock...paper...scissors...shoot', '...')`, or an array of + * strings, as in + * `splitTokens('rock;paper,scissors...shoot, [';', ',', '...'])`. By default, + * if no `delim` characters are specified, then any whitespace character is + * used to split. Whitespace characters include tab (`\t`), line feed (`\n`), + * carriage return (`\r`), form feed (`\f`), and space. * * @method splitTokens - * @param {String} value the String to be split - * @param {String} [delim] list of individual Strings that will be used as - * separators - * @return {String[]} Array of Strings + * @param {String} value string to split. + * @param {String} [delim] character(s) to use for splitting the string. + * @return {String[]} separated strings. + * * @example - *
+ *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a string variable. + * let string = 'rock paper scissors shoot'; + * + * // Split the string at each space. + * let words = splitTokens(string); + * + * // Print the array to the console. + * print(words); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textFont('Courier New'); + * textSize(12); + * + * // Iterate over the words array. + * for (let i = 0; i < words.length; i += 1) { + * + * // Calculate the y-coordinate. + * let y = (i + 1) * 20; + * + * // Display the word. + * text(words[i], 50, y); + * } + * + * describe( + * 'The words "rock", "paper", "scissors", and "shoot" written on separate lines. The text is black on a gray background.' + * ); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a string variable. + * let string = 'rock...paper...scissors...shoot'; + * + * // Split the string at each ... + * let words = splitTokens(string, '...'); + * + * // Print the array to the console. + * print(words); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textFont('Courier New'); + * textSize(12); + * + * // Iterate over the words array. + * for (let i = 0; i < words.length; i += 1) { + * + * // Calculate the y-coordinate. + * let y = (i + 1) * 20; + * + * // Display the word. + * text(words[i], 50, y); + * } + * + * describe( + * 'The words "rock", "paper", "scissors", and "shoot" written on separate lines. The text is black on a gray background.' + * ); + * } + * + *
+ * + *
* * function setup() { - * let myStr = 'Mango, Banana, Lime'; - * let myStrArr = splitTokens(myStr, ','); + * createCanvas(100, 100); * - * print(myStrArr); // prints : ["Mango"," Banana"," Lime"] + * background(200); + * + * // Create a string variable. + * let string = 'rock;paper,scissors...shoot'; + * + * // Split the string at each semicolon, comma, or ... + * let words = splitTokens(string, [';', ',', '...']); + * + * // Print the array to the console. + * print(words); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textFont('Courier New'); + * textSize(12); + * + * // Iterate over the words array. + * for (let i = 0; i < words.length; i += 1) { + * + * // Calculate the y-coordinate. + * let y = (i + 1) * 20; + * + * // Display the word. + * text(words[i], 50, y); + * } + * + * describe( + * 'The words "rock", "paper", "scissors", and "shoot" written on separate lines. The text is black on a gray background.' + * ); * } * *
@@ -102214,27 +117531,77 @@ }); }; /** - * Removes whitespace characters from the beginning and end of a String. In - * addition to standard whitespace characters such as space, carriage return, - * and tab, this function also removes the Unicode "nbsp" character. + * Removes whitespace from the start and end of a `String` without changing the middle. + * + * `trim()` trims + * whitespace characters + * such as spaces, carriage returns, tabs, Unicode "nbsp" character. + * + * The parameter, `str`, is the string to trim. If a single string is passed, + * as in `trim(' pad ')`, a single string is returned. If an array of + * strings is passed, as in `trim([' pad ', '\n space \n'])`, an array of + * strings is returned. * * @method trim - * @param {String} str a String to be trimmed - * @return {String} a trimmed String + * @param {String} str string to trim. + * @return {String} trimmed string. * * @example *
* - * let string = trim(' No new lines\n '); - * text(string + ' here', 2, 50); - * describe('“No new lines here” displayed center canvas'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create a string variable. + * let string = ' p5*js '; + * + * // Trim the whitespace. + * let trimmed = trim(string); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textSize(16); + * + * // Display the text. + * text(`Hello, ${trimmed}!`, 50, 50); + * + * describe('The text "Hello, p5*js!" written in black on a gray background.'); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Create an array of strings. + * let strings = [' wide ', '\n open ', '\n spaces ']; + * + * // Trim the whitespace. + * let trimmed = trim(strings); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textFont('Courier New'); + * textSize(10); + * + * // Display the text. + * text(`${trimmed[0]} ${trimmed[1]} ${trimmed[2]}`, 50, 50); + * + * describe('The text "wide open spaces" written in black on a gray background.'); + * } * *
*/ /** * @method trim - * @param {Array} strs an Array of Strings to be trimmed - * @return {String[]} an Array of trimmed Strings + * @param {String[]} strs strings to trim. + * @return {String[]} trimmed strings. */ _main.default.prototype.trim = function (str) { _main.default._validateParameters('trim', arguments); @@ -102248,34 +117615,34 @@ exports.default = _default; }, { - '../core/friendly_errors/fes_core': 289, - '../core/friendly_errors/file_errors': 290, - '../core/friendly_errors/validate_params': 293, - '../core/main': 298, - 'core-js/modules/es.array.filter': 173, - 'core-js/modules/es.array.index-of': 178, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.join': 180, - 'core-js/modules/es.array.map': 182, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.number.to-fixed': 193, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.regexp.constructor': 204, - 'core-js/modules/es.regexp.exec': 205, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.string.match': 211, - 'core-js/modules/es.string.pad-start': 212, - 'core-js/modules/es.string.replace': 214, - 'core-js/modules/es.string.split': 216, - 'core-js/modules/es.string.trim': 219, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/friendly_errors/fes_core': 297, + '../core/friendly_errors/file_errors': 298, + '../core/friendly_errors/validate_params': 301, + '../core/main': 306, + 'core-js/modules/es.array.filter': 175, + 'core-js/modules/es.array.index-of': 182, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.join': 184, + 'core-js/modules/es.array.map': 186, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.number.to-fixed': 200, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.regexp.constructor': 212, + 'core-js/modules/es.regexp.exec': 213, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.string.match': 219, + 'core-js/modules/es.string.pad-start': 220, + 'core-js/modules/es.string.replace': 222, + 'core-js/modules/es.string.split': 224, + 'core-js/modules/es.string.trim': 227, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 340: [ + 348: [ function (_dereq_, module, exports) { 'use strict'; Object.defineProperty(exports, '__esModule', { @@ -102295,17 +117662,32 @@ * @requires core */ /** - * p5.js communicates with the clock on your computer. The day() function - * returns the current day as a value from 1 - 31. + * Returns the current day as a number from 1–31. * * @method day - * @return {Integer} the current day + * @return {Integer} current day between 1 and 31. + * * @example *
* - * let d = day(); - * text('Current day: \n' + d, 5, 50); - * describe('Current day is displayed'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Get the current day. + * let d = day(); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textSize(12); + * textFont('Courier New'); + * + * // Display the day. + * text(`Current day: ${d}`, 20, 50, 60); + * + * describe(`The text 'Current day: ${d}' written in black on a gray background.`); + * } * *
*/ @@ -102314,17 +117696,32 @@ return new Date().getDate(); }; /** - * p5.js communicates with the clock on your computer. The hour() function - * returns the current hour as a value from 0 - 23. + * Returns the current hour as a number from 0–23. * * @method hour - * @return {Integer} the current hour + * @return {Integer} current hour between 0 and 23. + * * @example *
* - * let h = hour(); - * text('Current hour:\n' + h, 5, 50); - * describe('Current hour is displayed'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Get the current hour. + * let h = hour(); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textSize(12); + * textFont('Courier New'); + * + * // Display the hour. + * text(`Current hour: ${h}`, 20, 50, 60); + * + * describe(`The text 'Current hour: ${h}' written in black on a gray background.`); + * } * *
*/ @@ -102332,17 +117729,32 @@ return new Date().getHours(); }; /** - * p5.js communicates with the clock on your computer. The minute() function - * returns the current minute as a value from 0 - 59. + * Returns the current minute as a number from 0–59. * * @method minute - * @return {Integer} the current minute + * @return {Integer} current minute between 0 and 59. + * * @example *
* - * let m = minute(); - * text('Current minute: \n' + m, 5, 50); - * describe('Current minute is displayed'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Get the current minute. + * let m = minute(); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textSize(12); + * textFont('Courier New'); + * + * // Display the minute. + * text(`Current minute: ${m}`, 10, 50, 80); + * + * describe(`The text 'Current minute: ${m}' written in black on a gray background.`); + * } * *
*/ @@ -102350,60 +117762,195 @@ return new Date().getMinutes(); }; /** - * Returns the number of milliseconds (thousandths of a second) since - * starting the sketch (when `setup()` is called). This information is often - * used for timing events and animation sequences. + * Returns the number of milliseconds since a sketch started running. + * + * `millis()` keeps track of how long a sketch has been running in + * milliseconds (thousandths of a second). This information is often + * helpful for timing events and animations. + * + * If a sketch has a + * setup() function, then `millis()` begins tracking + * time before the code in setup() runs. If a + * sketch includes a preload() function, then + * `millis()` begins tracking time as soon as the code in + * preload() starts running. * * @method millis - * @return {Number} the number of milliseconds since starting the sketch + * @return {Number} number of milliseconds since starting the sketch. + * * @example *
* - * let millisecond = millis(); - * text('Milliseconds \nrunning: \n' + millisecond, 5, 40); - * describe('number of milliseconds since sketch has started displayed'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Get the number of milliseconds the sketch has run. + * let ms = millis(); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textSize(10); + * textFont('Courier New'); + * + * // Display how long it took setup() to be called. + * text(`Startup time: ${round(ms, 2)} ms`, 5, 50, 90); + * + * describe( + * `The text 'Startup time: ${round(ms, 2)} ms' written in black on a gray background.` + * ); + * } * *
- */ - _main.default.prototype.millis = function () { - if (this._millisStart === - 1) { - // Sketch has not started - return 0; - } else { - return window.performance.now() - this._millisStart; - } - }; - /** - * p5.js communicates with the clock on your computer. The month() function - * returns the current month as a value from 1 - 12. * - * @method month - * @return {Integer} the current month - * @example *
* - * let m = month(); - * text('Current month: \n' + m, 5, 50); - * describe('Current month is displayed'); + * function setup() { + * createCanvas(100, 100); + * + * describe('The text "Running time: S sec" written in black on a gray background. The number S increases as the sketch runs.'); + * } + * + * function draw() { + * background(200); + * + * // Get the number of seconds the sketch has run. + * let s = millis() / 1000; + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textSize(10); + * textFont('Courier New'); + * + * // Display how long the sketch has run. + * text(`Running time: ${nf(s, 1, 1)} sec`, 5, 50, 90); + * } * *
- */ - _main.default.prototype.month = function () { - //January is 0! - return new Date().getMonth() + 1; - }; + * + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * describe('A white circle oscillates left and right on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Get the number of seconds the sketch has run. + * let s = millis() / 1000; + * + * // Calculate an x-coordinate. + * let x = 30 * sin(s) + 50; + * + * // Draw the circle. + * circle(x, 50, 30); + * } + * + *
+ * + *
+ * + * // Load the GeoJSON. + * function preload() { + * loadJSON('https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson'); + * } + * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Get the number of milliseconds the sketch has run. + * let ms = millis(); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textFont('Courier New'); + * textSize(11); + * + * // Display how long it took to load the data. + * text(`It took ${round(ms, 2)} ms to load the data`, 5, 50, 100); + * + * describe( + * `The text "It took ${round(ms, 2)} ms to load the data" written in black on a gray background.` + * ); + * } + * + *
+ */ + _main.default.prototype.millis = function () { + if (this._millisStart === - 1) { + // Sketch has not started + return 0; + } else { + return window.performance.now() - this._millisStart; + } + }; + /** + * Returns the current month as a number from 1–12. + * + * @method month + * @return {Integer} current month between 1 and 12. + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Get the current month. + * let m = month(); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textSize(12); + * textFont('Courier New'); + * + * // Display the month. + * text(`Current month: ${m}`, 10, 50, 80); + * + * describe(`The text 'Current month: ${m}' written in black on a gray background.`); + * } + * + *
+ */ + _main.default.prototype.month = function () { + //January is 0! + return new Date().getMonth() + 1; + }; /** - * p5.js communicates with the clock on your computer. The second() function - * returns the current second as a value from 0 - 59. + * Returns the current second as a number from 0–59. * * @method second - * @return {Integer} the current second + * @return {Integer} current second between 0 and 59. + * * @example *
* - * let s = second(); - * text('Current second: \n' + s, 5, 50); - * describe('Current second is displayed'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Get the current second. + * let s = second(); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textSize(12); + * textFont('Courier New'); + * + * // Display the second. + * text(`Current second: ${s}`, 10, 50, 80); + * + * describe(`The text 'Current second: ${s}' written in black on a gray background.`); + * } * *
*/ @@ -102411,17 +117958,32 @@ return new Date().getSeconds(); }; /** - * p5.js communicates with the clock on your computer. The year() function - * returns the current year as an integer (2014, 2015, 2016, etc). + * Returns the current year as a number such as 1999. * * @method year - * @return {Integer} the current year + * @return {Integer} current year. + * * @example *
* - * let y = year(); - * text('Current year: \n' + y, 5, 50); - * describe('Current year is displayed'); + * function setup() { + * createCanvas(100, 100); + * + * background(200); + * + * // Get the current year. + * let y = year(); + * + * // Style the text. + * textAlign(LEFT, CENTER); + * textSize(12); + * textFont('Courier New'); + * + * // Display the year. + * text(`Current year: ${y}`, 10, 50, 80); + * + * describe(`The text 'Current year: ${y}' written in black on a gray background.`); + * } * *
*/ @@ -102432,10 +117994,10 @@ exports.default = _default; }, { - '../core/main': 298 + '../core/main': 306 } ], - 341: [ + 349: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -102551,1073 +118113,2327 @@ * @requires p5.Geometry */ /** - * Starts creating a new p5.Geometry. Subsequent shapes drawn will be added - * to the geometry and then returned when - * endGeometry() is called. One can also use - * buildGeometry() to pass a function that - * draws shapes. + * Begins adding shapes to a new + * p5.Geometry object. + * + * The `beginGeometry()` and endGeometry() + * functions help with creating complex 3D shapes from simpler ones such as + * sphere(). `beginGeometry()` begins adding shapes + * to a custom p5.Geometry object and + * endGeometry() stops adding them. + * + * `beginGeometry()` and endGeometry() can help + * to make sketches more performant. For example, if a complex 3D shape + * doesn’t change while a sketch runs, then it can be created with + * `beginGeometry()` and endGeometry(). + * Creating a p5.Geometry object once and then + * drawing it will run faster than repeatedly drawing the individual pieces. + * + * See buildGeometry() for another way to + * build 3D shapes. * - * If you need to draw complex shapes every frame which don't change over time, - * combining them upfront with `beginGeometry()` and `endGeometry()` and then - * drawing that will run faster than repeatedly drawing the individual pieces. + * Note: `beginGeometry()` can only be used in WebGL mode. * * @method beginGeometry * * @example *
* - * let shapes; + * // Click and drag the mouse to view the scene from different angles. + * + * let shape; * * function setup() { * createCanvas(100, 100, WEBGL); - * makeShapes(); - * } * - * function makeShapes() { + * // Start building the p5.Geometry object. * beginGeometry(); - * scale(0.18); * - * push(); - * translate(100, -50); - * scale(0.5); - * rotateX(PI/4); + * // Add a cone. * cone(); - * pop(); - * cone(); - * - * beginShape(); - * vertex(-20, -50); - * quadraticVertex( - * -40, -70, - * 0, -60 - * ); - * endShape(); - * - * beginShape(TRIANGLE_STRIP); - * for (let y = 20; y <= 60; y += 10) { - * for (let x of [20, 60]) { - * vertex(x, y); - * } - * } - * endShape(); * - * beginShape(); - * vertex(-100, -120); - * vertex(-120, -110); - * vertex(-105, -100); - * endShape(); + * // Stop building the p5.Geometry object. + * shape = endGeometry(); * - * shapes = endGeometry(); + * describe('A white cone drawn on a gray background.'); * } * * function draw() { - * background(255); - * lights(); - * orbitControl(); - * model(shapes); - * } - * - *
- * - * @alt - * A series of different flat, curved, and 3D shapes floating in space. - */ - - _main.default.prototype.beginGeometry = function () { - return this._renderer.beginGeometry(); - }; - /** - * Finishes creating a new p5.Geometry that was - * started using beginGeometry(). One can also - * use buildGeometry() to pass a function that - * draws shapes. + * background(50); * - * @method endGeometry - * @returns {p5.Geometry} The model that was built. - */ - _main.default.prototype.endGeometry = function () { - return this._renderer.endGeometry(); - }; - /** - * Creates a new p5.Geometry that contains all - * the shapes drawn in a provided callback function. The returned combined shape - * can then be drawn all at once using model(). + * // Enable orbiting with the mouse. + * orbitControl(); * - * If you need to draw complex shapes every frame which don't change over time, - * combining them with `buildGeometry()` once and then drawing that will run - * faster than repeatedly drawing the individual pieces. + * // Turn on the lights. + * lights(); * - * One can also draw shapes directly between - * beginGeometry() and - * endGeometry() instead of using a callback - * function. + * // Style the p5.Geometry object. + * noStroke(); * - * @method buildGeometry - * @param {Function} callback A function that draws shapes. - * @returns {p5.Geometry} The model that was built from the callback function. + * // Draw the p5.Geometry object. + * model(shape); + * } + *
+ *
* - * @example *
* - * let particles; - * let button; + * // Click and drag the mouse to view the scene from different angles. + * + * let shape; * * function setup() { * createCanvas(100, 100, WEBGL); - * button = createButton('New'); - * button.mousePressed(makeParticles); - * makeParticles(); - * } - * - * function makeParticles() { - * if (particles) freeGeometry(particles); - * - * particles = buildGeometry(() => { - * for (let i = 0; i < 60; i++) { - * push(); - * translate( - * randomGaussian(0, 20), - * randomGaussian(0, 20), - * randomGaussian(0, 20) - * ); - * sphere(5); - * pop(); - * } - * }); + * + * // Create the p5.Geometry object. + * createArrow(); + * + * describe('A white arrow drawn on a gray background.'); * } * * function draw() { - * background(255); - * noStroke(); - * lights(); + * background(50); + * + * // Enable orbiting with the mouse. * orbitControl(); - * model(particles); + * + * // Turn on the lights. + * lights(); + * + * // Style the p5.Geometry object. + * noStroke(); + * + * // Draw the p5.Geometry object. + * model(shape); * } - * - *
* - * @alt - * A cluster of spheres. - */ - _main.default.prototype.buildGeometry = function (callback) { - return this._renderer.buildGeometry(callback); - }; - /** - * Clears the resources of a model to free up browser memory. A model whose - * resources have been cleared can still be drawn, but the first time it is - * drawn again, it might take longer. + * function createArrow() { + * // Start building the p5.Geometry object. + * beginGeometry(); + * + * // Add shapes. + * push(); + * rotateX(PI); + * cone(10); + * translate(0, -10, 0); + * cylinder(3, 20); + * pop(); * - * This method works on models generated with - * buildGeometry() as well as those loaded - * from loadModel(). + * // Stop building the p5.Geometry object. + * shape = endGeometry(); + * } + * + *
* - * @method freeGeometry - * @param {p5.Geometry} geometry The geometry whose resources should be freed - */ - _main.default.prototype.freeGeometry = function (geometry) { - this._renderer._freeBuffers(geometry.gid); - }; - /** - * Draw a plane with given a width and height - * @method plane - * @param {Number} [width] width of the plane - * @param {Number} [height] height of the plane - * @param {Integer} [detailX] Optional number of triangle - * subdivisions in x-dimension - * @param {Integer} [detailY] Optional number of triangle - * subdivisions in y-dimension - * @chainable - * @example *
* - * // draw a plane - * // with width 50 and height 50 + * // Click and drag the mouse to view the scene from different angles. + * + * let blueArrow; + * let redArrow; + * * function setup() { * createCanvas(100, 100, WEBGL); - * describe('a white plane with black wireframe lines'); + * + * // Create the arrows. + * redArrow = createArrow('red'); + * blueArrow = createArrow('blue'); + * + * describe('A red arrow and a blue arrow drawn on a gray background. The blue arrow rotates slowly.'); * } * * function draw() { * background(200); - * plane(50, 50); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * lights(); + * + * // Style the arrows. + * noStroke(); + * + * // Draw the red arrow. + * model(redArrow); + * + * // Translate and rotate the coordinate system. + * translate(30, 0, 0); + * rotateZ(frameCount * 0.01); + * + * // Draw the blue arrow. + * model(blueArrow); + * } + * + * function createArrow(fillColor) { + * // Start building the p5.Geometry object. + * beginGeometry(); + * + * fill(fillColor); + * + * // Add shapes to the p5.Geometry object. + * push(); + * rotateX(PI); + * cone(10); + * translate(0, -10, 0); + * cylinder(3, 20); + * pop(); + * + * // Stop building the p5.Geometry object. + * let shape = endGeometry(); + * + * return shape; * } * *
* - * @alt - * Nothing displayed on canvas - * Rotating interior view of a box with sides that change color. - * 3d red and green gradient. - * Rotating interior view of a cylinder with sides that change color. - * Rotating view of a cylinder with sides that change color. - * 3d red and green gradient. - * rotating view of a multi-colored cylinder with concave sides. - */ - _main.default.prototype.plane = function (width, height, detailX, detailY) { - this._assert3d('plane'); - _main.default._validateParameters('plane', arguments); - if (typeof width === 'undefined') { - width = 50; - } - if (typeof height === 'undefined') { - height = width; - } - if (typeof detailX === 'undefined') { - detailX = 1; - } - if (typeof detailY === 'undefined') { - detailY = 1; - } - var gId = 'plane|'.concat(detailX, '|').concat(detailY); - if (!this._renderer.geometryInHash(gId)) { - var _plane = function _plane() { - var u, - v, - p; - for (var i = 0; i <= this.detailY; i++) { - v = i / this.detailY; - for (var j = 0; j <= this.detailX; j++) { - u = j / this.detailX; - p = new _main.default.Vector(u - 0.5, v - 0.5, 0); - this.vertices.push(p); - this.uvs.push(u, v); - } - } - }; - var planeGeom = new _main.default.Geometry(detailX, detailY, _plane); - planeGeom.computeFaces().computeNormals(); - if (detailX <= 1 && detailY <= 1) { - planeGeom._makeTriangleEdges()._edgesToVertices(); - } else if (this._renderer._doStroke) { - console.log('Cannot draw stroke on plane objects with more' + ' than 1 detailX or 1 detailY'); - } - this._renderer.createBuffers(gId, planeGeom); - } - this._renderer.drawBuffersScaled(gId, width, height, 1); - return this; - }; - /** - * Draw a box with given width, height and depth - * @method box - * @param {Number} [width] width of the box - * @param {Number} [height] height of the box - * @param {Number} [depth] depth of the box - * @param {Integer} [detailX] Optional number of triangle - * subdivisions in x-dimension - * @param {Integer} [detailY] Optional number of triangle - * subdivisions in y-dimension - * @chainable - * @example *
* - * // draw a spinning box - * // with width, height and depth of 50 + * // Click and drag the mouse to view the scene from different angles. + * + * let button; + * let particles; + * * function setup() { * createCanvas(100, 100, WEBGL); - * describe('a white box rotating in 3D space'); + * + * // Create a button to reset the particle system. + * button = createButton('Reset'); + * + * // Call resetModel() when the user presses the button. + * button.mousePressed(resetModel); + * + * // Add the original set of particles. + * resetModel(); * } * * function draw() { - * background(200); - * rotateX(frameCount * 0.01); - * rotateY(frameCount * 0.01); - * box(50); + * background(50); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * lights(); + * + * // Style the particles. + * noStroke(); + * + * // Draw the particles. + * model(particles); + * } + * + * function resetModel() { + * // If the p5.Geometry object has already been created, + * // free those resources. + * if (particles) { + * freeGeometry(particles); + * } + * + * // Create a new p5.Geometry object with random spheres. + * particles = createParticles(); + * } + * + * function createParticles() { + * // Start building the p5.Geometry object. + * beginGeometry(); + * + * // Add shapes. + * for (let i = 0; i < 60; i += 1) { + * // Calculate random coordinates. + * let x = randomGaussian(0, 20); + * let y = randomGaussian(0, 20); + * let z = randomGaussian(0, 20); + * + * push(); + * // Translate to the particle's coordinates. + * translate(x, y, z); + * // Draw the particle. + * sphere(5); + * pop(); + * } + * + * // Stop building the p5.Geometry object. + * let shape = endGeometry(); + * + * return shape; * } * *
*/ - _main.default.prototype.box = function (width, height, depth, detailX, detailY) { - this._assert3d('box'); - _main.default._validateParameters('box', arguments); - if (typeof width === 'undefined') { - width = 50; - } - if (typeof height === 'undefined') { - height = width; - } - if (typeof depth === 'undefined') { - depth = height; - } - var perPixelLighting = this._renderer.attributes && this._renderer.attributes.perPixelLighting; - if (typeof detailX === 'undefined') { - detailX = perPixelLighting ? 1 : 4; - } - if (typeof detailY === 'undefined') { - detailY = perPixelLighting ? 1 : 4; - } - var gId = 'box|'.concat(detailX, '|').concat(detailY); - if (!this._renderer.geometryInHash(gId)) { - var _box = function _box() { - var _this = this; - var cubeIndices = [ - [0, - 4, - 2, - 6], - // -1, 0, 0],// -x - [ - 1, - 3, - 5, - 7 - ], - // +1, 0, 0],// +x - [ - 0, - 1, - 4, - 5 - ], - // 0, -1, 0],// -y - [ - 2, - 6, - 3, - 7 - ], - // 0, +1, 0],// +y - [ - 0, - 2, - 1, - 3 - ], - // 0, 0, -1],// -z - [ - 4, - 5, - 6, - 7 - ] // 0, 0, +1] // +z - ]; - //using custom edges - //to avoid diagonal stroke lines across face of box - this.edges = [ - [0, - 1], - [ - 1, - 3 - ], - [ - 3, - 2 - ], - [ - 6, - 7 - ], - [ - 8, - 9 - ], - [ - 9, - 11 - ], - [ - 14, - 15 - ], - [ - 16, - 17 - ], - [ - 17, - 19 - ], - [ - 18, - 19 - ], - [ - 20, - 21 - ], - [ - 22, - 23 - ] - ]; - cubeIndices.forEach(function (cubeIndex, i) { - var v = i * 4; - for (var j = 0; j < 4; j++) { - var d = cubeIndex[j]; - //inspired by lightgl: - //https://github.com/evanw/lightgl.js - //octants:https://en.wikipedia.org/wiki/Octant_(solid_geometry) - var octant = new _main.default.Vector(((d & 1) * 2 - 1) / 2, ((d & 2) - 1) / 2, ((d & 4) / 2 - 1) / 2); - _this.vertices.push(octant); - _this.uvs.push(j & 1, (j & 2) / 2); - } - _this.faces.push([v, - v + 1, - v + 2]); - _this.faces.push([v + 2, - v + 1, - v + 3]); - }); - }; - var boxGeom = new _main.default.Geometry(detailX, detailY, _box); - boxGeom.computeNormals(); - if (detailX <= 4 && detailY <= 4) { - boxGeom._edgesToVertices(); - } else if (this._renderer._doStroke) { - console.log('Cannot draw stroke on box objects with more' + ' than 4 detailX or 4 detailY'); - } //initialize our geometry buffer with - //the key val pair: - //geometry Id, Geom object - this._renderer.createBuffers(gId, boxGeom); - } - this._renderer.drawBuffersScaled(gId, width, height, depth); - return this; + _main.default.prototype.beginGeometry = function () { + return this._renderer.beginGeometry(); }; /** - * Draw a sphere with given radius. + * Stops adding shapes to a new + * p5.Geometry object and returns the object. * - * DetailX and detailY determines the number of subdivisions in the x-dimension - * and the y-dimension of a sphere. More subdivisions make the sphere seem - * smoother. The recommended maximum values are both 24. Using a value greater - * than 24 may cause a warning or slow down the browser. - * @method sphere - * @param {Number} [radius] radius of circle - * @param {Integer} [detailX] optional number of subdivisions in x-dimension - * @param {Integer} [detailY] optional number of subdivisions in y-dimension + * The `beginGeometry()` and endGeometry() + * functions help with creating complex 3D shapes from simpler ones such as + * sphere(). `beginGeometry()` begins adding shapes + * to a custom p5.Geometry object and + * endGeometry() stops adding them. + * + * `beginGeometry()` and endGeometry() can help + * to make sketches more performant. For example, if a complex 3D shape + * doesn’t change while a sketch runs, then it can be created with + * `beginGeometry()` and endGeometry(). + * Creating a p5.Geometry object once and then + * drawing it will run faster than repeatedly drawing the individual pieces. + * + * See buildGeometry() for another way to + * build 3D shapes. + * + * Note: `endGeometry()` can only be used in WebGL mode. + * + * @method endGeometry + * @returns {p5.Geometry} new 3D shape. * - * @chainable * @example *
* - * // draw a sphere with radius 40 + * // Click and drag the mouse to view the scene from different angles. + * + * let shape; + * * function setup() { * createCanvas(100, 100, WEBGL); - * describe('a white sphere with black wireframe lines'); + * + * // Start building the p5.Geometry object. + * beginGeometry(); + * + * // Add a cone. + * cone(); + * + * // Stop building the p5.Geometry object. + * shape = endGeometry(); + * + * describe('A white cone drawn on a gray background.'); * } * * function draw() { - * background(205, 102, 94); - * sphere(40); + * background(50); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * lights(); + * + * // Style the p5.Geometry object. + * noStroke(); + * + * // Draw the p5.Geometry object. + * model(shape); * } * *
* - * @example *
* - * let detailX; - * // slide to see how detailX works + * // Click and drag the mouse to view the scene from different angles. + * + * let shape; + * * function setup() { * createCanvas(100, 100, WEBGL); - * detailX = createSlider(3, 24, 3); - * detailX.position(10, height + 5); - * detailX.style('width', '80px'); - * describe( - * 'a white sphere with low detail on the x-axis, including a slider to adjust detailX' - * ); + * + * // Create the p5.Geometry object. + * createArrow(); + * + * describe('A white arrow drawn on a gray background.'); * } * * function draw() { - * background(205, 105, 94); - * rotateY(millis() / 1000); - * sphere(40, detailX.value(), 16); + * background(50); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * lights(); + * + * // Style the p5.Geometry object. + * noStroke(); + * + * // Draw the p5.Geometry object. + * model(shape); + * } + * + * function createArrow() { + * // Start building the p5.Geometry object. + * beginGeometry(); + * + * // Add shapes. + * push(); + * rotateX(PI); + * cone(10); + * translate(0, -10, 0); + * cylinder(3, 20); + * pop(); + * + * // Stop building the p5.Geometry object. + * shape = endGeometry(); * } * *
* - * @example *
* - * let detailY; - * // slide to see how detailY works + * // Click and drag the mouse to view the scene from different angles. + * + * let blueArrow; + * let redArrow; + * * function setup() { * createCanvas(100, 100, WEBGL); - * detailY = createSlider(3, 16, 3); - * detailY.position(10, height + 5); - * detailY.style('width', '80px'); - * describe( - * 'a white sphere with low detail on the y-axis, including a slider to adjust detailY' - * ); + * + * // Create the arrows. + * redArrow = createArrow('red'); + * blueArrow = createArrow('blue'); + * + * describe('A red arrow and a blue arrow drawn on a gray background. The blue arrow rotates slowly.'); * } * * function draw() { - * background(205, 105, 94); - * rotateY(millis() / 1000); - * sphere(40, 16, detailY.value()); + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * lights(); + * + * // Style the arrows. + * noStroke(); + * + * // Draw the red arrow. + * model(redArrow); + * + * // Translate and rotate the coordinate system. + * translate(30, 0, 0); + * rotateZ(frameCount * 0.01); + * + * // Draw the blue arrow. + * model(blueArrow); * } - * - *
- */ - _main.default.prototype.sphere = function (radius, detailX, detailY) { - this._assert3d('sphere'); - _main.default._validateParameters('sphere', arguments); - if (typeof radius === 'undefined') { - radius = 50; - } - if (typeof detailX === 'undefined') { - detailX = 24; - } - if (typeof detailY === 'undefined') { - detailY = 16; - } - this.ellipsoid(radius, radius, radius, detailX, detailY); - return this; - }; - /** - * @private - * Helper function for creating both cones and cylinders - * Will only generate well-defined geometry when bottomRadius, height > 0 - * and topRadius >= 0 - * If topRadius == 0, topCap should be false - */ - var _truncatedCone = function _truncatedCone(bottomRadius, topRadius, height, detailX, detailY, bottomCap, topCap) { - bottomRadius = bottomRadius <= 0 ? 1 : bottomRadius; - topRadius = topRadius < 0 ? 0 : topRadius; - height = height <= 0 ? bottomRadius : height; - detailX = detailX < 3 ? 3 : detailX; - detailY = detailY < 1 ? 1 : detailY; - bottomCap = bottomCap === undefined ? true : bottomCap; - topCap = topCap === undefined ? topRadius !== 0 : topCap; - var start = bottomCap ? - 2 : 0; - var end = detailY + (topCap ? 2 : 0); - //ensure constant slant for interior vertex normals - var slant = Math.atan2(bottomRadius - topRadius, height); - var sinSlant = Math.sin(slant); - var cosSlant = Math.cos(slant); - var yy, - ii, - jj; - for (yy = start; yy <= end; ++yy) { - var v = yy / detailY; - var y = height * v; - var ringRadius = void 0; - if (yy < 0) { - //for the bottomCap edge - y = 0; - v = 0; - ringRadius = bottomRadius; - } else if (yy > detailY) { - //for the topCap edge - y = height; - v = 1; - ringRadius = topRadius; - } else { - //for the middle - ringRadius = bottomRadius + (topRadius - bottomRadius) * v; - } - if (yy === - 2 || yy === detailY + 2) { - //center of bottom or top caps - ringRadius = 0; - } - y -= height / 2; //shift coordiate origin to the center of object - for (ii = 0; ii < detailX; ++ii) { - var u = ii / (detailX - 1); - var ur = 2 * Math.PI * u; - var sur = Math.sin(ur); - var cur = Math.cos(ur); - //VERTICES - this.vertices.push(new _main.default.Vector(sur * ringRadius, y, cur * ringRadius)); - //VERTEX NORMALS - var vertexNormal = void 0; - if (yy < 0) { - vertexNormal = new _main.default.Vector(0, - 1, 0); - } else if (yy > detailY && topRadius) { - vertexNormal = new _main.default.Vector(0, 1, 0); - } else { - vertexNormal = new _main.default.Vector(sur * cosSlant, sinSlant, cur * cosSlant); - } - this.vertexNormals.push(vertexNormal); - //UVs - this.uvs.push(u, v); - } - } - var startIndex = 0; - if (bottomCap) { - for (jj = 0; jj < detailX; ++jj) { - var nextjj = (jj + 1) % detailX; - this.faces.push([startIndex + jj, - startIndex + detailX + nextjj, - startIndex + detailX + jj]); - } - startIndex += detailX * 2; - } - for (yy = 0; yy < detailY; ++yy) { - for (ii = 0; ii < detailX; ++ii) { - var nextii = (ii + 1) % detailX; - this.faces.push([startIndex + ii, - startIndex + nextii, - startIndex + detailX + nextii]); - this.faces.push([startIndex + ii, - startIndex + detailX + nextii, - startIndex + detailX + ii]); - } - startIndex += detailX; - } - if (topCap) { - startIndex += detailX; - for (ii = 0; ii < detailX; ++ii) { - this.faces.push([startIndex + ii, - startIndex + (ii + 1) % detailX, - startIndex + detailX]); - } - } - }; - /** - * Draw a cylinder with given radius and height * - * DetailX and detailY determines the number of subdivisions in the x-dimension - * and the y-dimension of a cylinder. More subdivisions make the cylinder seem smoother. - * The recommended maximum value for detailX is 24. Using a value greater than 24 - * may cause a warning or slow down the browser. + * function createArrow(fillColor) { + * // Start building the p5.Geometry object. + * beginGeometry(); + * + * fill(fillColor); + * + * // Add shapes to the p5.Geometry object. + * push(); + * rotateX(PI); + * cone(10); + * translate(0, -10, 0); + * cylinder(3, 20); + * pop(); + * + * // Stop building the p5.Geometry object. + * let shape = endGeometry(); + * + * return shape; + * } + * + *
* - * @method cylinder - * @param {Number} [radius] radius of the surface - * @param {Number} [height] height of the cylinder - * @param {Integer} [detailX] number of subdivisions in x-dimension; - * default is 24 - * @param {Integer} [detailY] number of subdivisions in y-dimension; - * default is 1 - * @param {Boolean} [bottomCap] whether to draw the bottom of the cylinder - * @param {Boolean} [topCap] whether to draw the top of the cylinder - * @chainable - * @example *
* - * // draw a spinning cylinder - * // with radius 20 and height 50 + * // Click and drag the mouse to view the scene from different angles. + * + * let button; + * let particles; + * * function setup() { * createCanvas(100, 100, WEBGL); - * describe('a rotating white cylinder'); + * + * // Create a button to reset the particle system. + * button = createButton('Reset'); + * + * // Call resetModel() when the user presses the button. + * button.mousePressed(resetModel); + * + * // Add the original set of particles. + * resetModel(); * } * * function draw() { - * background(205, 105, 94); - * rotateX(frameCount * 0.01); - * rotateZ(frameCount * 0.01); - * cylinder(20, 50); + * background(50); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * lights(); + * + * // Style the particles. + * noStroke(); + * + * // Draw the particles. + * model(particles); + * } + * + * function resetModel() { + * // If the p5.Geometry object has already been created, + * // free those resources. + * if (particles) { + * freeGeometry(particles); + * } + * + * // Create a new p5.Geometry object with random spheres. + * particles = createParticles(); + * } + * + * function createParticles() { + * // Start building the p5.Geometry object. + * beginGeometry(); + * + * // Add shapes. + * for (let i = 0; i < 60; i += 1) { + * // Calculate random coordinates. + * let x = randomGaussian(0, 20); + * let y = randomGaussian(0, 20); + * let z = randomGaussian(0, 20); + * + * push(); + * // Translate to the particle's coordinates. + * translate(x, y, z); + * // Draw the particle. + * sphere(5); + * pop(); + * } + * + * // Stop building the p5.Geometry object. + * let shape = endGeometry(); + * + * return shape; * } * *
+ */ + _main.default.prototype.endGeometry = function () { + return this._renderer.endGeometry(); + }; + /** + * Creates a custom p5.Geometry object from + * simpler 3D shapes. + * + * `buildGeometry()` helps with creating complex 3D shapes from simpler ones + * such as sphere(). It can help to make sketches + * more performant. For example, if a complex 3D shape doesn’t change while a + * sketch runs, then it can be created with `buildGeometry()`. Creating a + * p5.Geometry object once and then drawing it + * will run faster than repeatedly drawing the individual pieces. + * + * The parameter, `callback`, is a function with the drawing instructions for + * the new p5.Geometry object. It will be called + * once to create the new 3D shape. + * + * See beginGeometry() and + * endGeometry() for another way to build 3D + * shapes. + * + * Note: `buildGeometry()` can only be used in WebGL mode. + * + * @method buildGeometry + * @param {Function} callback function that draws the shape. + * @returns {p5.Geometry} new 3D shape. * * @example *
* - * // slide to see how detailX works - * let detailX; + * // Click and drag the mouse to view the scene from different angles. + * + * let shape; + * * function setup() { * createCanvas(100, 100, WEBGL); - * detailX = createSlider(3, 24, 3); - * detailX.position(10, height + 5); - * detailX.style('width', '80px'); - * describe( - * 'a rotating white cylinder with limited X detail, with a slider that adjusts detailX' - * ); + * + * // Create the p5.Geometry object. + * shape = buildGeometry(createShape); + * + * describe('A white cone drawn on a gray background.'); * } * * function draw() { - * background(205, 105, 94); - * rotateY(millis() / 1000); - * cylinder(20, 75, detailX.value(), 1); + * background(50); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * lights(); + * + * // Style the p5.Geometry object. + * noStroke(); + * + * // Draw the p5.Geometry object. + * model(shape); + * } + * + * // Create p5.Geometry object from a single cone. + * function createShape() { + * cone(); * } * *
* - * @example *
* - * // slide to see how detailY works - * let detailY; + * // Click and drag the mouse to view the scene from different angles. + * + * let shape; + * * function setup() { * createCanvas(100, 100, WEBGL); - * detailY = createSlider(1, 16, 1); - * detailY.position(10, height + 5); - * detailY.style('width', '80px'); - * describe( - * 'a rotating white cylinder with limited Y detail, with a slider that adjusts detailY' - * ); + * + * // Create the arrow. + * shape = buildGeometry(createArrow); + * + * describe('A white arrow drawn on a gray background.'); * } * * function draw() { - * background(205, 105, 94); - * rotateY(millis() / 1000); - * cylinder(20, 75, 16, detailY.value()); + * background(50); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * lights(); + * + * // Style the arrow. + * noStroke(); + * + * // Draw the arrow. + * model(shape); + * } + * + * function createArrow() { + * // Add shapes to the p5.Geometry object. + * push(); + * rotateX(PI); + * cone(10); + * translate(0, -10, 0); + * cylinder(3, 20); + * pop(); * } * *
- */ - _main.default.prototype.cylinder = function (radius, height, detailX, detailY, bottomCap, topCap) { - this._assert3d('cylinder'); - _main.default._validateParameters('cylinder', arguments); - if (typeof radius === 'undefined') { - radius = 50; - } - if (typeof height === 'undefined') { - height = radius; - } - if (typeof detailX === 'undefined') { - detailX = 24; - } - if (typeof detailY === 'undefined') { - detailY = 1; - } - if (typeof topCap === 'undefined') { - topCap = true; - } - if (typeof bottomCap === 'undefined') { - bottomCap = true; - } - var gId = 'cylinder|'.concat(detailX, '|').concat(detailY, '|').concat(bottomCap, '|').concat(topCap); - if (!this._renderer.geometryInHash(gId)) { - var cylinderGeom = new _main.default.Geometry(detailX, detailY); - _truncatedCone.call(cylinderGeom, 1, 1, 1, detailX, detailY, bottomCap, topCap); - // normals are computed in call to _truncatedCone - if (detailX <= 24 && detailY <= 16) { - cylinderGeom._makeTriangleEdges()._edgesToVertices(); - } else if (this._renderer._doStroke) { - console.log('Cannot draw stroke on cylinder objects with more' + ' than 24 detailX or 16 detailY'); - } - this._renderer.createBuffers(gId, cylinderGeom); - } - this._renderer.drawBuffersScaled(gId, radius, height, radius); - return this; - }; - /** - * Draw a cone with given radius and height * - * DetailX and detailY determine the number of subdivisions in the x-dimension and - * the y-dimension of a cone. More subdivisions make the cone seem smoother. The - * recommended maximum value for detailX is 24. Using a value greater than 24 - * may cause a warning or slow down the browser. - * @method cone - * @param {Number} [radius] radius of the bottom surface - * @param {Number} [height] height of the cone - * @param {Integer} [detailX] number of segments, - * the more segments the smoother geometry - * default is 24 - * @param {Integer} [detailY] number of segments, - * the more segments the smoother geometry - * default is 1 - * @param {Boolean} [cap] whether to draw the base of the cone - * @chainable - * @example *
* - * // draw a spinning cone - * // with radius 40 and height 70 + * // Click and drag the mouse to view the scene from different angles. + * + * let shape; + * * function setup() { * createCanvas(100, 100, WEBGL); - * describe('a rotating white cone'); + * + * // Create the p5.Geometry object. + * shape = buildGeometry(createArrow); + * + * describe('Two white arrows drawn on a gray background. The arrow on the right rotates slowly.'); * } * * function draw() { - * background(200); - * rotateX(frameCount * 0.01); + * background(50); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * lights(); + * + * // Style the arrows. + * noStroke(); + * + * // Draw the p5.Geometry object. + * model(shape); + * + * // Translate and rotate the coordinate system. + * translate(30, 0, 0); * rotateZ(frameCount * 0.01); - * cone(40, 70); + * + * // Draw the p5.Geometry object again. + * model(shape); + * } + * + * function createArrow() { + * // Add shapes to the p5.Geometry object. + * push(); + * rotateX(PI); + * cone(10); + * translate(0, -10, 0); + * cylinder(3, 20); + * pop(); * } * *
* - * @example *
* - * // slide to see how detailx works - * let detailX; + * // Click and drag the mouse to view the scene from different angles. + * + * let button; + * let particles; + * * function setup() { * createCanvas(100, 100, WEBGL); - * detailX = createSlider(3, 16, 3); - * detailX.position(10, height + 5); - * detailX.style('width', '80px'); - * describe( - * 'a rotating white cone with limited X detail, with a slider that adjusts detailX' - * ); + * + * // Create a button to reset the particle system. + * button = createButton('Reset'); + * + * // Call resetModel() when the user presses the button. + * button.mousePressed(resetModel); + * + * // Add the original set of particles. + * resetModel(); + * + * describe('A set of white spheres on a gray background. The spheres are positioned randomly. Their positions reset when the user presses the Reset button.'); * } * * function draw() { - * background(205, 102, 94); - * rotateY(millis() / 1000); - * cone(30, 65, detailX.value(), 16); + * background(50); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * lights(); + * + * // Style the particles. + * noStroke(); + * + * // Draw the particles. + * model(particles); + * } + * + * function resetModel() { + * // If the p5.Geometry object has already been created, + * // free those resources. + * if (particles) { + * freeGeometry(particles); + * } + * + * // Create a new p5.Geometry object with random spheres. + * particles = buildGeometry(createParticles); + * } + * + * function createParticles() { + * for (let i = 0; i < 60; i += 1) { + * // Calculate random coordinates. + * let x = randomGaussian(0, 20); + * let y = randomGaussian(0, 20); + * let z = randomGaussian(0, 20); + * + * push(); + * // Translate to the particle's coordinates. + * translate(x, y, z); + * // Draw the particle. + * sphere(5); + * pop(); + * } * } * *
+ */ + _main.default.prototype.buildGeometry = function (callback) { + return this._renderer.buildGeometry(callback); + }; + /** + * Clears a p5.Geometry object from the graphics + * processing unit (GPU) memory. + * + * p5.Geometry objects can contain lots of data + * about their vertices, surface normals, colors, and so on. Complex 3D shapes + * can use lots of memory which is a limited resource in many GPUs. Calling + * `freeGeometry()` can improve performance by freeing a + * p5.Geometry object’s resources from GPU memory. + * `freeGeometry()` works with p5.Geometry objects + * created with beginGeometry() and + * endGeometry(), + * buildGeometry(), and + * loadModel(). + * + * The parameter, `geometry`, is the p5.Geometry + * object to be freed. + * + * Note: A p5.Geometry object can still be drawn + * after its resources are cleared from GPU memory. It may take longer to draw + * the first time it’s redrawn. + * + * Note: `freeGeometry()` can only be used in WebGL mode. + * + * @method freeGeometry + * @param {p5.Geometry} geometry 3D shape whose resources should be freed. * * @example *
* - * // slide to see how detailY works - * let detailY; * function setup() { * createCanvas(100, 100, WEBGL); - * detailY = createSlider(3, 16, 3); - * detailY.position(10, height + 5); - * detailY.style('width', '80px'); - * describe( - * 'a rotating white cone with limited Y detail, with a slider that adjusts detailY' - * ); + * + * background(200); + * + * // Create a p5.Geometry object. + * beginGeometry(); + * cone(); + * let shape = endGeometry(); + * + * // Draw the shape. + * model(shape); + * + * // Free the shape's resources. + * freeGeometry(shape); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * let button; + * let particles; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a button to reset the particle system. + * button = createButton('Reset'); + * + * // Call resetModel() when the user presses the button. + * button.mousePressed(resetModel); + * + * // Add the original set of particles. + * resetModel(); * } * * function draw() { - * background(205, 102, 94); - * rotateY(millis() / 1000); - * cone(30, 65, 16, detailY.value()); + * background(50); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * lights(); + * + * // Style the particles. + * noStroke(); + * + * // Draw the particles. + * model(particles); + * } + * + * function resetModel() { + * // If the p5.Geometry object has already been created, + * // free those resources. + * if (particles) { + * freeGeometry(particles); + * } + * + * // Create a new p5.Geometry object with random spheres. + * particles = buildGeometry(createParticles); + * } + * + * function createParticles() { + * for (let i = 0; i < 60; i += 1) { + * // Calculate random coordinates. + * let x = randomGaussian(0, 20); + * let y = randomGaussian(0, 20); + * let z = randomGaussian(0, 20); + * + * push(); + * // Translate to the particle's coordinates. + * translate(x, y, z); + * // Draw the particle. + * sphere(5); + * pop(); + * } * } * *
*/ - _main.default.prototype.cone = function (radius, height, detailX, detailY, cap) { - this._assert3d('cone'); - _main.default._validateParameters('cone', arguments); - if (typeof radius === 'undefined') { - radius = 50; - } - if (typeof height === 'undefined') { - height = radius; - } - if (typeof detailX === 'undefined') { - detailX = 24; - } - if (typeof detailY === 'undefined') { - detailY = 1; - } - if (typeof cap === 'undefined') { - cap = true; - } - var gId = 'cone|'.concat(detailX, '|').concat(detailY, '|').concat(cap); - if (!this._renderer.geometryInHash(gId)) { - var coneGeom = new _main.default.Geometry(detailX, detailY); - _truncatedCone.call(coneGeom, 1, 0, 1, detailX, detailY, cap, false); - if (detailX <= 24 && detailY <= 16) { - coneGeom._makeTriangleEdges()._edgesToVertices(); - } else if (this._renderer._doStroke) { - console.log('Cannot draw stroke on cone objects with more' + ' than 24 detailX or 16 detailY'); - } - this._renderer.createBuffers(gId, coneGeom); - } - this._renderer.drawBuffersScaled(gId, radius, height, radius); - return this; + _main.default.prototype.freeGeometry = function (geometry) { + this._renderer._freeBuffers(geometry.gid); }; /** - * Draw an ellipsoid with given radius + * Draws a plane. * - * DetailX and detailY determine the number of subdivisions in the x-dimension and - * the y-dimension of a cone. More subdivisions make the ellipsoid appear to be smoother. - * Avoid detail number above 150, it may crash the browser. - * @method ellipsoid - * @param {Number} [radiusx] x-radius of ellipsoid - * @param {Number} [radiusy] y-radius of ellipsoid - * @param {Number} [radiusz] z-radius of ellipsoid - * @param {Integer} [detailX] number of segments, - * the more segments the smoother geometry - * default is 24. Avoid detail number above - * 150, it may crash the browser. - * @param {Integer} [detailY] number of segments, - * the more segments the smoother geometry - * default is 16. Avoid detail number above - * 150, it may crash the browser. + * A plane is a four-sided, flat shape with every angle measuring 90˚. It’s + * similar to a rectangle and offers advanced drawing features in WebGL mode. + * + * The first parameter, `width`, is optional. If a `Number` is passed, as in + * `plane(20)`, it sets the plane’s width and height. By default, `width` is + * 50. + * + * The second parameter, `height`, is also optional. If a `Number` is passed, + * as in `plane(20, 30)`, it sets the plane’s height. By default, `height` is + * set to the plane’s `width`. + * + * The third parameter, `detailX`, is also optional. If a `Number` is passed, + * as in `plane(20, 30, 5)` it sets the number of triangle subdivisions to use + * along the x-axis. All 3D shapes are made by connecting triangles to form + * their surfaces. By default, `detailX` is 1. + * + * The fourth parameter, `detailY`, is also optional. If a `Number` is passed, + * as in `plane(20, 30, 5, 7)` it sets the number of triangle subdivisions to + * use along the y-axis. All 3D shapes are made by connecting triangles to + * form their surfaces. By default, `detailY` is 1. + * + * Note: `plane()` can only be used in WebGL mode. + * + * @method plane + * @param {Number} [width] width of the plane. + * @param {Number} [height] height of the plane. + * @param {Integer} [detailX] number of triangle subdivisions along the x-axis. + * @param {Integer} [detailY] number of triangle subdivisions along the y-axis. * @chainable + * * @example *
* - * // draw an ellipsoid - * // with radius 30, 40 and 40. + * // Click and drag the mouse to view the scene from different angles. + * * function setup() { * createCanvas(100, 100, WEBGL); - * describe('a white 3d ellipsoid'); + * + * describe('A white plane on a gray background.'); * } * * function draw() { - * background(205, 105, 94); - * ellipsoid(30, 40, 40); + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the plane. + * plane(); * } * *
* - * @example *
* - * // slide to see how detailX works - * let detailX; + * // Click and drag the mouse to view the scene from different angles. + * * function setup() { * createCanvas(100, 100, WEBGL); - * detailX = createSlider(2, 24, 12); - * detailX.position(10, height + 5); - * detailX.style('width', '80px'); - * describe( - * 'a rotating white ellipsoid with limited X detail, with a slider that adjusts detailX' - * ); + * + * describe('A white plane on a gray background.'); * } * * function draw() { - * background(205, 105, 94); - * rotateY(millis() / 1000); - * ellipsoid(30, 40, 40, detailX.value(), 8); + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the plane. + * // Set its width and height to 30. + * plane(30); * } * *
* - * @example *
* - * // slide to see how detailY works - * let detailY; + * // Click and drag the mouse to view the scene from different angles. + * * function setup() { * createCanvas(100, 100, WEBGL); - * detailY = createSlider(2, 24, 6); - * detailY.position(10, height + 5); - * detailY.style('width', '80px'); - * describe( - * 'a rotating white ellipsoid with limited Y detail, with a slider that adjusts detailY' - * ); + * + * describe('A white plane on a gray background.'); * } * * function draw() { - * background(205, 105, 9); - * rotateY(millis() / 1000); - * ellipsoid(30, 40, 40, 12, detailY.value()); + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the plane. + * // Set its width to 30 and height to 50. + * plane(30, 50); * } * *
*/ - _main.default.prototype.ellipsoid = function (radiusX, radiusY, radiusZ, detailX, detailY) { - this._assert3d('ellipsoid'); - _main.default._validateParameters('ellipsoid', arguments); - if (typeof radiusX === 'undefined') { - radiusX = 50; - } - if (typeof radiusY === 'undefined') { - radiusY = radiusX; - } - if (typeof radiusZ === 'undefined') { - radiusZ = radiusX; - } - if (typeof detailX === 'undefined') { - detailX = 24; - } - if (typeof detailY === 'undefined') { - detailY = 16; - } - var gId = 'ellipsoid|'.concat(detailX, '|').concat(detailY); + _main.default.prototype.plane = function () { + var width = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 50; + var height = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : width; + var detailX = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1; + var detailY = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1; + this._assert3d('plane'); + _main.default._validateParameters('plane', arguments); + var gId = 'plane|'.concat(detailX, '|').concat(detailY); if (!this._renderer.geometryInHash(gId)) { - var _ellipsoid = function _ellipsoid() { + var _plane = function _plane() { + var u, + v, + p; for (var i = 0; i <= this.detailY; i++) { - var v = i / this.detailY; - var phi = Math.PI * v - Math.PI / 2; - var cosPhi = Math.cos(phi); - var sinPhi = Math.sin(phi); + v = i / this.detailY; for (var j = 0; j <= this.detailX; j++) { - var u = j / this.detailX; - var theta = 2 * Math.PI * u; - var cosTheta = Math.cos(theta); - var sinTheta = Math.sin(theta); - var p = new _main.default.Vector(cosPhi * sinTheta, sinPhi, cosPhi * cosTheta); + u = j / this.detailX; + p = new _main.default.Vector(u - 0.5, v - 0.5, 0); this.vertices.push(p); - this.vertexNormals.push(p); this.uvs.push(u, v); } } }; - var ellipsoidGeom = new _main.default.Geometry(detailX, detailY, _ellipsoid); - ellipsoidGeom.computeFaces(); - if (detailX <= 24 && detailY <= 24) { - ellipsoidGeom._makeTriangleEdges()._edgesToVertices(); + var planeGeom = new _main.default.Geometry(detailX, detailY, _plane); + planeGeom.computeFaces().computeNormals(); + if (detailX <= 1 && detailY <= 1) { + planeGeom._makeTriangleEdges()._edgesToVertices(); } else if (this._renderer._doStroke) { - console.log('Cannot draw stroke on ellipsoids with more' + ' than 24 detailX or 24 detailY'); + console.log('Cannot draw stroke on plane objects with more' + ' than 1 detailX or 1 detailY'); } - this._renderer.createBuffers(gId, ellipsoidGeom); + this._renderer.createBuffers(gId, planeGeom); } - this._renderer.drawBuffersScaled(gId, radiusX, radiusY, radiusZ); + this._renderer.drawBuffersScaled(gId, width, height, 1); return this; }; /** - * Draw a torus with given radius and tube radius + * Draws a box (rectangular prism). * - * DetailX and detailY determine the number of subdivisions in the x-dimension and - * the y-dimension of a torus. More subdivisions make the torus appear to be smoother. - * The default and maximum values for detailX and detailY are 24 and 16, respectively. - * Setting them to relatively small values like 4 and 6 allows you to create new - * shapes other than a torus. - * @method torus - * @param {Number} [radius] radius of the whole ring - * @param {Number} [tubeRadius] radius of the tube - * @param {Integer} [detailX] number of segments in x-dimension, - * the more segments the smoother geometry - * default is 24 - * @param {Integer} [detailY] number of segments in y-dimension, - * the more segments the smoother geometry - * default is 16 + * A box is a 3D shape with six faces. Each face makes a 90˚ with four + * neighboring faces. + * + * The first parameter, `width`, is optional. If a `Number` is passed, as in + * `box(20)`, it sets the box’s width and height. By default, `width` is 50. + * + * The second parameter, `height`, is also optional. If a `Number` is passed, + * as in `box(20, 30)`, it sets the box’s height. By default, `height` is set + * to the box’s `width`. + * + * The third parameter, `depth`, is also optional. If a `Number` is passed, as + * in `box(20, 30, 40)`, it sets the box’s depth. By default, `depth` is set + * to the box’s `height`. + * + * The fourth parameter, `detailX`, is also optional. If a `Number` is passed, + * as in `box(20, 30, 40, 5)`, it sets the number of triangle subdivisions to + * use along the x-axis. All 3D shapes are made by connecting triangles to + * form their surfaces. By default, `detailX` is 1. + * + * The fifth parameter, `detailY`, is also optional. If a number is passed, as + * in `box(20, 30, 40, 5, 7)`, it sets the number of triangle subdivisions to + * use along the y-axis. All 3D shapes are made by connecting triangles to + * form their surfaces. By default, `detailY` is 1. + * + * Note: `box()` can only be used in WebGL mode. + * + * @method box + * @param {Number} [width] width of the box. + * @param {Number} [height] height of the box. + * @param {Number} [depth] depth of the box. + * @param {Integer} [detailX] number of triangle subdivisions along the x-axis. + * @param {Integer} [detailY] number of triangle subdivisions along the y-axis. * @chainable + * * @example *
* - * // draw a spinning torus - * // with ring radius 30 and tube radius 15 + * // Click and drag the mouse to view the scene from different angles. + * * function setup() { * createCanvas(100, 100, WEBGL); - * describe('a rotating white torus'); + * + * describe('A white box on a gray background.'); * } * * function draw() { - * background(205, 102, 94); - * rotateX(frameCount * 0.01); - * rotateY(frameCount * 0.01); - * torus(30, 15); + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the box. + * box(); * } * *
* - * @example *
* - * // slide to see how detailX works - * let detailX; + * // Click and drag the mouse to view the scene from different angles. + * * function setup() { * createCanvas(100, 100, WEBGL); - * detailX = createSlider(3, 24, 3); - * detailX.position(10, height + 5); - * detailX.style('width', '80px'); - * describe( - * 'a rotating white torus with limited X detail, with a slider that adjusts detailX' - * ); + * + * describe('A white box on a gray background.'); * } * * function draw() { - * background(205, 102, 94); - * rotateY(millis() / 1000); - * torus(30, 15, detailX.value(), 12); + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the box. + * // Set its width and height to 30. + * box(30); * } * *
* - * @example *
* - * // slide to see how detailY works - * let detailY; + * // Click and drag the mouse to view the scene from different angles. + * * function setup() { * createCanvas(100, 100, WEBGL); - * detailY = createSlider(3, 16, 3); - * detailY.position(10, height + 5); - * detailY.style('width', '80px'); - * describe( - * 'a rotating white torus with limited Y detail, with a slider that adjusts detailY' - * ); + * + * describe('A white box on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the box. + * // Set its width to 30 and height to 50. + * box(30, 50); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white box on a gray background.'); * } * * function draw() { - * background(205, 102, 94); - * rotateY(millis() / 1000); - * torus(30, 15, 16, detailY.value()); + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the box. + * // Set its width to 30, height to 50, and depth to 10. + * box(30, 50, 10); * } * *
*/ - _main.default.prototype.torus = function (radius, tubeRadius, detailX, detailY) { - this._assert3d('torus'); - _main.default._validateParameters('torus', arguments); - if (typeof radius === 'undefined') { - radius = 50; - } else if (!radius) { + _main.default.prototype.box = function (width, height, depth, detailX, detailY) { + this._assert3d('box'); + _main.default._validateParameters('box', arguments); + if (typeof width === 'undefined') { + width = 50; + } + if (typeof height === 'undefined') { + height = width; + } + if (typeof depth === 'undefined') { + depth = height; + } + var perPixelLighting = this._renderer.attributes && this._renderer.attributes.perPixelLighting; + if (typeof detailX === 'undefined') { + detailX = perPixelLighting ? 1 : 4; + } + if (typeof detailY === 'undefined') { + detailY = perPixelLighting ? 1 : 4; + } + var gId = 'box|'.concat(detailX, '|').concat(detailY); + if (!this._renderer.geometryInHash(gId)) { + var _box = function _box() { + var _this = this; + var cubeIndices = [ + [0, + 4, + 2, + 6], + // -1, 0, 0],// -x + [ + 1, + 3, + 5, + 7 + ], + // +1, 0, 0],// +x + [ + 0, + 1, + 4, + 5 + ], + // 0, -1, 0],// -y + [ + 2, + 6, + 3, + 7 + ], + // 0, +1, 0],// +y + [ + 0, + 2, + 1, + 3 + ], + // 0, 0, -1],// -z + [ + 4, + 5, + 6, + 7 + ] // 0, 0, +1] // +z + ]; + //using custom edges + //to avoid diagonal stroke lines across face of box + this.edges = [ + [0, + 1], + [ + 1, + 3 + ], + [ + 3, + 2 + ], + [ + 6, + 7 + ], + [ + 8, + 9 + ], + [ + 9, + 11 + ], + [ + 14, + 15 + ], + [ + 16, + 17 + ], + [ + 17, + 19 + ], + [ + 18, + 19 + ], + [ + 20, + 21 + ], + [ + 22, + 23 + ] + ]; + cubeIndices.forEach(function (cubeIndex, i) { + var v = i * 4; + for (var j = 0; j < 4; j++) { + var d = cubeIndex[j]; + //inspired by lightgl: + //https://github.com/evanw/lightgl.js + //octants:https://en.wikipedia.org/wiki/Octant_(solid_geometry) + var octant = new _main.default.Vector(((d & 1) * 2 - 1) / 2, ((d & 2) - 1) / 2, ((d & 4) / 2 - 1) / 2); + _this.vertices.push(octant); + _this.uvs.push(j & 1, (j & 2) / 2); + } + _this.faces.push([v, + v + 1, + v + 2]); + _this.faces.push([v + 2, + v + 1, + v + 3]); + }); + }; + var boxGeom = new _main.default.Geometry(detailX, detailY, _box); + boxGeom.computeNormals(); + if (detailX <= 4 && detailY <= 4) { + boxGeom._edgesToVertices(); + } else if (this._renderer._doStroke) { + console.log('Cannot draw stroke on box objects with more' + ' than 4 detailX or 4 detailY'); + } //initialize our geometry buffer with + //the key val pair: + //geometry Id, Geom object + + this._renderer.createBuffers(gId, boxGeom); + } + this._renderer.drawBuffersScaled(gId, width, height, depth); + return this; + }; + /** + * Draws a sphere. + * + * A sphere is a 3D shape with triangular faces that connect to form a round + * surface. Spheres with few faces look like crystals. Spheres with many faces + * have smooth surfaces and look like balls. + * + * The first parameter, `radius`, is optional. If a `Number` is passed, as in + * `sphere(20)`, it sets the radius of the sphere. By default, `radius` is 50. + * + * The second parameter, `detailX`, is also optional. If a `Number` is passed, + * as in `sphere(20, 5)`, it sets the number of triangle subdivisions to use + * along the x-axis. All 3D shapes are made by connecting triangles to form + * their surfaces. By default, `detailX` is 24. + * + * The third parameter, `detailY`, is also optional. If a `Number` is passed, + * as in `sphere(20, 5, 2)`, it sets the number of triangle subdivisions to + * use along the y-axis. All 3D shapes are made by connecting triangles to + * form their surfaces. By default, `detailY` is 16. + * + * Note: `sphere()` can only be used in WebGL mode. + * + * @method sphere + * @param {Number} [radius] radius of the sphere. Defaults to 50. + * @param {Integer} [detailX] number of triangle subdivisions along the x-axis. Defaults to 24. + * @param {Integer} [detailY] number of triangle subdivisions along the y-axis. Defaults to 16. + * + * @chainable + * @example + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white sphere on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the sphere. + * sphere(); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white sphere on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the sphere. + * // Set its radius to 30. + * sphere(30); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white sphere on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the sphere. + * // Set its radius to 30. + * // Set its detailX to 6. + * sphere(30, 6); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white sphere on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the sphere. + * // Set its radius to 30. + * // Set its detailX to 24. + * // Set its detailY to 4. + * sphere(30, 24, 4); + * } + * + *
+ */ + _main.default.prototype.sphere = function () { + var radius = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 50; + var detailX = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 24; + var detailY = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 16; + this._assert3d('sphere'); + _main.default._validateParameters('sphere', arguments); + this.ellipsoid(radius, radius, radius, detailX, detailY); + return this; + }; + /** + * @private + * Helper function for creating both cones and cylinders + * Will only generate well-defined geometry when bottomRadius, height > 0 + * and topRadius >= 0 + * If topRadius == 0, topCap should be false + */ + var _truncatedCone = function _truncatedCone(bottomRadius, topRadius, height, detailX, detailY, bottomCap, topCap) { + bottomRadius = bottomRadius <= 0 ? 1 : bottomRadius; + topRadius = topRadius < 0 ? 0 : topRadius; + height = height <= 0 ? bottomRadius : height; + detailX = detailX < 3 ? 3 : detailX; + detailY = detailY < 1 ? 1 : detailY; + bottomCap = bottomCap === undefined ? true : bottomCap; + topCap = topCap === undefined ? topRadius !== 0 : topCap; + var start = bottomCap ? - 2 : 0; + var end = detailY + (topCap ? 2 : 0); + //ensure constant slant for interior vertex normals + var slant = Math.atan2(bottomRadius - topRadius, height); + var sinSlant = Math.sin(slant); + var cosSlant = Math.cos(slant); + var yy, + ii, + jj; + for (yy = start; yy <= end; ++yy) { + var v = yy / detailY; + var y = height * v; + var ringRadius = void 0; + if (yy < 0) { + //for the bottomCap edge + y = 0; + v = 0; + ringRadius = bottomRadius; + } else if (yy > detailY) { + //for the topCap edge + y = height; + v = 1; + ringRadius = topRadius; + } else { + //for the middle + ringRadius = bottomRadius + (topRadius - bottomRadius) * v; + } + if (yy === - 2 || yy === detailY + 2) { + //center of bottom or top caps + ringRadius = 0; + } + y -= height / 2; //shift coordiate origin to the center of object + for (ii = 0; ii < detailX; ++ii) { + var u = ii / (detailX - 1); + var ur = 2 * Math.PI * u; + var sur = Math.sin(ur); + var cur = Math.cos(ur); + //VERTICES + this.vertices.push(new _main.default.Vector(sur * ringRadius, y, cur * ringRadius)); + //VERTEX NORMALS + var vertexNormal = void 0; + if (yy < 0) { + vertexNormal = new _main.default.Vector(0, - 1, 0); + } else if (yy > detailY && topRadius) { + vertexNormal = new _main.default.Vector(0, 1, 0); + } else { + vertexNormal = new _main.default.Vector(sur * cosSlant, sinSlant, cur * cosSlant); + } + this.vertexNormals.push(vertexNormal); + //UVs + this.uvs.push(u, v); + } + } + var startIndex = 0; + if (bottomCap) { + for (jj = 0; jj < detailX; ++jj) { + var nextjj = (jj + 1) % detailX; + this.faces.push([startIndex + jj, + startIndex + detailX + nextjj, + startIndex + detailX + jj]); + } + startIndex += detailX * 2; + } + for (yy = 0; yy < detailY; ++yy) { + for (ii = 0; ii < detailX; ++ii) { + var nextii = (ii + 1) % detailX; + this.faces.push([startIndex + ii, + startIndex + nextii, + startIndex + detailX + nextii]); + this.faces.push([startIndex + ii, + startIndex + detailX + nextii, + startIndex + detailX + ii]); + } + startIndex += detailX; + } + if (topCap) { + startIndex += detailX; + for (ii = 0; ii < detailX; ++ii) { + this.faces.push([startIndex + ii, + startIndex + (ii + 1) % detailX, + startIndex + detailX]); + } + } + }; + /** + * Draws a cylinder. + * + * A cylinder is a 3D shape with triangular faces that connect a flat bottom + * to a flat top. Cylinders with few faces look like boxes. Cylinders with + * many faces have smooth surfaces. + * + * The first parameter, `radius`, is optional. If a `Number` is passed, as in + * `cylinder(20)`, it sets the radius of the cylinder’s base. By default, + * `radius` is 50. + * + * The second parameter, `height`, is also optional. If a `Number` is passed, + * as in `cylinder(20, 30)`, it sets the cylinder’s height. By default, + * `height` is set to the cylinder’s `radius`. + * + * The third parameter, `detailX`, is also optional. If a `Number` is passed, + * as in `cylinder(20, 30, 5)`, it sets the number of edges used to form the + * cylinder's top and bottom. Using more edges makes the top and bottom look + * more like circles. By default, `detailX` is 24. + * + * The fourth parameter, `detailY`, is also optional. If a `Number` is passed, + * as in `cylinder(20, 30, 5, 2)`, it sets the number of triangle subdivisions + * to use along the y-axis, between cylinder's the top and bottom. All 3D + * shapes are made by connecting triangles to form their surfaces. By default, + * `detailY` is 1. + * + * The fifth parameter, `bottomCap`, is also optional. If a `false` is passed, + * as in `cylinder(20, 30, 5, 2, false)` the cylinder’s bottom won’t be drawn. + * By default, `bottomCap` is `true`. + * + * The sixth parameter, `topCap`, is also optional. If a `false` is passed, as + * in `cylinder(20, 30, 5, 2, false, false)` the cylinder’s top won’t be + * drawn. By default, `topCap` is `true`. + * + * Note: `cylinder()` can only be used in WebGL mode. + * + * @method cylinder + * @param {Number} [radius] radius of the cylinder. Defaults to 50. + * @param {Number} [height] height of the cylinder. Defaults to the value of `radius`. + * @param {Integer} [detailX] number of edges along the top and bottom. Defaults to 24. + * @param {Integer} [detailY] number of triangle subdivisions along the y-axis. Defaults to 1. + * @param {Boolean} [bottomCap] whether to draw the cylinder's bottom. Defaults to `true`. + * @param {Boolean} [topCap] whether to draw the cylinder's top. Defaults to `true`. + * @chainable + * + * @example + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white cylinder on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the cylinder. + * cylinder(); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white cylinder on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the cylinder. + * // Set its radius and height to 30. + * cylinder(30); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white cylinder on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the cylinder. + * // Set its radius to 30 and height to 50. + * cylinder(30, 50); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white box on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the cylinder. + * // Set its radius to 30 and height to 50. + * // Set its detailX to 5. + * cylinder(30, 50, 5); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white cylinder on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the cylinder. + * // Set its radius to 30 and height to 50. + * // Set its detailX to 24 and detailY to 2. + * cylinder(30, 50, 24, 2); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white cylinder on a gray background. Its top is missing.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the cylinder. + * // Set its radius to 30 and height to 50. + * // Set its detailX to 24 and detailY to 1. + * // Don't draw its bottom. + * cylinder(30, 50, 24, 1, false); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white cylinder on a gray background. Its top and bottom are missing.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the cylinder. + * // Set its radius to 30 and height to 50. + * // Set its detailX to 24 and detailY to 1. + * // Don't draw its bottom or top. + * cylinder(30, 50, 24, 1, false, false); + * } + * + *
+ */ + _main.default.prototype.cylinder = function () { + var radius = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 50; + var height = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : radius; + var detailX = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 24; + var detailY = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1; + var bottomCap = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true; + var topCap = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : true; + this._assert3d('cylinder'); + _main.default._validateParameters('cylinder', arguments); + var gId = 'cylinder|'.concat(detailX, '|').concat(detailY, '|').concat(bottomCap, '|').concat(topCap); + if (!this._renderer.geometryInHash(gId)) { + var cylinderGeom = new _main.default.Geometry(detailX, detailY); + _truncatedCone.call(cylinderGeom, 1, 1, 1, detailX, detailY, bottomCap, topCap); + // normals are computed in call to _truncatedCone + if (detailX <= 24 && detailY <= 16) { + cylinderGeom._makeTriangleEdges()._edgesToVertices(); + } else if (this._renderer._doStroke) { + console.log('Cannot draw stroke on cylinder objects with more' + ' than 24 detailX or 16 detailY'); + } + this._renderer.createBuffers(gId, cylinderGeom); + } + this._renderer.drawBuffersScaled(gId, radius, height, radius); + return this; + }; + /** + * Draws a cone. + * + * A cone is a 3D shape with triangular faces that connect a flat bottom to a + * single point. Cones with few faces look like pyramids. Cones with many + * faces have smooth surfaces. + * + * The first parameter, `radius`, is optional. If a `Number` is passed, as in + * `cone(20)`, it sets the radius of the cone’s base. By default, `radius` is + * 50. + * + * The second parameter, `height`, is also optional. If a `Number` is passed, + * as in `cone(20, 30)`, it sets the cone’s height. By default, `height` is + * set to the cone’s `radius`. + * + * The third parameter, `detailX`, is also optional. If a `Number` is passed, + * as in `cone(20, 30, 5)`, it sets the number of edges used to form the + * cone's base. Using more edges makes the base look more like a circle. By + * default, `detailX` is 24. + * + * The fourth parameter, `detailY`, is also optional. If a `Number` is passed, + * as in `cone(20, 30, 5, 7)`, it sets the number of triangle subdivisions to + * use along the y-axis connecting the base to the tip. All 3D shapes are made + * by connecting triangles to form their surfaces. By default, `detailY` is 1. + * + * The fifth parameter, `cap`, is also optional. If a `false` is passed, as + * in `cone(20, 30, 5, 7, false)` the cone’s base won’t be drawn. By default, + * `cap` is `true`. + * + * Note: `cone()` can only be used in WebGL mode. + * + * @method cone + * @param {Number} [radius] radius of the cone's base. Defaults to 50. + * @param {Number} [height] height of the cone. Defaults to the value of `radius`. + * @param {Integer} [detailX] number of edges used to draw the base. Defaults to 24. + * @param {Integer} [detailY] number of triangle subdivisions along the y-axis. Defaults to 1. + * @param {Boolean} [cap] whether to draw the cone's base. Defaults to `true`. + * @chainable + * + * @example + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white cone on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the cone. + * cone(); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white cone on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the cone. + * // Set its radius and height to 30. + * cone(30); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white cone on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the cone. + * // Set its radius to 30 and height to 50. + * cone(30, 50); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white cone on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the cone. + * // Set its radius to 30 and height to 50. + * // Set its detailX to 5. + * cone(30, 50, 5); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white pyramid on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the cone. + * // Set its radius to 30 and height to 50. + * // Set its detailX to 5. + * cone(30, 50, 5); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white cone on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the cone. + * // Set its radius to 30 and height to 50. + * // Set its detailX to 24 and detailY to 2. + * cone(30, 50, 24, 2); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white cone on a gray background. Its base is missing.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the cone. + * // Set its radius to 30 and height to 50. + * // Set its detailX to 24 and detailY to 1. + * // Don't draw its base. + * cone(30, 50, 24, 1, false); + * } + * + *
+ */ + _main.default.prototype.cone = function () { + var radius = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 50; + var height = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : radius; + var detailX = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 24; + var detailY = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 1; + var cap = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true; + this._assert3d('cone'); + _main.default._validateParameters('cone', arguments); + var gId = 'cone|'.concat(detailX, '|').concat(detailY, '|').concat(cap); + if (!this._renderer.geometryInHash(gId)) { + var coneGeom = new _main.default.Geometry(detailX, detailY); + _truncatedCone.call(coneGeom, 1, 0, 1, detailX, detailY, cap, false); + if (detailX <= 24 && detailY <= 16) { + coneGeom._makeTriangleEdges()._edgesToVertices(); + } else if (this._renderer._doStroke) { + console.log('Cannot draw stroke on cone objects with more' + ' than 24 detailX or 16 detailY'); + } + this._renderer.createBuffers(gId, coneGeom); + } + this._renderer.drawBuffersScaled(gId, radius, height, radius); + return this; + }; + /** + * Draws an ellipsoid. + * + * An ellipsoid is a 3D shape with triangular faces that connect to form a + * round surface. Ellipsoids with few faces look like crystals. Ellipsoids + * with many faces have smooth surfaces and look like eggs. `ellipsoid()` + * defines a shape by its radii. This is different from + * ellipse() which uses diameters + * (width and height). + * + * The first parameter, `radiusX`, is optional. If a `Number` is passed, as in + * `ellipsoid(20)`, it sets the radius of the ellipsoid along the x-axis. By + * default, `radiusX` is 50. + * + * The second parameter, `radiusY`, is also optional. If a `Number` is passed, + * as in `ellipsoid(20, 30)`, it sets the ellipsoid’s radius along the y-axis. + * By default, `radiusY` is set to the ellipsoid’s `radiusX`. + * + * The third parameter, `radiusZ`, is also optional. If a `Number` is passed, + * as in `ellipsoid(20, 30, 40)`, it sets the ellipsoid’s radius along the + * z-axis. By default, `radiusZ` is set to the ellipsoid’s `radiusY`. + * + * The fourth parameter, `detailX`, is also optional. If a `Number` is passed, + * as in `ellipsoid(20, 30, 40, 5)`, it sets the number of triangle + * subdivisions to use along the x-axis. All 3D shapes are made by connecting + * triangles to form their surfaces. By default, `detailX` is 24. + * + * The fifth parameter, `detailY`, is also optional. If a `Number` is passed, + * as in `ellipsoid(20, 30, 40, 5, 7)`, it sets the number of triangle + * subdivisions to use along the y-axis. All 3D shapes are made by connecting + * triangles to form their surfaces. By default, `detailY` is 16. + * + * Note: `ellipsoid()` can only be used in WebGL mode. + * + * @method ellipsoid + * @param {Number} [radiusX] radius of the ellipsoid along the x-axis. Defaults to 50. + * @param {Number} [radiusY] radius of the ellipsoid along the y-axis. Defaults to `radiusX`. + * @param {Number} [radiusZ] radius of the ellipsoid along the z-axis. Defaults to `radiusY`. + * @param {Integer} [detailX] number of triangle subdivisions along the x-axis. Defaults to 24. + * @param {Integer} [detailY] number of triangle subdivisions along the y-axis. Defaults to 16. + * @chainable + * + * @example + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white sphere on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the ellipsoid. + * // Set its radiusX to 30. + * ellipsoid(30); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white ellipsoid on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the ellipsoid. + * // Set its radiusX to 30. + * // Set its radiusY to 40. + * ellipsoid(30, 40); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white ellipsoid on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the ellipsoid. + * // Set its radiusX to 30. + * // Set its radiusY to 40. + * // Set its radiusZ to 50. + * ellipsoid(30, 40, 50); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white ellipsoid on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the ellipsoid. + * // Set its radiusX to 30. + * // Set its radiusY to 40. + * // Set its radiusZ to 50. + * // Set its detailX to 4. + * ellipsoid(30, 40, 50, 4); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white ellipsoid on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the ellipsoid. + * // Set its radiusX to 30. + * // Set its radiusY to 40. + * // Set its radiusZ to 50. + * // Set its detailX to 4. + * // Set its detailY to 3. + * ellipsoid(30, 40, 50, 4, 3); + * } + * + *
+ */ + _main.default.prototype.ellipsoid = function () { + var radiusX = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 50; + var radiusY = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : radiusX; + var radiusZ = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : radiusX; + var detailX = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 24; + var detailY = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 16; + this._assert3d('ellipsoid'); + _main.default._validateParameters('ellipsoid', arguments); + var gId = 'ellipsoid|'.concat(detailX, '|').concat(detailY); + if (!this._renderer.geometryInHash(gId)) { + var _ellipsoid = function _ellipsoid() { + for (var i = 0; i <= this.detailY; i++) { + var v = i / this.detailY; + var phi = Math.PI * v - Math.PI / 2; + var cosPhi = Math.cos(phi); + var sinPhi = Math.sin(phi); + for (var j = 0; j <= this.detailX; j++) { + var u = j / this.detailX; + var theta = 2 * Math.PI * u; + var cosTheta = Math.cos(theta); + var sinTheta = Math.sin(theta); + var p = new _main.default.Vector(cosPhi * sinTheta, sinPhi, cosPhi * cosTheta); + this.vertices.push(p); + this.vertexNormals.push(p); + this.uvs.push(u, v); + } + } + }; + var ellipsoidGeom = new _main.default.Geometry(detailX, detailY, _ellipsoid); + ellipsoidGeom.computeFaces(); + if (detailX <= 24 && detailY <= 24) { + ellipsoidGeom._makeTriangleEdges()._edgesToVertices(); + } else if (this._renderer._doStroke) { + console.log('Cannot draw stroke on ellipsoids with more' + ' than 24 detailX or 24 detailY'); + } + this._renderer.createBuffers(gId, ellipsoidGeom); + } + this._renderer.drawBuffersScaled(gId, radiusX, radiusY, radiusZ); + return this; + }; + /** + * Draws a torus. + * + * A torus is a 3D shape with triangular faces that connect to form a ring. + * Toruses with few faces look flattened. Toruses with many faces have smooth + * surfaces. + * + * The first parameter, `radius`, is optional. If a `Number` is passed, as in + * `torus(30)`, it sets the radius of the ring. By default, `radius` is 50. + * + * The second parameter, `tubeRadius`, is also optional. If a `Number` is + * passed, as in `torus(30, 15)`, it sets the radius of the tube. By default, + * `tubeRadius` is 10. + * + * The third parameter, `detailX`, is also optional. If a `Number` is passed, + * as in `torus(30, 15, 5)`, it sets the number of edges used to draw the hole + * of the torus. Using more edges makes the hole look more like a circle. By + * default, `detailX` is 24. + * + * The fourth parameter, `detailY`, is also optional. If a `Number` is passed, + * as in `torus(30, 15, 5, 7)`, it sets the number of triangle subdivisions to + * use while filling in the torus’ height. By default, `detailY` is 16. + * + * Note: `torus()` can only be used in WebGL mode. + * + * @method torus + * @param {Number} [radius] radius of the torus. Defaults to 50. + * @param {Number} [tubeRadius] radius of the tube. Defaults to 10. + * @param {Integer} [detailX] number of edges that form the hole. Defaults to 24. + * @param {Integer} [detailY] number of triangle subdivisions along the y-axis. Defaults to 16. + * @chainable + * + * @example + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white torus on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the torus. + * torus(); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white torus on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the torus. + * // Set its radius to 30. + * torus(30); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white torus on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the torus. + * // Set its radius to 30 and tubeRadius to 15. + * torus(30, 15); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white torus on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the torus. + * // Set its radius to 30 and tubeRadius to 15. + * // Set its detailX to 5. + * torus(30, 15, 5); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white torus on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the torus. + * // Set its radius to 30 and tubeRadius to 15. + * // Set its detailX to 5. + * // Set its detailY to 3. + * torus(30, 15, 5, 3); + * } + * + *
+ */ + _main.default.prototype.torus = function (radius, tubeRadius, detailX, detailY) { + this._assert3d('torus'); + _main.default._validateParameters('torus', arguments); + if (typeof radius === 'undefined') { + radius = 50; + } else if (!radius) { return; // nothing to draw } if (typeof tubeRadius === 'undefined') { @@ -103704,10 +120520,8 @@ *
*
*/ - _main.default.RendererGL.prototype.point = function (x, y, z) { - if (typeof z === 'undefined') { - z = 0; - } + _main.default.RendererGL.prototype.point = function (x, y) { + var z = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; var _vertex = [ ]; _vertex.push(new _main.default.Vector(x, y, z)); @@ -103767,7 +120581,7 @@ // onto the required vector prior to rendering, and moves the // origin appropriately. - var uMVMatrix = this.uMVMatrix.copy(); + var uModelMatrix = this.uModelMatrix.copy(); try { // triangle orientation. var orientation = Math.sign(x1 * y2 - x2 * y1 + x2 * y3 - x3 * y2 + x3 * y1 - x1 * y3); @@ -103790,26 +120604,26 @@ y1, 0, 1 // the resulting origin - ]).mult(this.uMVMatrix); - this.uMVMatrix = mult; + ]).mult(this.uModelMatrix); + this.uModelMatrix = mult; this.drawBuffers(gId); } finally { - this.uMVMatrix = uMVMatrix; + this.uModelMatrix = uModelMatrix; } return this; }; _main.default.RendererGL.prototype.ellipse = function (args) { this.arc(args[0], args[1], args[2], args[3], 0, constants.TWO_PI, constants.OPEN, args[4]); }; - _main.default.RendererGL.prototype.arc = function (args) { - var x = arguments[0]; - var y = arguments[1]; - var width = arguments[2]; - var height = arguments[3]; - var start = arguments[4]; - var stop = arguments[5]; - var mode = arguments[6]; - var detail = arguments[7] || 25; + _main.default.RendererGL.prototype.arc = function () { + var x = arguments.length <= 0 ? undefined : arguments[0]; + var y = arguments.length <= 1 ? undefined : arguments[1]; + var width = arguments.length <= 2 ? undefined : arguments[2]; + var height = arguments.length <= 3 ? undefined : arguments[3]; + var start = arguments.length <= 4 ? undefined : arguments[4]; + var stop = arguments.length <= 5 ? undefined : arguments[5]; + var mode = arguments.length <= 6 ? undefined : arguments[6]; + var detail = (arguments.length <= 7 ? undefined : arguments[7]) || 25; var shape; var gId; // check if it is an ellipse or an arc @@ -103888,15 +120702,15 @@ } this.createBuffers(gId, arcGeom); } - var uMVMatrix = this.uMVMatrix.copy(); + var uModelMatrix = this.uModelMatrix.copy(); try { - this.uMVMatrix.translate([x, + this.uModelMatrix.translate([x, y, 0]); - this.uMVMatrix.scale(width, height, 1); + this.uModelMatrix.scale(width, height, 1); this.drawBuffers(gId); } finally { - this.uMVMatrix = uMVMatrix; + this.uModelMatrix = uModelMatrix; } return this; }; @@ -103951,15 +120765,15 @@ // // before rendering, this square is scaled & moved to the required location. - var uMVMatrix = this.uMVMatrix.copy(); + var uModelMatrix = this.uModelMatrix.copy(); try { - this.uMVMatrix.translate([x, + this.uModelMatrix.translate([x, y, 0]); - this.uMVMatrix.scale(width, height, 1); + this.uModelMatrix.scale(width, height, 1); this.drawBuffers(gId); } finally { - this.uMVMatrix = uMVMatrix; + this.uModelMatrix = uModelMatrix; } } else { // Use Immediate mode to round the rectangle corner, @@ -104048,14 +120862,10 @@ return this; }; /* eslint-disable max-len */ - _main.default.RendererGL.prototype.quad = function (x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4, detailX, detailY) { + _main.default.RendererGL.prototype.quad = function (x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4) { + var detailX = arguments.length > 12 && arguments[12] !== undefined ? arguments[12] : 2; + var detailY = arguments.length > 13 && arguments[13] !== undefined ? arguments[13] : 2; /* eslint-enable max-len */ - if (typeof detailX === 'undefined') { - detailX = 2; - } - if (typeof detailY === 'undefined') { - detailY = 2; - } var gId = 'quad|'.concat(x1, '|').concat(y1, '|').concat(z1, '|').concat(x2, '|').concat(y2, '|').concat(z2, '|').concat(x3, '|').concat(y3, '|').concat(z3, '|').concat(x4, '|').concat(y4, '|').concat(z4, '|').concat(detailX, '|').concat(detailY); if (!this.geometryInHash(gId)) { var quadGeom = new _main.default.Geometry(detailX, detailY, function () { @@ -104716,27 +121526,27 @@ exports.default = _default; }, { - '../core/constants': 286, - '../core/main': 298, - './p5.Geometry': 350, - 'core-js/modules/es.array.concat': 169, - 'core-js/modules/es.array.for-each': 175, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.math.hypot': 188, - 'core-js/modules/es.math.sign': 190, - 'core-js/modules/es.number.to-fixed': 193, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/constants': 294, + '../core/main': 306, + './p5.Geometry': 358, + 'core-js/modules/es.array.concat': 171, + 'core-js/modules/es.array.for-each': 179, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.math.hypot': 194, + 'core-js/modules/es.math.sign': 196, + 'core-js/modules/es.number.to-fixed': 200, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 342: [ + 350: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -104880,7 +121690,7 @@ this.renderer = renderer; renderer._pInst.push(); this.identityMatrix = new _main.default.Matrix(); - renderer.uMVMatrix = new _main.default.Matrix(); + renderer.uModelMatrix = new _main.default.Matrix(); this.geometry = new _main.default.Geometry(); this.geometry.gid = '_p5_GeometryBuilder_'.concat(GeometryBuilder.nextGeometryId); GeometryBuilder.nextGeometryId++; @@ -104897,7 +121707,7 @@ var _this = this; if (!this.hasTransform) return vertices; return vertices.map(function (v) { - return _this.renderer.uMVMatrix.multiplyPoint(v); + return _this.renderer.uModelMatrix.multiplyPoint(v); }); } /** * @private @@ -104928,11 +121738,11 @@ _this$geometry$vertex, _this$geometry$uvs, _this$geometry$vertex2; - this.hasTransform = !this.renderer.uMVMatrix.mat4.every(function (v, i) { + this.hasTransform = !this.renderer.uModelMatrix.mat4.every(function (v, i) { return v === _this3.identityMatrix.mat4[i]; }); if (this.hasTransform) { - this.renderer.uNMatrix.inverseTranspose(this.renderer.uMVMatrix); + this.renderer.uNMatrix.inverseTranspose(this.renderer.uModelMatrix); } var startIdx = this.geometry.vertices.length; (_this$geometry$vertic = this.geometry.vertices).push.apply(_this$geometry$vertic, _toConsumableArray(this.transformVertices(input.vertices))); @@ -105038,25 +121848,25 @@ exports.default = _default; }, { - '../core/constants': 286, - '../core/main': 298, - 'core-js/modules/es.array.every': 171, - 'core-js/modules/es.array.from': 176, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.map': 182, - 'core-js/modules/es.object.assign': 194, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/constants': 294, + '../core/main': 306, + 'core-js/modules/es.array.every': 173, + 'core-js/modules/es.array.from': 180, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.map': 186, + 'core-js/modules/es.object.assign': 201, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 343: [ + 351: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -105170,59 +121980,154 @@ * @requires core */ /** - * Allows movement around a 3D sketch using a mouse or trackpad or touch. + * Allows the user to orbit around a 3D sketch using a mouse, trackpad, or + * touchscreen. + * + * 3D sketches are viewed through an imaginary camera. Calling + * `orbitControl()` within the draw() function allows + * the user to change the camera’s position: + * + * ```js + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Rest of sketch. + * } + * ``` + * * Left-clicking and dragging or swipe motion will rotate the camera position - * about the center of the sketch, right-clicking and dragging or multi-swipe - * will pan the camera position without rotation, and using the mouse wheel - * (scrolling) or pinch in/out will move the camera further or closer - * from the center of the sketch. This function can be called with parameters - * dictating sensitivity to mouse/touch movement along the X and Y axes. - * Calling this function without parameters is equivalent to calling - * orbitControl(1,1). To reverse direction of movement in either axis, - * enter a negative number for sensitivity. + * about the center of the sketch. Right-clicking and dragging or multi-swipe + * will pan the camera position without rotation. Using the mouse wheel + * (scrolling) or pinch in/out will move the camera further or closer from the + * center of the sketch. + * + * The first three parameters, `sensitivityX`, `sensitivityY`, and + * `sensitivityZ`, are optional. They’re numbers that set the sketch’s + * sensitivity to movement along each axis. For example, calling + * `orbitControl(1, 2, -1)` keeps movement along the x-axis at its default + * value, makes the sketch twice as sensitive to movement along the y-axis, + * and reverses motion along the z-axis. By default, all sensitivity values + * are 1. + * + * The fourth parameter, `options`, is also optional. It’s an object that + * changes the behavior of orbiting. For example, calling + * `orbitControl(1, 1, 1, options)` keeps the default sensitivity values while + * changing the behaviors set with `options`. The object can have the + * following properties: + * + * ```js + * let options = { + * // Setting this to false makes mobile interactions smoother by + * // preventing accidental interactions with the page while orbiting. + * // By default, it's true. + * disableTouchActions: true, + * + * // Setting this to true makes the camera always rotate in the + * // direction the mouse/touch is moving. + * // By default, it's false. + * freeRotation: false + * }; + * + * orbitControl(1, 1, 1, options); + * ``` + * * @method orbitControl * @for p5 - * @param {Number} [sensitivityX] sensitivity to mouse movement along X axis - * @param {Number} [sensitivityY] sensitivity to mouse movement along Y axis - * @param {Number} [sensitivityZ] sensitivity to scroll movement along Z axis - * @param {Object} [options] An optional object that can contain additional settings, - * disableTouchActions - Boolean, default value is true. - * Setting this to true makes mobile interactions smoother by preventing - * accidental interactions with the page while orbiting. But if you're already - * doing it via css or want the default touch actions, consider setting it to false. - * freeRotation - Boolean, default value is false. - * By default, horizontal movement of the mouse or touch pointer rotates the camera - * around the y-axis, and vertical movement rotates the camera around the x-axis. - * But if setting this option to true, the camera always rotates in the direction - * the pointer is moving. For zoom and move, the behavior is the same regardless of - * true/false. + * @param {Number} [sensitivityX] sensitivity to movement along the x-axis. Defaults to 1. + * @param {Number} [sensitivityY] sensitivity to movement along the y-axis. Defaults to 1. + * @param {Number} [sensitivityZ] sensitivity to movement along the z-axis. Defaults to 1. + * @param {Object} [options] object with two optional properties, `disableTouchActions` + * and `freeRotation`. Both are `Boolean`s. `disableTouchActions` + * defaults to `true` and `freeRotation` defaults to `false`. * @chainable + * * @example *
* + * // Click and drag the mouse to view the scene from different angles. + * * function setup() { * createCanvas(100, 100, WEBGL); - * normalMaterial(); - * describe( - * 'Camera orbits around a box when mouse is hold-clicked & then moved.' - * ); + * + * describe('A multicolor box on a gray background. The camera angle changes when the user interacts using a mouse, trackpad, or touchscreen.'); * } + * * function draw() { * background(200); * - * // If you execute the line commented out instead of next line, the direction of rotation - * // will be the direction the mouse or touch pointer moves, not around the X or Y axis. + * // Enable orbiting with the mouse. * orbitControl(); - * // orbitControl(1, 1, 1, {freeRotation: true}); * - * rotateY(0.5); + * // Style the box. + * normalMaterial(); + * + * // Draw the box. * box(30, 50); * } * *
* - * @alt - * Camera orbits around a box when mouse is hold-clicked & then moved. + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A multicolor box on a gray background. The camera angle changes when the user interacts using a mouse, trackpad, or touchscreen.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * // Make the interactions 3X sensitive. + * orbitControl(3, 3, 3); + * + * // Style the box. + * normalMaterial(); + * + * // Draw the box. + * box(30, 50); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A multicolor box on a gray background. The camera angle changes when the user interacts using a mouse, trackpad, or touchscreen.'); + * } + * + * function draw() { + * background(200); + * + * // Create an options object. + * let options = { + * disableTouchActions: false, + * freeRotation: true + * }; + * + * // Enable orbiting with the mouse. + * // Prevent accidental touch actions on touchscreen devices + * // and enable free rotation. + * orbitControl(1, 1, 1, options); + * + * // Style the box. + * normalMaterial(); + * + * // Draw the box. + * box(30, 50); + * } + * + *
*/ // implementation based on three.js 'orbitControls': // https://github.com/mrdoob/three.js/blob/6afb8595c0bf8b2e72818e42b64e6fe22707d896/examples/jsm/controls/OrbitControls.js#L22 @@ -105366,7 +122271,7 @@ if (pointersInCanvas) this._renderer.executeZoom = true; } else { // quit zoom when you stop wheeling. - this._renderer.zoomFlag = false; + this._renderer.executeZoom = false; } if (this.mouseIsPressed) { if (this.mouseButton === this.LEFT) { @@ -105478,147 +122383,182 @@ return this; }; /** - * debugMode() helps visualize 3D space by adding a grid to indicate where the - * ‘ground’ is in a sketch and an axes icon which indicates the +X, +Y, and +Z - * directions. This function can be called without parameters to create a - * default grid and axes icon, or it can be called according to the examples - * above to customize the size and position of the grid and/or axes icon. The - * grid is drawn using the most recently set stroke color and weight. To - * specify these parameters, add a call to stroke() and strokeWeight() - * just before the end of the draw() loop. - * - * By default, the grid will run through the origin (0,0,0) of the sketch - * along the XZ plane - * and the axes icon will be offset from the origin. Both the grid and axes - * icon will be sized according to the current canvas size. Note that because the - * grid runs parallel to the default camera view, it is often helpful to use - * debugMode along with orbitControl to allow full view of the grid. + * Adds a grid and an axes icon to clarify orientation in 3D sketches. + * + * `debugMode()` adds a grid that shows where the “ground” is in a sketch. By + * default, the grid will run through the origin `(0, 0, 0)` of the sketch + * along the XZ plane. `debugMode()` also adds an axes icon that points along + * the positive x-, y-, and z-axes. Calling `debugMode()` displays the grid + * and axes icon with their default size and position. + * + * There are four ways to call `debugMode()` with optional parameters to + * customize the debugging environment. + * + * The first way to call `debugMode()` has one parameter, `mode`. If the + * system constant `GRID` is passed, as in `debugMode(GRID)`, then the grid + * will be displayed and the axes icon will be hidden. If the constant `AXES` + * is passed, as in `debugMode(AXES)`, then the axes icon will be displayed + * and the grid will be hidden. + * + * The second way to call `debugMode()` has six parameters. The first + * parameter, `mode`, selects either `GRID` or `AXES` to be displayed. The + * next five parameters, `gridSize`, `gridDivisions`, `xOff`, `yOff`, and + * `zOff` are optional. They’re numbers that set the appearance of the grid + * (`gridSize` and `gridDivisions`) and the placement of the axes icon + * (`xOff`, `yOff`, and `zOff`). For example, calling + * `debugMode(20, 5, 10, 10, 10)` sets the `gridSize` to 20 pixels, the number + * of `gridDivisions` to 5, and offsets the axes icon by 10 pixels along the + * x-, y-, and z-axes. + * + * The third way to call `debugMode()` has five parameters. The first + * parameter, `mode`, selects either `GRID` or `AXES` to be displayed. The + * next four parameters, `axesSize`, `xOff`, `yOff`, and `zOff` are optional. + * They’re numbers that set the appearance of the size of the axes icon + * (`axesSize`) and its placement (`xOff`, `yOff`, and `zOff`). + * + * The fourth way to call `debugMode()` has nine optional parameters. The + * first five parameters, `gridSize`, `gridDivisions`, `gridXOff`, `gridYOff`, + * and `gridZOff` are numbers that set the appearance of the grid. For + * example, calling `debugMode(100, 5, 0, 0, 0)` sets the `gridSize` to 100, + * the number of `gridDivisions` to 5, and sets all the offsets to 0 so that + * the grid is centered at the origin. The next four parameters, `axesSize`, + * `xOff`, `yOff`, and `zOff` are numbers that set the appearance of the size + * of the axes icon (`axesSize`) and its placement (`axesXOff`, `axesYOff`, + * and `axesZOff`). For example, calling + * `debugMode(100, 5, 0, 0, 0, 50, 10, 10, 10)` sets the `gridSize` to 100, + * the number of `gridDivisions` to 5, and sets all the offsets to 0 so that + * the grid is centered at the origin. It then sets the `axesSize` to 50 and + * offsets the icon 10 pixels along each axis. + * * @method debugMode + * * @example *
* + * // Click and drag the mouse to view the scene from different angles. + * * function setup() { * createCanvas(100, 100, WEBGL); - * camera(0, -30, 100, 0, 0, 0, 0, 1, 0); - * normalMaterial(); + * + * // Enable debug mode. * debugMode(); - * describe( - * 'a 3D box is centered on a grid in a 3D sketch. an icon indicates the direction of each axis: a red line points +X, a green line +Y, and a blue line +Z. the grid and icon disappear when the spacebar is pressed.' - * ); + * + * describe('A multicolor box on a gray background. A grid and axes icon are displayed near the box.'); * } * * function draw() { * background(200); + * + * // Enable orbiting with the mouse. * orbitControl(); - * box(15, 30); - * // Press the spacebar to turn debugMode off! - * if (keyIsDown(32)) { - * noDebugMode(); - * } - * } - * - *
- * @alt - * a 3D box is centered on a grid in a 3D sketch. an icon - * indicates the direction of each axis: a red line points +X, - * a green line +Y, and a blue line +Z. the grid and icon disappear when the - * spacebar is pressed. * - * @example - *
- * - * function setup() { - * createCanvas(100, 100, WEBGL); - * camera(0, -30, 100, 0, 0, 0, 0, 1, 0); + * // Style the box. * normalMaterial(); - * debugMode(GRID); - * describe('a 3D box is centered on a grid in a 3D sketch.'); - * } * - * function draw() { - * background(200); - * orbitControl(); - * box(15, 30); + * // Draw the box. + * box(20, 40); * } * *
- * @alt - * a 3D box is centered on a grid in a 3D sketch. * - * @example *
* + * // Click and drag the mouse to view the scene from different angles. + * * function setup() { * createCanvas(100, 100, WEBGL); - * camera(0, -30, 100, 0, 0, 0, 0, 1, 0); - * normalMaterial(); + * + * // Enable debug mode. + * // Only display the axes icon. * debugMode(AXES); - * describe( - * 'a 3D box is centered in a 3D sketch. an icon indicates the direction of each axis: a red line points +X, a green line +Y, and a blue line +Z.' - * ); + * + * describe('A multicolor box on a gray background. A grid and axes icon are displayed near the box.'); * } * * function draw() { * background(200); + * + * // Enable orbiting with the mouse. * orbitControl(); - * box(15, 30); + * + * // Style the box. + * normalMaterial(); + * + * // Draw the box. + * box(20, 40); * } * *
- * @alt - * a 3D box is centered in a 3D sketch. an icon - * indicates the direction of each axis: a red line points +X, - * a green line +Y, and a blue line +Z. * - * @example *
* + * // Click and drag the mouse to view the scene from different angles. + * * function setup() { * createCanvas(100, 100, WEBGL); - * camera(0, -30, 100, 0, 0, 0, 0, 1, 0); - * normalMaterial(); - * debugMode(GRID, 100, 10, 0, 0, 0); - * describe('a 3D box is centered on a grid in a 3D sketch'); + * + * // Enable debug mode. + * // Only display the grid and customize it: + * // - size: 50 + * // - divisions: 10 + * // - offsets: 0, 20, 0 + * debugMode(GRID, 50, 10, 0, 20, 0); + * + * describe('A multicolor box on a gray background. A grid is displayed below the box.'); * } * * function draw() { * background(200); + * + * // Enable orbiting with the mouse. * orbitControl(); - * box(15, 30); + * + * // Style the box. + * normalMaterial(); + * + * // Draw the box. + * box(20, 40); * } * *
- * @alt - * a 3D box is centered on a grid in a 3D sketch * - * @example *
* + * // Click and drag the mouse to view the scene from different angles. + * * function setup() { * createCanvas(100, 100, WEBGL); - * camera(0, -30, 100, 0, 0, 0, 0, 1, 0); - * normalMaterial(); - * debugMode(100, 10, 0, 0, 0, 20, 0, -40, 0); - * describe( - * 'a 3D box is centered on a grid in a 3D sketch. an icon indicates the direction of each axis: a red line points +X, a green line +Y, and a blue line +Z.' - * ); + * + * // Enable debug mode. + * // Display the grid and axes icon and customize them: + * // Grid + * // ---- + * // - size: 50 + * // - divisions: 10 + * // - offsets: 0, 20, 0 + * // Axes + * // ---- + * // - size: 50 + * // - offsets: 0, 0, 0 + * debugMode(50, 10, 0, 20, 0, 50, 0, 0, 0); + * + * describe('A multicolor box on a gray background. A grid is displayed below the box. An axes icon is displayed at the center of the box.'); * } * * function draw() { - * noStroke(); * background(200); + * + * // Enable orbiting with the mouse. * orbitControl(); - * box(15, 30); - * // set the stroke color and weight for the grid! - * stroke(255, 0, 150); - * strokeWeight(0.8); + * + * // Style the box. + * normalMaterial(); + * + * // Draw the box. + * box(20, 40); * } * *
- * @alt - * a 3D box is centered on a grid in a 3D sketch. an icon - * indicates the direction of each axis: a red line points +X, - * a green line +Y, and a blue line +Z. */ /** * @method debugMode @@ -105627,16 +122567,16 @@ /** * @method debugMode * @param {Constant} mode - * @param {Number} [gridSize] size of one side of the grid - * @param {Number} [gridDivisions] number of divisions in the grid - * @param {Number} [xOff] X axis offset from origin (0,0,0) - * @param {Number} [yOff] Y axis offset from origin (0,0,0) - * @param {Number} [zOff] Z axis offset from origin (0,0,0) + * @param {Number} [gridSize] side length of the grid. + * @param {Number} [gridDivisions] number of divisions in the grid. + * @param {Number} [xOff] offset from origin along the x-axis. + * @param {Number} [yOff] offset from origin along the y-axis. + * @param {Number} [zOff] offset from origin along the z-axis. */ /** * @method debugMode * @param {Constant} mode - * @param {Number} [axesSize] size of axes icon + * @param {Number} [axesSize] length of axes icon markers. * @param {Number} [xOff] * @param {Number} [yOff] * @param {Number} [zOff] @@ -105645,13 +122585,13 @@ * @method debugMode * @param {Number} [gridSize] * @param {Number} [gridDivisions] - * @param {Number} [gridXOff] - * @param {Number} [gridYOff] - * @param {Number} [gridZOff] + * @param {Number} [gridXOff] grid offset from the origin along the x-axis. + * @param {Number} [gridYOff] grid offset from the origin along the y-axis. + * @param {Number} [gridZOff] grid offset from the origin along the z-axis. * @param {Number} [axesSize] - * @param {Number} [axesXOff] - * @param {Number} [axesYOff] - * @param {Number} [axesZOff] + * @param {Number} [axesXOff] axes icon offset from the origin along the x-axis. + * @param {Number} [axesYOff] axes icon offset from the origin along the y-axis. + * @param {Number} [axesZOff] axes icon offset from the origin along the z-axis. */ _main.default.prototype.debugMode = function () { this._assert3d('debugMode'); @@ -105668,46 +122608,51 @@ } // then add new debugMode functions according to the argument list if (args[0] === constants.GRID) { - this.registerMethod('post', this._grid.call(this, args[1], args[2], args[3], args[4], args[5])); + this.registerMethod('post', this._grid(args[1], args[2], args[3], args[4], args[5])); } else if (args[0] === constants.AXES) { - this.registerMethod('post', this._axesIcon.call(this, args[1], args[2], args[3], args[4])); + this.registerMethod('post', this._axesIcon(args[1], args[2], args[3], args[4])); } else { - this.registerMethod('post', this._grid.call(this, args[0], args[1], args[2], args[3], args[4])); - this.registerMethod('post', this._axesIcon.call(this, args[5], args[6], args[7], args[8])); + this.registerMethod('post', this._grid(args[0], args[1], args[2], args[3], args[4])); + this.registerMethod('post', this._axesIcon(args[5], args[6], args[7], args[8])); } }; /** - * Turns off debugMode() in a 3D sketch. + * Turns off debugMode() in a 3D sketch. + * * @method noDebugMode + * * @example *
* + * // Click and drag the mouse to view the scene from different angles. + * * function setup() { * createCanvas(100, 100, WEBGL); - * camera(0, -30, 100, 0, 0, 0, 0, 1, 0); - * normalMaterial(); + * + * // Enable debug mode. * debugMode(); - * describe( - * 'a 3D box is centered on a grid in a 3D sketch. an icon indicates the direction of each axis: a red line points +X, a green line +Y, and a blue line +Z. the grid and icon disappear when the spacebar is pressed.' - * ); + * + * describe('A multicolor box on a gray background. A grid and axes icon are displayed near the box. They disappear when the user double-clicks.'); * } * * function draw() { * background(200); + * + * // Enable orbiting with the mouse. * orbitControl(); - * box(15, 30); - * // Press the spacebar to turn debugMode off! - * if (keyIsDown(32)) { - * noDebugMode(); - * } + * + * // Style the box. + * normalMaterial(); + * + * // Draw the box. box(20, 40); + * } + * + * // Disable debug mode when the user double-clicks. + * function doubleClicked() { + * noDebugMode(); * } * *
- * @alt - * a 3D box is centered on a grid in a 3D sketch. an icon - * indicates the direction of each axis: a red line points +X, - * a green line +Y, and a blue line +Z. the grid and icon disappear when the - * spacebar is pressed. */ _main.default.prototype.noDebugMode = function () { this._assert3d('noDebugMode'); @@ -105751,7 +122696,7 @@ return function () { this.push(); this.stroke(this._renderer.curStrokeColor[0] * 255, this._renderer.curStrokeColor[1] * 255, this._renderer.curStrokeColor[2] * 255); - this._renderer.uMVMatrix.set(this._renderer._curCamera.cameraMatrix.mat4[0], this._renderer._curCamera.cameraMatrix.mat4[1], this._renderer._curCamera.cameraMatrix.mat4[2], this._renderer._curCamera.cameraMatrix.mat4[3], this._renderer._curCamera.cameraMatrix.mat4[4], this._renderer._curCamera.cameraMatrix.mat4[5], this._renderer._curCamera.cameraMatrix.mat4[6], this._renderer._curCamera.cameraMatrix.mat4[7], this._renderer._curCamera.cameraMatrix.mat4[8], this._renderer._curCamera.cameraMatrix.mat4[9], this._renderer._curCamera.cameraMatrix.mat4[10], this._renderer._curCamera.cameraMatrix.mat4[11], this._renderer._curCamera.cameraMatrix.mat4[12], this._renderer._curCamera.cameraMatrix.mat4[13], this._renderer._curCamera.cameraMatrix.mat4[14], this._renderer._curCamera.cameraMatrix.mat4[15]); + this._renderer.uModelMatrix.reset(); // Lines along X axis for (var q = 0; q <= numDivs; q++) { this.beginShape(this.LINES); @@ -105793,7 +122738,7 @@ } return function () { this.push(); - this._renderer.uMVMatrix.set(this._renderer._curCamera.cameraMatrix.mat4[0], this._renderer._curCamera.cameraMatrix.mat4[1], this._renderer._curCamera.cameraMatrix.mat4[2], this._renderer._curCamera.cameraMatrix.mat4[3], this._renderer._curCamera.cameraMatrix.mat4[4], this._renderer._curCamera.cameraMatrix.mat4[5], this._renderer._curCamera.cameraMatrix.mat4[6], this._renderer._curCamera.cameraMatrix.mat4[7], this._renderer._curCamera.cameraMatrix.mat4[8], this._renderer._curCamera.cameraMatrix.mat4[9], this._renderer._curCamera.cameraMatrix.mat4[10], this._renderer._curCamera.cameraMatrix.mat4[11], this._renderer._curCamera.cameraMatrix.mat4[12], this._renderer._curCamera.cameraMatrix.mat4[13], this._renderer._curCamera.cameraMatrix.mat4[14], this._renderer._curCamera.cameraMatrix.mat4[15]); + this._renderer.uModelMatrix.reset(); // X axis this.strokeWeight(2); this.stroke(255, 0, 0); @@ -105820,28 +122765,30 @@ exports.default = _default; }, { - '../core/constants': 286, - '../core/main': 298, - 'core-js/modules/es.array.for-each': 175, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.splice': 185, - 'core-js/modules/es.math.hypot': 188, - 'core-js/modules/es.math.sign': 190, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.for-each': 255, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/constants': 294, + '../core/main': 306, + 'core-js/modules/es.array.for-each': 179, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.splice': 189, + 'core-js/modules/es.math.hypot': 194, + 'core-js/modules/es.math.sign': 196, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.for-each': 263, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 344: [ + 352: [ function (_dereq_, module, exports) { 'use strict'; + _dereq_('core-js/modules/es.array.filter'); + _dereq_('core-js/modules/es.array.filter'); Object.defineProperty(exports, '__esModule', { value: true }); @@ -105859,107 +122806,178 @@ * @requires core */ /** - * Creates an ambient light with the given color. + * Creates a light that shines from all directions. * - * Ambient light does not come from a specific direction. - * Objects are evenly lit from all sides. Ambient lights are - * almost always used in combination with other types of lights. + * Ambient light does not come from one direction. Instead, 3D shapes are + * lit evenly from all sides. Ambient lights are almost always used in + * combination with other types of lights. * - * Note: lights need to be called (whether directly or indirectly) - * within draw() to remain persistent in a looping program. - * Placing them in setup() will cause them to only have an effect - * the first time through the loop. + * There are three ways to call `ambientLight()` with optional parameters to + * set the light’s color. + * + * The first way to call `ambientLight()` has two parameters, `gray` and + * `alpha`. `alpha` is optional. Grayscale and alpha values between 0 and 255 + * can be passed to set the ambient light’s color, as in `ambientLight(50)` or + * `ambientLight(50, 30)`. + * + * The second way to call `ambientLight()` has one parameter, color. A + * p5.Color object, an array of color values, or a + * CSS color string, as in `ambientLight('magenta')`, can be passed to set the + * ambient light’s color. + * + * The third way to call `ambientLight()` has four parameters, `v1`, `v2`, + * `v3`, and `alpha`. `alpha` is optional. RGBA, HSBA, or HSLA values can be + * passed to set the ambient light’s colors, as in `ambientLight(255, 0, 0)` + * or `ambientLight(255, 0, 0, 30)`. Color values will be interpreted using + * the current colorMode(). * * @method ambientLight - * @param {Number} v1 red or hue value relative to - * the current color range - * @param {Number} v2 green or saturation value - * relative to the current color range - * @param {Number} v3 blue or brightness value - * relative to the current color range - * @param {Number} [alpha] alpha value relative to current - * color range (default is 0-255) + * @param {Number} v1 red or hue value in the current + * colorMode(). + * @param {Number} v2 green or saturation value in the current + * colorMode(). + * @param {Number} v3 blue, brightness, or lightness value in the current + * colorMode(). + * @param {Number} [alpha] alpha (transparency) value in the current + * colorMode(). * @chainable * * @example *
* + * // Click and drag the mouse to view the scene from different angles. + * // Double-click the canvas to turn on the light. + * + * let isLit = false; + * * function setup() { * createCanvas(100, 100, WEBGL); - * noStroke(); - * describe('sphere with coral color under black light'); + * + * describe('A sphere drawn against a gray background. The sphere appears to change color when the user double-clicks.'); * } + * * function draw() { - * background(100); - * ambientLight(0); // black light (no light) - * ambientMaterial(255, 127, 80); // coral material - * sphere(40); + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Control the light. + * if (isLit === true) { + * // Use a grayscale value of 80. + * ambientLight(80); + * } + * + * // Draw the sphere. + * sphere(30); + * } + * + * // Turn on the ambient light when the user double-clicks. + * function doubleClicked() { + * isLit = true; * } * *
- * @alt - * sphere with coral color under black light * - * @example *
* + * // Click and drag the mouse to view the scene from different angles. + * * function setup() { * createCanvas(100, 100, WEBGL); - * noStroke(); - * describe('sphere with coral color under white light'); + * + * describe('A faded magenta sphere drawn against a gray background.'); * } + * * function draw() { - * background(100); - * ambientLight(255); // white light - * ambientMaterial(255, 127, 80); // coral material - * sphere(40); + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * // Use a p5.Color object. + * let c = color('orchid'); + * ambientLight(c); + * + * // Draw the sphere. + * sphere(); * } * *
- * @alt - * sphere with coral color under white light * - * @example *
* + * // Click and drag the mouse to view the scene from different angles. + * * function setup() { - * createCanvas(100,100,WEBGL); - * camera(0,-100,300); + * createCanvas(100, 100, WEBGL); + * + * describe('A faded magenta sphere drawn against a gray background.'); * } + * * function draw() { - * background(230); - * ambientMaterial(237,34,93); //Pink Material - * ambientLight(mouseY); - * //As you move the mouse up to down it changes from no ambient light to full ambient light. - * rotateY(millis()/2000); - * box(100); + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * // Use a CSS color string. + * ambientLight('#DA70D6'); + * + * // Draw the sphere. + * sphere(30); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A faded magenta sphere drawn against a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * // Use RGB values + * ambientLight(218, 112, 214); + * + * // Draw the sphere. + * sphere(30); * } * *
- * @alt - * pink ambient material cube under the ambient light */ /** * @method ambientLight - * @param {Number} gray number specifying value between - * white and black + * @param {Number} gray grayscale value between 0 and 255. * @param {Number} [alpha] * @chainable */ /** * @method ambientLight - * @param {String} value a color string + * @param {String} value color as a CSS string. * @chainable */ /** * @method ambientLight - * @param {Number[]} values an array containing the red,green,blue & - * and alpha components of the color + * @param {Number[]} values color as an array of RGBA, HSBA, or HSLA + * values. * @chainable */ /** * @method ambientLight - * @param {p5.Color} color color as a p5.Color + * @param {p5.Color} color color as a p5.Color object. * @chainable */ @@ -105972,97 +122990,241 @@ return this; }; /** - * Sets the color of the specular highlight of a non-ambient light - * (i.e. all lights except ambientLight()). - * - * specularColor() affects only the lights which are created after - * it in the code. - * - * This function is used in combination with - * specularMaterial(). - * If a geometry does not use specularMaterial(), this function - * will have no effect. + * Sets the specular color for lights. * - * The default color is white (255, 255, 255), which is used if - * specularColor() is not explicitly called. + * `specularColor()` affects lights that bounce off a surface in a preferred + * direction. These lights include + * directionalLight(), + * pointLight(), and + * spotLight(). The function helps to create + * highlights on p5.Geometry objects that are + * styled with specularMaterial(). If a + * geometry does not use + * specularMaterial(), then + * `specularColor()` will have no effect. + * + * Note: `specularColor()` doesn’t affect lights that bounce in all + * directions, including ambientLight() and + * imageLight(). + * + * There are three ways to call `specularColor()` with optional parameters to + * set the specular highlight color. + * + * The first way to call `specularColor()` has two optional parameters, `gray` + * and `alpha`. Grayscale and alpha values between 0 and 255, as in + * `specularColor(50)` or `specularColor(50, 80)`, can be passed to set the + * specular highlight color. + * + * The second way to call `specularColor()` has one optional parameter, + * `color`. A p5.Color object, an array of color + * values, or a CSS color string can be passed to set the specular highlight + * color. * - * Note: specularColor is equivalent to the Processing function - * lightSpecular. + * The third way to call `specularColor()` has four optional parameters, `v1`, + * `v2`, `v3`, and `alpha`. RGBA, HSBA, or HSLA values, as in + * `specularColor(255, 0, 0, 80)`, can be passed to set the specular highlight + * color. Color values will be interpreted using the current + * colorMode(). * * @method specularColor - * @param {Number} v1 red or hue value relative to - * the current color range - * @param {Number} v2 green or saturation value - * relative to the current color range - * @param {Number} v3 blue or brightness value - * relative to the current color range + * @param {Number} v1 red or hue value in the current + * colorMode(). + * @param {Number} v2 green or saturation value in the current + * colorMode(). + * @param {Number} v3 blue, brightness, or lightness value in the current + * colorMode(). * @chainable + * * @example *
* - * let setRedSpecularColor = true; + * // Click and drag the mouse to view the scene from different angles. * * function setup() { * createCanvas(100, 100, WEBGL); - * noStroke(); - * describe( - * 'Sphere with specular highlight. Clicking the mouse toggles the specular highlight color between red and the default white.' - * ); + * + * describe('A white sphere drawn on a gray background.'); * } * * function draw() { - * background(0); + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // No specular color. + * // Draw the sphere. + * sphere(30); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * // Double-click the canvas to add a point light. + * + * let isLit = false; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A sphere drawn on a gray background. A spotlight starts shining when the user double-clicks.'); + * } * - * ambientLight(60); + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); * - * // add a point light to showcase specular color - * // -- use mouse location to position the light - * let lightPosX = mouseX - width / 2; - * let lightPosY = mouseY - height / 2; - * // -- set the light's specular color - * if (setRedSpecularColor) { - * specularColor(255, 0, 0); // red specular highlight + * // Style the sphere. + * noStroke(); + * specularColor(100); + * specularMaterial(255, 255, 255); + * + * // Control the light. + * if (isLit === true) { + * // Add a white point light from the top-right. + * pointLight(255, 255, 255, 30, -20, 40); * } - * // -- create the light - * pointLight(200, 200, 200, lightPosX, lightPosY, 50); // white light * - * // use specular material with high shininess - * specularMaterial(150); - * shininess(50); + * // Draw the sphere. + * sphere(30); + * } * - * sphere(30, 64, 64); + * // Turn on the point light when the user double-clicks. + * function doubleClicked() { + * isLit = true; * } + * + *
* - * function mouseClicked() { - * setRedSpecularColor = !setRedSpecularColor; + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A black sphere drawn on a gray background. An area on the surface of the sphere is highlighted in blue.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Add a specular highlight. + * // Use a p5.Color object. + * let c = color('dodgerblue'); + * specularColor(c); + * + * // Add a white point light from the top-right. + * pointLight(255, 255, 255, 30, -20, 40); + * + * // Style the sphere. + * noStroke(); + * + * // Add a white specular material. + * specularMaterial(255, 255, 255); + * + * // Draw the sphere. + * sphere(30); * } * *
* - * @alt - * Sphere with specular highlight. Clicking the mouse toggles the - * specular highlight color between red and the default white. + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A black sphere drawn on a gray background. An area on the surface of the sphere is highlighted in blue.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Add a specular highlight. + * // Use a CSS color string. + * specularColor('#1E90FF'); + * + * // Add a white point light from the top-right. + * pointLight(255, 255, 255, 30, -20, 40); + * + * // Style the sphere. + * noStroke(); + * + * // Add a white specular material. + * specularMaterial(255, 255, 255); + * + * // Draw the sphere. + * sphere(30); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A black sphere drawn on a gray background. An area on the surface of the sphere is highlighted in blue.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Add a specular highlight. + * // Use RGB values. + * specularColor(30, 144, 255); + * + * // Add a white point light from the top-right. + * pointLight(255, 255, 255, 30, -20, 40); + * + * // Style the sphere. + * noStroke(); + * + * // Add a white specular material. + * specularMaterial(255, 255, 255); + * + * // Draw the sphere. + * sphere(30); + * } + * + *
*/ /** * @method specularColor - * @param {Number} gray number specifying value between - * white and black + * @param {Number} gray grayscale value between 0 and 255. * @chainable */ /** * @method specularColor - * @param {String} value color as a CSS string + * @param {String} value color as a CSS string. * @chainable */ /** * @method specularColor - * @param {Number[]} values color as an array containing the - * red, green, and blue components + * @param {Number[]} values color as an array of RGBA, HSBA, or HSLA + * values. * @chainable */ /** * @method specularColor - * @param {p5.Color} color color as a p5.Color + * @param {p5.Color} color color as a p5.Color object. * @chainable */ _main.default.prototype.specularColor = function (v1, v2, v3) { @@ -106077,75 +123239,169 @@ return this; }; /** - * Creates a directional light with the given color and direction. + * Creates a light that shines in one direction. + * + * Directional lights don’t shine from a specific point. They’re like a sun + * that shines from somewhere offscreen. The light’s direction is set using + * three `(x, y, z)` values between -1 and 1. For example, setting a light’s + * direction as `(1, 0, 0)` will light p5.Geometry + * objects from the left since the light faces directly to the right. + * + * There are four ways to call `directionalLight()` with parameters to set the + * light’s color and direction. + * + * The first way to call `directionalLight()` has six parameters. The first + * three parameters, `v1`, `v2`, and `v3`, set the light’s color using the + * current colorMode(). The last three + * parameters, `x`, `y`, and `z`, set the light’s direction. For example, + * `directionalLight(255, 0, 0, 1, 0, 0)` creates a red `(255, 0, 0)` light + * that shines to the right `(1, 0, 0)`. + * + * The second way to call `directionalLight()` has four parameters. The first + * three parameters, `v1`, `v2`, and `v3`, set the light’s color using the + * current colorMode(). The last parameter, + * `direction` sets the light’s direction using a + * p5.Geometry object. For example, + * `directionalLight(255, 0, 0, lightDir)` creates a red `(255, 0, 0)` light + * that shines in the direction the `lightDir` vector points. + * + * The third way to call `directionalLight()` has four parameters. The first + * parameter, `color`, sets the light’s color using a + * p5.Color object or an array of color values. The + * last three parameters, `x`, `y`, and `z`, set the light’s direction. For + * example, `directionalLight(myColor, 1, 0, 0)` creates a light that shines + * to the right `(1, 0, 0)` with the color value of `myColor`. + * + * The fourth way to call `directionalLight()` has two parameters. The first + * parameter, `color`, sets the light’s color using a + * p5.Color object or an array of color values. The + * second parameter, `direction`, sets the light’s direction using a + * p5.Color object. For example, + * `directionalLight(myColor, lightDir)` creates a light that shines in the + * direction the `lightDir` vector points with the color value of `myColor`. * - * Directional light comes from one direction. - * The direction is specified as numbers inclusively between -1 and 1. - * For example, setting the direction as (0, -1, 0) will cause the - * geometry to be lit from below (since the light will be facing - * directly upwards). Similarly, setting the direction as (1, 0, 0) - * will cause the geometry to be lit from the left (since the light - * will be facing directly rightwards). + * @method directionalLight + * @param {Number} v1 red or hue value in the current + * colorMode(). + * @param {Number} v2 green or saturation value in the current + * colorMode(). + * @param {Number} v3 blue, brightness, or lightness value in the current + * colorMode(). + * @param {Number} x x-component of the light's direction between -1 and 1. + * @param {Number} y y-component of the light's direction between -1 and 1. + * @param {Number} z z-component of the light's direction between -1 and 1. + * @chainable * - * Directional lights do not have a specific point of origin, and - * therefore cannot be positioned closer or farther away from a geometry. + * @example + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * // Double-click to turn on the directional light. * - * A maximum of **5** directional lights can be active at once. + * let isLit = false; * - * Note: lights need to be called (whether directly or indirectly) - * within draw() to remain persistent in a looping program. - * Placing them in setup() will cause them to only have an effect - * the first time through the loop. + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A sphere drawn on a gray background. A red light starts shining from above when the user double-clicks.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Control the light. + * if (isLit === true) { + * // Add a red directional light from above. + * // Use RGB values and XYZ directions. + * directionalLight(255, 0, 0, 0, 1, 0); + * } + * + * // Style the sphere. + * noStroke(); + * + * // Draw the sphere. + * sphere(30); + * } + * + *
* - * @method directionalLight - * @param {Number} v1 red or hue value relative to the current - * color range - * @param {Number} v2 green or saturation value relative to the - * current color range - * @param {Number} v3 blue or brightness value relative to the - * current color range - * @param {Number} x x component of direction (inclusive range of -1 to 1) - * @param {Number} y y component of direction (inclusive range of -1 to 1) - * @param {Number} z z component of direction (inclusive range of -1 to 1) - * @chainable - * @example *
* + * // Click and drag the mouse to view the scene from different angles. + * * function setup() { * createCanvas(100, 100, WEBGL); - * describe( - * 'scene with sphere and directional light. The direction of the light is controlled with the mouse position.' - * ); + * + * describe('A sphere drawn on a gray background. The top of the sphere appears bright red. The color gets darker toward the bottom.'); * } + * * function draw() { - * background(0); - * //move your mouse to change light direction - * let dirX = (mouseX / width - 0.5) * 2; - * let dirY = (mouseY / height - 0.5) * 2; - * directionalLight(250, 250, 250, -dirX, -dirY, -1); + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Add a red directional light from above. + * // Use a p5.Color object and XYZ directions. + * let c = color(255, 0, 0); + * directionalLight(c, 0, 1, 0); + * + * // Style the sphere. * noStroke(); - * sphere(40); + * + * // Draw the sphere. + * sphere(30); * } * *
* - * @alt - * scene with sphere and directional light. The direction of - * the light is controlled with the mouse position. + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A sphere drawn on a gray background. The top of the sphere appears bright red. The color gets darker toward the bottom.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Add a red directional light from above. + * // Use a p5.Color object and a p5.Vector object. + * let c = color(255, 0, 0); + * let lightDir = createVector(0, 1, 0); + * directionalLight(c, lightDir); + * + * // Style the sphere. + * noStroke(); + * + * // Draw the sphere. + * sphere(30); + * } + * + *
*/ /** * @method directionalLight * @param {Number} v1 * @param {Number} v2 * @param {Number} v3 - * @param {p5.Vector} direction direction of light as a - * p5.Vector + * @param {p5.Vector} direction direction of the light as a + * p5.Vector object. * @chainable */ /** * @method directionalLight - * @param {p5.Color|Number[]|String} color color as a p5.Color, - * as an array, or as a CSS string + * @param {p5.Color|Number[]|String} color color as a p5.Color object, + * an array of color values, or as a CSS string. * @param {Number} x * @param {Number} y * @param {Number} z @@ -106189,75 +123445,224 @@ return this; }; /** - * Creates a point light with the given color and position. - * - * A point light emits light from a single point in all directions. - * Because the light is emitted from a specific point (position), - * it has a different effect when it is positioned farther vs. nearer - * an object. - * - * A maximum of **5** point lights can be active at once. - * - * Note: lights need to be called (whether directly or indirectly) - * within draw() to remain persistent in a looping program. - * Placing them in setup() will cause them to only have an effect - * the first time through the loop. + * Creates a light that shines from a point in all directions. + * + * Point lights are like light bulbs that shine in all directions. They can be + * placed at different positions to achieve different lighting effects. A + * maximum of 5 point lights can be active at once. + * + * There are four ways to call `pointLight()` with parameters to set the + * light’s color and position. + * + * The first way to call `pointLight()` has six parameters. The first three + * parameters, `v1`, `v2`, and `v3`, set the light’s color using the current + * colorMode(). The last three parameters, `x`, + * `y`, and `z`, set the light’s position. For example, + * `pointLight(255, 0, 0, 50, 0, 0)` creates a red `(255, 0, 0)` light that + * shines from the coordinates `(50, 0, 0)`. + * + * The second way to call `pointLight()` has four parameters. The first three + * parameters, `v1`, `v2`, and `v3`, set the light’s color using the current + * colorMode(). The last parameter, position sets + * the light’s position using a p5.Vector object. + * For example, `pointLight(255, 0, 0, lightPos)` creates a red `(255, 0, 0)` + * light that shines from the position set by the `lightPos` vector. + * + * The third way to call `pointLight()` has four parameters. The first + * parameter, `color`, sets the light’s color using a + * p5.Color object or an array of color values. The + * last three parameters, `x`, `y`, and `z`, set the light’s position. For + * example, `directionalLight(myColor, 50, 0, 0)` creates a light that shines + * from the coordinates `(50, 0, 0)` with the color value of `myColor`. + * + * The fourth way to call `pointLight()` has two parameters. The first + * parameter, `color`, sets the light’s color using a + * p5.Color object or an array of color values. The + * second parameter, `position`, sets the light’s position using a + * p5.Vector object. For example, + * `directionalLight(myColor, lightPos)` creates a light that shines from the + * position set by the `lightPos` vector with the color value of `myColor`. * * @method pointLight - * @param {Number} v1 red or hue value relative to the current - * color range - * @param {Number} v2 green or saturation value relative to the - * current color range - * @param {Number} v3 blue or brightness value relative to the - * current color range - * @param {Number} x x component of position - * @param {Number} y y component of position - * @param {Number} z z component of position + * @param {Number} v1 red or hue value in the current + * colorMode(). + * @param {Number} v2 green or saturation value in the current + * colorMode(). + * @param {Number} v3 blue, brightness, or lightness value in the current + * colorMode(). + * @param {Number} x x-coordinate of the light. + * @param {Number} y y-coordinate of the light. + * @param {Number} z z-coordinate of the light. * @chainable + * * @example + * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * // Double-click to turn on the point light. + * + * let isLit = false; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A sphere drawn on a gray background. A red light starts shining from above when the user double-clicks.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Control the light. + * if (isLit === true) { + * // Add a red point light from above. + * // Use RGB values and XYZ coordinates. + * pointLight(255, 0, 0, 0, -150, 0); + * } + * + * // Style the sphere. + * noStroke(); + * + * // Draw the sphere. + * sphere(30); + * } + * + * // Turn on the point light when the user double-clicks. + * function doubleClicked() { + * isLit = true; + * } + * + *
+ * *
* + * // Click and drag the mouse to view the scene from different angles. + * * function setup() { * createCanvas(100, 100, WEBGL); - * describe( - * 'scene with sphere and point light. The position of the light is controlled with the mouse position.' - * ); + * + * describe('A sphere drawn on a gray background. The top of the sphere appears bright red. The color gets darker toward the bottom.'); * } + * * function draw() { - * background(0); - * // move your mouse to change light position - * let locX = mouseX - width / 2; - * let locY = mouseY - height / 2; - * // to set the light position, - * // think of the world's coordinate as: - * // -width/2,-height/2 ----------- width/2,-height/2 - * // | | - * // | 0,0 | - * // | | - * // -width/2,height/2 ----------- width/2,height/2 - * pointLight(250, 250, 250, locX, locY, 50); + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Add a red point light from above. + * // Use a p5.Color object and XYZ directions. + * let c = color(255, 0, 0); + * pointLight(c, 0, -150, 0); + * + * // Style the sphere. * noStroke(); - * sphere(40); + * + * // Draw the sphere. + * sphere(30); * } * *
* - * @alt - * scene with sphere and point light. The position of - * the light is controlled with the mouse position. + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A sphere drawn on a gray background. The top of the sphere appears bright red. The color gets darker toward the bottom.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Add a red point light from above. + * // Use a p5.Color object and a p5.Vector object. + * let c = color(255, 0, 0); + * let lightPos = createVector(0, -150, 0); + * pointLight(c, lightPos); + * + * // Style the sphere. + * noStroke(); + * + * // Draw the sphere. + * sphere(30); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('Four spheres arranged in a square and drawn on a gray background. The spheres appear bright red toward the center of the square. The color gets darker toward the corners of the square.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Add a red point light that points to the center of the scene. + * // Use a p5.Color object and a p5.Vector object. + * let c = color(255, 0, 0); + * let lightPos = createVector(0, 0, 65); + * pointLight(c, lightPos); + * + * // Style the spheres. + * noStroke(); + * + * // Draw a sphere up and to the left. + * push(); + * translate(-25, -25, 25); + * sphere(10); + * pop(); + * + * // Draw a box up and to the right. + * push(); + * translate(25, -25, 25); + * sphere(10); + * pop(); + * + * // Draw a sphere down and to the left. + * push(); + * translate(-25, 25, 25); + * sphere(10); + * pop(); + * + * // Draw a box down and to the right. + * push(); + * translate(25, 25, 25); + * sphere(10); + * pop(); + * } + * + *
*/ /** * @method pointLight * @param {Number} v1 * @param {Number} v2 * @param {Number} v3 - * @param {p5.Vector} position of light as a p5.Vector + * @param {p5.Vector} position position of the light as a + * p5.Vector object. * @chainable */ /** * @method pointLight - * @param {p5.Color|Number[]|String} color color as a p5.Color, - * as an array, or as a CSS string + * @param {p5.Color|Number[]|String} color color as a p5.Color object, + * an array of color values, or a CSS string. * @param {Number} x * @param {Number} y * @param {Number} z @@ -106299,96 +123704,123 @@ return this; }; /** - * Creates an image light with the given image. + * Creates an ambient light from an image. * - * The image light simulates light from all the directions. - * This is done by using the image as a texture for an infinitely - * large sphere light. This sphere contains - * or encapsulates the whole scene/drawing. - * It will have different effect for varying shininess of the - * object in the drawing. - * Under the hood it is mainly doing 2 types of calculations, - * the first one is creating an irradiance map the - * environment map of the input image. - * The second one is managing reflections based on the shininess - * or roughness of the material used in the scene. + * `imageLight()` simulates a light shining from all directions. The effect is + * like placing the sketch at the center of a giant sphere that uses the image + * as its texture. The image's diffuse light will be affected by + * fill() and the specular reflections will be + * affected by specularMaterial() and + * shininess(). * - * Note: The image's diffuse light will be affected by fill() - * and the specular reflections will be affected by specularMaterial() - * and shininess(). + * The parameter, `img`, is the p5.Image object to + * use as the light source. * * @method imageLight - * @param {p5.image} img image for the background + * @param {p5.image} img image to use as the light source. + * * @example *
* + * // Click and drag the mouse to view the scene from different angles. + * * let img; + * + * // Load an image and create a p5.Image object. * function preload() { - * img = loadImage('assets/outdoor_image.jpg'); + * img = loadImage('assets/outdoor_spheremap.jpg'); * } + * * function setup() { * createCanvas(100, 100, WEBGL); + * + * describe('A sphere floating above a landscape. The surface of the sphere reflects the landscape.'); * } + * * function draw() { - * background(220); - * imageMode(CENTER); - * push(); - * translate(0, 0, -200); - * scale(2); - * image(img, 0, 0, width, height); - * pop(); + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the image as a panorama (360˚ background). + * panorama(img); + * + * // Add a soft ambient light. * ambientLight(50); + * + * // Add light from the image. * imageLight(img); + * + * // Style the sphere. * specularMaterial(20); + * shininess(100); * noStroke(); - * scale(2); - * rotateX(frameCount * 0.005); - * rotateY(frameCount * 0.005); - * box(25); + * + * // Draw the sphere. + * sphere(30); * } * *
- * @alt - * image light example + */ + _main.default.prototype.imageLight = function (img) { + // activeImageLight property is checked by _setFillUniforms + // for sending uniforms to the fillshader + this._renderer.activeImageLight = img; + this._renderer._enableLighting = true; + }; + /** + * Creates an immersive 3D background. + * + * `panorama()` transforms images containing 360˚ content, such as maps or + * HDRIs, into immersive 3D backgrounds that surround a sketch. Exploring the + * space requires changing the camera's perspective with functions such as + * orbitControl() or + * camera(). + * + * @method panorama + * @param {p5.Image} img 360˚ image to use as the background. + * * @example *
* + * // Click and drag the mouse to view the scene from different angles. + * * let img; - * let slider; + * + * // Load an image and create a p5.Image object. * function preload() { * img = loadImage('assets/outdoor_spheremap.jpg'); * } + * * function setup() { - * createCanvas(100, 100, WEBGL); - * slider = createSlider(0, 400, 100, 1); - * slider.position(0, height); + * createCanvas(100 ,100 ,WEBGL); + * + * describe('A sphere floating above a landscape. The surface of the sphere reflects the landscape. The full landscape is viewable in 3D as the user drags the mouse.'); * } + * * function draw() { - * background(220); - * imageMode(CENTER); - * push(); - * translate(0, 0, -200); - * scale(2); - * image(img, 0, 0, width, height); - * pop(); - * ambientLight(50); + * // Add the panorama. + * panorama(img); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Use the image as a light source. * imageLight(img); - * specularMaterial(20); - * shininess(slider.value()); + * + * // Style the sphere. * noStroke(); - * scale(2); - * sphere(15); + * specularMaterial(50); + * shininess(200); + * metalness(100); + * + * // Draw the sphere. + * sphere(30); * } * *
- * @alt - * light with slider having a slider for varying roughness */ - _main.default.prototype.imageLight = function (img) { - // activeImageLight property is checked by _setFillUniforms - // for sending uniforms to the fillshader - this._renderer.activeImageLight = img; - this._renderer._enableLighting = true; + _main.default.prototype.panorama = function (img) { + this.filter(this._renderer._getSphereMapping(img)); }; /** * Places an ambient and directional light in the scene. @@ -106402,26 +123834,68 @@ * * @method lights * @chainable + * * @example *
* + * // Click and drag the mouse to view the scene from different angles. + * // Double-click to turn on the lights. + * + * let isLit = false; + * * function setup() { * createCanvas(100, 100, WEBGL); - * describe('the light is partially ambient and partially directional'); + * + * describe('A white box drawn against a gray background. The quality of the light changes when the user double-clicks.'); * } + * * function draw() { - * background(0); - * lights(); - * rotateX(millis() / 1000); - * rotateY(millis() / 1000); - * rotateZ(millis() / 1000); + * background(50); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Control the lights. + * if (isLit === true) { + * lights(); + * } + * + * // Draw the box. * box(); * } + * + * // Turn on the lights when the user double-clicks. + * function doubleClicked() { + * isLit = true; + * } * *
* - * @alt - * the light is partially ambient and partially directional + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white box drawn against a gray background.'); + * } + * + * function draw() { + * background(50); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * ambientLight(128, 128, 128); + * directionalLight(128, 128, 128, 0, 0, -1); + * + * // Draw the box. + * box(); + * } + * + *
*/ _main.default.prototype.lights = function () { this._assert3d('lights'); @@ -106435,57 +123909,66 @@ * Sets the falloff rate for pointLight() * and spotLight(). * - * lightFalloff() affects only the lights which are created after it - * in the code. + * A light’s falloff describes the intensity of its beam at a distance. For + * example, a lantern has a slow falloff, a flashlight has a medium falloff, + * and a laser pointer has a sharp falloff. * - * The `constant`, `linear`, an `quadratic` parameters are used to calculate falloff as follows: + * `lightFalloff()` has three parameters, `constant`, `linear`, and + * `quadratic`. They’re numbers used to calculate falloff at a distance, `d`, + * as follows: * - * d = distance from light position to vertex position + * `falloff = 1 / (constant + d * linear + (d * d) * quadratic)` * - * falloff = 1 / (CONSTANT + d \* LINEAR + (d \* d) \* QUADRATIC) + * Note: `constant`, `linear`, and `quadratic` should always be set to values + * greater than 0. * * @method lightFalloff - * @param {Number} constant CONSTANT value for determining falloff - * @param {Number} linear LINEAR value for determining falloff - * @param {Number} quadratic QUADRATIC value for determining falloff + * @param {Number} constant constant value for calculating falloff. + * @param {Number} linear linear value for calculating falloff. + * @param {Number} quadratic quadratic value for calculating falloff. * @chainable + * * @example *
* + * // Click and drag the mouse to view the scene from different angles. + * // Double-click to change the falloff rate. + * + * let useFalloff = false; + * * function setup() { * createCanvas(100, 100, WEBGL); - * noStroke(); - * describe( - * 'Two spheres with different falloff values show different intensity of light' - * ); + * + * describe('A sphere drawn against a gray background. The intensity of the light changes when the user double-clicks.'); * } + * * function draw() { - * ortho(); - * background(0); + * background(50); * - * let locX = mouseX - width / 2; - * let locY = mouseY - height / 2; - * locX /= 2; // half scale + * // Enable orbiting with the mouse. + * orbitControl(); * - * lightFalloff(1, 0, 0); - * push(); - * translate(-25, 0, 0); - * pointLight(250, 250, 250, locX - 25, locY, 50); - * sphere(20); - * pop(); + * // Set the light falloff. + * if (useFalloff === true) { + * lightFalloff(2, 0, 0); + * } * - * lightFalloff(0.97, 0.03, 0); - * push(); - * translate(25, 0, 0); - * pointLight(250, 250, 250, locX + 25, locY, 50); - * sphere(20); - * pop(); + * // Add a white point light from the front. + * pointLight(255, 255, 255, 0, 0, 100); + * + * // Style the sphere. + * noStroke(); + * + * // Draw the sphere. + * sphere(30); + * } + * + * // Change the falloff value when the user double-clicks. + * function doubleClicked() { + * useFalloff = true; * } * *
- * - * @alt - * Two spheres with different falloff values show different intensity of light */ _main.default.prototype.lightFalloff = function (constantAttenuation, linearAttenuation, quadraticAttenuation) { this._assert3d('lightFalloff'); @@ -106512,84 +123995,138 @@ return this; }; /** - * Creates a spot light with the given color, position, - * light direction, angle, and concentration. + * Creates a light that shines from a point in one direction. * - * Like a pointLight(), a spotLight() - * emits light from a specific point (position). It has a different effect - * when it is positioned farther vs. nearer an object. + * Spot lights are like flashlights that shine in one direction creating a + * cone of light. The shape of the cone can be controlled using the angle and + * concentration parameters. A maximum of 5 spot lights can be active at once. * - * However, unlike a pointLight(), the light is emitted in **one direction** - * along a conical shape. The shape of the cone can be controlled using - * the `angle` and `concentration` parameters. + * There are eight ways to call `spotLight()` with parameters to set the + * light’s color, position, direction. For example, + * `spotLight(255, 0, 0, 0, 0, 0, 1, 0, 0)` creates a red `(255, 0, 0)` light + * at the origin `(0, 0, 0)` that points to the right `(1, 0, 0)`. * - * The `angle` parameter is used to - * determine the radius of the cone. And the `concentration` - * parameter is used to focus the light towards the center of - * the cone. Both parameters are optional, however if you want - * to specify `concentration`, you must also specify `angle`. - * The minimum concentration value is 1. + * The `angle` parameter is optional. It sets the radius of the light cone. + * For example, `spotLight(255, 0, 0, 0, 0, 0, 1, 0, 0, PI / 16)` creates a + * red `(255, 0, 0)` light at the origin `(0, 0, 0)` that points to the right + * `(1, 0, 0)` with an angle of `PI / 16` radians. By default, `angle` is + * `PI / 3` radians. * - * A maximum of **5** spot lights can be active at once. - * - * Note: lights need to be called (whether directly or indirectly) - * within draw() to remain persistent in a looping program. - * Placing them in setup() will cause them to only have an effect - * the first time through the loop. + * The `concentration` parameter is also optional. It focuses the light + * towards the center of the light cone. For example, + * `spotLight(255, 0, 0, 0, 0, 0, 1, 0, 0, PI / 16, 50)` creates a red + * `(255, 0, 0)` light at the origin `(0, 0, 0)` that points to the right + * `(1, 0, 0)` with an angle of `PI / 16` radians at concentration of 50. By + * default, `concentration` is 100. * * @method spotLight - * @param {Number} v1 red or hue value relative to the current color range - * @param {Number} v2 green or saturation value relative to the current color range - * @param {Number} v3 blue or brightness value relative to the current color range - * @param {Number} x x component of position - * @param {Number} y y component of position - * @param {Number} z z component of position - * @param {Number} rx x component of light direction (inclusive range of -1 to 1) - * @param {Number} ry y component of light direction (inclusive range of -1 to 1) - * @param {Number} rz z component of light direction (inclusive range of -1 to 1) - * @param {Number} [angle] angle of cone. Defaults to PI/3 - * @param {Number} [concentration] concentration of cone. Defaults to 100 + * @param {Number} v1 red or hue value in the current + * colorMode(). + * @param {Number} v2 green or saturation value in the current + * colorMode(). + * @param {Number} v3 blue, brightness, or lightness value in the current + * colorMode(). + * @param {Number} x x-coordinate of the light. + * @param {Number} y y-coordinate of the light. + * @param {Number} z z-coordinate of the light. + * @param {Number} rx x-component of light direction between -1 and 1. + * @param {Number} ry y-component of light direction between -1 and 1. + * @param {Number} rz z-component of light direction between -1 and 1. + * @param {Number} [angle] angle of the light cone. Defaults to `PI / 3`. + * @param {Number} [concentration] concentration of the light. Defaults to 100. * @chainable * * @example *
* + * // Click and drag the mouse to view the scene from different angles. + * // Double-click to adjust the spotlight. + * + * let isLit = false; + * * function setup() { * createCanvas(100, 100, WEBGL); - * describe( - * 'scene with sphere and spot light. The position of the light is controlled with the mouse position.' - * ); + * + * describe('A white sphere drawn on a gray background. A red spotlight starts shining when the user double-clicks.'); * } + * * function draw() { - * background(0); - * // move your mouse to change light position - * let locX = mouseX - width / 2; - * let locY = mouseY - height / 2; - * // to set the light position, - * // think of the world's coordinate as: - * // -width/2,-height/2 ----------- width/2,-height/2 - * // | | - * // | 0,0 | - * // | | - * // -width/2,height/2 ----------- width/2,height/2 - * ambientLight(50); - * spotLight(0, 250, 0, locX, locY, 100, 0, 0, -1, Math.PI / 16); - * noStroke(); - * sphere(40); + * background(50); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * lights(); + * + * // Control the spotlight. + * if (isLit === true) { + * // Add a red spot light that shines into the screen. + * // Set its angle to PI / 32 radians. + * spotLight(255, 0, 0, 0, 0, 100, 0, 0, -1, PI / 32); + * } + * + * // Draw the sphere. + * sphere(30); + * } + * + * // Turn on the spotlight when the user double-clicks. + * function doubleClicked() { + * isLit = true; * } * *
* - * @alt - * scene with sphere and spot light. The position of - * the light is controlled with the mouse position. + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * // Double-click to adjust the spotlight. + * + * let isLit = false; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white sphere drawn on a gray background. A red spotlight starts shining when the user double-clicks.'); + * } + * + * function draw() { + * background(50); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * lights(); + * + * // Control the spotlight. + * if (isLit === true) { + * // Add a red spot light that shines into the screen. + * // Set its angle to PI / 3 radians (default). + * // Set its concentration to 1000. + * let c = color(255, 0, 0); + * let position = createVector(0, 0, 100); + * let direction = createVector(0, 0, -1); + * spotLight(c, position, direction, PI / 3, 1000); + * } + * + * // Draw the sphere. + * sphere(30); + * } + * + * // Turn on the spotlight when the user double-clicks. + * function doubleClicked() { + * isLit = true; + * } + * + *
*/ /** * @method spotLight - * @param {p5.Color|Number[]|String} color color as a p5.Color, - * as an array, or as a CSS string - * @param {p5.Vector} position position of light as a p5.Vector - * @param {p5.Vector} direction direction of light as a p5.Vector + * @param {p5.Color|Number[]|String} color color as a p5.Color object, + * an array of color values, or a CSS string. + * @param {p5.Vector} position position of the light as a p5.Vector object. + * @param {p5.Vector} direction direction of light as a p5.Vector object. * @param {Number} [angle] * @param {Number} [concentration] */ @@ -106824,52 +124361,62 @@ return this; }; /** - * Removes all lights present in a sketch. + * Removes all lights from the sketch. * - * All subsequent geometry is rendered without lighting (until a new - * light is created with a call to one of the lighting functions - * (lights(), + * Calling `noLights()` removes any lights created with + * lights(), * ambientLight(), * directionalLight(), - * pointLight(), - * spotLight()). + * pointLight(), or + * spotLight(). These functions may be called + * after `noLights()` to create a new lighting scheme. * * @method noLights * @chainable + * * @example *
* + * // Click and drag the mouse to view the scene from different angles. + * * function setup() { * createCanvas(100, 100, WEBGL); - * describe( - * 'Three white spheres. Each appears as a different color due to lighting.' - * ); + * + * describe('Two spheres drawn against a gray background. The top sphere is white and the bottom sphere is red.'); * } + * * function draw() { - * background(200); + * background(50); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * lights(); + * + * // Style the spheres. * noStroke(); * - * ambientLight(255, 0, 0); - * translate(-30, 0, 0); - * ambientMaterial(255); - * sphere(13); + * // Draw the top sphere. + * push(); + * translate(0, -25, 0); + * sphere(20); + * pop(); * + * // Turn off the lights. * noLights(); - * translate(30, 0, 0); - * ambientMaterial(255); - * sphere(13); * - * ambientLight(0, 255, 0); - * translate(30, 0, 0); - * ambientMaterial(255); - * sphere(13); + * // Add a red directional light that points into the screen. + * directionalLight(255, 0, 0, 0, 0, -1); + * + * // Draw the bottom sphere. + * push(); + * translate(0, 25, 0); + * sphere(20); + * pop(); * } * *
- * - * @alt - * Three white spheres. Each appears as a different - * color due to lighting. */ _main.default.prototype.noLights = function () { this._assert3d('noLights'); @@ -106877,6 +124424,7 @@ args[_key] = arguments[_key]; } _main.default._validateParameters('noLights', args); + this._renderer.activeImageLight = null; this._renderer._enableLighting = false; this._renderer.ambientLightColors.length = 0; this._renderer.specularColors = [ @@ -106900,40 +124448,77 @@ this._renderer.linearAttenuation = 0; this._renderer.quadraticAttenuation = 0; this._renderer._useShininess = 1; + this._renderer._useMetalness = 0; return this; }; var _default = _main.default; exports.default = _default; }, { - '../core/main': 298 + '../core/main': 306, + 'core-js/modules/es.array.filter': 175 } ], - 345: [ + 353: [ function (_dereq_, module, exports) { 'use strict'; + _dereq_('core-js/modules/es.symbol'); + _dereq_('core-js/modules/es.symbol.description'); + _dereq_('core-js/modules/es.symbol.iterator'); _dereq_('core-js/modules/es.array.concat'); + _dereq_('core-js/modules/es.array.from'); _dereq_('core-js/modules/es.array.index-of'); + _dereq_('core-js/modules/es.array.iterator'); + _dereq_('core-js/modules/es.array.join'); _dereq_('core-js/modules/es.array.slice'); _dereq_('core-js/modules/es.array.splice'); + _dereq_('core-js/modules/es.object.assign'); _dereq_('core-js/modules/es.object.to-string'); + _dereq_('core-js/modules/es.promise'); _dereq_('core-js/modules/es.regexp.exec'); + _dereq_('core-js/modules/es.regexp.to-string'); + _dereq_('core-js/modules/es.set'); + _dereq_('core-js/modules/es.string.iterator'); _dereq_('core-js/modules/es.string.match'); _dereq_('core-js/modules/es.string.split'); _dereq_('core-js/modules/es.string.trim'); + _dereq_('core-js/modules/web.dom-collections.iterator'); + function _typeof2(obj) { + if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') { + _typeof2 = function _typeof2(obj) { + return typeof obj; + }; + } else { + _typeof2 = function _typeof2(obj) { + return obj && typeof Symbol === 'function' && obj.constructor === Symbol && obj !== Symbol.prototype ? 'symbol' : typeof obj; + }; + } + return _typeof2(obj); + } + _dereq_('core-js/modules/es.symbol'); + _dereq_('core-js/modules/es.symbol.description'); + _dereq_('core-js/modules/es.symbol.iterator'); _dereq_('core-js/modules/es.array.concat'); _dereq_('core-js/modules/es.array.index-of'); + _dereq_('core-js/modules/es.array.iterator'); + _dereq_('core-js/modules/es.array.join'); _dereq_('core-js/modules/es.array.slice'); _dereq_('core-js/modules/es.array.splice'); + _dereq_('core-js/modules/es.object.assign'); _dereq_('core-js/modules/es.object.to-string'); + _dereq_('core-js/modules/es.promise'); _dereq_('core-js/modules/es.regexp.exec'); + _dereq_('core-js/modules/es.set'); + _dereq_('core-js/modules/es.string.iterator'); _dereq_('core-js/modules/es.string.match'); _dereq_('core-js/modules/es.string.split'); _dereq_('core-js/modules/es.string.trim'); + _dereq_('core-js/modules/web.dom-collections.iterator'); Object.defineProperty(exports, '__esModule', { value: true }); exports.default = void 0; + _dereq_('regenerator-runtime/runtime'); var _main = _interopRequireDefault(_dereq_('../core/main')); _dereq_('./p5.Geometry'); function _interopRequireDefault(obj) { @@ -106941,98 +124526,377 @@ default: obj }; - } /** - * @module Shape - * @submodule 3D Models - * @for p5 - * @requires core - * @requires p5.Geometry - */ + } + function _toConsumableArray(arr) { + return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); + } + function _nonIterableSpread() { + throw new TypeError('Invalid attempt to spread non-iterable instance'); + } + function _iterableToArray(iter) { + if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === '[object Arguments]') return Array.from(iter); + } + function _arrayWithoutHoles(arr) { + if (Array.isArray(arr)) { + for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { + arr2[i] = arr[i]; + } + return arr2; + } + } + function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { + try { + var info = gen[key](arg); + var value = info.value; + } catch (error) { + reject(error); + return; + } + if (info.done) { + resolve(value); + } else { + Promise.resolve(value).then(_next, _throw); + } + } + function _asyncToGenerator(fn) { + return function () { + var self = this, + args = arguments; + return new Promise(function (resolve, reject) { + var gen = fn.apply(self, args); + function _next(value) { + asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'next', value); + } + function _throw(err) { + asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'throw', err); + } + _next(undefined); + }); + }; + } + function _typeof(obj) { + if (typeof Symbol === 'function' && _typeof2(Symbol.iterator) === 'symbol') { + _typeof = function _typeof(obj) { + return _typeof2(obj); + }; + } else { + _typeof = function _typeof(obj) { + return obj && typeof Symbol === 'function' && obj.constructor === Symbol && obj !== Symbol.prototype ? 'symbol' : _typeof2(obj); + }; + } + return _typeof(obj); + } /** + * @module Shape + * @submodule 3D Models + * @for p5 + * @requires core + * @requires p5.Geometry + */ /** - * Load a 3d model from an OBJ or STL file. + * Loads a 3D model to create a + * p5.Geometry object. + * + * `loadModel()` can load 3D models from OBJ and STL files. Once the model is + * loaded, it can be displayed with the + * model() function, as in `model(shape)`. + * + * There are three ways to call `loadModel()` with optional parameters to help + * process the model. + * + * The first parameter, `path`, is always a `String` with the path to the + * file. Paths to local files should be relative, as in + * `loadModel('assets/model.obj')`. URLs such as + * `'https://example.com/model.obj'` may be blocked due to browser security. + * + * The first way to call `loadModel()` has three optional parameters after the + * file path. The first optional parameter, `successCallback`, is a function + * to call once the model loads. For example, + * `loadModel('assets/model.obj', handleModel)` will call the `handleModel()` + * function once the model loads. The second optional parameter, + * `failureCallback`, is a function to call if the model fails to load. For + * example, `loadModel('assets/model.obj', handleModel, handleFailure)` will + * call the `handleFailure()` function if an error occurs while loading. The + * third optional parameter, `fileType`, is the model’s file extension as a + * string. For example, + * `loadModel('assets/model', handleModel, handleFailure, '.obj')` will try to + * load the file model as a `.obj` file. + * + * The second way to call `loadModel()` has four optional parameters after the + * file path. The first optional parameter is a `Boolean` value. If `true` is + * passed, as in `loadModel('assets/model.obj', true)`, then the model will be + * resized to ensure it fits the canvas. The next three parameters are + * `successCallback`, `failureCallback`, and `fileType` as described above. + * + * The third way to call `loadModel()` has one optional parameter after the + * file path. The optional parameter, `options`, is an `Object` with options, + * as in `loadModel('assets/model.obj', options)`. The `options` object can + * have the following properties: + * + * ```js + * let options = { + * // Enables standardized size scaling during loading if set to true. + * normalize: true, + * + * // Function to call once the model loads. + * successCallback: handleModel, + * + * // Function to call if an error occurs while loading. + * failureCallback: handleError, + * + * // Model's file extension. + * fileType: '.stl', + * + * // Flips the U texture coordinates of the model. + * flipU: false, + * + * // Flips the V texture coordinates of the model. + * flipV: false + * }; * - * loadModel() should be placed inside of preload(). - * This allows the model to load fully before the rest of your code is run. + * // Pass the options object to loadModel(). + * loadModel('assets/model.obj', options); + * ``` * - * One of the limitations of the OBJ and STL format is that it doesn't have a built-in - * sense of scale. This means that models exported from different programs might - * be very different sizes. If your model isn't displaying, try calling - * loadModel() with the normalized parameter set to true. This will resize the - * model to a scale appropriate for p5. You can also make additional changes to - * the final size of your model with the scale() function. + * Models can take time to load. Calling `loadModel()` in + * preload() ensures models load before they're + * used in setup() or draw(). * - * Also, the support for colored STL files is not present. STL files with color will be - * rendered without color properties. + * Note: There’s no support for colored STL files. STL files with color will + * be rendered without color. * * @method loadModel - * @param {String} path Path of the model to be loaded - * @param {Boolean} normalize If true, scale the model to a - * standardized size when loading - * @param {function(p5.Geometry)} [successCallback] Function to be called - * once the model is loaded. Will be passed - * the 3D model object. - * @param {function(Event)} [failureCallback] called with event error if - * the model fails to load. - * @param {String} [fileType] The file extension of the model - * (.stl, .obj). + * @param {String} path path of the model to be loaded. + * @param {Boolean} normalize if `true`, scale the model to fit the canvas. + * @param {function(p5.Geometry)} [successCallback] function to call once the model is loaded. Will be passed + * the p5.Geometry object. + * @param {function(Event)} [failureCallback] function to call if the model fails to load. Will be passed an `Error` event object. + * @param {String} [fileType] model’s file extension. Either `'.obj'` or `'.stl'`. * @return {p5.Geometry} the p5.Geometry object * * @example *
* - * //draw a spinning octahedron - * let octahedron; + * // Click and drag the mouse to view the scene from different angles. + * + * let shape; * + * // Load the file and create a p5.Geometry object. * function preload() { - * octahedron = loadModel('assets/octahedron.obj'); + * shape = loadModel('assets/teapot.obj'); * } * * function setup() { * createCanvas(100, 100, WEBGL); - * describe('Vertically rotating 3-d octahedron.'); + * + * describe('A white teapot drawn against a gray background.'); * } * * function draw() { * background(200); - * rotateX(frameCount * 0.01); - * rotateY(frameCount * 0.01); - * model(octahedron); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the shape. + * model(shape); * } * *
* - * @alt - * Vertically rotating 3-d octahedron. + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * let shape; + * + * // Load the file and create a p5.Geometry object. + * // Normalize the geometry's size to fit the canvas. + * function preload() { + * shape = loadModel('assets/teapot.obj', true); + * } + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white teapot drawn against a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the shape. + * model(shape); + * } + * + *
* - * @example *
* - * //draw a spinning teapot - * let teapot; + * // Click and drag the mouse to view the scene from different angles. + * + * let shape; * + * // Load the file and create a p5.Geometry object. * function preload() { - * // Load model with normalise parameter set to true - * teapot = loadModel('assets/teapot.obj', true); + * loadModel('assets/teapot.obj', true, handleModel); * } * * function setup() { * createCanvas(100, 100, WEBGL); - * describe('Vertically rotating 3-d teapot with red, green and blue gradient.'); + * + * describe('A white teapot drawn against a gray background.'); * } * * function draw() { * background(200); - * scale(0.4); // Scaled to make model fit into canvas - * rotateX(frameCount * 0.01); - * rotateY(frameCount * 0.01); - * normalMaterial(); // For effect - * model(teapot); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the shape. + * model(shape); + * } + * + * // Set the shape variable and log the geometry's + * // ID to the console. + * function handleModel(data) { + * shape = data; + * console.log(shape.gid); * } * *
* - * @alt - * Vertically rotating 3-d teapot with red, green and blue gradient. + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * let shape; + * + * // Load the file and create a p5.Geometry object. + * function preload() { + * loadModel('assets/wrong.obj', true, handleModel, handleError); + * } + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white teapot drawn against a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the shape. + * model(shape); + * } + * + * // Set the shape variable and print the geometry's + * // ID to the console. + * function handleModel(data) { + * shape = data; + * console.log(shape.gid); + * } + * + * // Print an error message if the file doesn't load. + * function handleError(error) { + * console.error('Oops!', error); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * let shape; + * + * // Load the file and create a p5.Geometry object. + * function preload() { + * loadModel('assets/teapot.obj', true, handleModel, handleError, '.obj'); + * } + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white teapot drawn against a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the shape. + * model(shape); + * } + * + * // Set the shape variable and print the geometry's + * // ID to the console. + * function handleModel(data) { + * shape = data; + * console.log(shape.gid); + * } + * + * // Print an error message if the file doesn't load. + * function handleError(error) { + * console.error('Oops!', error); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * let shape; + * let options = { + * normalize: true, + * successCallback: handleModel, + * failureCallback: handleError, + * fileType: '.obj' + * }; + * + * // Load the file and create a p5.Geometry object. + * function preload() { + * loadModel('assets/teapot.obj', options); + * } + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white teapot drawn against a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the shape. + * model(shape); + * } + * + * // Set the shape variable and print the geometry's + * // ID to the console. + * function handleModel(data) { + * shape = data; + * console.log(shape.gid); + * } + * + * // Print an error message if the file doesn't load. + * function handleError(error) { + * console.error('Oops!', error); + * } + * + *
*/ /** * @method loadModel @@ -107040,25 +124904,45 @@ * @param {function(p5.Geometry)} [successCallback] * @param {function(Event)} [failureCallback] * @param {String} [fileType] - * @return {p5.Geometry} the p5.Geometry object + * @return {p5.Geometry} new p5.Geometry object. + */ + /** + * @method loadModel + * @param {String} path + * @param {Object} [options] loading options. + * @param {function(p5.Geometry)} [options.successCallback] + * @param {function(Event)} [options.failureCallback] + * @param {String} [options.fileType] + * @param {boolean} [options.normalize] + * @param {boolean} [options.flipU] + * @param {boolean} [options.flipV] + * @return {p5.Geometry} new p5.Geometry object. */ - _main.default.prototype.loadModel = function (path) { + _main.default.prototype.loadModel = function (path, options) { _main.default._validateParameters('loadModel', arguments); - var normalize; + var normalize = false; var successCallback; var failureCallback; + var flipU = false; + var flipV = false; var fileType = path.slice( - 4); - if (typeof arguments[1] === 'boolean') { - normalize = arguments[1]; + if (options && _typeof(options) === 'object') { + normalize = options.normalize || false; + successCallback = options.successCallback; + failureCallback = options.failureCallback; + fileType = options.fileType || fileType; + flipU = options.flipU || false; + flipV = options.flipV || false; + } else if (typeof options === 'boolean') { + normalize = options; successCallback = arguments[2]; failureCallback = arguments[3]; if (typeof arguments[4] !== 'undefined') { fileType = arguments[4]; } } else { - normalize = false; - successCallback = arguments[1]; + successCallback = typeof arguments[1] === 'function' ? arguments[1] : undefined; failureCallback = arguments[2]; if (typeof arguments[3] !== 'undefined') { fileType = arguments[3]; @@ -107067,28 +124951,187 @@ var model = new _main.default.Geometry(); model.gid = ''.concat(path, '|').concat(normalize); var self = this; + function getMaterials(_x) { + return _getMaterials.apply(this, arguments); + } + function _getMaterials() { + _getMaterials = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee2(lines) { + var parsedMaterialPromises, + i, + mtllibMatch, + parsedMaterials, + materials; + return regeneratorRuntime.wrap(function _callee2$(_context2) { + while (1) { + switch (_context2.prev = _context2.next) { + case 0: + parsedMaterialPromises = [ + ]; + for (i = 0; i < lines.length; i++) { + mtllibMatch = lines[i].match(/^mtllib (.+)/); + if (mtllibMatch) { + (function () { + var mtlPath = ''; + var mtlFilename = mtllibMatch[1]; + var objPathParts = path.split('/'); + if (objPathParts.length > 1) { + objPathParts.pop(); + var objFolderPath = objPathParts.join('/'); + mtlPath = objFolderPath + '/' + mtlFilename; + } else { + mtlPath = mtlFilename; + } + parsedMaterialPromises.push(fileExists(mtlPath).then(function (exists) { + if (exists) { + return parseMtl(self, mtlPath); + } else { + console.warn('MTL file not found or error in parsing; proceeding without materials: '.concat(mtlPath)); + return { + }; + } + }).catch(function (error) { + console.warn('Error loading MTL file: '.concat(mtlPath), error); + return { + }; + })); + }) (); + } + } + _context2.prev = 2; + _context2.next = 5; + return Promise.all(parsedMaterialPromises); + case 5: + parsedMaterials = _context2.sent; + materials = Object.assign.apply(Object, [ + { + } + ].concat(_toConsumableArray(parsedMaterials))); + return _context2.abrupt('return', materials); + case 10: + _context2.prev = 10; + _context2.t0 = _context2['catch'](2); + return _context2.abrupt('return', { + }); + case 13: + case 'end': + return _context2.stop(); + } + } + }, _callee2, null, [ + [2, + 10] + ]); + })); + return _getMaterials.apply(this, arguments); + } + function fileExists(_x2) { + return _fileExists.apply(this, arguments); + } + function _fileExists() { + _fileExists = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee3(url) { + var response; + return regeneratorRuntime.wrap(function _callee3$(_context3) { + while (1) { + switch (_context3.prev = _context3.next) { + case 0: + _context3.prev = 0; + _context3.next = 3; + return fetch(url, { + method: 'HEAD' + }); + case 3: + response = _context3.sent; + return _context3.abrupt('return', response.ok); + case 7: + _context3.prev = 7; + _context3.t0 = _context3['catch'](0); + return _context3.abrupt('return', false); + case 10: + case 'end': + return _context3.stop(); + } + } + }, _callee3, null, [ + [0, + 7] + ]); + })); + return _fileExists.apply(this, arguments); + } if (fileType.match(/\.stl$/i)) { this.httpDo(path, 'GET', 'arrayBuffer', function (arrayBuffer) { parseSTL(model, arrayBuffer); if (normalize) { model.normalize(); } - self._decrementPreload(); - if (typeof successCallback === 'function') { - successCallback(model); + if (flipU) { + model.flipU(); } - }, failureCallback); - } else if (fileType.match(/\.obj$/i)) { - this.loadStrings(path, function (strings) { - parseObj(model, strings); - if (normalize) { - model.normalize(); + if (flipV) { + model.flipV(); } self._decrementPreload(); if (typeof successCallback === 'function') { successCallback(model); } }, failureCallback); + } else if (fileType.match(/\.obj$/i)) { + this.loadStrings(path, /*#__PURE__*/ function () { + var _ref = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee(lines) { + var parsedMaterials; + return regeneratorRuntime.wrap(function _callee$(_context) { + while (1) { + switch (_context.prev = _context.next) { + case 0: + _context.prev = 0; + _context.next = 3; + return getMaterials(lines); + case 3: + parsedMaterials = _context.sent; + parseObj(model, lines, parsedMaterials); + _context.next = 11; + break; + case 7: + _context.prev = 7; + _context.t0 = _context['catch'](0); + if (failureCallback) { + failureCallback(_context.t0); + } else { + _main.default._friendlyError('Error during parsing: ' + _context.t0.message); + } + return _context.abrupt('return'); + case 11: + _context.prev = 11; + if (normalize) { + model.normalize(); + } + if (flipU) { + model.flipU(); + } + if (flipV) { + model.flipV(); + } + self._decrementPreload(); + if (typeof successCallback === 'function') { + successCallback(model); + } + return _context.finish(11); + case 18: + case 'end': + return _context.stop(); + } + } + }, _callee, null, [ + [0, + 7, + 11, + 18] + ]); + })); + return function (_x3) { + return _ref.apply(this, arguments); + }; + }(), failureCallback); } else { _main.default._friendlyFileLoadError(3, path); if (failureCallback) { @@ -107099,7 +125142,49 @@ } return model; }; - /** + function parseMtl(p5, mtlPath) { + return new Promise(function (resolve, reject) { + var currentMaterial = null; + var materials = { + }; + p5.loadStrings(mtlPath, function (lines) { + for (var line = 0; line < lines.length; ++line) { + var tokens = lines[line].trim().split(/\s+/); + if (tokens[0] === 'newmtl') { + var materialName = tokens[1]; + currentMaterial = materialName; + materials[currentMaterial] = { + }; + } else if (tokens[0] === 'Kd') { + //Diffuse color + materials[currentMaterial].diffuseColor = [ + parseFloat(tokens[1]), + parseFloat(tokens[2]), + parseFloat(tokens[3]) + ]; + } else if (tokens[0] === 'Ka') { + //Ambient Color + materials[currentMaterial].ambientColor = [ + parseFloat(tokens[1]), + parseFloat(tokens[2]), + parseFloat(tokens[3]) + ]; + } else if (tokens[0] === 'Ks') { + //Specular color + materials[currentMaterial].specularColor = [ + parseFloat(tokens[1]), + parseFloat(tokens[2]), + parseFloat(tokens[3]) + ]; + } else if (tokens[0] === 'map_Kd') { + //Texture path + materials[currentMaterial].texturePath = tokens[1]; + } + } + resolve(materials); + }, reject); + }); + } /** * Parse OBJ lines into model. For reference, this is what a simple model of a * square might look like: * @@ -107110,7 +125195,10 @@ * * f 4 3 2 1 */ + function parseObj(model, lines) { + var materials = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : { + }; // OBJ allows a face to specify an index for a vertex (in the above example), // but it also allows you to specify a custom combination of vertex, UV // coordinate, and vertex normal. So, "3/4/3" would mean, "use vertex 3 with @@ -107128,15 +125216,23 @@ vn: [ ] }; - var indexedVerts = { - }; + // Map from source index → Map of material → destination index + var usedVerts = { + }; // Track colored vertices + var currentMaterial = null; + var coloredVerts = new Set(); //unique vertices with color + var hasColoredVertices = false; + var hasColorlessVertices = false; for (var line = 0; line < lines.length; ++line) { // Each line is a separate object (vertex, face, vertex normal, etc) // For each line, split it into tokens on whitespace. The first token // describes the type. var tokens = lines[line].trim().split(/\b\s+/); if (tokens.length > 0) { - if (tokens[0] === 'v' || tokens[0] === 'vn') { + if (tokens[0] === 'usemtl') { + // Switch to a new material + currentMaterial = tokens[1]; + } else if (tokens[0] === 'v' || tokens[0] === 'vn') { // Check if this line describes a vertex or vertex normal. // It will have three numeric parameters. var vertex = new _main.default.Vector(parseFloat(tokens[1]), parseFloat(tokens[2]), parseFloat(tokens[3])); @@ -107165,33 +125261,51 @@ for (var tokenInd = 0; tokenInd < vertexTokens.length; ++tokenInd) { // Now, convert the given token into an index var vertString = tokens[vertexTokens[tokenInd]]; - var vertIndex = 0; + var vertParts = vertString.split('/'); // TODO: Faces can technically use negative numbers to refer to the // previous nth vertex. I haven't seen this used in practice, but // it might be good to implement this in the future. - if (indexedVerts[vertString] !== undefined) { - vertIndex = indexedVerts[vertString]; - } else { - var vertParts = vertString.split('/'); - for (var i = 0; i < vertParts.length; i++) { - vertParts[i] = parseInt(vertParts[i]) - 1; - } - vertIndex = indexedVerts[vertString] = model.vertices.length; + for (var i = 0; i < vertParts.length; i++) { + vertParts[i] = parseInt(vertParts[i]) - 1; + } + if (!usedVerts[vertString]) { + usedVerts[vertString] = { + }; + } + if (usedVerts[vertString][currentMaterial] === undefined) { + var vertIndex = model.vertices.length; model.vertices.push(loadedVerts.v[vertParts[0]].copy()); - if (loadedVerts.vt[vertParts[1]]) { - model.uvs.push(loadedVerts.vt[vertParts[1]].slice()); - } else { - model.uvs.push([0, - 0]); - } - if (loadedVerts.vn[vertParts[2]]) { - model.vertexNormals.push(loadedVerts.vn[vertParts[2]].copy()); + model.uvs.push(loadedVerts.vt[vertParts[1]] ? loadedVerts.vt[vertParts[1]].slice() : [ + 0, + 0 + ]); + model.vertexNormals.push(loadedVerts.vn[vertParts[2]] ? loadedVerts.vn[vertParts[2]].copy() : new _main.default.Vector()); + usedVerts[vertString][currentMaterial] = vertIndex; + face.push(vertIndex); + if (currentMaterial && materials[currentMaterial] && materials[currentMaterial].diffuseColor) { + // Mark this vertex as colored + coloredVerts.add(loadedVerts.v[vertParts[0]]); //since a set would only push unique values } + } else { + face.push(usedVerts[vertString][currentMaterial]); } - face.push(vertIndex); } if (face[0] !== face[1] && face[0] !== face[2] && face[1] !== face[2]) { model.faces.push(face); + //same material for all vertices in a particular face + if (currentMaterial && materials[currentMaterial] && materials[currentMaterial].diffuseColor) { + hasColoredVertices = true; + //flag to track color or no color model + hasColoredVertices = true; + var materialDiffuseColor = materials[currentMaterial].diffuseColor; + for (var _i = 0; _i < face.length; _i++) { + model.vertexColors.push(materialDiffuseColor[0]); + model.vertexColors.push(materialDiffuseColor[1]); + model.vertexColors.push(materialDiffuseColor[2]); + } + } else { + hasColorlessVertices = true; + } } } } @@ -107201,6 +125315,10 @@ if (model.vertexNormals.length === 0) { model.computeNormals(); } + if (hasColoredVertices === hasColorlessVertices) { + // If both are true or both are false, throw an error because the model is inconsistent + throw new Error('Model coloring is inconsistent. Either all vertices should have colors or none should.'); + } return model; } /** * STL files can be of two types, ASCII and Binary, @@ -107465,36 +125583,132 @@ } return model; } /** - * Render a 3d model to the screen. + * Draws a p5.Geometry object to the canvas. + * + * The parameter, `model`, is the + * p5.Geometry object to draw. + * p5.Geometry objects can be built with + * buildGeometry(), or + * beginGeometry() and + * endGeometry(). They can also be loaded from + * a file with loadGeometry(). + * + * Note: `model()` can only be used in WebGL mode. + * + * @method model + * @param {p5.Geometry} model 3D shape to be drawn. + * + * @example + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * let shape; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create the p5.Geometry object. + * shape = buildGeometry(createShape); + * + * describe('A white cone drawn on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the p5.Geometry object. + * model(shape); + * } + * + * // Create p5.Geometry object from a single cone. + * function createShape() { + * cone(); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * let shape; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create the p5.Geometry object. + * shape = buildGeometry(createArrow); + * + * describe('Two white arrows drawn on a gray background. The arrow on the right rotates slowly.'); + * } + * + * function draw() { + * background(50); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * lights(); + * + * // Style the arrows. + * noStroke(); + * + * // Draw the p5.Geometry object. + * model(shape); + * + * // Translate and rotate the coordinate system. + * translate(30, 0, 0); + * rotateZ(frameCount * 0.01); + * + * // Draw the p5.Geometry object again. + * model(shape); + * } + * + * function createArrow() { + * // Add shapes to the p5.Geometry object. + * push(); + * rotateX(PI); + * cone(10); + * translate(0, -10, 0); + * cylinder(3, 20); + * pop(); + * } + * + *
* - * @method model - * @param {p5.Geometry} model Loaded 3d model to be rendered - * @example *
* - * //draw a spinning octahedron - * let octahedron; + * // Click and drag the mouse to view the scene from different angles. * + * let shape; + * + * // Load the file and create a p5.Geometry object. * function preload() { - * octahedron = loadModel('assets/octahedron.obj'); + * shape = loadModel('assets/octahedron.obj'); * } * * function setup() { * createCanvas(100, 100, WEBGL); - * describe('Vertically rotating 3-d octahedron.'); + * + * describe('A white octahedron drawn against a gray background.'); * } * * function draw() { * background(200); - * rotateX(frameCount * 0.01); - * rotateY(frameCount * 0.01); - * model(octahedron); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the shape. + * model(shape); * } * *
- * - * @alt - * Vertically rotating 3-d octahedron. */ _main.default.prototype.model = function (model) { @@ -107515,20 +125729,33 @@ exports.default = _default; }, { - '../core/main': 298, - './p5.Geometry': 350, - 'core-js/modules/es.array.concat': 169, - 'core-js/modules/es.array.index-of': 178, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.array.splice': 185, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.regexp.exec': 205, - 'core-js/modules/es.string.match': 211, - 'core-js/modules/es.string.split': 216, - 'core-js/modules/es.string.trim': 219 + '../core/main': 306, + './p5.Geometry': 358, + 'core-js/modules/es.array.concat': 171, + 'core-js/modules/es.array.from': 180, + 'core-js/modules/es.array.index-of': 182, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.join': 184, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.array.splice': 189, + 'core-js/modules/es.object.assign': 201, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.promise': 209, + 'core-js/modules/es.regexp.exec': 213, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.set': 215, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.string.match': 219, + 'core-js/modules/es.string.split': 224, + 'core-js/modules/es.string.trim': 227, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/web.dom-collections.iterator': 264, + 'regenerator-runtime/runtime': 282 } ], - 346: [ + 354: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -107637,62 +125864,120 @@ * @requires core */ /** - * Creates a new p5.Shader object - * from the provided vertex and fragment shader files. + * Loads vertex and fragment shaders to create a + * p5.Shader object. + * + * Shaders are programs that run on the graphics processing unit (GPU). They + * can process many pixels at the same time, making them fast for many + * graphics tasks. They’re written in a language called + * GLSL + * and run along with the rest of the code in a sketch. * - * The shader files are loaded asynchronously in the - * background, so this method should be used in preload(). + * Once the p5.Shader object is created, it can be + * used with the shader() function, as in + * `shader(myShader)`. A shader program consists of two files, a vertex shader + * and a fragment shader. The vertex shader affects where 3D geometry is drawn + * on the screen and the fragment shader affects color. * - * Shaders can alter the positioning of shapes drawn with them. - * To ensure consistency in rendering, it's recommended to use the vertex shader in the createShader example. + * `loadShader()` loads the vertex and fragment shaders from their `.vert` and + * `.frag` files. For example, calling + * `loadShader('assets/shader.vert', 'assets/shader.frag')` loads both + * required shaders and returns a p5.Shader object. * - * Note, shaders can only be used in WEBGL mode. + * The third parameter, `successCallback`, is optional. If a function is + * passed, it will be called once the shader has loaded. The callback function + * can use the new p5.Shader object as its + * parameter. + * + * The fourth parameter, `failureCallback`, is also optional. If a function is + * passed, it will be called if the shader fails to load. The callback + * function can use the event error as its parameter. + * + * Shaders can take time to load. Calling `loadShader()` in + * preload() ensures shaders load before they're + * used in setup() or draw(). + * + * Note: Shaders can only be used in WebGL mode. * * @method loadShader - * @param {String} vertFilename path to file containing vertex shader - * source code - * @param {String} fragFilename path to file containing fragment shader - * source code - * @param {function} [callback] callback to be executed after loadShader - * completes. On success, the p5.Shader object is passed as the first argument. - * @param {function} [errorCallback] callback to be executed when an error - * occurs inside loadShader. On error, the error is passed as the first - * argument. - * @return {p5.Shader} a shader object created from the provided - * vertex and fragment shader files. + * @param {String} vertFilename path of the vertex shader to be loaded. + * @param {String} fragFilename path of the fragment shader to be loaded. + * @param {function} [successCallback] function to call once the shader is loaded. Can be passed the + * p5.Shader object. + * @param {function} [failureCallback] function to call if the shader fails to load. Can be passed an + * `Error` event object. + * @return {p5.Shader} new shader created from the vertex and fragment shader files. * * @example *
* - * let mandel; + * // Note: A "uniform" is a global variable within a shader program. + * + * let mandelbrot; + * + * // Load the shader and create a p5.Shader object. * function preload() { - * // load the shader definitions from files - * mandel = loadShader('assets/shader.vert', 'assets/shader.frag'); + * mandelbrot = loadShader('assets/shader.vert', 'assets/shader.frag'); * } + * * function setup() { * createCanvas(100, 100, WEBGL); - * // use the shader - * shader(mandel); - * noStroke(); - * mandel.setUniform('p', [-0.74364388703, 0.13182590421]); - * describe('zooming Mandelbrot set. a colorful, infinitely detailed fractal.'); + * + * // Compile and apply the p5.Shader object. + * shader(mandelbrot); + * + * // Set the shader uniform p to an array. + * mandelbrot.setUniform('p', [-0.74364388703, 0.13182590421]); + * + * // Set the shader uniform r to the value 1.5. + * mandelbrot.setUniform('r', 1.5); + * + * // Add a quad as a display surface for the shader. + * quad(-1, -1, 1, -1, 1, 1, -1, 1); + * + * describe('A black fractal image on a magenta background.'); + * } + * + *
+ * + *
+ * + * // Note: A "uniform" is a global variable within a shader program. + * + * let mandelbrot; + * + * // Load the shader and create a p5.Shader object. + * function preload() { + * mandelbrot = loadShader('assets/shader.vert', 'assets/shader.frag'); + * } + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Use the p5.Shader object. + * shader(mandelbrot); + * + * // Set the shader uniform p to an array. + * mandelbrot.setUniform('p', [-0.74364388703, 0.13182590421]); + * + * describe('A fractal image zooms in and out of focus.'); * } * * function draw() { - * mandel.setUniform('r', 1.5 * exp(-6.5 * (1 + sin(millis() / 2000)))); + * // Set the shader uniform r to a value that oscillates between 0 and 2. + * mandelbrot.setUniform('r', sin(frameCount * 0.01) + 1); + * + * // Add a quad as a display surface for the shader. * quad(-1, -1, 1, -1, 1, 1, -1, 1); * } * *
- * - * @alt - * zooming Mandelbrot set. a colorful, infinitely detailed fractal. */ - _main.default.prototype.loadShader = function (vertFilename, fragFilename, callback, errorCallback) { + _main.default.prototype.loadShader = function (vertFilename, fragFilename, successCallback, failureCallback) { _main.default._validateParameters('loadShader', arguments); - if (!errorCallback) { - errorCallback = console.error; + if (!failureCallback) { + failureCallback = console.error; } var loadedShader = new _main.default.Shader(); var self = this; @@ -107700,8 +125985,8 @@ var loadedVert = false; var onLoad = function onLoad() { self._decrementPreload(); - if (callback) { - callback(loadedShader); + if (successCallback) { + successCallback(loadedShader); } }; this.loadStrings(vertFilename, function (result) { @@ -107710,41 +125995,109 @@ if (loadedFrag) { onLoad(); } - }, errorCallback); + }, failureCallback); this.loadStrings(fragFilename, function (result) { loadedShader._fragSrc = result.join('\n'); loadedFrag = true; if (loadedVert) { onLoad(); } - }, errorCallback); + }, failureCallback); return loadedShader; }; /** - * Creates a new p5.Shader object - * from the provided vertex and fragment shader code. + * Creates a new p5.Shader object. * - * Note, shaders can only be used in WEBGL mode. + * Shaders are programs that run on the graphics processing unit (GPU). They + * can process many pixels at the same time, making them fast for many + * graphics tasks. They’re written in a language called + * GLSL + * and run along with the rest of the code in a sketch. * - * Shaders can alter the positioning of shapes drawn with them. - * To ensure consistency in rendering, it's recommended to use the vertex shader shown in the example below. + * Once the p5.Shader object is created, it can be + * used with the shader() function, as in + * `shader(myShader)`. A shader program consists of two parts, a vertex shader + * and a fragment shader. The vertex shader affects where 3D geometry is drawn + * on the screen and the fragment shader affects color. + * + * The first parameter, `vertSrc`, sets the vertex shader. It’s a string that + * contains the vertex shader program written in GLSL. + * + * The second parameter, `fragSrc`, sets the fragment shader. It’s a string + * that contains the fragment shader program written in GLSL. + * + * Note: Only filter shaders can be used in 2D mode. All shaders can be used + * in WebGL mode. * * @method createShader - * @param {String} vertSrc source code for the vertex shader - * @param {String} fragSrc source code for the fragment shader - * @returns {p5.Shader} a shader object created from the provided + * @param {String} vertSrc source code for the vertex shader. + * @param {String} fragSrc source code for the fragment shader. + * @returns {p5.Shader} new shader object created from the * vertex and fragment shaders. * * @example *
* + * // Note: A "uniform" is a global variable within a shader program. * - * // the vertex shader is called for each vertex - * let vs = ` + * // Create a string with the vertex shader program. + * // The vertex shader is called for each vertex. + * let vertSrc = ` * precision highp float; * uniform mat4 uModelViewMatrix; * uniform mat4 uProjectionMatrix; + * attribute vec3 aPosition; + * attribute vec2 aTexCoord; + * varying vec2 vTexCoord; + * + * void main() { + * vTexCoord = aTexCoord; + * vec4 positionVec4 = vec4(aPosition, 1.0); + * gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4; + * } + * `; + * + * // Create a string with the fragment shader program. + * // The fragment shader is called for each pixel. + * let fragSrc = ` + * precision highp float; + * + * void main() { + * // Set each pixel's RGBA value to yellow. + * gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0); + * } + * `; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Shader object. + * let shaderProgram = createShader(vertSrc, fragSrc); + * + * // Compile and apply the p5.Shader object. + * shader(shaderProgram); + * + * // Style the drawing surface. + * noStroke(); + * + * // Add a plane as a drawing surface. + * plane(100, 100); + * + * describe('A yellow square.'); + * } + * + *
+ * + *
+ * + * // Note: A "uniform" is a global variable within a shader program. * + * // Create a string with the vertex shader program. + * // The vertex shader is called for each vertex. + * let vertSrc = ` + * precision highp float; + * uniform mat4 uModelViewMatrix; + * uniform mat4 uProjectionMatrix; * attribute vec3 aPosition; * attribute vec2 aTexCoord; * varying vec2 vTexCoord; @@ -107753,78 +126106,192 @@ * vTexCoord = aTexCoord; * vec4 positionVec4 = vec4(aPosition, 1.0); * gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4; - * } + * } * `; * + * // Create a string with the fragment shader program. + * // The fragment shader is called for each pixel. + * let fragSrc = ` + * precision highp float; + * uniform vec2 p; + * uniform float r; + * const int numIterations = 500; + * varying vec2 vTexCoord; + * + * void main() { + * vec2 c = p + gl_FragCoord.xy * r; + * vec2 z = c; + * float n = 0.0; + * + * for (int i = numIterations; i > 0; i--) { + * if (z.x * z.x + z.y * z.y > 4.0) { + * n = float(i) / float(numIterations); + * break; + * } + * z = vec2(z.x * z.x - z.y * z.y, 2.0 * z.x * z.y) + c; + * } + * + * gl_FragColor = vec4( + * 0.5 - cos(n * 17.0) / 2.0, + * 0.5 - cos(n * 13.0) / 2.0, + * 0.5 - cos(n * 23.0) / 2.0, + * 1.0 + * ); + * } + * `; * - * // the fragment shader is called for each pixel - * let fs = ` - * precision highp float; - * uniform vec2 p; - * uniform float r; - * const int I = 500; - * varying vec2 vTexCoord; - * void main() { - * vec2 c = p + gl_FragCoord.xy * r, z = c; - * float n = 0.0; - * for (int i = I; i > 0; i --) { - * if(z.x*z.x+z.y*z.y > 4.0) { - * n = float(i)/float(I); - * break; - * } - * z = vec2(z.x*z.x-z.y*z.y, 2.0*z.x*z.y) + c; - * } - * gl_FragColor = vec4(0.5-cos(n*17.0)/2.0,0.5-cos(n*13.0)/2.0,0.5-cos(n*23.0)/2.0,1.0); - * }`; - * - * let mandel; * function setup() { * createCanvas(100, 100, WEBGL); * - * // create and initialize the shader - * mandel = createShader(vs, fs); - * shader(mandel); + * // Create a p5.Shader object. + * let mandelbrot = createShader(vertSrc, fragSrc); + * + * // Compile and apply the p5.Shader object. + * shader(mandelbrot); + * + * // Set the shader uniform p to an array. + * // p is the center point of the Mandelbrot image. + * mandelbrot.setUniform('p', [-0.74364388703, 0.13182590421]); + * + * // Set the shader uniform r to 0.005. + * // r is the size of the image in Mandelbrot-space. + * mandelbrot.setUniform('r', 0.005); + * + * // Style the drawing surface. * noStroke(); * - * // 'p' is the center point of the Mandelbrot image - * mandel.setUniform('p', [-0.74364388703, 0.13182590421]); - * describe('zooming Mandelbrot set. a colorful, infinitely detailed fractal.'); + * // Add a plane as a drawing surface. + * plane(100, 100); + * + * describe('A black fractal image on a magenta background.'); + * } + * + *
+ * + *
+ * + * // Note: A "uniform" is a global variable within a shader program. + * + * // Create a string with the vertex shader program. + * // The vertex shader is called for each vertex. + * let vertSrc = ` + * precision highp float; + * uniform mat4 uModelViewMatrix; + * uniform mat4 uProjectionMatrix; + * + * attribute vec3 aPosition; + * attribute vec2 aTexCoord; + * varying vec2 vTexCoord; + * + * void main() { + * vTexCoord = aTexCoord; + * vec4 positionVec4 = vec4(aPosition, 1.0); + * gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4; + * } + * `; + * + * // Create a string with the fragment shader program. + * // The fragment shader is called for each pixel. + * let fragSrc = ` + * precision highp float; + * uniform vec2 p; + * uniform float r; + * const int numIterations = 500; + * varying vec2 vTexCoord; + * + * void main() { + * vec2 c = p + gl_FragCoord.xy * r; + * vec2 z = c; + * float n = 0.0; + * + * for (int i = numIterations; i > 0; i--) { + * if (z.x * z.x + z.y * z.y > 4.0) { + * n = float(i) / float(numIterations); + * break; + * } + * + * z = vec2(z.x * z.x - z.y * z.y, 2.0 * z.x * z.y) + c; + * } + * + * gl_FragColor = vec4( + * 0.5 - cos(n * 17.0) / 2.0, + * 0.5 - cos(n * 13.0) / 2.0, + * 0.5 - cos(n * 23.0) / 2.0, + * 1.0 + * ); + * } + * `; + * + * let mandelbrot; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Shader object. + * mandelbrot = createShader(vertSrc, fragSrc); + * + * // Apply the p5.Shader object. + * shader(mandelbrot); + * + * // Set the shader uniform p to an array. + * // p is the center point of the Mandelbrot image. + * mandelbrot.setUniform('p', [-0.74364388703, 0.13182590421]); + * + * describe('A fractal image zooms in and out of focus.'); * } * * function draw() { - * // 'r' is the size of the image in Mandelbrot-space - * mandel.setUniform('r', 1.5 * exp(-6.5 * (1 + sin(millis() / 2000)))); - * plane(width, height); + * // Set the shader uniform r to a value that oscillates + * // between 0 and 0.005. + * // r is the size of the image in Mandelbrot-space. + * let radius = 0.005 * (sin(frameCount * 0.01) + 1); + * mandelbrot.setUniform('r', radius); + * + * // Style the drawing surface. + * noStroke(); + * + * // Add a plane as a drawing surface. + * plane(100, 100); * } * *
- * - * @alt - * zooming Mandelbrot set. a colorful, infinitely detailed fractal. */ _main.default.prototype.createShader = function (vertSrc, fragSrc) { _main.default._validateParameters('createShader', arguments); return new _main.default.Shader(this._renderer, vertSrc, fragSrc); }; /** - * Creates a new p5.Shader using only a fragment shader, as a convenience method for creating image effects. - * It's like createShader() but with a default vertex shader included. + * Creates a p5.Shader object to be used with the + * filter() function. + * + * `createFilterShader()` works like + * createShader() but has a default vertex + * shader included. `createFilterShader()` is intended to be used along with + * filter() for filtering the contents of a canvas. + * A filter shader will be applied to the whole canvas instead of just + * p5.Geometry objects. + * + * The parameter, `fragSrc`, sets the fragment shader. It’s a string that + * contains the fragment shader program written in + * GLSL. * - * createFilterShader() is intended to be used along with filter() for filtering the contents of a canvas. - * A filter shader will not be applied to any geometries. + * The p5.Shader object that's created has some + * uniforms that can be set: + * - `sampler2D tex0`, which contains the canvas contents as a texture. + * - `vec2 canvasSize`, which is the width and height of the canvas, not including pixel density. + * - `vec2 texelSize`, which is the size of a physical pixel including pixel density. This is calculated as `1.0 / (width * density)` for the pixel width and `1.0 / (height * density)` for the pixel height. * - * The fragment shader receives some uniforms: - * - `sampler2D tex0`, which contains the canvas contents as a texture -* - `vec2 canvasSize`, which is the p5 width and height of the canvas (not including pixel density) - * - `vec2 texelSize`, which is the size of a physical pixel including pixel density (`1.0/(width*density)`, `1.0/(height*density)`) + * The p5.Shader that's created also provides + * `varying vec2 vTexCoord`, a coordinate with values between 0 and 1. + * `vTexCoord` describes where on the canvas the pixel will be drawn. * * For more info about filters and shaders, see Adam Ferriss' repo of shader examples - * or the introduction to shaders page. + * or the Introduction to Shaders tutorial. * * @method createFilterShader - * @param {String} fragSrc source code for the fragment shader - * @returns {p5.Shader} a shader object created from the provided - * fragment shader. + * @param {String} fragSrc source code for the fragment shader. + * @returns {p5.Shader} new shader object created from the fragment shader. + * * @example *
* @@ -107897,42 +126364,138 @@ return shader; }; /** - * Sets the p5.Shader object to - * be used to render subsequent shapes. - * - * Shaders can alter the positioning of shapes drawn with them. - * To ensure consistency in rendering, it's recommended to use the vertex shader in the createShader example. + * Sets the p5.Shader object to apply while drawing. * - * Custom shaders can be created using the + * Shaders are programs that run on the graphics processing unit (GPU). They + * can process many pixels or vertices at the same time, making them fast for + * many graphics tasks. They’re written in a language called + * GLSL + * and run along with the rest of the code in a sketch. + * p5.Shader objects can be created using the * createShader() and * loadShader() functions. * - * Use resetShader() to - * restore the default shaders. + * The parameter, `s`, is the p5.Shader object to + * apply. For example, calling `shader(myShader)` applies `myShader` to + * process each pixel on the canvas. The shader will be used for: + * - Fills when a texture is enabled if it includes a uniform `sampler2D`. + * - Fills when lights are enabled if it includes the attribute `aNormal`, or if it has any of the following uniforms: `uUseLighting`, `uAmbientLightCount`, `uDirectionalLightCount`, `uPointLightCount`, `uAmbientColor`, `uDirectionalDiffuseColors`, `uDirectionalSpecularColors`, `uPointLightLocation`, `uPointLightDiffuseColors`, `uPointLightSpecularColors`, `uLightingDirection`, or `uSpecular`. + * - Fills whenever there are no lights or textures. + * - Strokes if it includes the uniform `uStrokeWeight`. + * + * The source code from a p5.Shader object's + * fragment and vertex shaders will be compiled the first time it's passed to + * `shader()`. See + * MDN + * for more information about compiling shaders. + * + * Calling resetShader() restores a sketch’s + * default shaders. * - * Note, shaders can only be used in WEBGL mode. + * Note: Shaders can only be used in WebGL mode. * * @method shader * @chainable - * @param {p5.Shader} s the p5.Shader object - * to use for rendering shapes. + * @param {p5.Shader} s p5.Shader object + * to apply. * * @example *
* - * // Click within the image to toggle - * // the shader used by the quad shape - * // Note: for an alternative approach to the same example, - * // involving changing uniforms please refer to: - * // https://p5js.org/reference/#/p5.Shader/setUniform + * // Note: A "uniform" is a global variable within a shader program. + * + * // Create a string with the vertex shader program. + * // The vertex shader is called for each vertex. + * let vertSrc = ` + * precision highp float; + * uniform mat4 uModelViewMatrix; + * uniform mat4 uProjectionMatrix; + * + * attribute vec3 aPosition; + * attribute vec2 aTexCoord; + * varying vec2 vTexCoord; + * + * void main() { + * vTexCoord = aTexCoord; + * vec4 positionVec4 = vec4(aPosition, 1.0); + * gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4; + * } + * `; + * + * // Create a string with the fragment shader program. + * // The fragment shader is called for each pixel. + * let fragSrc = ` + * precision highp float; + * + * void main() { + * // Set each pixel's RGBA value to yellow. + * gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0); + * } + * `; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Shader object. + * let shaderProgram = createShader(vertSrc, fragSrc); + * + * // Apply the p5.Shader object. + * shader(shaderProgram); + * + * // Style the drawing surface. + * noStroke(); + * + * // Add a plane as a drawing surface. + * plane(100, 100); + * + * describe('A yellow square.'); + * } + * + *
+ * + *
+ * + * // Note: A "uniform" is a global variable within a shader program. + * + * let mandelbrot; + * + * // Load the shader and create a p5.Shader object. + * function preload() { + * mandelbrot = loadShader('assets/shader.vert', 'assets/shader.frag'); + * } + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Use the p5.Shader object. + * shader(mandelbrot); + * + * // Set the shader uniform p to an array. + * mandelbrot.setUniform('p', [-0.74364388703, 0.13182590421]); + * + * describe('A fractal image zooms in and out of focus.'); + * } + * + * function draw() { + * // Set the shader uniform r to a value that oscillates between 0 and 2. + * mandelbrot.setUniform('r', sin(frameCount * 0.01) + 1); + * + * // Add a quad as a display surface for the shader. + * quad(-1, -1, 1, -1, 1, 1, -1, 1); + * } + * + *
+ * + *
+ * + * // Note: A "uniform" is a global variable within a shader program. * * let redGreen; * let orangeBlue; * let showRedGreen = false; * + * // Load the shader and create two separate p5.Shader objects. * function preload() { - * // note that we are using two instances - * // of the same vertex and fragment shaders * redGreen = loadShader('assets/shader.vert', 'assets/shader-gradient.frag'); * orangeBlue = loadShader('assets/shader.vert', 'assets/shader-gradient.frag'); * } @@ -107940,46 +126503,51 @@ * function setup() { * createCanvas(100, 100, WEBGL); * - * // initialize the colors for redGreen shader + * // Initialize the redGreen shader. * shader(redGreen); + * + * // Set the redGreen shader's center and background color. * redGreen.setUniform('colorCenter', [1.0, 0.0, 0.0]); * redGreen.setUniform('colorBackground', [0.0, 1.0, 0.0]); * - * // initialize the colors for orangeBlue shader + * // Initialize the orangeBlue shader. * shader(orangeBlue); + * + * // Set the orangeBlue shader's center and background color. * orangeBlue.setUniform('colorCenter', [1.0, 0.5, 0.0]); * orangeBlue.setUniform('colorBackground', [0.226, 0.0, 0.615]); * - * noStroke(); - * * describe( - * 'canvas toggles between a circular gradient of orange and blue vertically. and a circular gradient of red and green moving horizontally when mouse is clicked/pressed.' + * 'The scene toggles between two circular gradients when the user double-clicks. An orange and blue gradient vertically, and red and green gradient moves horizontally.' * ); * } * * function draw() { - * // update the offset values for each shader, - * // moving orangeBlue in vertical and redGreen - * // in horizontal direction - * orangeBlue.setUniform('offset', [0, sin(millis() / 2000) + 1]); - * redGreen.setUniform('offset', [sin(millis() / 2000), 1]); + * // Update the offset values for each shader. + * // Move orangeBlue vertically. + * // Move redGreen horizontally. + * orangeBlue.setUniform('offset', [0, sin(frameCount * 0.01) + 1]); + * redGreen.setUniform('offset', [sin(frameCount * 0.01), 1]); * * if (showRedGreen === true) { * shader(redGreen); * } else { * shader(orangeBlue); * } + * + * // Style the drawing surface. + * noStroke(); + * + * // Add a quad as a drawing surface. * quad(-1, -1, 1, -1, 1, 1, -1, 1); * } * - * function mouseClicked() { + * // Toggle between shaders when the user double-clicks. + * function doubleClicked() { * showRedGreen = !showRedGreen; * } * *
- * - * @alt - * canvas toggles between a circular gradient of orange and blue vertically. and a circular gradient of red and green moving horizontally when mouse is clicked/pressed. */ _main.default.prototype.shader = function (s) { this._assert3d('shader'); @@ -107994,211 +126562,254 @@ return this; }; /** - * Restores the default shaders. Code that runs after resetShader() - * will not be affected by the shader previously set by - * shader() + * Restores the default shaders. + * + * `resetShader()` deactivates any shaders previously applied by + * shader(). + * + * Note: Shaders can only be used in WebGL mode. * * @method resetShader * @chainable + * * @example *
* - * // This variable will hold our shader object - * let shaderProgram; - * - * // This variable will hold our vertex shader source code + * // Create a string with the vertex shader program. + * // The vertex shader is called for each vertex. * let vertSrc = ` - * attribute vec3 aPosition; - * attribute vec2 aTexCoord; - * uniform mat4 uProjectionMatrix; - * uniform mat4 uModelViewMatrix; - * varying vec2 vTexCoord; - * - * void main() { - * vTexCoord = aTexCoord; - * vec4 position = vec4(aPosition, 1.0); - * gl_Position = uProjectionMatrix * uModelViewMatrix * position; - * } + * attribute vec3 aPosition; + * attribute vec2 aTexCoord; + * uniform mat4 uProjectionMatrix; + * uniform mat4 uModelViewMatrix; + * varying vec2 vTexCoord; + * + * void main() { + * vTexCoord = aTexCoord; + * vec4 position = vec4(aPosition, 1.0); + * gl_Position = uProjectionMatrix * uModelViewMatrix * position; + * } * `; * - * // This variable will hold our fragment shader source code + * // Create a string with the fragment shader program. + * // The fragment shader is called for each pixel. * let fragSrc = ` - * precision mediump float; - * - * varying vec2 vTexCoord; + * precision mediump float; + * varying vec2 vTexCoord; * - * void main() { - * vec2 uv = vTexCoord; - * vec3 color = vec3(uv.x, uv.y, min(uv.x + uv.y, 1.0)); - * gl_FragColor = vec4(color, 1.0); - * } + * void main() { + * vec2 uv = vTexCoord; + * vec3 color = vec3(uv.x, uv.y, min(uv.x + uv.y, 1.0)); + * gl_FragColor = vec4(color, 1.0); + * } * `; * + * let myShader; + * * function setup() { - * // Shaders require WEBGL mode to work * createCanvas(100, 100, WEBGL); * - * // Create our shader - * shaderProgram = createShader(vertSrc, fragSrc); + * // Create a p5.Shader object. + * myShader = createShader(vertSrc, fragSrc); * * describe( - * 'Two rotating cubes. The left one is painted using a custom (user-defined) shader, while the right one is painted using the default fill shader.' + * 'Two rotating cubes on a gray background. The left one has a blue-purple gradient on each face. The right one is red.' * ); * } * * function draw() { - * // Clear the scene * background(200); * - * // Draw a box using our shader - * // shader() sets the active shader with our shader - * shader(shaderProgram); + * // Draw a box using the p5.Shader. + * // shader() sets the active shader to myShader. + * shader(myShader); * push(); - * translate(-width / 4, 0, 0); - * rotateX(millis() * 0.00025); - * rotateY(millis() * 0.0005); + * translate(-25, 0, 0); + * rotateX(frameCount * 0.01); + * rotateY(frameCount * 0.01); * box(width / 4); * pop(); * - * // Draw a box using the default fill shader - * // resetShader() restores the default fill shader + * // Draw a box using the default fill shader. + * // resetShader() restores the default fill shader. * resetShader(); * fill(255, 0, 0); * push(); - * translate(width / 4, 0, 0); - * rotateX(millis() * 0.00025); - * rotateY(millis() * 0.0005); + * translate(25, 0, 0); + * rotateX(frameCount * 0.01); + * rotateY(frameCount * 0.01); * box(width / 4); * pop(); * } * *
- * @alt - * Two rotating cubes. The left one is painted using a custom (user-defined) shader, - * while the right one is painted using the default fill shader. */ _main.default.prototype.resetShader = function () { this._renderer.userFillShader = this._renderer.userStrokeShader = null; return this; }; /** - * Sets the texture that will be used to render subsequent shapes. + * Sets the texture that will be used on shapes. + * + * A texture is like a skin that wraps around a shape. `texture()` works with + * built-in shapes, such as square() and + * sphere(), and custom shapes created with + * functions such as buildGeometry(). To + * texture a geometry created with beginShape(), + * uv coordinates must be passed to each + * vertex() call. * - * A texture is like a "skin" that wraps around a 3D geometry. Currently - * supported textures are images, video, and offscreen renders. + * The parameter, `tex`, is the texture to apply. `texture()` can use a range + * of sources including images, videos, and offscreen renderers such as + * p5.Graphics and + * p5.Framebuffer objects. * * To texture a geometry created with beginShape(), * you will need to specify uv coordinates in vertex(). * - * Note, texture() can only be used in WEBGL mode. - * - * You can view more materials in this - * example. + * Note: `texture()` can only be used in WebGL mode. * * @method texture - * @param {p5.Image|p5.MediaElement|p5.Graphics|p5.Texture|p5.Framebuffer|p5.FramebufferTexture} tex image to use as texture + * @param {p5.Image|p5.MediaElement|p5.Graphics|p5.Texture|p5.Framebuffer|p5.FramebufferTexture} tex media to use as the texture. * @chainable + * * @example *
* * let img; + * + * // Load an image and create a p5.Image object. * function preload() { * img = loadImage('assets/laDefense.jpg'); * } * * function setup() { * createCanvas(100, 100, WEBGL); - * describe('spinning cube with a texture from an image'); + * + * describe('A spinning cube with an image of a ceiling on each face.'); * } * * function draw() { * background(0); + * + * // Rotate around the x-, y-, and z-axes. * rotateZ(frameCount * 0.01); * rotateX(frameCount * 0.01); * rotateY(frameCount * 0.01); - * //pass image as texture + * + * // Apply the image as a texture. * texture(img); - * box(width / 2); + * + * // Draw the box. + * box(50); * } * *
- * @alt - * spinning cube with a texture from an image * - * @example *
* * let pg; * * function setup() { * createCanvas(100, 100, WEBGL); - * pg = createGraphics(200, 200); - * pg.textSize(75); - * describe('plane with a texture from an image created by createGraphics()'); + * + * // Create a p5.Graphics object. + * pg = createGraphics(100, 100); + * + * // Draw a circle to the p5.Graphics object. + * pg.background(200); + * pg.circle(50, 50, 30); + * + * describe('A spinning cube with circle at the center of each face.'); * } * * function draw() { * background(0); - * pg.background(255); - * pg.text('hello!', 0, 100); - * //pass image as texture + * + * // Rotate around the x-, y-, and z-axes. + * rotateZ(frameCount * 0.01); + * rotateX(frameCount * 0.01); + * rotateY(frameCount * 0.01); + * + * // Apply the p5.Graphics object as a texture. * texture(pg); - * rotateX(0.5); - * noStroke(); - * plane(50); + * + * // Draw the box. + * box(50); * } * *
- * @alt - * plane with a texture from an image created by createGraphics() * - * @example *
* * let vid; + * + * // Load a video and create a p5.MediaElement object. * function preload() { * vid = createVideo('assets/fingers.mov'); - * vid.hide(); * } + * * function setup() { * createCanvas(100, 100, WEBGL); - * describe('rectangle with video as texture'); + * + * // Hide the video. + * vid.hide(); + * + * // Set the video to loop. + * vid.loop(); + * + * describe('A rectangle with video as texture'); * } * * function draw() { * background(0); - * //pass video frame as texture + * + * // Rotate around the y-axis. + * rotateY(frameCount * 0.01); + * + * // Apply the video as a texture. * texture(vid); - * rect(-40, -40, 80, 80); - * } * - * function mousePressed() { - * vid.loop(); + * // Draw the rectangle. + * rect(-40, -40, 80, 80); * } * *
* - * @alt - * rectangle with video as texture - * - * @example *
* - * let img; + * let vid; * + * // Load a video and create a p5.MediaElement object. * function preload() { - * img = loadImage('assets/laDefense.jpg'); + * vid = createVideo('assets/fingers.mov'); * } * * function setup() { * createCanvas(100, 100, WEBGL); - * describe('quad with a texture, mapped using normalized coordinates'); + * + * // Hide the video. + * vid.hide(); + * + * // Set the video to loop. + * vid.loop(); + * + * describe('A rectangle with video as texture'); * } * * function draw() { * background(0); - * texture(img); + * + * // Rotate around the y-axis. + * rotateY(frameCount * 0.01); + * + * // Set the texture mode. * textureMode(NORMAL); + * + * // Apply the video as a texture. + * texture(vid); + * + * // Draw a custom shape using uv coordinates. * beginShape(); * vertex(-40, -40, 0, 0); * vertex(40, -40, 1, 0); @@ -108208,8 +126819,6 @@ * } * *
- * @alt - * quad with a texture, mapped using normalized coordinates */ _main.default.prototype.texture = function (tex) { this._assert3d('texture'); @@ -108224,72 +126833,173 @@ return this; }; /** - * Sets the coordinate space for texture mapping. The default mode is IMAGE - * which refers to the actual coordinates of the image. - * NORMAL refers to a normalized space of values ranging from 0 to 1. + * Changes the coordinate system used for textures when they’re applied to + * custom shapes. + * + * In order for texture() to work, a shape needs a + * way to map the points on its surface to the pixels in an image. Built-in + * shapes such as rect() and + * box() already have these texture mappings based on + * their vertices. Custom shapes created with + * vertex() require texture mappings to be passed as + * uv coordinates. + * + * Each call to vertex() must include 5 arguments, + * as in `vertex(x, y, z, u, v)`, to map the vertex at coordinates `(x, y, z)` + * to the pixel at coordinates `(u, v)` within an image. For example, the + * corners of a rectangular image are mapped to the corners of a rectangle by default: + * + * + * // Apply the image as a texture. + * texture(img); + * + * // Draw the rectangle. + * rect(0, 0, 30, 50); + * + * + * If the image in the code snippet above has dimensions of 300 x 500 pixels, + * the same result could be achieved as follows: + * + * + * // Apply the image as a texture. + * texture(img); + * + * // Draw the rectangle. + * beginShape(); + * + * // Top-left. + * // u: 0, v: 0 + * vertex(0, 0, 0, 0, 0); + * + * // Top-right. + * // u: 300, v: 0 + * vertex(30, 0, 0, 300, 0); + * + * // Bottom-right. + * // u: 300, v: 500 + * vertex(30, 50, 0, 300, 500); + * + * // Bottom-left. + * // u: 0, v: 500 + * vertex(0, 50, 0, 0, 500); + * + * endShape(); + * + * + * `textureMode()` changes the coordinate system for uv coordinates. + * + * The parameter, `mode`, accepts two possible constants. If `NORMAL` is + * passed, as in `textureMode(NORMAL)`, then the texture’s uv coordinates can + * be provided in the range 0 to 1 instead of the image’s dimensions. This can + * be helpful for using the same code for multiple images of different sizes. + * For example, the code snippet above could be rewritten as follows: + * + * + * // Set the texture mode to use normalized coordinates. + * textureMode(NORMAL); + * + * // Apply the image as a texture. + * texture(img); + * + * // Draw the rectangle. + * beginShape(); + * + * // Top-left. + * // u: 0, v: 0 + * vertex(0, 0, 0, 0, 0); + * + * // Top-right. + * // u: 1, v: 0 + * vertex(30, 0, 0, 1, 0); + * + * // Bottom-right. + * // u: 1, v: 1 + * vertex(30, 50, 0, 1, 1); + * + * // Bottom-left. + * // u: 0, v: 1 + * vertex(0, 50, 0, 0, 1); + * + * endShape(); + * + * + * By default, `mode` is `IMAGE`, which scales uv coordinates to the + * dimensions of the image. Calling `textureMode(IMAGE)` applies the default. + * + * Note: `textureMode()` can only be used in WebGL mode. * - * With IMAGE, if an image is 100×200 pixels, mapping the image onto the entire - * size of a quad would require the points (0,0) (100, 0) (100,200) (0,200). - * The same mapping in NORMAL is (0,0) (1,0) (1,1) (0,1). * @method textureMode - * @param {Constant} mode either IMAGE or NORMAL + * @param {Constant} mode either IMAGE or NORMAL. + * * @example *
* * let img; * + * // Load an image and create a p5.Image object. * function preload() { * img = loadImage('assets/laDefense.jpg'); * } * * function setup() { * createCanvas(100, 100, WEBGL); - * describe('quad with a texture, mapped using normalized coordinates'); + * + * describe('An image of a ceiling against a black background.'); * } * * function draw() { + * background(0); + * + * // Apply the image as a texture. * texture(img); - * textureMode(NORMAL); + * + * // Draw the custom shape. + * // Use the image's width and height as uv coordinates. * beginShape(); - * vertex(-50, -50, 0, 0); - * vertex(50, -50, 1, 0); - * vertex(50, 50, 1, 1); - * vertex(-50, 50, 0, 1); + * vertex(-30, -30, 0, 0); + * vertex(30, -30, img.width, 0); + * vertex(30, 30, img.width, img.height); + * vertex(-30, 30, 0, img.height); * endShape(); * } * *
- * @alt - * quad with a texture, mapped using normalized coordinates * - * @example *
* * let img; * + * // Load an image and create a p5.Image object. * function preload() { * img = loadImage('assets/laDefense.jpg'); * } * * function setup() { * createCanvas(100, 100, WEBGL); - * describe('quad with a texture, mapped using image coordinates'); + * + * describe('An image of a ceiling against a black background.'); * } * * function draw() { + * background(0); + * + * // Set the texture mode. + * textureMode(NORMAL); + * + * // Apply the image as a texture. * texture(img); - * textureMode(IMAGE); + * + * // Draw the custom shape. + * // Use normalized uv coordinates. * beginShape(); - * vertex(-50, -50, 0, 0); - * vertex(50, -50, img.width, 0); - * vertex(50, 50, img.width, img.height); - * vertex(-50, 50, 0, img.height); + * vertex(-30, -30, 0, 0); + * vertex(30, -30, 1, 0); + * vertex(30, 30, 1, 1); + * vertex(-30, 30, 0, 1); * endShape(); * } * *
- * @alt - * quad with a texture, mapped using image coordinates */ _main.default.prototype.textureMode = function (mode) { if (mode !== constants.IMAGE && mode !== constants.NORMAL) { @@ -108299,67 +127009,278 @@ } }; /** - * Sets the global texture wrapping mode. This controls how textures behave - * when their uv's go outside of the 0 to 1 range. There are three options: - * CLAMP, REPEAT, and MIRROR. + * Changes the way textures behave when a shape’s uv coordinates go beyond the + * texture. + * + * In order for texture() to work, a shape needs a + * way to map the points on its surface to the pixels in an image. Built-in + * shapes such as rect() and + * box() already have these texture mappings based on + * their vertices. Custom shapes created with + * vertex() require texture mappings to be passed as + * uv coordinates. + * + * Each call to vertex() must include 5 arguments, + * as in `vertex(x, y, z, u, v)`, to map the vertex at coordinates `(x, y, z)` + * to the pixel at coordinates `(u, v)` within an image. For example, the + * corners of a rectangular image are mapped to the corners of a rectangle by default: + * + * ```js + * // Apply the image as a texture. + * texture(img); + * + * // Draw the rectangle. + * rect(0, 0, 30, 50); + * ``` + * + * If the image in the code snippet above has dimensions of 300 x 500 pixels, + * the same result could be achieved as follows: + * + * ```js + * // Apply the image as a texture. + * texture(img); + * + * // Draw the rectangle. + * beginShape(); + * + * // Top-left. + * // u: 0, v: 0 + * vertex(0, 0, 0, 0, 0); + * + * // Top-right. + * // u: 300, v: 0 + * vertex(30, 0, 0, 300, 0); + * + * // Bottom-right. + * // u: 300, v: 500 + * vertex(30, 50, 0, 300, 500); + * + * // Bottom-left. + * // u: 0, v: 500 + * vertex(0, 50, 0, 0, 500); + * + * endShape(); + * ``` + * + * `textureWrap()` controls how textures behave when their uv's go beyond the + * texture. Doing so can produce interesting visual effects such as tiling. + * For example, the custom shape above could have u-coordinates are greater + * than the image’s width: + * + * ```js + * // Apply the image as a texture. + * texture(img); + * + * // Draw the rectangle. + * beginShape(); + * vertex(0, 0, 0, 0, 0); * - * CLAMP causes the pixels at the edge of the texture to extend to the bounds. - * REPEAT causes the texture to tile repeatedly until reaching the bounds. - * MIRROR works similarly to REPEAT but it flips the texture with every new tile. + * // Top-right. + * // u: 600 + * vertex(30, 0, 0, 600, 0); * - * REPEAT & MIRROR are only available if the texture - * is a power of two size (128, 256, 512, 1024, etc.). + * // Bottom-right. + * // u: 600 + * vertex(30, 50, 0, 600, 500); * - * This method will affect all textures in your sketch until a subsequent - * textureWrap() call is made. + * vertex(0, 50, 0, 0, 500); + * endShape(); + * ``` + * + * The u-coordinates of 600 are greater than the texture image’s width of 300. + * This creates interesting possibilities. + * + * The first parameter, `wrapX`, accepts three possible constants. If `CLAMP` + * is passed, as in `textureWrap(CLAMP)`, the pixels at the edge of the + * texture will extend to the shape’s edges. If `REPEAT` is passed, as in + * `textureWrap(REPEAT)`, the texture will tile repeatedly until reaching the + * shape’s edges. If `MIRROR` is passed, as in `textureWrap(MIRROR)`, the + * texture will tile repeatedly until reaching the shape’s edges, flipping + * its orientation between tiles. By default, textures `CLAMP`. + * + * The second parameter, `wrapY`, is optional. It accepts the same three + * constants, `CLAMP`, `REPEAT`, and `MIRROR`. If one of these constants is + * passed, as in `textureWRAP(MIRROR, REPEAT)`, then the texture will `MIRROR` + * horizontally and `REPEAT` vertically. By default, `wrapY` will be set to + * the same value as `wrapX`. + * + * Note: `textureWrap()` can only be used in WebGL mode. * - * If only one argument is provided, it will be applied to both the - * horizontal and vertical axes. * @method textureWrap * @param {Constant} wrapX either CLAMP, REPEAT, or MIRROR * @param {Constant} [wrapY] either CLAMP, REPEAT, or MIRROR + * * @example *
* * let img; + * + * function preload() { + * img = loadImage('assets/rockies128.jpg'); + * } + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe( + * 'An image of a landscape occupies the top-left corner of a square. Its edge colors smear to cover the other thre quarters of the square.' + * ); + * } + * + * function draw() { + * background(0); + * + * // Set the texture mode. + * textureMode(NORMAL); + * + * // Set the texture wrapping. + * // Note: CLAMP is the default mode. + * textureWrap(CLAMP); + * + * // Apply the image as a texture. + * texture(img); + * + * // Style the shape. + * noStroke(); + * + * // Draw the shape. + * // Use uv coordinates > 1. + * beginShape(); + * vertex(-30, -30, 0, 0, 0); + * vertex(30, -30, 0, 2, 0); + * vertex(30, 30, 0, 2, 2); + * vertex(-30, 30, 0, 0, 2); + * endShape(); + * } + * + *
+ * + *
+ * + * let img; + * + * function preload() { + * img = loadImage('assets/rockies128.jpg'); + * } + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('Four identical images of a landscape arranged in a grid.'); + * } + * + * function draw() { + * background(0); + * + * // Set the texture mode. + * textureMode(NORMAL); + * + * // Set the texture wrapping. + * textureWrap(REPEAT); + * + * // Apply the image as a texture. + * texture(img); + * + * // Style the shape. + * noStroke(); + * + * // Draw the shape. + * // Use uv coordinates > 1. + * beginShape(); + * vertex(-30, -30, 0, 0, 0); + * vertex(30, -30, 0, 2, 0); + * vertex(30, 30, 0, 2, 2); + * vertex(-30, 30, 0, 0, 2); + * endShape(); + * } + * + *
+ * + *
+ * + * let img; + * + * function preload() { + * img = loadImage('assets/rockies128.jpg'); + * } + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe( + * 'Four identical images of a landscape arranged in a grid. The images are reflected horizontally and vertically, creating a kaleidoscope effect.' + * ); + * } + * + * function draw() { + * background(0); + * + * // Set the texture mode. + * textureMode(NORMAL); + * + * // Set the texture wrapping. + * textureWrap(MIRROR); + * + * // Apply the image as a texture. + * texture(img); + * + * // Style the shape. + * noStroke(); + * + * // Draw the shape. + * // Use uv coordinates > 1. + * beginShape(); + * vertex(-30, -30, 0, 0, 0); + * vertex(30, -30, 0, 2, 0); + * vertex(30, 30, 0, 2, 2); + * vertex(-30, 30, 0, 0, 2); + * endShape(); + * } + * + *
+ * + *
+ * + * let img; + * * function preload() { * img = loadImage('assets/rockies128.jpg'); * } * * function setup() { * createCanvas(100, 100, WEBGL); - * textureWrap(MIRROR); - * describe('an image of the rocky mountains repeated in mirrored tiles'); + * + * describe( + * 'Four identical images of a landscape arranged in a grid. The top row and bottom row are reflections of each other.' + * ); * } * * function draw() { * background(0); * - * let dX = mouseX; - * let dY = mouseY; - * - * let u = lerp(1.0, 2.0, dX); - * let v = lerp(1.0, 2.0, dY); + * // Set the texture mode. + * textureMode(NORMAL); * - * scale(width / 2); + * // Set the texture wrapping. + * textureWrap(REPEAT, MIRROR); * + * // Apply the image as a texture. * texture(img); * - * beginShape(TRIANGLES); - * vertex(-1, -1, 0, 0, 0); - * vertex(1, -1, 0, u, 0); - * vertex(1, 1, 0, u, v); + * // Style the shape. + * noStroke(); * - * vertex(1, 1, 0, u, v); - * vertex(-1, 1, 0, 0, v); - * vertex(-1, -1, 0, 0, 0); + * // Draw the shape. + * // Use uv coordinates > 1. + * beginShape(); + * vertex(-30, -30, 0, 0, 0); + * vertex(30, -30, 0, 2, 0); + * vertex(30, 30, 0, 2, 2); + * vertex(-30, 30, 0, 0, 2); * endShape(); * } * *
- * - * @alt - * an image of the rocky mountains repeated in mirrored tiles */ _main.default.prototype.textureWrap = function (wrapX) { var wrapY = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : wrapX; @@ -108391,34 +127312,40 @@ /** * Sets the current material as a normal material. * - * A normal material is not affected by light. It is often used as - * a placeholder material when debugging. + * A normal material sets surfaces facing the x-axis to red, those facing the + * y-axis to green, and those facing the z-axis to blue. Normal material isn't + * affected by light. It’s often used as a placeholder material when debugging. * - * Surfaces facing the X-axis become red, those facing the Y-axis - * become green, and those facing the Z-axis become blue. - * - * You can view more materials in this - * example. + * Note: `normalMaterial()` can only be used in WebGL mode. * * @method normalMaterial * @chainable + * * @example *
* + * // Click and drag the mouse to view the scene from different angles. + * * function setup() { * createCanvas(100, 100, WEBGL); - * describe('Sphere with normal material'); + * + * describe('A multicolor torus drawn on a gray background.'); * } * * function draw() { * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Style the torus. * normalMaterial(); - * sphere(40); + * + * // Draw the torus. + * torus(30); * } * *
- * @alt - * Sphere with normal material */ _main.default.prototype.normalMaterial = function () { this._assert3d('normalMaterial'); @@ -108441,101 +127368,219 @@ return this; }; /** - * Sets the ambient color of the material. + * Sets the ambient color of shapes’ surface material. + * + * The `ambientMaterial()` color sets the components of the + * ambientLight() color that shapes will + * reflect. For example, calling `ambientMaterial(255, 255, 0)` would cause a + * shape to reflect red and green light, but not blue light. * - * The ambientMaterial() color represents the components - * of the **ambientLight()** color that the object reflects. + * `ambientMaterial()` can be called three ways with different parameters to + * set the material’s color. * - * Consider an ambientMaterial() with the color yellow (255, 255, 0). - * If the ambientLight() emits the color white (255, 255, 255), then the object - * will appear yellow as it will reflect the red and green components - * of the light. If the ambientLight() emits the color red (255, 0, 0), then - * the object will appear red as it will reflect the red component - * of the light. If the ambientLight() emits the color blue (0, 0, 255), - * then the object will appear black, as there is no component of - * the light that it can reflect. + * The first way to call `ambientMaterial()` has one parameter, `gray`. + * Grayscale values between 0 and 255, as in `ambientMaterial(50)`, can be + * passed to set the material’s color. Higher grayscale values make shapes + * appear brighter. * - * You can view more materials in this - * example. + * The second way to call `ambientMaterial()` has one parameter, `color`. A + * p5.Color object, an array of color values, or a + * CSS color string, as in `ambientMaterial('magenta')`, can be passed to set + * the material’s color. + * + * The third way to call `ambientMaterial()` has three parameters, `v1`, `v2`, + * and `v3`. RGB, HSB, or HSL values, as in `ambientMaterial(255, 0, 0)`, can + * be passed to set the material’s colors. Color values will be interpreted + * using the current colorMode(). + * + * Note: `ambientMaterial()` can only be used in WebGL mode. * * @method ambientMaterial - * @param {Number} v1 red or hue value relative to the current - * color range - * @param {Number} v2 green or saturation value relative to the - * current color range - * @param {Number} v3 blue or brightness value relative to the - * current color range + * @param {Number} v1 red or hue value in the current + * colorMode(). + * @param {Number} v2 green or saturation value in the + * current colorMode(). + * @param {Number} v3 blue, brightness, or lightness value in the + * current colorMode(). * @chainable + * * @example *
* + * // Click and drag the mouse to view the scene from different angles. + * * function setup() { * createCanvas(100, 100, WEBGL); - * describe('sphere reflecting red, blue, and green light'); + * + * describe('A magenta cube drawn on a gray background.'); * } + * * function draw() { - * background(0); - * noStroke(); - * ambientLight(255); - * ambientMaterial(70, 130, 230); - * sphere(40); + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on a magenta ambient light. + * ambientLight(255, 0, 255); + * + * // Draw the box. + * box(); * } * *
- * @alt - * sphere reflecting red, blue, and green light * - * @example *
* - * // ambientLight is both red and blue (magenta), - * // so object only reflects it's red and blue components + * // Click and drag the mouse to view the scene from different angles. + * * function setup() { * createCanvas(100, 100, WEBGL); - * describe('box reflecting only red and blue light'); + * + * describe('A purple cube drawn on a gray background.'); * } + * * function draw() { - * background(70); - * ambientLight(255, 0, 255); // magenta light - * ambientMaterial(255); // white material - * box(30); + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on a magenta ambient light. + * ambientLight(255, 0, 255); + * + * // Add a dark gray ambient material. + * ambientMaterial(150); + * + * // Draw the box. + * box(); * } * *
- * @alt - * box reflecting only red and blue light * - * @example *
* - * // ambientLight is green. Since object does not contain - * // green, it does not reflect any light + * // Click and drag the mouse to view the scene from different angles. + * * function setup() { * createCanvas(100, 100, WEBGL); - * describe('box reflecting no light'); + * + * describe('A red cube drawn on a gray background.'); * } + * * function draw() { - * background(70); - * ambientLight(0, 255, 0); // green light - * ambientMaterial(255, 0, 255); // magenta material - * box(30); + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on a magenta ambient light. + * ambientLight(255, 0, 255); + * + * // Add a yellow ambient material using RGB values. + * ambientMaterial(255, 255, 0); + * + * // Draw the box. + * box(); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A red cube drawn on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on a magenta ambient light. + * ambientLight(255, 0, 255); + * + * // Add a yellow ambient material using a p5.Color object. + * let c = color(255, 255, 0); + * ambientMaterial(c); + * + * // Draw the box. + * box(); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A red cube drawn on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on a magenta ambient light. + * ambientLight(255, 0, 255); + * + * // Add a yellow ambient material using a color string. + * ambientMaterial('yellow'); + * + * // Draw the box. + * box(); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A yellow cube drawn on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on a white ambient light. + * ambientLight(255, 255, 255); + * + * // Add a yellow ambient material using a color string. + * ambientMaterial('yellow'); + * + * // Draw the box. + * box(); * } * *
- * @alt - * box reflecting no light */ /** * @method ambientMaterial - * @param {Number} gray number specifying value between - * white and black + * @param {Number} gray grayscale value between 0 (black) and 255 (white). * @chainable */ /** * @method ambientMaterial * @param {p5.Color|Number[]|String} color - * color as a p5.Color, - * as an array, or as a CSS string + * color as a p5.Color object, + * an array of color values, or a CSS string. * @chainable */ _main.default.prototype.ambientMaterial = function (v1, v2, v3) { @@ -108550,59 +127595,84 @@ return this; }; /** - * Sets the emissive color of the material. + * Sets the emissive color of shapes’ surface material. + * + * The `emissiveMaterial()` color sets a color shapes display at full + * strength, regardless of lighting. This can give the appearance that a shape + * is glowing. However, emissive materials don’t actually emit light that + * can affect surrounding objects. + * + * `emissiveMaterial()` can be called three ways with different parameters to + * set the material’s color. + * + * The first way to call `emissiveMaterial()` has one parameter, `gray`. + * Grayscale values between 0 and 255, as in `emissiveMaterial(50)`, can be + * passed to set the material’s color. Higher grayscale values make shapes + * appear brighter. * - * An emissive material will display the emissive color at - * full strength regardless of lighting. This can give the - * appearance that the object is glowing. + * The second way to call `emissiveMaterial()` has one parameter, `color`. A + * p5.Color object, an array of color values, or a + * CSS color string, as in `emissiveMaterial('magenta')`, can be passed to set + * the material’s color. * - * Note, "emissive" is a misnomer in the sense that the material - * does not actually emit light that will affect surrounding objects. + * The third way to call `emissiveMaterial()` has four parameters, `v1`, `v2`, + * `v3`, and `alpha`. `alpha` is optional. RGBA, HSBA, or HSLA values can be + * passed to set the material’s colors, as in `emissiveMaterial(255, 0, 0)` or + * `emissiveMaterial(255, 0, 0, 30)`. Color values will be interpreted using + * the current colorMode(). * - * You can view more materials in this - * example. + * Note: `emissiveMaterial()` can only be used in WebGL mode. * * @method emissiveMaterial - * @param {Number} v1 red or hue value relative to the current - * color range - * @param {Number} v2 green or saturation value relative to the - * current color range - * @param {Number} v3 blue or brightness value relative to the - * current color range - * @param {Number} [alpha] alpha value relative to current color - * range (default is 0-255) + * @param {Number} v1 red or hue value in the current + * colorMode(). + * @param {Number} v2 green or saturation value in the + * current colorMode(). + * @param {Number} v3 blue, brightness, or lightness value in the + * current colorMode(). + * @param {Number} [alpha] alpha value in the current + * colorMode(). * @chainable + * * @example *
* + * // Click and drag the mouse to view the scene from different angles. + * * function setup() { * createCanvas(100, 100, WEBGL); - * describe('sphere with green emissive material'); + * + * describe('A red cube drawn on a gray background.'); * } + * * function draw() { - * background(0); - * noStroke(); - * ambientLight(0); - * emissiveMaterial(130, 230, 0); - * sphere(40); + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on a white ambient light. + * ambientLight(255, 255, 255); + * + * // Add a red emissive material using RGB values. + * emissiveMaterial(255, 0, 0); + * + * // Draw the box. + * box(); * } * *
- * - * @alt - * sphere with green emissive material */ /** * @method emissiveMaterial - * @param {Number} gray number specifying value between - * white and black + * @param {Number} gray grayscale value between 0 (black) and 255 (white). * @chainable */ /** * @method emissiveMaterial * @param {p5.Color|Number[]|String} color - * color as a p5.Color, - * as an array, or as a CSS string + * color as a p5.Color object, + * an array of color values, or a CSS string. * @chainable */ _main.default.prototype.emissiveMaterial = function (v1, v2, v3, a) { @@ -108616,74 +127686,243 @@ return this; }; /** - * Sets the specular color of the material. + * Sets the specular color of shapes’ surface material. * - * A specular material is reflective (shiny). The shininess can be - * controlled by the shininess() function. + * The `specularMaterial()` color sets the components of light color that + * glossy coats on shapes will reflect. For example, calling + * `specularMaterial(255, 255, 0)` would cause a shape to reflect red and + * green light, but not blue light. * - * Like ambientMaterial(), - * the specularMaterial() color is the color the object will reflect - * under ambientLight(). - * However unlike ambientMaterial(), for all other types of lights - * (directionalLight(), + * Unlike ambientMaterial(), + * `specularMaterial()` will reflect the full color of light sources including + * directionalLight(), * pointLight(), - * spotLight()), - * a specular material will reflect the **color of the light source**. - * This is what gives it its "shiny" appearance. + * and spotLight(). This is what gives it shapes + * their "shiny" appearance. The material’s shininess can be controlled by the + * shininess() function. * - * You can view more materials in this - * example. + * `specularMaterial()` can be called three ways with different parameters to + * set the material’s color. + * + * The first way to call `specularMaterial()` has one parameter, `gray`. + * Grayscale values between 0 and 255, as in `specularMaterial(50)`, can be + * passed to set the material’s color. Higher grayscale values make shapes + * appear brighter. + * + * The second way to call `specularMaterial()` has one parameter, `color`. A + * p5.Color> object, an array of color values, or a CSS + * color string, as in `specularMaterial('magenta')`, can be passed to set the + * material’s color. + * + * The third way to call `specularMaterial()` has four parameters, `v1`, `v2`, + * `v3`, and `alpha`. `alpha` is optional. RGBA, HSBA, or HSLA values can be + * passed to set the material’s colors, as in `specularMaterial(255, 0, 0)` or + * `specularMaterial(255, 0, 0, 30)`. Color values will be interpreted using + * the current colorMode(). * * @method specularMaterial - * @param {Number} gray number specifying value between white and black. - * @param {Number} [alpha] alpha value relative to current color range - * (default is 0-255) + * @param {Number} gray grayscale value between 0 (black) and 255 (white). + * @param {Number} [alpha] alpha value in the current current + * colorMode(). * @chainable * * @example *
* + * // Click and drag the mouse to view the scene from different angles. + * // Double-click the canvas to apply a specular material. + * + * let isGlossy = false; + * * function setup() { * createCanvas(100, 100, WEBGL); + * + * describe('A red torus drawn on a gray background. It becomes glossy when the user double-clicks.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on a white point light at the top-right. + * pointLight(255, 255, 255, 30, -40, 30); + * + * // Add a glossy coat if the user has double-clicked. + * if (isGlossy === true) { + * specularMaterial(255); + * shininess(50); + * } + * + * // Style the torus. * noStroke(); - * describe('torus with specular material'); + * fill(255, 0, 0); + * + * // Draw the torus. + * torus(30); + * } + * + * // Make the torus glossy when the user double-clicks. + * function doubleClicked() { + * isGlossy = true; + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * // Double-click the canvas to apply a specular material. + * + * let isGlossy = false; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe( + * 'A red torus drawn on a gray background. It becomes glossy and reflects green light when the user double-clicks.' + * ); * } * * function draw() { - * background(0); + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); * - * ambientLight(60); + * // Turn on a white point light at the top-right. + * pointLight(255, 255, 255, 30, -40, 30); * - * // add point light to showcase specular material - * let locX = mouseX - width / 2; - * let locY = mouseY - height / 2; - * pointLight(255, 255, 255, locX, locY, 50); + * // Add a glossy green coat if the user has double-clicked. + * if (isGlossy === true) { + * specularMaterial(0, 255, 0); + * shininess(50); + * } + * + * // Style the torus. + * noStroke(); + * fill(255, 0, 0); * - * specularMaterial(250); - * shininess(50); - * torus(30, 10, 64, 64); + * // Draw the torus. + * torus(30); + * } + * + * // Make the torus glossy when the user double-clicks. + * function doubleClicked() { + * isGlossy = true; + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * // Double-click the canvas to apply a specular material. + * + * let isGlossy = false; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe( + * 'A red torus drawn on a gray background. It becomes glossy and reflects green light when the user double-clicks.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on a white point light at the top-right. + * pointLight(255, 255, 255, 30, -40, 30); + * + * // Add a glossy green coat if the user has double-clicked. + * if (isGlossy === true) { + * // Create a p5.Color object. + * let c = color('green'); + * specularMaterial(c); + * shininess(50); + * } + * + * // Style the torus. + * noStroke(); + * fill(255, 0, 0); + * + * // Draw the torus. + * torus(30); + * } + * + * // Make the torus glossy when the user double-clicks. + * function doubleClicked() { + * isGlossy = true; + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * // Double-click the canvas to apply a specular material. + * + * let isGlossy = false; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe( + * 'A red torus drawn on a gray background. It becomes glossy and reflects green light when the user double-clicks.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on a white point light at the top-right. + * pointLight(255, 255, 255, 30, -40, 30); + * + * // Add a glossy green coat if the user has double-clicked. + * if (isGlossy === true) { + * specularMaterial('#00FF00'); + * shininess(50); + * } + * + * // Style the torus. + * noStroke(); + * fill(255, 0, 0); + * + * // Draw the torus. + * torus(30); + * } + * + * // Make the torus glossy when the user double-clicks. + * function doubleClicked() { + * isGlossy = true; * } * *
- * @alt - * torus with specular material */ /** * @method specularMaterial - * @param {Number} v1 red or hue value relative to - * the current color range + * @param {Number} v1 red or hue value in + * the current colorMode(). * @param {Number} v2 green or saturation value - * relative to the current color range - * @param {Number} v3 blue or brightness value - * relative to the current color range + * in the current colorMode(). + * @param {Number} v3 blue, brightness, or lightness value + * in the current colorMode(). * @param {Number} [alpha] * @chainable */ /** * @method specularMaterial * @param {p5.Color|Number[]|String} color - * color as a p5.Color, - * as an array, or as a CSS string + * color as a p5.Color object, + * an array of color values, or a CSS string. * @chainable */ _main.default.prototype.specularMaterial = function (v1, v2, v3, alpha) { @@ -108700,37 +127939,61 @@ * Sets the amount of gloss ("shininess") of a * specularMaterial(). * - * The default and minimum value is 1. + * Shiny materials focus reflected light more than dull materials. + * `shininess()` affects the way materials reflect light sources including + * directionalLight(), + * pointLight(), + * and spotLight(). + * + * The parameter, `shine`, is a number that sets the amount of shininess. + * `shine` must be greater than 1, which is its default value. * * @method shininess - * @param {Number} shine degree of shininess + * @param {Number} shine amount of shine. * @chainable + * * @example *
* * function setup() { * createCanvas(100, 100, WEBGL); - * describe('two spheres, one more shiny than the other'); + * + * describe( + * 'Two red spheres drawn on a gray background. White light reflects from their surfaces as the mouse moves. The right sphere is shinier than the left sphere.' + * ); * } + * * function draw() { - * background(0); + * background(200); + * + * // Turn on a red ambient light. + * ambientLight(255, 0, 0); + * + * // Get the mouse's coordinates. + * let mx = mouseX - 50; + * let my = mouseY - 50; + * + * // Turn on a white point light that follows the mouse. + * pointLight(255, 255, 255, mx, my, 50); + * + * // Style the sphere. * noStroke(); - * let locX = mouseX - width / 2; - * let locY = mouseY - height / 2; - * ambientLight(60, 60, 60); - * pointLight(255, 255, 255, locX, locY, 50); - * specularMaterial(250); + * + * // Add a specular material with a grayscale value. + * specularMaterial(255); + * + * // Draw the left sphere with low shininess. * translate(-25, 0, 0); - * shininess(1); + * shininess(10); * sphere(20); + * + * // Draw the right sphere with high shininess. * translate(50, 0, 0); - * shininess(20); + * shininess(100); * sphere(20); * } * *
- * @alt - * two spheres, one more shiny than the other */ _main.default.prototype.shininess = function (shine) { this._assert3d('shininess'); @@ -108742,16 +128005,133 @@ return this; }; /** + * Sets the amount of "metalness" of a + * specularMaterial(). + * + * `metalness()` can make materials appear more metallic. It affects the way + * materials reflect light sources including + * affects the way materials reflect light sources including + * directionalLight(), + * pointLight(), + * spotLight(), and + * imageLight(). + * + * The parameter, `metallic`, is a number that sets the amount of metalness. + * `metallic` must be greater than 1, which is its default value. Higher + * values, such as `metalness(100)`, make specular materials appear more + * metallic. + * + * @method metalness + * @param {Number} metallic amount of metalness. + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe( + * 'Two blue spheres drawn on a gray background. White light reflects from their surfaces as the mouse moves. The right sphere is more metallic than the left sphere.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Turn on an ambient light. + * ambientLight(200); + * + * // Get the mouse's coordinates. + * let mx = mouseX - 50; + * let my = mouseY - 50; + * + * // Turn on a white point light that follows the mouse. + * pointLight(255, 255, 255, mx, my, 50); + * + * // Style the spheres. + * noStroke(); + * fill(30, 30, 255); + * specularMaterial(255); + * shininess(20); + * + * // Draw the left sphere with low metalness. + * translate(-25, 0, 0); + * metalness(1); + * sphere(20); + * + * // Draw the right sphere with high metalness. + * translate(50, 0, 0); + * metalness(50); + * sphere(20); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * let img; + * + * function preload() { + * img = loadImage('assets/outdoor_spheremap.jpg'); + * } + * + * function setup() { + * createCanvas(100 ,100 ,WEBGL); + * + * describe( + * 'Two spheres floating above a landscape. The surface of the spheres reflect the landscape. The right sphere is more reflective than the left sphere.' + * ); + * } + * + * function draw() { + * // Add the panorama. + * panorama(img); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Use the image as a light source. + * imageLight(img); + * + * // Style the spheres. + * noStroke(); + * specularMaterial(50); + * shininess(200); + * + * // Draw the left sphere with low metalness. + * translate(-25, 0, 0); + * metalness(1); + * sphere(20); + * + * // Draw the right sphere with high metalness. + * translate(50, 0, 0); + * metalness(50); + * sphere(20); + * } + * + *
+ */ + _main.default.prototype.metalness = function (metallic) { + this._assert3d('metalness'); + var metalMix = 1 - Math.exp( - metallic / 100); + this._renderer._useMetalness = metalMix; + return this; + }; + /** * @private blends colors according to color components. * If alpha value is less than 1, or non-standard blendMode * we need to enable blending on our gl context. - * @param {Number[]} color [description] - * @return {Number[]]} Normalized numbers array + * @param {Number[]} color The currently set color, with values in 0-1 range + * @param {Boolean} [hasTransparency] Whether the shape being drawn has other + * transparency internally, e.g. via vertex colors + * @return {Number[]} Normalized numbers array */ - _main.default.RendererGL.prototype._applyColorBlend = function (colors) { + _main.default.RendererGL.prototype._applyColorBlend = function (colors, hasTransparency) { var gl = this.GL; var isTexture = this.drawMode === constants.TEXTURE; - var doBlend = this.userFillShader || this.userStrokeShader || this.userPointShader || isTexture || this.curBlendMode !== constants.BLEND || colors[colors.length - 1] < 1 || this._isErasing; + var doBlend = hasTransparency || this.userFillShader || this.userStrokeShader || this.userPointShader || isTexture || this.curBlendMode !== constants.BLEND || colors[colors.length - 1] < 1 || this._isErasing; if (doBlend !== this._isBlending) { if (doBlend || this.curBlendMode !== constants.BLEND && this.curBlendMode !== constants.ADD) { gl.enable(gl.BLEND); @@ -108767,7 +128147,7 @@ /** * @private sets blending in gl context to curBlendMode * @param {Number[]} color [description] - * @return {Number[]]} Normalized numbers array + * @return {Number[]} Normalized numbers array */ _main.default.RendererGL.prototype._applyBlendMode = function () { if (this._cachedBlendMode === this.curBlendMode) { @@ -108835,24 +128215,24 @@ exports.default = _default; }, { - '../core/constants': 286, - '../core/main': 298, - './p5.Texture': 357, - 'core-js/modules/es.array.includes': 177, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.join': 180, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.string.includes': 209, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/constants': 294, + '../core/main': 306, + './p5.Texture': 366, + 'core-js/modules/es.array.includes': 181, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.join': 184, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.string.includes': 217, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 347: [ + 355: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.array.slice'); @@ -108899,248 +128279,509 @@ // p5.Prototype Methods //////////////////////////////////////////////////////////////////////////////// /** - * Sets the position of the current camera in a 3D sketch. - * Parameters for this function define the camera's position, - * the center of the sketch (where the camera is pointing), - * and an up direction (the orientation of the camera). + * Sets the position and orientation of the current camera in a 3D sketch. * - * This function simulates the movements of the camera, allowing objects to be - * viewed from various angles. Remember, it does not move the objects themselves - * but the camera instead. For example when the centerX value is positive, - * and the camera is rotating to the right side of the sketch, - * the object will seem like it's moving to the left. + * `camera()` allows objects to be viewed from different angles. It has nine + * parameters that are all optional. * - * See this example - * to view the position of your camera. + * The first three parameters, `x`, `y`, and `z`, are the coordinates of the + * camera’s position. For example, calling `camera(0, 0, 0)` places the camera + * at the origin `(0, 0, 0)`. By default, the camera is placed at + * `(0, 0, 800)`. + * + * The next three parameters, `centerX`, `centerY`, and `centerZ` are the + * coordinates of the point where the camera faces. For example, calling + * `camera(0, 0, 0, 10, 20, 30)` places the camera at the origin `(0, 0, 0)` + * and points it at `(10, 20, 30)`. By default, the camera points at the + * origin `(0, 0, 0)`. + * + * The last three parameters, `upX`, `upY`, and `upZ` are the components of + * the "up" vector. The "up" vector orients the camera’s y-axis. For example, + * calling `camera(0, 0, 0, 10, 20, 30, 0, -1, 0)` places the camera at the + * origin `(0, 0, 0)`, points it at `(10, 20, 30)`, and sets the "up" vector + * to `(0, -1, 0)` which is like holding it upside-down. By default, the "up" + * vector is `(0, 1, 0)`. + * + * Note: `camera()` can only be used in WebGL mode. * - * If no parameters are given, the following default is used: - * camera(0, 0, (height/2) / tan(PI/6), 0, 0, 0, 0, 1, 0) * @method camera * @constructor * @for p5 - * @param {Number} [x] camera position value on x axis - * @param {Number} [y] camera position value on y axis - * @param {Number} [z] camera position value on z axis - * @param {Number} [centerX] x coordinate representing center of the sketch - * @param {Number} [centerY] y coordinate representing center of the sketch - * @param {Number} [centerZ] z coordinate representing center of the sketch - * @param {Number} [upX] x component of direction 'up' from camera - * @param {Number} [upY] y component of direction 'up' from camera - * @param {Number} [upZ] z component of direction 'up' from camera + * @param {Number} [x] x-coordinate of the camera. Defaults to 0. + * @param {Number} [y] y-coordinate of the camera. Defaults to 0. + * @param {Number} [z] z-coordinate of the camera. Defaults to 800. + * @param {Number} [centerX] x-coordinate of the point the camera faces. Defaults to 0. + * @param {Number} [centerY] y-coordinate of the point the camera faces. Defaults to 0. + * @param {Number} [centerZ] z-coordinate of the point the camera faces. Defaults to 0. + * @param {Number} [upX] x-component of the camera’s "up" vector. Defaults to 0. + * @param {Number} [upY] y-component of the camera’s "up" vector. Defaults to 1. + * @param {Number} [upZ] z-component of the camera’s "up" vector. Defaults to 0. + * @chainable + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white cube on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Move the camera to the top-right. + * camera(200, -400, 800); + * + * // Draw the box. + * box(); + * } + * + *
+ * + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white cube apperas to sway left and right on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Calculate the camera's x-coordinate. + * let x = 400 * cos(frameCount * 0.01); + * + * // Orbit the camera around the box. + * camera(x, -400, 800); + * + * // Draw the box. + * box(); + * } + * + *
+ * + *
+ * + * // Adjust the range sliders to change the camera's position. + * + * let xSlider; + * let ySlider; + * let zSlider; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create slider objects to set the camera's coordinates. + * xSlider = createSlider(-400, 400, 400); + * xSlider.position(0, 100); + * xSlider.size(100); + * ySlider = createSlider(-400, 400, -200); + * ySlider.position(0, 120); + * ySlider.size(100); + * zSlider = createSlider(0, 1600, 800); + * zSlider.position(0, 140); + * zSlider.size(100); + * + * describe( + * 'A white cube drawn against a gray background. Three range sliders appear beneath the image. The camera position changes when the user moves the sliders.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Get the camera's coordinates from the sliders. + * let x = xSlider.value(); + * let y = ySlider.value(); + * let z = zSlider.value(); + * + * // Move the camera. + * camera(x, y, z); + * + * // Draw the box. + * box(); + * } + * + *
+ */ + + _main.default.prototype.camera = function () { + var _this$_renderer$_curC; + this._assert3d('camera'); + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + _main.default._validateParameters('camera', args); + (_this$_renderer$_curC = this._renderer._curCamera).camera.apply(_this$_renderer$_curC, args); + return this; + }; + /** + * Sets a perspective projection for the current camera in a 3D sketch. + * + * In a perspective projection, shapes that are further from the camera appear + * smaller than shapes that are near the camera. This technique, called + * foreshortening, creates realistic 3D scenes. It’s applied by default in + * WebGL mode. + * + * `perspective()` changes the camera’s perspective by changing its viewing + * frustum. The frustum is the volume of space that’s visible to the camera. + * Its shape is a pyramid with its top cut off. The camera is placed where + * the top of the pyramid should be and views everything between the frustum’s + * top (near) plane and its bottom (far) plane. + * + * The first parameter, `fovy`, is the camera’s vertical field of view. It’s + * an angle that describes how tall or narrow a view the camera has. For + * example, calling `perspective(0.5)` sets the camera’s vertical field of + * view to 0.5 radians. By default, `fovy` is calculated based on the sketch’s + * height and the camera’s default z-coordinate, which is 800. The formula for + * the default `fovy` is `2 * atan(height / 2 / 800)`. + * + * The second parameter, `aspect`, is the camera’s aspect ratio. It’s a number + * that describes the ratio of the top plane’s width to its height. For + * example, calling `perspective(0.5, 1.5)` sets the camera’s field of view to + * 0.5 radians and aspect ratio to 1.5, which would make shapes appear thinner + * on a square canvas. By default, aspect is set to `width / height`. + * + * The third parameter, `near`, is the distance from the camera to the near + * plane. For example, calling `perspective(0.5, 1.5, 100)` sets the camera’s + * field of view to 0.5 radians, its aspect ratio to 1.5, and places the near + * plane 100 pixels from the camera. Any shapes drawn less than 100 pixels + * from the camera won’t be visible. By default, near is set to `0.1 * 800`, + * which is 1/10th the default distance between the camera and the origin. + * + * The fourth parameter, `far`, is the distance from the camera to the far + * plane. For example, calling `perspective(0.5, 1.5, 100, 10000)` sets the + * camera’s field of view to 0.5 radians, its aspect ratio to 1.5, places the + * near plane 100 pixels from the camera, and places the far plane 10,000 + * pixels from the camera. Any shapes drawn more than 10,000 pixels from the + * camera won’t be visible. By default, far is set to `10 * 800`, which is 10 + * times the default distance between the camera and the origin. + * + * Note: `perspective()` can only be used in WebGL mode. + * + * @method perspective + * @for p5 + * @param {Number} [fovy] camera frustum vertical field of view. Defaults to + * `2 * atan(height / 2 / 800)`. + * @param {Number} [aspect] camera frustum aspect ratio. Defaults to + * `width / height`. + * @param {Number} [near] distance from the camera to the near clipping plane. + * Defaults to `0.1 * 800`. + * @param {Number} [far] distance from the camera to the far clipping plane. + * Defaults to `10 * 800`. * @chainable + * * @example *
* + * // Double-click to squeeze the box. + * + * let isSqueezed = false; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * describe('A white rectangular prism on a gray background. The box appears to become thinner when the user double-clicks.'); + * } + * + * function draw() { + * background(200); + * + * // Place the camera at the top-right. + * camera(400, -400, 800); + * + * if (isSqueezed === true) { + * // Set fovy to 0.2. + * // Set aspect to 1.5. + * perspective(0.2, 1.5); + * } + * + * // Draw the box. + * box(); + * } + * + * // Change the camera's perspective when the user double-clicks. + * function doubleClicked() { + * isSqueezed = true; + * } + * + *
+ * + *
+ * * function setup() { * createCanvas(100, 100, WEBGL); - * describe('a square moving closer and then away from the camera.'); + * + * describe('A white rectangular prism on a gray background. The prism moves away from the camera until it disappears.'); * } + * * function draw() { - * background(204); - * //move the camera away from the plane by a sin wave - * camera(0, 0, 20 + sin(frameCount * 0.01) * 10, 0, 0, 0, 0, 1, 0); - * plane(10, 10); + * background(200); + * + * // Place the camera at the top-right. + * camera(400, -400, 800); + * + * // Set fovy to 0.2. + * // Set aspect to 1.5. + * // Set near to 600. + * // Set far to 1200. + * perspective(0.2, 1.5, 600, 1200); + * + * // Move the origin away from the camera. + * let x = -frameCount; + * let y = frameCount; + * let z = -2 * frameCount; + * translate(x, y, z); + * + * // Draw the box. + * box(); * } * *
+ */ + _main.default.prototype.perspective = function () { + var _this$_renderer$_curC2; + this._assert3d('perspective'); + for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args[_key2] = arguments[_key2]; + } + _main.default._validateParameters('perspective', args); + (_this$_renderer$_curC2 = this._renderer._curCamera).perspective.apply(_this$_renderer$_curC2, args); + return this; + }; + /** + * Enables or disables perspective for lines in 3D sketches. + * + * In WebGL mode, lines can be drawn with a thinner stroke when they’re + * further from the camera. Doing so gives them a more realistic appearance. + * + * By default, lines are drawn differently based on the type of perspective + * being used: + * - `perspective()` and `frustum()` simulate a realistic perspective. In + * these modes, stroke weight is affected by the line’s distance from the + * camera. Doing so results in a more natural appearance. `perspective()` is + * the default mode for 3D sketches. + * - `ortho()` doesn’t simulate a realistic perspective. In this mode, stroke + * weights are consistent regardless of the line’s distance from the camera. + * Doing so results in a more predictable and consistent appearance. + * + * `linePerspective()` can override the default line drawing mode. + * + * The parameter, `enable`, is optional. It’s a `Boolean` value that sets the + * way lines are drawn. If `true` is passed, as in `linePerspective(true)`, + * then lines will appear thinner when they are further from the camera. If + * `false` is passed, as in `linePerspective(false)`, then lines will have + * consistent stroke weights regardless of their distance from the camera. By + * default, `linePerspective()` is enabled. + * + * Calling `linePerspective()` without passing an argument returns `true` if + * it's enabled and `false` if not. + * + * Note: `linePerspective()` can only be used in WebGL mode. + * + * @method linePerspective + * @for p5 + * @param {boolean} enable whether to enable line perspective. * * @example *
* - * //move slider to see changes! - * //sliders control the first 6 parameters of camera() - * let sliderGroup = []; - * let X; - * let Y; - * let Z; - * let centerX; - * let centerY; - * let centerZ; - * let h = 20; + * // Double-click the canvas to toggle the line perspective. * * function setup() { * createCanvas(100, 100, WEBGL); - * //create sliders - * for (var i = 0; i < 6; i++) { - * if (i === 2) { - * sliderGroup[i] = createSlider(10, 400, 200); - * } else { - * sliderGroup[i] = createSlider(-400, 400, 0); - * } - * h = map(i, 0, 6, 5, 85); - * sliderGroup[i].position(10, height + h); - * sliderGroup[i].style('width', '80px'); + * + * describe( + * 'A white cube with black edges on a gray background. Its edges toggle between thick and thin when the user double-clicks.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Translate the origin toward the camera. + * translate(-10, 10, 600); + * + * // Rotate the coordinate system. + * rotateY(-0.1); + * rotateX(-0.1); + * + * // Draw the row of boxes. + * for (let i = 0; i < 6; i += 1) { + * translate(0, 0, -40); + * box(10); * } + * } + * + * // Toggle the line perspective when the user double-clicks. + * function doubleClicked() { + * let isEnabled = linePerspective(); + * linePerspective(!isEnabled); + * } + * + *
+ * + *
+ * + * // Double-click the canvas to toggle the line perspective. + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * * describe( - * 'White square repeatedly grows to fill canvas and then shrinks. An interactive example of a red cube with 3 sliders for moving it across x, y, z axis and 3 sliders for shifting its center.' + * 'A row of cubes with black edges on a gray background. Their edges toggle between thick and thin when the user double-clicks.' * ); * } * - * function draw() { - * background(60); - * // assigning sliders' value to each parameters - * X = sliderGroup[0].value(); - * Y = sliderGroup[1].value(); - * Z = sliderGroup[2].value(); - * centerX = sliderGroup[3].value(); - * centerY = sliderGroup[4].value(); - * centerZ = sliderGroup[5].value(); - * camera(X, Y, Z, centerX, centerY, centerZ, 0, 1, 0); - * stroke(255); - * fill(255, 102, 94); - * box(85); + * function draw() { + * background(200); + * + * // Use an orthographic projection. + * ortho(); + * + * // Translate the origin toward the camera. + * translate(-10, 10, 600); + * + * // Rotate the coordinate system. + * rotateY(-0.1); + * rotateX(-0.1); + * + * // Draw the row of boxes. + * for (let i = 0; i < 6; i += 1) { + * translate(0, 0, -40); + * box(10); + * } + * } + * + * // Toggle the line perspective when the user double-clicks. + * function doubleClicked() { + * let isEnabled = linePerspective(); + * linePerspective(!isEnabled); * } * *
- * @alt - * White square repeatedly grows to fill canvas and then shrinks. - * An interactive example of a red cube with 3 sliders for moving it across x, y, - * z axis and 3 sliders for shifting its center. */ - - _main.default.prototype.camera = function () { - var _this$_renderer$_curC; - this._assert3d('camera'); - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; + /** + * @method linePerspective + * @return {boolean} whether line perspective is enabled. + */ + _main.default.prototype.linePerspective = function (enable) { + _main.default._validateParameters('linePerspective', arguments); + if (!(this._renderer instanceof _main.default.RendererGL)) { + throw new Error('linePerspective() must be called in WebGL mode.'); + } + if (enable !== undefined) { + // Set the line perspective if enable is provided + this._renderer._curCamera.useLinePerspective = enable; + } else { + // If no argument is provided, return the current value + return this._renderer._curCamera.useLinePerspective; } - _main.default._validateParameters('camera', args); - (_this$_renderer$_curC = this._renderer._curCamera).camera.apply(_this$_renderer$_curC, args); - return this; }; /** - * Sets a perspective projection for the current camera in a 3D sketch. - * This projection represents depth through foreshortening: objects - * that are close to the camera appear their actual size while those - * that are further away from the camera appear smaller. + * Sets an orthographic projection for the current camera in a 3D sketch. * - * The parameters to this function define the viewing frustum - * (the truncated pyramid within which objects are seen by the camera) through - * vertical field of view, aspect ratio (usually width/height), and near and far - * clipping planes. + * In an orthographic projection, shapes with the same size always appear the + * same size, regardless of whether they are near or far from the camera. * - * If no parameters are given, the default values are used as: + * `ortho()` changes the camera’s perspective by changing its viewing frustum + * from a truncated pyramid to a rectangular prism. The camera is placed in + * front of the frustum and views everything between the frustum’s near plane + * and its far plane. `ortho()` has six optional parameters to define the + * frustum. * - * - `fov` : The default field of view for the camera is such that the full height of renderer is visible when it is positioned at a default distance of 800 units from the camera. - * - `aspect` : The default aspect ratio is the ratio of renderer's width to renderer's height. - * - `near` : The default value for the near clipping plane is 80, which is 0.1 times the default distance from the camera to its subject. - * - `far` : The default value for the far clipping plane is 8000, which is 10 times the default distance from the camera to its subject. + * The first four parameters, `left`, `right`, `bottom`, and `top`, set the + * coordinates of the frustum’s sides, bottom, and top. For example, calling + * `ortho(-100, 100, 200, -200)` creates a frustum that’s 200 pixels wide and + * 400 pixels tall. By default, these coordinates are set based on the + * sketch’s width and height, as in + * `ortho(-width / 2, width / 2, -height / 2, height / 2)`. * - * If you prefer a fixed field of view, follow these steps: - * 1. Choose your desired field of view angle (`fovy`). This is how wide the camera can see. - * 2. To ensure that you can see the entire width across horizontally and height across vertically, place the camera a distance of `(height / 2) / tan(fovy / 2)` back from its subject. - * 3. Call perspective with the chosen field of view, canvas aspect ratio, and near/far values: - * `perspective(fovy, width / height, cameraDistance / 10, cameraDistance * 10);` + * The last two parameters, `near` and `far`, set the distance of the + * frustum’s near and far plane from the camera. For example, calling + * `ortho(-100, 100, 200, 200, 50, 1000)` creates a frustum that’s 200 pixels + * wide, 400 pixels tall, starts 50 pixels from the camera, and ends 1,000 + * pixels from the camera. By default, `near` and `far` are set to 0 and + * `max(width, height) + 800`, respectively. * - * @method perspective + * Note: `ortho()` can only be used in WebGL mode. + * + * @method ortho * @for p5 - * @param {Number} [fovy] camera frustum vertical field of view, - * from bottom to top of view, in angleMode units - * @param {Number} [aspect] camera frustum aspect ratio - * @param {Number} [near] frustum near plane length - * @param {Number} [far] frustum far plane length + * @param {Number} [left] x-coordinate of the frustum’s left plane. Defaults to `-width / 2`. + * @param {Number} [right] x-coordinate of the frustum’s right plane. Defaults to `width / 2`. + * @param {Number} [bottom] y-coordinate of the frustum’s bottom plane. Defaults to `height / 2`. + * @param {Number} [top] y-coordinate of the frustum’s top plane. Defaults to `-height / 2`. + * @param {Number} [near] z-coordinate of the frustum’s near plane. Defaults to 0. + * @param {Number} [far] z-coordinate of the frustum’s far plane. Defaults to `max(width, height) + 800`. * @chainable + * * @example *
* - * //drag the mouse to look around! * function setup() { * createCanvas(100, 100, WEBGL); - * perspective(PI / 3.0, width / height, 0.1, 500); - * describe( - * 'two colored 3D boxes move back and forth, rotating as mouse is dragged.' - * ); + * + * describe('A row of tiny, white cubes on a gray background. All the cubes appear the same size.'); * } + * * function draw() { * background(200); - * orbitControl(); - * normalMaterial(); * - * translate(0, 0, 550); - * rotateX(-0.3); - * rotateY(-0.2); + * // Apply an orthographic projection. + * ortho(); * - * push(); - * translate(-15, 0, sin(frameCount / 30) * 95); - * box(30); - * pop(); - * push(); - * translate(15, 0, sin(frameCount / 30 + PI) * 95); - * box(30); - * pop(); + * // Translate the origin toward the camera. + * translate(-10, 10, 600); + * + * // Rotate the coordinate system. + * rotateY(-0.1); + * rotateX(-0.1); + * + * // Draw the row of boxes. + * for (let i = 0; i < 6; i += 1) { + * translate(0, 0, -40); + * box(10); + * } * } * *
* - * @alt - * two colored 3D boxes move back and forth, rotating as mouse is dragged. - */ - _main.default.prototype.perspective = function () { - var _this$_renderer$_curC2; - this._assert3d('perspective'); - for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { - args[_key2] = arguments[_key2]; - } - _main.default._validateParameters('perspective', args); - (_this$_renderer$_curC2 = this._renderer._curCamera).perspective.apply(_this$_renderer$_curC2, args); - return this; - }; - /** - * Sets an orthographic projection for the current camera in a 3D sketch - * and defines a box-shaped viewing frustum within which objects are seen. - * In this projection, all objects with the same dimension appear the same - * size, regardless of whether they are near or far from the camera. - * - * The parameters to this function specify the viewing frustum where - * left and right are the minimum and maximum x values, top and bottom are - * the minimum and maximum y values, and near and far are the minimum and - * maximum z values. - * - * If no parameters are given, the following default is used: - * ortho(-width/2, width/2, -height/2, height/2). - * @method ortho - * @for p5 - * @param {Number} [left] camera frustum left plane - * @param {Number} [right] camera frustum right plane - * @param {Number} [bottom] camera frustum bottom plane - * @param {Number} [top] camera frustum top plane - * @param {Number} [near] camera frustum near plane - * @param {Number} [far] camera frustum far plane - * @chainable - * @example *
* - * //drag the mouse to look around! - * //there's no vanishing point * function setup() { * createCanvas(100, 100, WEBGL); - * ortho(-width / 2, width / 2, height / 2, -height / 2, 0, 500); - * describe( - * 'two 3D boxes move back and forth along same plane, rotating as mouse is dragged.' - * ); + * + * describe('A white cube on a gray background.'); * } + * * function draw() { * background(200); - * orbitControl(); - * normalMaterial(); * - * translate(0,0,500); - * rotateX(0.2); - * rotateY(-0.2); - * push(); - * translate(-15, 0, sin(frameCount / 30) * 65); - * box(30); - * pop(); - * push(); - * translate(15, 0, sin(frameCount / 30 + PI) * 65); - * box(30); - * pop(); + * // Apply an orthographic projection. + * // Center the frustum. + * // Set its width and height to 20. + * // Place its near plane 300 pixels from the camera. + * // Place its far plane 350 pixels from the camera. + * ortho(-10, 10, -10, 10, 300, 350); + * + * // Translate the origin toward the camera. + * translate(-10, 10, 600); + * + * // Rotate the coordinate system. + * rotateY(-0.1); + * rotateX(-0.1); + * + * // Draw the row of boxes. + * for (let i = 0; i < 6; i += 1) { + * translate(0, 0, -40); + * box(10); + * } * } * *
- * - * @alt - * two 3D boxes move back and forth along same plane, rotating as mouse is dragged. */ _main.default.prototype.ortho = function () { var _this$_renderer$_curC3; @@ -109153,64 +128794,109 @@ return this; }; /** - * Sets the frustum of the current camera as defined by - * the parameters. + * Sets the frustum of the current camera in a 3D sketch. * - * A frustum is a geometric form: a pyramid with its top - * cut off. With the viewer's eye at the imaginary top of - * the pyramid, the six planes of the frustum act as clipping - * planes when rendering a 3D view. Thus, any form inside the - * clipping planes is visible; anything outside - * those planes is not visible. + * In a frustum projection, shapes that are further from the camera appear + * smaller than shapes that are near the camera. This technique, called + * foreshortening, creates realistic 3D scenes. * - * Setting the frustum changes the perspective of the scene being rendered. - * This can be achieved more simply in many cases by using - * perspective(). + * `frustum()` changes the default camera’s perspective by changing its + * viewing frustum. The frustum is the volume of space that’s visible to the + * camera. The frustum’s shape is a pyramid with its top cut off. The camera + * is placed where the top of the pyramid should be and points towards the + * base of the pyramid. It views everything within the frustum. + * + * The first four parameters, `left`, `right`, `bottom`, and `top`, set the + * coordinates of the frustum’s sides, bottom, and top. For example, calling + * `frustum(-100, 100, 200, -200)` creates a frustum that’s 200 pixels wide + * and 400 pixels tall. By default, these coordinates are set based on the + * sketch’s width and height, as in + * `ortho(-width / 20, width / 20, height / 20, -height / 20)`. + * + * The last two parameters, `near` and `far`, set the distance of the + * frustum’s near and far plane from the camera. For example, calling + * `ortho(-100, 100, 200, -200, 50, 1000)` creates a frustum that’s 200 pixels + * wide, 400 pixels tall, starts 50 pixels from the camera, and ends 1,000 + * pixels from the camera. By default, near is set to `0.1 * 800`, which is + * 1/10th the default distance between the camera and the origin. `far` is set + * to `10 * 800`, which is 10 times the default distance between the camera + * and the origin. + * + * Note: `frustum()` can only be used in WebGL mode. * - * If no parameters are given, the following default is used: - * frustum(-width/20, width/20, height/20, -height/20, eyeZ/10, eyeZ*10), - * where eyeZ is equal to ((height/2) / tan(PI/6)). * @method frustum * @for p5 - * @param {Number} [left] camera frustum left plane - * @param {Number} [right] camera frustum right plane - * @param {Number} [bottom] camera frustum bottom plane - * @param {Number} [top] camera frustum top plane - * @param {Number} [near] camera frustum near plane - * @param {Number} [far] camera frustum far plane + * @param {Number} [left] x-coordinate of the frustum’s left plane. Defaults to `-width / 20`. + * @param {Number} [right] x-coordinate of the frustum’s right plane. Defaults to `width / 20`. + * @param {Number} [bottom] y-coordinate of the frustum’s bottom plane. Defaults to `height / 20`. + * @param {Number} [top] y-coordinate of the frustum’s top plane. Defaults to `-height / 20`. + * @param {Number} [near] z-coordinate of the frustum’s near plane. Defaults to `0.1 * 800`. + * @param {Number} [far] z-coordinate of the frustum’s far plane. Defaults to `10 * 800`. * @chainable + * * @example *
* * function setup() { * createCanvas(100, 100, WEBGL); - * setAttributes('antialias', true); - * frustum(-0.1, 0.1, -0.1, 0.1, 0.1, 200); - * describe( - * 'two 3D boxes move back and forth along same plane, rotating as mouse is dragged.' - * ); + * + * describe('A row of white cubes on a gray background.'); * } + * * function draw() { * background(200); - * orbitControl(); - * normalMaterial(); - * translate(0,0,700); - * rotateY(-0.2); - * rotateX(-0.3); - * push(); - * translate(-15, 0, sin(frameCount / 30) * 25); - * box(30); - * pop(); - * push(); - * translate(15, 0, sin(frameCount / 30 + PI) * 25); - * box(30); - * pop(); + * + * // Apply the default frustum projection. + * frustum(); + * + * // Translate the origin toward the camera. + * translate(-10, 10, 600); + * + * // Rotate the coordinate system. + * rotateY(-0.1); + * rotateX(-0.1); + * + * // Draw the row of boxes. + * for (let i = 0; i < 6; i += 1) { + * translate(0, 0, -40); + * box(10); + * } * } * *
* - * @alt - * two 3D boxes move back and forth along same plane, rotating as mouse is dragged. + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * describe('A white cube on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Adjust the frustum. + * // Center it. + * // Set its width and height to 20 pixels. + * // Place its near plane 300 pixels from the camera. + * // Place its far plane 350 pixels from the camera. + * frustum(-10, 10, -10, 10, 300, 350); + * + * // Translate the origin toward the camera. + * translate(-10, 10, 600); + * + * // Rotate the coordinate system. + * rotateY(-0.1); + * rotateX(-0.1); + * + * // Draw the row of boxes. + * for (let i = 0; i < 6; i += 1) { + * translate(0, 0, -40); + * box(10); + * } + * } + * + *
*/ _main.default.prototype.frustum = function () { var _this$_renderer$_curC4; @@ -109229,55 +128915,72 @@ * Creates a new p5.Camera object and sets it * as the current (active) camera. * - * The new camera is initialized with a default position - * (see camera()) - * and a default perspective projection - * (see perspective()). - * Its properties can be controlled with the p5.Camera - * methods. + * The new camera is initialized with a default position `(0, 0, 800)` and a + * default perspective projection. Its properties can be controlled with + * p5.Camera methods such as + * `myCamera.lookAt(0, 0, 0)`. * * Note: Every 3D sketch starts with a default camera initialized. - * This camera can be controlled with the global methods + * This camera can be controlled with the functions * camera(), - * perspective(), ortho(), - * and frustum() if it is the only camera - * in the scene. + * perspective(), + * ortho(), and + * frustum() if it's the only camera in the scene. + * + * Note: `createCamera()` can only be used in WebGL mode. + * * @method createCamera - * @return {p5.Camera} The newly created camera object. + * @return {p5.Camera} the new camera. * @for p5 + * * @example - *
- * // Creates a camera object and animates it around a box. - * let camera; + *
+ * + * // Double-click to toggle between cameras. + * + * let cam1; + * let cam2; + * let usingCam1 = true; + * * function setup() { * createCanvas(100, 100, WEBGL); - * background(0); - * camera = createCamera(); - * describe('An example that creates a camera and moves it around the box.'); + * + * // Create the first camera. + * // Keep its default settings. + * cam1 = createCamera(); + * + * // Create the second camera. + * // Place it at the top-left. + * // Point it at the origin. + * cam2 = createCamera(); + * cam2.setPosition(400, -400, 800); + * cam2.lookAt(0, 0, 0); + * + * // Set the current camera to cam1. + * setCamera(cam1); + * + * describe('A white cube on a gray background. The camera toggles between frontal and aerial views when the user double-clicks.'); * } * * function draw() { - * background(0); - * // The camera will automatically - * // rotate to look at [0, 0, 0]. - * camera.lookAt(0, 0, 0); - * - * // The camera will move on the - * // x axis. - * camera.setPosition(sin(frameCount / 60) * 200, 0, 100); - * box(20); - * - * // A 'ground' box to give the viewer - * // a better idea of where the camera - * // is looking. - * translate(0, 50, 0); - * rotateX(HALF_PI); - * box(150, 150, 20); + * background(200); + * + * // Draw the box. + * box(); * } - *
* - * @alt - * An example that creates a camera and moves it around the box. + * // Toggle the current camera when the user double-clicks. + * function doubleClicked() { + * if (usingCam1 === true) { + * setCamera(cam2); + * usingCam1 = false; + * } else { + * setCamera(cam1); + * usingCam1 = true; + * } + * } + *
+ *
*/ _main.default.prototype.createCamera = function () { this._assert3d('createCamera'); @@ -109290,377 +128993,1298 @@ return _cam; }; /** - * This class describes a camera for use in p5's - * - * WebGL mode. It contains camera position, orientation, and projection - * information necessary for rendering a 3D scene. - * - * New p5.Camera objects can be made through the - * createCamera() function and controlled through - * the methods described below. A camera created in this way will use a default - * position in the scene and a default perspective projection until these - * properties are changed through the various methods available. It is possible - * to create multiple cameras, in which case the current camera - * can be set through the setCamera() method. - * - * Note: - * The methods below operate in two coordinate systems: the 'world' coordinate - * system describe positions in terms of their relationship to the origin along - * the X, Y and Z axes whereas the camera's 'local' coordinate system - * describes positions from the camera's point of view: left-right, up-down, - * and forward-backward. The move() method, - * for instance, moves the camera along its own axes, whereas the - * setPosition() - * method sets the camera's position in world-space. - * - * The camera object propreties - * eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ - * which describes camera position, orientation, and projection - * are also accessible via the camera object generated using - * createCamera() + * A class to describe a camera for viewing a 3D sketch. + * + * Each `p5.Camera` object represents a camera that views a section of 3D + * space. It stores information about the camera’s position, orientation, and + * projection. + * + * In WebGL mode, the default camera is a `p5.Camera` object that can be + * controlled with the camera(), + * perspective(), + * ortho(), and + * frustum() functions. Additional cameras can be + * created with createCamera() and activated + * with setCamera(). + * + * Note: `p5.Camera`’s methods operate in two coordinate systems: + * - The “world” coordinate system describes positions in terms of their + * relationship to the origin along the x-, y-, and z-axes. For example, + * calling `myCamera.setPosition()` places the camera in 3D space using + * "world" coordinates. + * - The "local" coordinate system describes positions from the camera's point + * of view: left-right, up-down, and forward-backward. For example, calling + * `myCamera.move()` moves the camera along its own axes. * * @class p5.Camera * @param {rendererGL} rendererGL instance of WebGL renderer + * * @example *
* * let cam; - * let delta = 0.01; + * let delta = 0.001; * * function setup() { * createCanvas(100, 100, WEBGL); - * normalMaterial(); + * + * // Create a p5.Camera object. * cam = createCamera(); - * // set initial pan angle - * cam.pan(-0.8); + * + * // Place the camera at the top-center. + * cam.setPosition(0, -400, 800); + * + * // Point the camera at the origin. + * cam.lookAt(0, 0, 0); + * * describe( - * 'camera view pans left and right across a series of rotating 3D boxes.' + * 'A white cube on a gray background. The cube goes in and out of view as the camera pans left and right.' * ); * } * * function draw() { * background(200); * - * // pan camera according to angle 'delta' + * // Turn the camera left and right, called "panning". * cam.pan(delta); * - * // every 160 frames, switch direction - * if (frameCount % 160 === 0) { + * // Switch directions every 120 frames. + * if (frameCount % 120 === 0) { * delta *= -1; * } * - * rotateX(frameCount * 0.01); - * translate(-100, 0, 0); - * box(20); - * translate(35, 0, 0); - * box(20); - * translate(35, 0, 0); - * box(20); - * translate(35, 0, 0); - * box(20); - * translate(35, 0, 0); - * box(20); - * translate(35, 0, 0); - * box(20); - * translate(35, 0, 0); - * box(20); + * // Draw the box. + * box(); * } * *
* - * @alt - * camera view pans left and right across a series of rotating 3D boxes. + *
+ * + * // Double-click to toggle between cameras. + * + * let cam1; + * let cam2; + * let isDefaultCamera = true; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create the first camera. + * // Keep its default settings. + * cam1 = createCamera(); + * + * // Create the second camera. + * // Place it at the top-left. + * // Point it at the origin. + * cam2 = createCamera(); + * cam2.setPosition(400, -400, 800); + * cam2.lookAt(0, 0, 0); + * + * // Set the current camera to cam1. + * setCamera(cam1); + * + * describe( + * 'A white cube on a gray background. The camera toggles between frontal and aerial views when the user double-clicks.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Draw the box. + * box(); + * } + * + * // Toggle the current camera when the user double-clicks. + * function doubleClicked() { + * if (isDefaultCamera === true) { + * setCamera(cam2); + * isDefaultCamera = false; + * } else { + * setCamera(cam1); + * isDefaultCamera = true; + * } + * } + * + *
*/ _main.default.Camera = /*#__PURE__*/ function () { function Camera(renderer) { _classCallCheck(this, Camera); this._renderer = renderer; this.cameraType = 'default'; + this.useLinePerspective = true; this.cameraMatrix = new _main.default.Matrix(); this.projMatrix = new _main.default.Matrix(); this.yScale = 1; } /** - * camera position value on x axis + * The camera’s y-coordinate. + * + * By default, the camera’s y-coordinate is set to 0 in "world" space. + * * @property {Number} eyeX * @readonly + * + * @example + *
+ * + * let cam; + * let font; + * + * // Load a font and create a p5.Font object. + * function preload() { + * font = loadFont('assets/inconsolata.otf'); + * } + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Camera object. + * cam = createCamera(); + * + * // Place the camera at the top-center. + * cam.setPosition(0, -400, 800); + * + * // Point the camera at the origin. + * cam.lookAt(0, 0, 0); + * + * describe( + * 'A white cube on a gray background. The text "eyeX: 0" is written in black beneath it.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Style the box. + * fill(255); + * + * // Draw the box. + * box(); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * textFont(font); + * fill(0); + * + * // Display the value of eyeX, rounded to the nearest integer. + * text(`eyeX: ${round(cam.eyeX)}`, 0, 55); + * } + * + *
+ * + *
+ * + * let cam; + * let font; + * + * // Load a font and create a p5.Font object. + * function preload() { + * font = loadFont('assets/inconsolata.otf'); + * } + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Camera object. + * cam = createCamera(); + * + * // Place the camera at the top-center. + * cam.setPosition(0, -400, 800); + * + * // Point the camera at the origin. + * cam.lookAt(0, 0, 0); + * + * describe( + * 'A white cube on a gray background. The cube appears to move left and right as the camera moves. The text "eyeX: X" is written in black beneath the cube. X oscillates between -25 and 25.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Style the box. + * fill(255); + * + * // Draw the box. + * box(); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * textFont(font); + * fill(0); + * + * // Calculate the new x-coordinate. + * let x = 25 * sin(frameCount * 0.01); + * + * // Set the camera's position. + * cam.setPosition(x, -400, 800); + * + * // Display the value of eyeX, rounded to the nearest integer. + * text(`eyeX: ${round(cam.eyeX)}`, 0, 55); + * } + * + *
+ */ + /** + * The camera’s y-coordinate. + * + * By default, the camera’s y-coordinate is set to 0 in "world" space. + * + * @property {Number} eyeY + * @readonly + * + * @example + *
+ * + * let cam; + * let font; + * + * // Load a font and create a p5.Font object. + * function preload() { + * font = loadFont('assets/inconsolata.otf'); + * } + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Camera object. + * cam = createCamera(); + * + * // Place the camera at the top-center. + * cam.setPosition(0, -400, 800); + * + * // Point the camera at the origin. + * cam.lookAt(0, 0, 0); + * + * describe( + * 'A white cube on a gray background. The text "eyeY: -400" is written in black beneath it.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Style the box. + * fill(255); + * + * // Draw the box. + * box(); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * textFont(font); + * fill(0); + * + * // Display the value of eyeY, rounded to the nearest integer. + * text(`eyeX: ${round(cam.eyeY)}`, 0, 55); + * } + * + *
+ * + *
+ * + * let cam; + * let font; + * + * // Load a font and create a p5.Font object. + * function preload() { + * font = loadFont('assets/inconsolata.otf'); + * } + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Camera object. + * cam = createCamera(); + * + * // Place the camera at the top-center. + * cam.setPosition(0, -400, 800); + * + * // Point the camera at the origin. + * cam.lookAt(0, 0, 0); + * + * describe( + * 'A white cube on a gray background. The cube appears to move up and down as the camera moves. The text "eyeY: Y" is written in black beneath the cube. Y oscillates between -374 and -425.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Style the box. + * fill(255); + * + * // Draw the box. + * box(); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * textFont(font); + * fill(0); + * + * // Calculate the new y-coordinate. + * let y = 25 * sin(frameCount * 0.01) - 400; + * + * // Set the camera's position. + * cam.setPosition(0, y, 800); + * + * // Display the value of eyeY, rounded to the nearest integer. + * text(`eyeY: ${round(cam.eyeY)}`, 0, 55); + * } + * + *
+ */ + /** + * The camera’s z-coordinate. + * + * By default, the camera’s z-coordinate is set to 800 in "world" space. + * + * @property {Number} eyeZ + * @readonly + * + * @example + *
+ * + * let cam; + * let font; + * + * // Load a font and create a p5.Font object. + * function preload() { + * font = loadFont('assets/inconsolata.otf'); + * } + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Camera object. + * cam = createCamera(); + * + * // Place the camera at the top-center. + * cam.setPosition(0, -400, 800); + * + * // Point the camera at the origin. + * cam.lookAt(0, 0, 0); + * + * describe( + * 'A white cube on a gray background. The text "eyeZ: 800" is written in black beneath it.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Style the box. + * fill(255); + * + * // Draw the box. + * box(); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * textFont(font); + * fill(0); + * + * // Display the value of eyeZ, rounded to the nearest integer. + * text(`eyeZ: ${round(cam.eyeZ)}`, 0, 55); + * } + * + *
+ * + *
+ * + * let cam; + * let font; + * + * // Load a font and create a p5.Font object. + * function preload() { + * font = loadFont('assets/inconsolata.otf'); + * } + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Camera object. + * cam = createCamera(); + * + * // Place the camera at the top-center. + * cam.setPosition(0, -400, 800); + * + * // Point the camera at the origin. + * cam.lookAt(0, 0, 0); + * + * describe( + * 'A white cube on a gray background. The cube appears to move forward and back as the camera moves. The text "eyeZ: Z" is written in black beneath the cube. Z oscillates between 700 and 900.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Style the box. + * fill(255); + * + * // Draw the box. + * box(); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * textFont(font); + * fill(0); + * + * // Calculate the new z-coordinate. + * let z = 100 * sin(frameCount * 0.01) + 800; + * + * // Set the camera's position. + * cam.setPosition(0, -400, z); + * + * // Display the value of eyeZ, rounded to the nearest integer. + * text(`eyeZ: ${round(cam.eyeZ)}`, 0, 55); + * } + * + *
+ */ + /** + * The x-coordinate of the place where the camera looks. + * + * By default, the camera looks at the origin `(0, 0, 0)` in "world" space, so + * `myCamera.centerX` is 0. + * + * @property {Number} centerX + * @readonly + * + * @example + *
+ * + * let cam; + * let font; + * + * // Load a font and create a p5.Font object. + * function preload() { + * font = loadFont('assets/inconsolata.otf'); + * } + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Camera object. + * cam = createCamera(); + * + * // Place the camera at the top-center. + * cam.setPosition(0, -400, 800); + * + * // Point the camera at (10, 20, -30). + * cam.lookAt(10, 20, -30); + * + * describe( + * 'A white cube on a gray background. The text "centerX: 10" is written in black beneath it.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Style the box. + * fill(255); + * + * // Draw the box. + * box(); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * textFont(font); + * fill(0); + * + * // Display the value of centerX, rounded to the nearest integer. + * text(`centerX: ${round(cam.centerX)}`, 0, 55); + * } + * + *
+ * + *
+ * + * let cam; + * let font; + * + * // Load a font and create a p5.Font object. + * function preload() { + * font = loadFont('assets/inconsolata.otf'); + * } + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Camera object. + * cam = createCamera(); + * + * // Place the camera at the top-right. + * cam.setPosition(100, -400, 800); + * + * // Point the camera at (10, 20, -30). + * cam.lookAt(10, 20, -30); + * + * describe( + * 'A white cube on a gray background. The cube appears to move left and right as the camera shifts its focus. The text "centerX: X" is written in black beneath the cube. X oscillates between -15 and 35.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Style the box. + * fill(255); + * + * // Draw the box. + * box(); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * textFont(font); + * fill(0); + * + * // Calculate the new x-coordinate. + * let x = 25 * sin(frameCount * 0.01) + 10; + * + * // Point the camera. + * cam.lookAt(x, 20, -30); + * + * // Display the value of centerX, rounded to the nearest integer. + * text(`centerX: ${round(cam.centerX)}`, 0, 55); + * } + * + *
+ */ + /** + * The y-coordinate of the place where the camera looks. + * + * By default, the camera looks at the origin `(0, 0, 0)` in "world" space, so + * `myCamera.centerY` is 0. + * + * @property {Number} centerY + * @readonly + * + * @example + *
+ * + * let cam; + * let font; + * + * // Load a font and create a p5.Font object. + * function preload() { + * font = loadFont('assets/inconsolata.otf'); + * } + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Camera object. + * cam = createCamera(); + * + * // Place the camera at the top-center. + * cam.setPosition(0, -400, 800); + * + * // Point the camera at (10, 20, -30). + * cam.lookAt(10, 20, -30); + * + * describe( + * 'A white cube on a gray background. The text "centerY: 20" is written in black beneath it.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Style the box. + * fill(255); + * + * // Draw the box. + * box(); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * textFont(font); + * fill(0); + * + * // Display the value of centerY, rounded to the nearest integer. + * text(`centerY: ${round(cam.centerY)}`, 0, 55); + * } + * + *
+ * + *
+ * + * let cam; + * let font; + * + * // Load a font and create a p5.Font object. + * function preload() { + * font = loadFont('assets/inconsolata.otf'); + * } + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Camera object. + * cam = createCamera(); + * + * // Place the camera at the top-right. + * cam.setPosition(100, -400, 800); + * + * // Point the camera at (10, 20, -30). + * cam.lookAt(10, 20, -30); + * + * describe( + * 'A white cube on a gray background. The cube appears to move up and down as the camera shifts its focus. The text "centerY: Y" is written in black beneath the cube. Y oscillates between -5 and 45.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Style the box. + * fill(255); + * + * // Draw the box. + * box(); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * textFont(font); + * fill(0); + * + * // Calculate the new y-coordinate. + * let y = 25 * sin(frameCount * 0.01) + 20; + * + * // Point the camera. + * cam.lookAt(10, y, -30); + * + * // Display the value of centerY, rounded to the nearest integer. + * text(`centerY: ${round(cam.centerY)}`, 0, 55); + * } + * + *
+ */ + /** + * The y-coordinate of the place where the camera looks. + * + * By default, the camera looks at the origin `(0, 0, 0)` in "world" space, so + * `myCamera.centerZ` is 0. + * + * @property {Number} centerZ + * @readonly + * * @example + *
+ * + * let cam; + * let font; + * + * // Load a font and create a p5.Font object. + * function preload() { + * font = loadFont('assets/inconsolata.otf'); + * } * - *
- * let cam, div; * function setup() { * createCanvas(100, 100, WEBGL); - * background(0); + * + * // Create a p5.Camera object. * cam = createCamera(); - * div = createDiv(); - * div.position(0, 0); - * describe('An example showing the use of camera object properties'); + * + * // Place the camera at the top-center. + * cam.setPosition(0, -400, 800); + * + * // Point the camera at (10, 20, -30). + * cam.lookAt(10, 20, -30); + * + * describe( + * 'A white cube on a gray background. The text "centerZ: -30" is written in black beneath it.' + * ); * } * * function draw() { - * orbitControl(); - * box(10); - * div.html('eyeX = ' + cam.eyeX); + * background(200); + * + * // Style the box. + * fill(255); + * + * // Draw the box. + * box(); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * textFont(font); + * fill(0); + * + * // Display the value of centerZ, rounded to the nearest integer. + * text(`centerZ: ${round(cam.centerZ)}`, 0, 55); * } - *
+ *
+ *
* - * @alt - * An example showing the use of camera object properties + *
+ * + * let cam; + * let font; + * + * // Load a font and create a p5.Font object. + * function preload() { + * font = loadFont('assets/inconsolata.otf'); + * } * - */ - /** - * camera position value on y axis - * @property {Number} eyeY - * @readonly - * @example - *
- * let cam, div; * function setup() { * createCanvas(100, 100, WEBGL); - * background(0); + * + * // Create a p5.Camera object. * cam = createCamera(); - * div = createDiv(); - * div.position(0, 0); - * describe('An example showing the use of camera object properties'); + * + * // Place the camera at the top-right. + * cam.setPosition(100, -400, 800); + * + * // Point the camera at (10, 20, -30). + * cam.lookAt(10, 20, -30); + * + * describe( + * 'A white cube on a gray background. The cube appears to move forward and back as the camera shifts its focus. The text "centerZ: Z" is written in black beneath the cube. Z oscillates between -55 and -25.' + * ); * } * * function draw() { - * orbitControl(); - * box(10); - * div.html('eyeY = ' + cam.eyeY); - * } - *
+ * background(200); + * + * // Style the box. + * fill(255); + * + * // Draw the box. + * box(); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * textFont(font); + * fill(0); + * + * // Calculate the new z-coordinate. + * let z = 25 * sin(frameCount * 0.01) - 30; * - * @alt - * An example showing the use of camera object properties + * // Point the camera. + * cam.lookAt(10, 20, z); * + * // Display the value of centerZ, rounded to the nearest integer. + * text(`centerZ: ${round(cam.centerZ)}`, 0, 55); + * } + *
+ *
*/ /** - * camera position value on z axis - * @property {Number} eyeZ + * The x-component of the camera's "up" vector. + * + * The camera's "up" vector orients its y-axis. By default, the "up" vector is + * `(0, 1, 0)`, so its x-component is 0 in "local" space. + * + * @property {Number} upX * @readonly + * * @example - *
- * let cam, div; + *
+ * + * let cam; + * let font; + * + * // Load a font and create a p5.Font object. + * function preload() { + * font = loadFont('assets/inconsolata.otf'); + * } + * * function setup() { * createCanvas(100, 100, WEBGL); - * background(0); + * + * // Create a p5.Camera object. * cam = createCamera(); - * div = createDiv(); - * div.position(0, 0); - * describe('An example showing the use of camera object properties'); + * + * // Place the camera at the top-right: (100, -400, 800) + * // Point it at the origin: (0, 0, 0) + * // Set its "up" vector: (0, 1, 0). + * cam.camera(100, -400, 800, 0, 0, 0, 0, 1, 0); + * + * describe( + * 'A white cube on a gray background. The text "upX: 0" is written in black beneath it.' + * ); * } * * function draw() { - * orbitControl(); - * box(10); - * div.html('eyeZ = ' + cam.eyeZ); + * background(200); + * + * // Style the box. + * fill(255); + * + * // Draw the box. + * box(); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * textFont(font); + * fill(0); + * + * // Display the value of upX, rounded to the nearest tenth. + * text(`upX: ${round(cam.upX, 1)}`, 0, 55); * } - *
+ *
+ *
* - * @alt - * An example showing the use of camera object properties + *
+ * + * let cam; + * let font; + * + * // Load a font and create a p5.Font object. + * function preload() { + * font = loadFont('assets/inconsolata.otf'); + * } * - */ - /** - * x coordinate representing center of the sketch - * @property {Number} centerX - * @readonly - * @example - *
- * let cam, div; * function setup() { * createCanvas(100, 100, WEBGL); - * background(255); + * + * // Create a p5.Camera object. * cam = createCamera(); - * cam.lookAt(1, 0, 0); - * div = createDiv('centerX = ' + cam.centerX); - * div.position(0, 0); - * div.style('color', 'white'); - * describe('An example showing the use of camera object properties'); + * + * // Place the camera at the top-right: (100, -400, 800) + * // Point it at the origin: (0, 0, 0) + * // Set its "up" vector: (0, 1, 0). + * cam.camera(100, -400, 800, 0, 0, 0, 0, 1, 0); + * + * describe( + * 'A white cube on a gray background. The cube appears to rock back and forth. The text "upX: X" is written in black beneath it. X oscillates between -1 and 1.' + * ); * } * * function draw() { - * orbitControl(); - * box(10); - * } - *
+ * background(200); + * + * // Style the box. + * fill(255); + * + * // Draw the box. + * box(); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * textFont(font); + * fill(0); * - * @alt - * An example showing the use of camera object properties + * // Calculate the x-component. + * let x = sin(frameCount * 0.01); * + * // Update the camera's "up" vector. + * cam.camera(100, -400, 800, 0, 0, 0, x, 1, 0); + * + * // Display the value of upX, rounded to the nearest tenth. + * text(`upX: ${round(cam.upX, 1)}`, 0, 55); + * } + *
+ *
*/ /** - * y coordinate representing center of the sketch - * @property {Number} centerY + * The y-component of the camera's "up" vector. + * + * The camera's "up" vector orients its y-axis. By default, the "up" vector is + * `(0, 1, 0)`, so its y-component is 1 in "local" space. + * + * @property {Number} upY * @readonly + * * @example - *
- * let cam, div; + *
+ * + * let cam; + * let font; + * + * // Load a font and create a p5.Font object. + * function preload() { + * font = loadFont('assets/inconsolata.otf'); + * } + * * function setup() { * createCanvas(100, 100, WEBGL); - * background(255); + * + * // Create a p5.Camera object. * cam = createCamera(); - * cam.lookAt(0, 1, 0); - * div = createDiv('centerY = ' + cam.centerY); - * div.position(0, 0); - * div.style('color', 'white'); - * describe('An example showing the use of camera object properties'); + * + * // Place the camera at the top-right: (100, -400, 800) + * // Point it at the origin: (0, 0, 0) + * // Set its "up" vector: (0, 1, 0). + * cam.camera(100, -400, 800, 0, 0, 0, 0, 1, 0); + * + * describe( + * 'A white cube on a gray background. The text "upY: 1" is written in black beneath it.' + * ); * } * * function draw() { - * orbitControl(); - * box(10); + * background(200); + * + * // Style the box. + * fill(255); + * + * // Draw the box. + * box(); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * textFont(font); + * fill(0); + * + * // Display the value of upY, rounded to the nearest tenth. + * text(`upY: ${round(cam.upY, 1)}`, 0, 55); * } - *
+ *
+ *
+ * + *
+ * + * let cam; + * let font; * - * @alt - * An example showing the use of camera object properties + * // Load a font and create a p5.Font object. + * function preload() { + * font = loadFont('assets/inconsolata.otf'); + * } * - */ - /** - * z coordinate representing center of the sketch - * @property {Number} centerZ - * @readonly - * @example - *
- * let cam, div; * function setup() { * createCanvas(100, 100, WEBGL); - * background(255); + * + * // Create a p5.Camera object. * cam = createCamera(); - * cam.lookAt(0, 0, 1); - * div = createDiv('centerZ = ' + cam.centerZ); - * div.position(0, 0); - * div.style('color', 'white'); - * describe('An example showing the use of camera object properties'); + * + * // Place the camera at the top-right: (100, -400, 800) + * // Point it at the origin: (0, 0, 0) + * // Set its "up" vector: (0, 1, 0). + * cam.camera(100, -400, 800, 0, 0, 0, 0, 1, 0); + * + * describe( + * 'A white cube on a gray background. The cube flips upside-down periodically. The text "upY: Y" is written in black beneath it. Y oscillates between -1 and 1.' + * ); * } * * function draw() { - * orbitControl(); - * box(10); - * } - *
+ * background(200); + * + * // Style the box. + * fill(255); + * + * // Draw the box. + * box(); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * textFont(font); + * fill(0); + * + * // Calculate the y-component. + * let y = sin(frameCount * 0.01); * - * @alt - * An example showing the use of camera object properties + * // Update the camera's "up" vector. + * cam.camera(100, -400, 800, 0, 0, 0, 0, y, 0); * + * // Display the value of upY, rounded to the nearest tenth. + * text(`upY: ${round(cam.upY, 1)}`, 0, 55); + * } + *
+ *
*/ /** - * x component of direction 'up' from camera - * @property {Number} upX + * The z-component of the camera's "up" vector. + * + * The camera's "up" vector orients its y-axis. By default, the "up" vector is + * `(0, 1, 0)`, so its z-component is 0 in "local" space. + * + * @property {Number} upZ * @readonly + * * @example - *
- * let cam, div; + *
+ * + * let cam; + * let font; + * + * // Load a font and create a p5.Font object. + * function preload() { + * font = loadFont('assets/inconsolata.otf'); + * } + * * function setup() { * createCanvas(100, 100, WEBGL); - * background(255); + * + * // Create a p5.Camera object. * cam = createCamera(); - * div = createDiv('upX = ' + cam.upX); - * div.position(0, 0); - * div.style('color', 'blue'); - * div.style('font-size', '18px'); - * describe('An example showing the use of camera object properties'); + * + * // Place the camera at the top-right: (100, -400, 800) + * // Point it at the origin: (0, 0, 0) + * // Set its "up" vector: (0, 1, 0). + * cam.camera(100, -400, 800, 0, 0, 0, 0, 1, 0); + * + * describe( + * 'A white cube on a gray background. The text "upZ: 0" is written in black beneath it.' + * ); * } - *
* - * @alt - * An example showing the use of camera object properties + * function draw() { + * background(200); * - */ - /** - * y component of direction 'up' from camera - * @property {Number} upY - * @readonly - * @example - *
- * let cam, div; - * function setup() { - * createCanvas(100, 100, WEBGL); - * background(255); - * cam = createCamera(); - * div = createDiv('upY = ' + cam.upY); - * div.position(0, 0); - * div.style('color', 'blue'); - * div.style('font-size', '18px'); - * describe('An example showing the use of camera object properties'); + * // Style the box. + * fill(255); + * + * // Draw the box. + * box(); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * textFont(font); + * fill(0); + * + * // Display the value of upZ, rounded to the nearest tenth. + * text(`upZ: ${round(cam.upZ, 1)}`, 0, 55); * } - *
+ *
+ *
+ * + *
+ * + * let cam; + * let font; * - * @alt - * An example showing the use of camera object properties + * // Load a font and create a p5.Font object. + * function preload() { + * font = loadFont('assets/inconsolata.otf'); + * } * - */ - /** - * z component of direction 'up' from camera - * @property {Number} upZ - * @readonly - * @example - *
- * let cam, div; * function setup() { * createCanvas(100, 100, WEBGL); - * background(255); + * + * // Create a p5.Camera object. * cam = createCamera(); - * div = createDiv('upZ = ' + cam.upZ); - * div.position(0, 0); - * div.style('color', 'blue'); - * div.style('font-size', '18px'); - * describe('An example showing the use of camera object properties'); + * + * // Place the camera at the top-right: (100, -400, 800) + * // Point it at the origin: (0, 0, 0) + * // Set its "up" vector: (0, 1, 0). + * cam.camera(100, -400, 800, 0, 0, 0, 0, 1, 0); + * + * describe( + * 'A white cube on a gray background. The cube appears to rock back and forth. The text "upZ: Z" is written in black beneath it. Z oscillates between -1 and 1.' + * ); * } - *
* - * @alt - * An example showing the use of camera object properties + * function draw() { + * background(200); + * + * // Style the box. + * fill(255); + * + * // Draw the box. + * box(); + * + * // Style the text. + * textAlign(CENTER); + * textSize(16); + * textFont(font); + * fill(0); + * + * // Calculate the z-component. + * let z = sin(frameCount * 0.01); * + * // Update the camera's "up" vector. + * cam.camera(100, -400, 800, 0, 0, 0, 0, 1, z); + * + * // Display the value of upZ, rounded to the nearest tenth. + * text(`upZ: ${round(cam.upZ, 1)}`, 0, 55); + * } + *
+ *
*/ //////////////////////////////////////////////////////////////////////////////// // Camera Projection Methods //////////////////////////////////////////////////////////////////////////////// /** - * Sets a perspective projection. - * Accepts the same parameters as the global - * perspective(). - * More information on this function can be found there. + * Sets a perspective projection for the camera. + * + * In a perspective projection, shapes that are further from the camera appear + * smaller than shapes that are near the camera. This technique, called + * foreshortening, creates realistic 3D scenes. It’s applied by default in new + * `p5.Camera` objects. + * + * `myCamera.perspective()` changes the camera’s perspective by changing its + * viewing frustum. The frustum is the volume of space that’s visible to the + * camera. The frustum’s shape is a pyramid with its top cut off. The camera + * is placed where the top of the pyramid should be and points towards the + * base of the pyramid. It views everything within the frustum. + * + * The first parameter, `fovy`, is the camera’s vertical field of view. It’s + * an angle that describes how tall or narrow a view the camera has. For + * example, calling `myCamera.perspective(0.5)` sets the camera’s vertical + * field of view to 0.5 radians. By default, `fovy` is calculated based on the + * sketch’s height and the camera’s default z-coordinate, which is 800. The + * formula for the default `fovy` is `2 * atan(height / 2 / 800)`. + * + * The second parameter, `aspect`, is the camera’s aspect ratio. It’s a number + * that describes the ratio of the top plane’s width to its height. For + * example, calling `myCamera.perspective(0.5, 1.5)` sets the camera’s field + * of view to 0.5 radians and aspect ratio to 1.5, which would make shapes + * appear thinner on a square canvas. By default, `aspect` is set to + * `width / height`. + * + * The third parameter, `near`, is the distance from the camera to the near + * plane. For example, calling `myCamera.perspective(0.5, 1.5, 100)` sets the + * camera’s field of view to 0.5 radians, its aspect ratio to 1.5, and places + * the near plane 100 pixels from the camera. Any shapes drawn less than 100 + * pixels from the camera won’t be visible. By default, `near` is set to + * `0.1 * 800`, which is 1/10th the default distance between the camera and + * the origin. + * + * The fourth parameter, `far`, is the distance from the camera to the far + * plane. For example, calling `myCamera.perspective(0.5, 1.5, 100, 10000)` + * sets the camera’s field of view to 0.5 radians, its aspect ratio to 1.5, + * places the near plane 100 pixels from the camera, and places the far plane + * 10,000 pixels from the camera. Any shapes drawn more than 10,000 pixels + * from the camera won’t be visible. By default, `far` is set to `10 * 800`, + * which is 10 times the default distance between the camera and the origin. + * * @method perspective * @for p5.Camera + * @param {Number} [fovy] camera frustum vertical field of view. Defaults to + * `2 * atan(height / 2 / 800)`. + * @param {Number} [aspect] camera frustum aspect ratio. Defaults to + * `width / height`. + * @param {Number} [near] distance from the camera to the near clipping plane. + * Defaults to `0.1 * 800`. + * @param {Number} [far] distance from the camera to the far clipping plane. + * Defaults to `10 * 800`. + * * @example *
* - * // drag the mouse to look around! + * // Double-click to toggle between cameras. * - * let cam; + * let cam1; + * let cam2; + * let isDefaultCamera = true; * * function setup() { * createCanvas(100, 100, WEBGL); - * // create a camera - * cam = createCamera(); - * // give it a perspective projection - * cam.perspective(PI / 3.0, width / height, 0.1, 500); + * + * // Create the first camera. + * // Keep its default settings. + * cam1 = createCamera(); + * + * // Create the second camera. + * cam2 = createCamera(); + * + * // Place it at the top-right. + * cam2.camera(400, -400, 800); + * + * // Set its fovy to 0.2. + * // Set its aspect to 1.5. + * // Set its near to 600. + * // Set its far to 1200. + * cam2.perspective(0.2, 1.5, 600, 1200); + * + * // Set the current camera to cam1. + * setCamera(cam1); + * + * describe('A white cube on a gray background. The camera toggles between a frontal view and a skewed aerial view when the user double-clicks.'); * } * * function draw() { * background(200); - * orbitControl(); - * normalMaterial(); * - * translate(0, 0, 550); - * rotateX(-0.3); - * rotateY(-0.2); + * // Draw the box. + * box(); + * } + * + * // Toggle the current camera when the user double-clicks. + * function doubleClicked() { + * if (isDefaultCamera === true) { + * setCamera(cam2); + * isDefaultCamera = false; + * } else { + * setCamera(cam1); + * isDefaultCamera = true; + * } + * } + * + *
+ * + *
+ * + * // Double-click to toggle between cameras. + * + * let cam1; + * let cam2; + * let isDefaultCamera = true; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create the first camera. + * // Keep its default settings. + * cam1 = createCamera(); + * + * // Create the second camera. + * cam2 = createCamera(); + * + * // Place it at the top-right. + * cam2.camera(400, -400, 800); + * + * // Set its fovy to 0.2. + * // Set its aspect to 1.5. + * // Set its near to 600. + * // Set its far to 1200. + * cam2.perspective(0.2, 1.5, 600, 1200); + * + * // Set the current camera to cam1. + * setCamera(cam1); + * + * describe('A white cube moves left and right on a gray background. The camera toggles between a frontal and a skewed aerial view when the user double-clicks.'); + * } + * + * function draw() { + * background(200); + * + * // Translate the origin left and right. + * let x = 100 * sin(frameCount * 0.01); + * translate(x, 0, 0); + * + * // Draw the box. + * box(); + * } * - * push(); - * translate(-15, 0, sin(frameCount / 30) * 95); - * box(30); - * pop(); - * push(); - * translate(15, 0, sin(frameCount / 30 + PI) * 95); - * box(30); - * pop(); + * // Toggle the current camera when the user double-clicks. + * function doubleClicked() { + * if (isDefaultCamera === true) { + * setCamera(cam2); + * isDefaultCamera = false; + * } else { + * setCamera(cam1); + * isDefaultCamera = true; + * } * } * *
- * @alt - * two colored 3D boxes move back and forth, rotating as mouse is dragged. */ _createClass(Camera, [ @@ -109703,62 +130327,177 @@ this.projMatrix.set(f / aspect, 0, 0, 0, 0, - f * this.yScale, 0, 0, 0, 0, (far + near) * nf, - 1, 0, 0, 2 * far * near * nf, 0); /* eslint-enable indent */ if (this._isActive()) { - this._renderer.uPMatrix.set(this.projMatrix.mat4[0], this.projMatrix.mat4[1], this.projMatrix.mat4[2], this.projMatrix.mat4[3], this.projMatrix.mat4[4], this.projMatrix.mat4[5], this.projMatrix.mat4[6], this.projMatrix.mat4[7], this.projMatrix.mat4[8], this.projMatrix.mat4[9], this.projMatrix.mat4[10], this.projMatrix.mat4[11], this.projMatrix.mat4[12], this.projMatrix.mat4[13], this.projMatrix.mat4[14], this.projMatrix.mat4[15]); + this._renderer.uPMatrix.set(this.projMatrix); } } /** - * Sets an orthographic projection. - * Accepts the same parameters as the global - * ortho(). - * More information on this function can be found there. + * Sets an orthographic projection for the camera. + * + * In an orthographic projection, shapes with the same size always appear the + * same size, regardless of whether they are near or far from the camera. + * + * `myCamera.ortho()` changes the camera’s perspective by changing its viewing + * frustum from a truncated pyramid to a rectangular prism. The frustum is the + * volume of space that’s visible to the camera. The camera is placed in front + * of the frustum and views everything within the frustum. `myCamera.ortho()` + * has six optional parameters to define the viewing frustum. + * + * The first four parameters, `left`, `right`, `bottom`, and `top`, set the + * coordinates of the frustum’s sides, bottom, and top. For example, calling + * `myCamera.ortho(-100, 100, 200, -200)` creates a frustum that’s 200 pixels + * wide and 400 pixels tall. By default, these dimensions are set based on + * the sketch’s width and height, as in + * `myCamera.ortho(-width / 2, width / 2, -height / 2, height / 2)`. + * + * The last two parameters, `near` and `far`, set the distance of the + * frustum’s near and far plane from the camera. For example, calling + * `myCamera.ortho(-100, 100, 200, -200, 50, 1000)` creates a frustum that’s + * 200 pixels wide, 400 pixels tall, starts 50 pixels from the camera, and + * ends 1,000 pixels from the camera. By default, `near` and `far` are set to + * 0 and `max(width, height) + 800`, respectively. + * * @method ortho * @for p5.Camera + * @param {Number} [left] x-coordinate of the frustum’s left plane. Defaults to `-width / 2`. + * @param {Number} [right] x-coordinate of the frustum’s right plane. Defaults to `width / 2`. + * @param {Number} [bottom] y-coordinate of the frustum’s bottom plane. Defaults to `height / 2`. + * @param {Number} [top] y-coordinate of the frustum’s top plane. Defaults to `-height / 2`. + * @param {Number} [near] z-coordinate of the frustum’s near plane. Defaults to 0. + * @param {Number} [far] z-coordinate of the frustum’s far plane. Defaults to `max(width, height) + 800`. + * * @example *
* - * // drag the mouse to look around! - * // there's no vanishing point + * // Double-click to toggle between cameras. * - * let cam; + * let cam1; + * let cam2; + * let isDefaultCamera = true; * * function setup() { * createCanvas(100, 100, WEBGL); - * // create a camera - * cam = createCamera(); - * // give it an orthographic projection - * cam.ortho(-width / 2, width / 2, height / 2, -height / 2, 0, 500); + * + * // Create the first camera. + * // Keep its default settings. + * cam1 = createCamera(); + * + * // Create the second camera. + * cam2 = createCamera(); + * + * // Apply an orthographic projection. + * cam2.ortho(); + * + * // Set the current camera to cam1. + * setCamera(cam1); + * + * describe('A row of white cubes against a gray background. The camera toggles between a perspective and an orthographic projection when the user double-clicks.'); * } + * * function draw() { * background(200); - * orbitControl(); - * normalMaterial(); - * translate(0,0,500); - * rotateX(0.2); - * rotateY(-0.2); - * push(); - * translate(-15, 0, sin(frameCount / 30) * 65); - * box(30); - * pop(); - * push(); - * translate(15, 0, sin(frameCount / 30 + PI) * 65); - * box(30); - * pop(); + * + * // Translate the origin toward the camera. + * translate(-10, 10, 500); + * + * // Rotate the coordinate system. + * rotateY(-0.1); + * rotateX(-0.1); + * + * // Draw the row of boxes. + * for (let i = 0; i < 6; i += 1) { + * translate(0, 0, -40); + * box(10); + * } + * } + * + * // Toggle the current camera when the user double-clicks. + * function doubleClicked() { + * if (isDefaultCamera === true) { + * setCamera(cam2); + * isDefaultCamera = false; + * } else { + * setCamera(cam1); + * isDefaultCamera = true; + * } + * } + * + *
+ * + *
+ * + * // Double-click to toggle between cameras. + * + * let cam1; + * let cam2; + * let isDefaultCamera = true; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create the first camera. + * // Keep its default settings. + * cam1 = createCamera(); + * + * // Create the second camera. + * cam2 = createCamera(); + * + * // Apply an orthographic projection. + * cam2.ortho(); + * + * // Set the current camera to cam1. + * setCamera(cam1); + * + * describe('A row of white cubes slither like a snake against a gray background. The camera toggles between a perspective and an orthographic projection when the user double-clicks.'); + * } + * + * function draw() { + * background(200); + * + * // Translate the origin toward the camera. + * translate(-10, 10, 500); + * + * // Rotate the coordinate system. + * rotateY(-0.1); + * rotateX(-0.1); + * + * // Draw the row of boxes. + * for (let i = 0; i < 6; i += 1) { + * push(); + * // Calculate the box's coordinates. + * let x = 10 * sin(frameCount * 0.02 + i * 0.6); + * let z = -40 * i; + * // Translate the origin. + * translate(x, 0, z); + * // Draw the box. + * box(10); + * pop(); + * } + * } + * + * // Toggle the current camera when the user double-clicks. + * function doubleClicked() { + * if (isDefaultCamera === true) { + * setCamera(cam2); + * isDefaultCamera = false; + * } else { + * setCamera(cam1); + * isDefaultCamera = true; + * } * } * *
- * @alt - * two 3D boxes move back and forth along same plane, rotating as mouse is dragged. */ }, { key: 'ortho', value: function ortho(left, right, bottom, top, near, far) { - if (left === undefined) left = - this._renderer.width / 2; - if (right === undefined) right = + this._renderer.width / 2; - if (bottom === undefined) bottom = - this._renderer.height / 2; - if (top === undefined) top = + this._renderer.height / 2; + var source = this.fbo || this._renderer; + if (left === undefined) left = - source.width / 2; + if (right === undefined) right = + source.width / 2; + if (bottom === undefined) bottom = - source.height / 2; + if (top === undefined) top = + source.height / 2; if (near === undefined) near = 0; - if (far === undefined) far = Math.max(this._renderer.width, this._renderer.height); + if (far === undefined) far = Math.max(source.width, source.height) + 800; this.cameraNear = near; this.cameraFar = far; var w = right - left; @@ -109775,50 +130514,110 @@ this.projMatrix.set(x, 0, 0, 0, 0, - y, 0, 0, 0, 0, z, 0, tx, ty, tz, 1); /* eslint-enable indent */ if (this._isActive()) { - this._renderer.uPMatrix.set(this.projMatrix.mat4[0], this.projMatrix.mat4[1], this.projMatrix.mat4[2], this.projMatrix.mat4[3], this.projMatrix.mat4[4], this.projMatrix.mat4[5], this.projMatrix.mat4[6], this.projMatrix.mat4[7], this.projMatrix.mat4[8], this.projMatrix.mat4[9], this.projMatrix.mat4[10], this.projMatrix.mat4[11], this.projMatrix.mat4[12], this.projMatrix.mat4[13], this.projMatrix.mat4[14], this.projMatrix.mat4[15]); + this._renderer.uPMatrix.set(this.projMatrix); } this.cameraType = 'custom'; } /** * Sets the camera's frustum. - * Accepts the same parameters as the global - * frustum(). - * More information on this function can be found there. + * + * In a frustum projection, shapes that are further from the camera appear + * smaller than shapes that are near the camera. This technique, called + * foreshortening, creates realistic 3D scenes. + * + * `myCamera.frustum()` changes the camera’s perspective by changing its + * viewing frustum. The frustum is the volume of space that’s visible to the + * camera. The frustum’s shape is a pyramid with its top cut off. The camera + * is placed where the top of the pyramid should be and points towards the + * base of the pyramid. It views everything within the frustum. + * + * The first four parameters, `left`, `right`, `bottom`, and `top`, set the + * coordinates of the frustum’s sides, bottom, and top. For example, calling + * `myCamera.frustum(-100, 100, 200, -200)` creates a frustum that’s 200 + * pixels wide and 400 pixels tall. By default, these coordinates are set + * based on the sketch’s width and height, as in + * `myCamera.frustum(-width / 20, width / 20, height / 20, -height / 20)`. + * + * The last two parameters, `near` and `far`, set the distance of the + * frustum’s near and far plane from the camera. For example, calling + * `myCamera.frustum(-100, 100, 200, -200, 50, 1000)` creates a frustum that’s + * 200 pixels wide, 400 pixels tall, starts 50 pixels from the camera, and ends + * 1,000 pixels from the camera. By default, near is set to `0.1 * 800`, which + * is 1/10th the default distance between the camera and the origin. `far` is + * set to `10 * 800`, which is 10 times the default distance between the + * camera and the origin. + * * @method frustum * @for p5.Camera + * @param {Number} [left] x-coordinate of the frustum’s left plane. Defaults to `-width / 20`. + * @param {Number} [right] x-coordinate of the frustum’s right plane. Defaults to `width / 20`. + * @param {Number} [bottom] y-coordinate of the frustum’s bottom plane. Defaults to `height / 20`. + * @param {Number} [top] y-coordinate of the frustum’s top plane. Defaults to `-height / 20`. + * @param {Number} [near] z-coordinate of the frustum’s near plane. Defaults to `0.1 * 800`. + * @param {Number} [far] z-coordinate of the frustum’s far plane. Defaults to `10 * 800`. + * * @example *
* - * let cam; + * // Double-click to toggle between cameras. + * + * let cam1; + * let cam2; + * let isDefaultCamera = true; * * function setup() { - * x = createCanvas(100, 100, WEBGL); - * setAttributes('antialias', true); - * // create a camera - * cam = createCamera(); - * // set its frustum - * cam.frustum(-0.1, 0.1, -0.1, 0.1, 0.1, 200); + * createCanvas(100, 100, WEBGL); + * + * // Create the first camera. + * // Keep its default settings. + * cam1 = createCamera(); + * + * // Create the second camera. + * cam2 = createCamera(); + * + * // Adjust the frustum. + * // Center it. + * // Set its width and height to 20 pixels. + * // Place its near plane 300 pixels from the camera. + * // Place its far plane 350 pixels from the camera. + * cam2.frustum(-10, 10, -10, 10, 300, 350); + * + * // Set the current camera to cam1. + * setCamera(cam1); + * + * describe( + * 'A row of white cubes against a gray background. The camera zooms in on one cube when the user double-clicks.' + * ); * } * * function draw() { * background(200); - * orbitControl(); - * normalMaterial(); - * translate(0,0,700); - * rotateY(-0.2); - * rotateX(-0.3); - * push(); - * translate(-15, 0, sin(frameCount / 30) * 25); - * box(30); - * pop(); - * push(); - * translate(15, 0, sin(frameCount / 30 + PI) * 25); - * box(30); - * pop(); + * + * // Translate the origin toward the camera. + * translate(-10, 10, 600); + * + * // Rotate the coordinate system. + * rotateY(-0.1); + * rotateX(-0.1); + * + * // Draw the row of boxes. + * for (let i = 0; i < 6; i += 1) { + * translate(0, 0, -40); + * box(10); + * } + * } + * + * // Toggle the current camera when the user double-clicks. + * function doubleClicked() { + * if (isDefaultCamera === true) { + * setCamera(cam2); + * isDefaultCamera = false; + * } else { + * setCamera(cam1); + * isDefaultCamera = true; + * } * } * *
- * @alt - * two 3D boxes move back and forth along same plane, rotating as mouse is dragged. */ }, @@ -109847,7 +130646,7 @@ this.projMatrix.set(x, 0, 0, 0, 0, - y, 0, 0, tx, ty, tz, - 1, 0, 0, z, 0); /* eslint-enable indent */ if (this._isActive()) { - this._renderer.uPMatrix.set(this.projMatrix.mat4[0], this.projMatrix.mat4[1], this.projMatrix.mat4[2], this.projMatrix.mat4[3], this.projMatrix.mat4[4], this.projMatrix.mat4[5], this.projMatrix.mat4[6], this.projMatrix.mat4[7], this.projMatrix.mat4[8], this.projMatrix.mat4[9], this.projMatrix.mat4[10], this.projMatrix.mat4[11], this.projMatrix.mat4[12], this.projMatrix.mat4[13], this.projMatrix.mat4[14], this.projMatrix.mat4[15]); + this._renderer.uPMatrix.set(this.projMatrix); } this.cameraType = 'custom'; } //////////////////////////////////////////////////////////////////////////////// @@ -109886,11 +130685,22 @@ rotatedCenter[2] += this.eyeZ; this.camera(this.eyeX, this.eyeY, this.eyeZ, rotatedCenter[0], rotatedCenter[1], rotatedCenter[2], this.upX, this.upY, this.upZ); } /** - * Panning rotates the camera view to the left and right. - * @method pan + * Rotates the camera in a clockwise/counter-clockwise direction. + * + * Rolling rotates the camera without changing its orientation. The rotation + * happens in the camera’s "local" space. + * + * The parameter, `angle`, is the angle the camera should rotate. Passing a + * positive angle, as in `myCamera.roll(0.001)`, rotates the camera in counter-clockwise direction. + * Passing a negative angle, as in `myCamera.roll(-0.001)`, rotates the + * camera in clockwise direction. + * + * Note: Angles are interpreted based on the current + * angleMode(). + * + * @method roll * @param {Number} angle amount to rotate camera in current * angleMode units. - * Greater than 0 values rotate counterclockwise (to the left). * @example *
* @@ -109900,43 +130710,104 @@ * function setup() { * createCanvas(100, 100, WEBGL); * normalMaterial(); + * // Create a p5.Camera object. * cam = createCamera(); - * // set initial pan angle - * cam.pan(-0.8); * } * * function draw() { * background(200); * - * // pan camera according to angle 'delta' - * cam.pan(delta); - * - * // every 160 frames, switch direction - * if (frameCount % 160 === 0) { - * delta *= -1; - * } + * // Roll camera according to angle 'delta' + * cam.roll(delta); * - * rotateX(frameCount * 0.01); - * translate(-100, 0, 0); + * translate(0, 0, 0); * box(20); - * translate(35, 0, 0); + * translate(0, 25, 0); * box(20); - * translate(35, 0, 0); + * translate(0, 26, 0); * box(20); - * translate(35, 0, 0); + * translate(0, 27, 0); * box(20); - * translate(35, 0, 0); + * translate(0, 28, 0); * box(20); - * translate(35, 0, 0); + * translate(0,29, 0); * box(20); - * translate(35, 0, 0); + * translate(0, 30, 0); * box(20); * } * *
* * @alt - * camera view pans left and right across a series of rotating 3D boxes. + * camera view rotates in counter clockwise direction with vertically stacked boxes in front of it. + */ + + }, + { + key: 'roll', + value: function roll(amount) { + var local = this._getLocalAxes(); + var axisQuaternion = _main.default.Quat.fromAxisAngle(this._renderer._pInst._toRadians(amount), local.z[0], local.z[1], local.z[2]); + // const upQuat = new p5.Quat(0, this.upX, this.upY, this.upZ); + var newUpVector = axisQuaternion.rotateVector(new _main.default.Vector(this.upX, this.upY, this.upZ)); + this.camera(this.eyeX, this.eyeY, this.eyeZ, this.centerX, this.centerY, this.centerZ, newUpVector.x, newUpVector.y, newUpVector.z); + } /** + * Rotates the camera left and right. + * + * Panning rotates the camera without changing its position. The rotation + * happens in the camera’s "local" space. + * + * The parameter, `angle`, is the angle the camera should rotate. Passing a + * positive angle, as in `myCamera.pan(0.001)`, rotates the camera to the + * right. Passing a negative angle, as in `myCamera.pan(-0.001)`, rotates the + * camera to the left. + * + * Note: Angles are interpreted based on the current + * angleMode(). + * + * @method pan + * @param {Number} angle amount to rotate in the current + * angleMode(). + * + * @example + *
+ * + * let cam; + * let delta = 0.001; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Camera object. + * cam = createCamera(); + * + * // Place the camera at the top-center. + * cam.setPosition(0, -400, 800); + * + * // Point the camera at the origin. + * cam.lookAt(0, 0, 0); + * + * describe( + * 'A white cube on a gray background. The cube goes in and out of view as the camera pans left and right.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Pan with the camera. + * cam.pan(delta); + * + * // Switch directions every 120 frames. + * if (frameCount % 120 === 0) { + * delta *= -1; + * } + * + * // Draw the box. + * box(); + * } + * + *
*/ }, @@ -109946,57 +130817,62 @@ var local = this._getLocalAxes(); this._rotateView(amount, local.y[0], local.y[1], local.y[2]); } /** - * Tilting rotates the camera view up and down. + * Rotates the camera up and down. + * + * Tilting rotates the camera without changing its position. The rotation + * happens in the camera’s "local" space. + * + * The parameter, `angle`, is the angle the camera should rotate. Passing a + * positive angle, as in `myCamera.tilt(0.001)`, rotates the camera down. + * Passing a negative angle, as in `myCamera.tilt(-0.001)`, rotates the camera + * up. + * + * Note: Angles are interpreted based on the current + * angleMode(). + * * @method tilt - * @param {Number} angle amount to rotate camera in current - * angleMode units. - * Greater than 0 values rotate counterclockwise (to the left). + * @param {Number} angle amount to rotate in the current + * angleMode(). + * * @example *
* * let cam; - * let delta = 0.01; + * let delta = 0.001; * * function setup() { * createCanvas(100, 100, WEBGL); - * normalMaterial(); + * + * // Create a p5.Camera object. * cam = createCamera(); - * // set initial tilt - * cam.tilt(-0.8); + * + * // Place the camera at the top-center. + * cam.setPosition(0, -400, 800); + * + * // Point the camera at the origin. + * cam.lookAt(0, 0, 0); + * + * describe( + * 'A white cube on a gray background. The cube goes in and out of view as the camera tilts up and down.' + * ); * } * * function draw() { * background(200); * - * // pan camera according to angle 'delta' + * // Pan with the camera. * cam.tilt(delta); * - * // every 160 frames, switch direction - * if (frameCount % 160 === 0) { + * // Switch directions every 120 frames. + * if (frameCount % 120 === 0) { * delta *= -1; * } * - * rotateY(frameCount * 0.01); - * translate(0, -100, 0); - * box(20); - * translate(0, 35, 0); - * box(20); - * translate(0, 35, 0); - * box(20); - * translate(0, 35, 0); - * box(20); - * translate(0, 35, 0); - * box(20); - * translate(0, 35, 0); - * box(20); - * translate(0, 35, 0); - * box(20); + * // Draw the box. + * box(); * } * *
- * - * @alt - * camera view tilts up and down across a series of rotating 3D boxes. */ }, @@ -110006,53 +130882,83 @@ var local = this._getLocalAxes(); this._rotateView(amount, local.x[0], local.x[1], local.x[2]); } /** - * Reorients the camera to look at a position in world space. + * Points the camera at a location. + * + * `myCamera.lookAt()` changes the camera’s orientation without changing its + * position. + * + * The parameters, `x`, `y`, and `z`, are the coordinates in "world" space + * where the camera should point. For example, calling + * `myCamera.lookAt(10, 20, 30)` points the camera at the coordinates + * `(10, 20, 30)`. + * * @method lookAt * @for p5.Camera - * @param {Number} x x position of a point in world space - * @param {Number} y y position of a point in world space - * @param {Number} z z position of a point in world space + * @param {Number} x x-coordinate of the position where the camera should look in "world" space. + * @param {Number} y y-coordinate of the position where the camera should look in "world" space. + * @param {Number} z z-coordinate of the position where the camera should look in "world" space. + * * @example *
* + * // Double-click to look at a different cube. + * * let cam; + * let isLookingLeft = true; * * function setup() { * createCanvas(100, 100, WEBGL); - * normalMaterial(); + * + * // Create a p5.Camera object. * cam = createCamera(); + * + * // Place the camera at the top-center. + * cam.setPosition(0, -400, 800); + * + * // Point the camera at the origin. + * cam.lookAt(-30, 0, 0); + * + * describe( + * 'A red cube and a blue cube on a gray background. The camera switches focus between the cubes when the user double-clicks.' + * ); * } * * function draw() { * background(200); * - * // look at a new random point every 60 frames - * if (frameCount % 60 === 0) { - * cam.lookAt(random(-100, 100), random(-50, 50), 0); - * } - * - * rotateX(frameCount * 0.01); - * translate(-100, 0, 0); - * box(20); - * translate(35, 0, 0); - * box(20); - * translate(35, 0, 0); - * box(20); - * translate(35, 0, 0); - * box(20); - * translate(35, 0, 0); - * box(20); - * translate(35, 0, 0); + * // Draw the box on the left. + * push(); + * // Translate the origin to the left. + * translate(-30, 0, 0); + * // Style the box. + * fill(255, 0, 0); + * // Draw the box. * box(20); - * translate(35, 0, 0); + * pop(); + * + * // Draw the box on the right. + * push(); + * // Translate the origin to the right. + * translate(30, 0, 0); + * // Style the box. + * fill(0, 0, 255); + * // Draw the box. * box(20); + * pop(); + * } + * + * // Change the camera's focus when the user double-clicks. + * function doubleClicked() { + * if (isLookingLeft === true) { + * cam.lookAt(30, 0, 0); + * isLookingLeft = false; + * } else { + * cam.lookAt(-30, 0, 0); + * isLookingLeft = true; + * } * } * *
- * - * @alt - * camera view of rotating 3D cubes changes to look at a new random - * point every second . */ }, @@ -110064,88 +130970,169 @@ // Camera Position Methods //////////////////////////////////////////////////////////////////////////////// /** - * Sets the camera's position and orientation. - * Accepts the same parameters as the global - * camera(). - * More information on this function can be found there. + * Sets the position and orientation of the camera. + * + * `myCamera.camera()` allows objects to be viewed from different angles. It + * has nine parameters that are all optional. + * + * The first three parameters, `x`, `y`, and `z`, are the coordinates of the + * camera’s position in "world" space. For example, calling + * `myCamera.camera(0, 0, 0)` places the camera at the origin `(0, 0, 0)`. By + * default, the camera is placed at `(0, 0, 800)`. + * + * The next three parameters, `centerX`, `centerY`, and `centerZ` are the + * coordinates of the point where the camera faces in "world" space. For + * example, calling `myCamera.camera(0, 0, 0, 10, 20, 30)` places the camera + * at the origin `(0, 0, 0)` and points it at `(10, 20, 30)`. By default, the + * camera points at the origin `(0, 0, 0)`. + * + * The last three parameters, `upX`, `upY`, and `upZ` are the components of + * the "up" vector in "local" space. The "up" vector orients the camera’s + * y-axis. For example, calling + * `myCamera.camera(0, 0, 0, 10, 20, 30, 0, -1, 0)` places the camera at the + * origin `(0, 0, 0)`, points it at `(10, 20, 30)`, and sets the "up" vector + * to `(0, -1, 0)` which is like holding it upside-down. By default, the "up" + * vector is `(0, 1, 0)`. + * * @method camera * @for p5.Camera + * @param {Number} [x] x-coordinate of the camera. Defaults to 0. + * @param {Number} [y] y-coordinate of the camera. Defaults to 0. + * @param {Number} [z] z-coordinate of the camera. Defaults to 800. + * @param {Number} [centerX] x-coordinate of the point the camera faces. Defaults to 0. + * @param {Number} [centerY] y-coordinate of the point the camera faces. Defaults to 0. + * @param {Number} [centerZ] z-coordinate of the point the camera faces. Defaults to 0. + * @param {Number} [upX] x-component of the camera’s "up" vector. Defaults to 0. + * @param {Number} [upY] x-component of the camera’s "up" vector. Defaults to 1. + * @param {Number} [upZ] z-component of the camera’s "up" vector. Defaults to 0. + * * @example *
* - * let cam; + * // Double-click to toggle between cameras. + * + * let cam1; + * let cam2; + * let isDefaultCamera = true; * * function setup() { * createCanvas(100, 100, WEBGL); - * // Create a camera. - * // createCamera() sets the newly created camera as - * // the current (active) camera. - * cam = createCamera(); + * + * // Create the first camera. + * // Keep its default settings. + * cam1 = createCamera(); + * + * // Create the second camera. + * cam2 = createCamera(); + * + * // Place it at the top-right: (1200, -600, 100) + * // Point it at the row of boxes: (-10, -10, 400) + * // Set its "up" vector to the default: (0, 1, 0) + * cam2.camera(1200, -600, 100, -10, -10, 400, 0, 1, 0); + * + * // Set the current camera to cam1. + * setCamera(cam1); + * + * describe( + * 'A row of white cubes against a gray background. The camera toggles between a frontal and an aerial view when the user double-clicks.' + * ); * } * * function draw() { - * background(204); - * // Move the camera away from the plane by a sin wave - * cam.camera(0, 0, 20 + sin(frameCount * 0.01) * 10, 0, 0, 0, 0, 1, 0); - * plane(10, 10); + * background(200); + * + * // Translate the origin toward the camera. + * translate(-10, 10, 500); + * + * // Rotate the coordinate system. + * rotateY(-0.1); + * rotateX(-0.1); + * + * // Draw the row of boxes. + * for (let i = 0; i < 6; i += 1) { + * translate(0, 0, -30); + * box(10); + * } + * } + * + * // Toggle the current camera when the user double-clicks. + * function doubleClicked() { + * if (isDefaultCamera === true) { + * setCamera(cam2); + * isDefaultCamera = false; + * } else { + * setCamera(cam1); + * isDefaultCamera = true; + * } * } * *
- * @alt - * White square repeatedly grows to fill canvas and then shrinks. * - * @example *
* - * // move slider to see changes! - * // sliders control the first 6 parameters of camera() - * - * let sliderGroup = []; - * let X; - * let Y; - * let Z; - * let centerX; - * let centerY; - * let centerZ; - * let h = 20; - * let cam; + * // Double-click to toggle between cameras. + * + * let cam1; + * let cam2; + * let isDefaultCamera = true; * * function setup() { * createCanvas(100, 100, WEBGL); - * // create a camera - * cam = createCamera(); - * // create sliders - * for (var i = 0; i < 6; i++) { - * if (i === 2) { - * sliderGroup[i] = createSlider(10, 400, 200); - * } else { - * sliderGroup[i] = createSlider(-400, 400, 0); - * } - * h = map(i, 0, 6, 5, 85); - * sliderGroup[i].position(10, height + h); - * sliderGroup[i].style('width', '80px'); - * } + * + * // Create the first camera. + * // Keep its default settings. + * cam1 = createCamera(); + * + * // Create the second camera. + * cam2 = createCamera(); + * + * // Place it at the right: (1200, 0, 100) + * // Point it at the row of boxes: (-10, -10, 400) + * // Set its "up" vector to the default: (0, 1, 0) + * cam2.camera(1200, 0, 100, -10, -10, 400, 0, 1, 0); + * + * // Set the current camera to cam1. + * setCamera(cam1); + * + * describe( + * 'A row of white cubes against a gray background. The camera toggles between a static frontal view and an orbiting view when the user double-clicks.' + * ); * } * * function draw() { - * background(60); - * // assigning sliders' value to each parameters - * X = sliderGroup[0].value(); - * Y = sliderGroup[1].value(); - * Z = sliderGroup[2].value(); - * centerX = sliderGroup[3].value(); - * centerY = sliderGroup[4].value(); - * centerZ = sliderGroup[5].value(); - * cam.camera(X, Y, Z, centerX, centerY, centerZ, 0, 1, 0); - * stroke(255); - * fill(255, 102, 94); - * box(85); + * background(200); + * + * // Update cam2's position. + * let x = 1200 * cos(frameCount * 0.01); + * let y = -600 * sin(frameCount * 0.01); + * cam2.camera(x, y, 100, -10, -10, 400, 0, 1, 0); + * + * // Translate the origin toward the camera. + * translate(-10, 10, 500); + * + * // Rotate the coordinate system. + * rotateY(-0.1); + * rotateX(-0.1); + * + * // Draw the row of boxes. + * for (let i = 0; i < 6; i += 1) { + * translate(0, 0, -30); + * box(10); + * } + * } + * + * // Toggle the current camera when the user double-clicks. + * function doubleClicked() { + * if (isDefaultCamera === true) { + * setCamera(cam2); + * isDefaultCamera = false; + * } else { + * setCamera(cam1); + * isDefaultCamera = true; + * } * } * *
- * @alt - * An interactive example of a red cube with 3 sliders for moving it across x, y, - * z axis and 3 sliders for shifting its center. */ }, @@ -110190,58 +131177,83 @@ ty, tz]); if (this._isActive()) { - this._renderer.uMVMatrix.set(this.cameraMatrix.mat4[0], this.cameraMatrix.mat4[1], this.cameraMatrix.mat4[2], this.cameraMatrix.mat4[3], this.cameraMatrix.mat4[4], this.cameraMatrix.mat4[5], this.cameraMatrix.mat4[6], this.cameraMatrix.mat4[7], this.cameraMatrix.mat4[8], this.cameraMatrix.mat4[9], this.cameraMatrix.mat4[10], this.cameraMatrix.mat4[11], this.cameraMatrix.mat4[12], this.cameraMatrix.mat4[13], this.cameraMatrix.mat4[14], this.cameraMatrix.mat4[15]); + this._renderer.uViewMatrix.set(this.cameraMatrix); } return this; } /** - * Move camera along its local axes while maintaining current camera orientation. + * Moves the camera along its "local" axes without changing its orientation. + * + * The parameters, `x`, `y`, and `z`, are the distances the camera should + * move. For example, calling `myCamera.move(10, 20, 30)` moves the camera 10 + * pixels to the right, 20 pixels down, and 30 pixels backward in its "local" + * space. + * * @method move - * @param {Number} x amount to move along camera's left-right axis - * @param {Number} y amount to move along camera's up-down axis - * @param {Number} z amount to move along camera's forward-backward axis + * @param {Number} x distance to move along the camera’s "local" x-axis. + * @param {Number} y distance to move along the camera’s "local" y-axis. + * @param {Number} z distance to move along the camera’s "local" z-axis. * @example *
* - * // see the camera move along its own axes while maintaining its orientation + * // Click the canvas to begin detecting key presses. + * * let cam; - * let delta = 0.5; * * function setup() { * createCanvas(100, 100, WEBGL); - * normalMaterial(); + * + * // Create the first camera. + * // Keep its default settings. * cam = createCamera(); + * + * // Place the camera at the top-right. + * cam.setPosition(400, -400, 800); + * + * // Point it at the origin. + * cam.lookAt(0, 0, 0); + * + * describe( + * 'A white cube drawn against a gray background. The cube appears to move when the user presses certain keys.' + * ); * } * * function draw() { * background(200); * - * // move the camera along its local axes - * cam.move(delta, delta, 0); + * // Move the camera along its "local" axes + * // when the user presses certain keys. + * if (keyIsPressed === true) { * - * // every 100 frames, switch direction - * if (frameCount % 150 === 0) { - * delta *= -1; + * // Move horizontally. + * if (keyCode === LEFT_ARROW) { + * cam.move(-1, 0, 0); + * } + * if (keyCode === RIGHT_ARROW) { + * cam.move(1, 0, 0); + * } + * + * // Move vertically. + * if (keyCode === UP_ARROW) { + * cam.move(0, -1, 0); + * } + * if (keyCode === DOWN_ARROW) { + * cam.move(0, 1, 0); + * } + * + * // Move in/out of the screen. + * if (key === 'i') { + * cam.move(0, 0, -1); + * } + * if (key === 'o') { + * cam.move(0, 0, 1); + * } * } * - * translate(-10, -10, 0); - * box(50, 8, 50); - * translate(15, 15, 0); - * box(50, 8, 50); - * translate(15, 15, 0); - * box(50, 8, 50); - * translate(15, 15, 0); - * box(50, 8, 50); - * translate(15, 15, 0); - * box(50, 8, 50); - * translate(15, 15, 0); - * box(50, 8, 50); + * // Draw the box. + * box(); * } * *
- * - * @alt - * camera view moves along a series of 3D boxes, maintaining the same - * orientation throughout the move */ }, @@ -110268,48 +131280,140 @@ ]; this.camera(this.eyeX + dx[0] + dy[0] + dz[0], this.eyeY + dx[1] + dy[1] + dz[1], this.eyeZ + dx[2] + dy[2] + dz[2], this.centerX + dx[0] + dy[0] + dz[0], this.centerY + dx[1] + dy[1] + dz[1], this.centerZ + dx[2] + dy[2] + dz[2], this.upX, this.upY, this.upZ); } /** - * Set camera position in world-space while maintaining current camera + * Sets the camera’s position in "world" space without changing its * orientation. + * + * The parameters, `x`, `y`, and `z`, are the coordinates where the camera + * should be placed. For example, calling `myCamera.setPosition(10, 20, 30)` + * places the camera at coordinates `(10, 20, 30)` in "world" space. + * * @method setPosition - * @param {Number} x x position of a point in world space - * @param {Number} y y position of a point in world space - * @param {Number} z z position of a point in world space + * @param {Number} x x-coordinate in "world" space. + * @param {Number} y y-coordinate in "world" space. + * @param {Number} z z-coordinate in "world" space. + * * @example *
* - * // press '1' '2' or '3' keys to set camera position + * // Double-click to toggle between cameras. * - * let cam; + * let cam1; + * let cam2; + * let isDefaultCamera = true; * * function setup() { * createCanvas(100, 100, WEBGL); - * normalMaterial(); - * cam = createCamera(); + * + * // Create the first camera. + * // Keep its default settings. + * cam1 = createCamera(); + * + * // Create the second camera. + * cam2 = createCamera(); + * + * // Place it closer to the origin. + * cam2.setPosition(0, 0, 600); + * + * // Set the current camera to cam1. + * setCamera(cam1); + * + * describe( + * 'A row of white cubes against a gray background. The camera toggles the amount of zoom when the user double-clicks.' + * ); * } * * function draw() { * background(200); * - * // '1' key - * if (keyIsDown(49)) { - * cam.setPosition(30, 0, 80); + * // Translate the origin toward the camera. + * translate(-10, 10, 500); + * + * // Rotate the coordinate system. + * rotateY(-0.1); + * rotateX(-0.1); + * + * // Draw the row of boxes. + * for (let i = 0; i < 6; i += 1) { + * translate(0, 0, -30); + * box(10); * } - * // '2' key - * if (keyIsDown(50)) { - * cam.setPosition(0, 0, 80); + * } + * + * // Toggle the current camera when the user double-clicks. + * function doubleClicked() { + * if (isDefaultCamera === true) { + * setCamera(cam2); + * isDefaultCamera = false; + * } else { + * setCamera(cam1); + * isDefaultCamera = true; * } - * // '3' key - * if (keyIsDown(51)) { - * cam.setPosition(-30, 0, 80); + * } + * + *
+ * + *
+ * + * // Double-click to toggle between cameras. + * + * let cam1; + * let cam2; + * let isDefaultCamera = true; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create the first camera. + * // Keep its default settings. + * cam1 = createCamera(); + * + * // Create the second camera. + * cam2 = createCamera(); + * + * // Place it closer to the origin. + * cam2.setPosition(0, 0, 600); + * + * // Set the current camera to cam1. + * setCamera(cam1); + * + * describe( + * 'A row of white cubes against a gray background. The camera toggles between a static view and a view that zooms in and out when the user double-clicks.' + * ); + * } + * + * function draw() { + * background(200); + * + * // Update cam2's z-coordinate. + * let z = 100 * sin(frameCount * 0.01) + 700; + * cam2.setPosition(0, 0, z); + * + * // Translate the origin toward the camera. + * translate(-10, 10, 500); + * + * // Rotate the coordinate system. + * rotateY(-0.1); + * rotateX(-0.1); + * + * // Draw the row of boxes. + * for (let i = 0; i < 6; i += 1) { + * translate(0, 0, -30); + * box(10); * } + * } * - * box(20); + * // Toggle the current camera when the user double-clicks. + * function doubleClicked() { + * if (isDefaultCamera === true) { + * setCamera(cam2); + * isDefaultCamera = false; + * } else { + * setCamera(cam1); + * isDefaultCamera = true; + * } * } * *
- * - * @alt - * camera position changes as the user presses keys, altering view of a 3D box */ }, @@ -110321,52 +131425,60 @@ var diffZ = z - this.eyeZ; this.camera(x, y, z, this.centerX + diffX, this.centerY + diffY, this.centerZ + diffZ, this.upX, this.upY, this.upZ); } /** - * Copies information about the argument camera's view and projection to - * the target camera. If the target camera is active, it will be reflected - * on the screen. + * Sets the camera’s position, orientation, and projection by copying another + * camera. + * + * The parameter, `cam`, is the `p5.Camera` object to copy. For example, calling + * `cam2.set(cam1)` will set `cam2` using `cam1`’s configuration. * * @method set - * @param {p5.Camera} cam source camera + * @param {p5.Camera} cam camera to copy. * * @example *
* - * let cam, initialCam; + * // Double-click to "reset" the camera zoom. + * + * let cam1; + * let cam2; * * function setup() { * createCanvas(100, 100, WEBGL); - * strokeWeight(3); * - * // Set the initial state to initialCamera and set it to the camera - * // used for drawing. Then set cam to be the active camera. - * cam = createCamera(); - * initialCam = createCamera(); - * initialCam.camera(100, 100, 100, 0, 0, 0, 0, 0, -1); - * cam.set(initialCam); + * // Create the first camera. + * cam1 = createCamera(); * - * setCamera(cam); + * // Place the camera at the top-right. + * cam1.setPosition(400, -400, 800); + * + * // Point it at the origin. + * cam1.lookAt(0, 0, 0); + * + * // Create the second camera. + * cam2 = createCamera(); + * + * // Copy cam1's configuration. + * cam2.set(cam1); + * + * describe( + * 'A white cube drawn against a gray background. The camera slowly moves forward. The camera resets when the user double-clicks.' + * ); * } * * function draw() { - * orbitControl(); - * background(255); - * box(50); - * translate(0, 0, -25); - * plane(100); + * background(200); + * + * // Update cam2's position. + * cam2.move(0, 0, -1); + * + * // Draw the box. + * box(); * } * - * function doubleClicked(){ - * // Double-click to return the camera to its initial position. - * cam.set(initialCam); + * // "Reset" the camera when the user double-clicks. + * function doubleClicked() { + * cam2.set(cam1); * } - * - *
- * @alt - * Prepare two cameras. One is the camera that sets the initial state, - * and the other is the camera that moves with interaction. - * Draw a plane and a box on top of it, operate the camera using orbitControl(). - * Double-click to set the camera in the initial state and return to - * the initial state. */ }, @@ -110396,116 +131508,85 @@ } this.cameraMatrix = cam.cameraMatrix.copy(); this.projMatrix = cam.projMatrix.copy(); - // If the target camera is active, update uMVMatrix and uPMatrix. if (this._isActive()) { - this._renderer.uMVMatrix.mat4 = this.cameraMatrix.mat4.slice(); - this._renderer.uPMatrix.mat4 = this.projMatrix.mat4.slice(); + this._renderer.uModelMatrix.reset(); + this._renderer.uViewMatrix.set(this.cameraMatrix); + this._renderer.uPMatrix.set(this.projMatrix); } } /** - * For the cameras cam0 and cam1 with the given arguments, their view are combined - * with the parameter amt that represents the quantity, and the obtained view is applied. - * For example, if cam0 is looking straight ahead and cam1 is looking straight - * to the right and amt is 0.5, the applied camera will look to the halfway - * between front and right. - * If the applied camera is active, the applied result will be reflected on the screen. - * When applying this function, all cameras involved must have exactly the same projection - * settings. For example, if one is perspective, ortho, frustum, the other two must also be - * perspective, ortho, frustum respectively. However, if all cameras have ortho settings, - * interpolation is possible if the ratios of left, right, top and bottom are equal to each other. - * For example, when it is changed by orbitControl(). + * Sets the camera’s position and orientation to values that are in-between + * those of two other cameras. + * + * `myCamera.slerp()` uses spherical linear interpolation to calculate a + * position and orientation that’s in-between two other cameras. Doing so is + * helpful for transitioning smoothly between two perspectives. + * + * The first two parameters, `cam0` and `cam1`, are the `p5.Camera` objects + * that should be used to set the current camera. + * + * The third parameter, `amt`, is the amount to interpolate between `cam0` and + * `cam1`. 0.0 keeps the camera’s position and orientation equal to `cam0`’s, + * 0.5 sets them halfway between `cam0`’s and `cam1`’s , and 1.0 sets the + * position and orientation equal to `cam1`’s. + * + * For example, calling `myCamera.slerp(cam0, cam1, 0.1)` sets cam’s position + * and orientation very close to `cam0`’s. Calling + * `myCamera.slerp(cam0, cam1, 0.9)` sets cam’s position and orientation very + * close to `cam1`’s. + * + * Note: All of the cameras must use the same projection. * * @method slerp - * @param {p5.Camera} cam0 first p5.Camera - * @param {p5.Camera} cam1 second p5.Camera - * @param {Number} amt amount to use for interpolation during slerp + * @param {p5.Camera} cam0 first camera. + * @param {p5.Camera} cam1 second camera. + * @param {Number} amt amount of interpolation between 0.0 (`cam0`) and 1.0 (`cam1`). * * @example *
* - * let cam0, cam1, cam; + * let cam; + * let cam0; + * let cam1; + * * function setup() { * createCanvas(100, 100, WEBGL); - * strokeWeight(3); * - * // camera for slerp. + * // Create the main camera. + * // Keep its default settings. * cam = createCamera(); - * // cam0 is looking at the cube from the front. - * // cam1 is pointing straight to the right in the cube - * // at the same position as cam0 by doing a pan(-PI/2). - * cam0 = createCamera(); - * cam1 = createCamera(); - * cam1.pan(-PI/2); * - * // we only use cam. - * setCamera(cam); - * } + * // Create the first camera. + * // Keep its default settings. + * cam0 = createCamera(); * - * function draw() { - * // calculate amount. - * const amt = 0.5 - 0.5 * cos(frameCount * TAU / 120); - * // slerp cam0 and cam1 with amt, set to cam. - * // When amt moves from 0 to 1, cam moves from cam0 to cam1, - * // shaking the camera to the right. - * cam.slerp(cam0, cam1, amt); + * // Create the second camera. + * cam1 = createCamera(); * - * background(255); - * // Every time the camera turns right, the cube drifts left. - * box(40); - * } - * - *
- * @alt - * Prepare two cameras. One camera is facing straight ahead to the cube and the other - * camera is in the same position and looking straight to the right. - * If you use a camera which interpolates these with slerp(), the facing direction - * of the camera will change smoothly between the front and the right. + * // Place it at the top-right. + * cam1.setPosition(400, -400, 800); * - * @example - *
- * - * let cam, lastCam, initialCam; - * let countForReset = 30; - * // This sample uses orbitControl() to move the camera. - * // Double-clicking the canvas restores the camera to its initial state. - * function setup() { - * createCanvas(100, 100, WEBGL); - * strokeWeight(3); + * // Point it at the origin. + * cam1.lookAt(0, 0, 0); * - * cam = createCamera(); // main camera - * lastCam = createCamera(); // Camera for recording loc info before reset - * initialCam = createCamera(); // Camera for recording the initial state + * // Set the current camera to cam. + * setCamera(cam); * - * setCamera(cam); // set main camera + * describe('A white cube drawn against a gray background. The camera slowly oscillates between a frontal view and an aerial view.'); * } * * function draw() { - * if (countForReset < 30) { - * // if the reset count is less than 30, - * // it will move closer to the original camera as it increases. - * countForReset++; - * cam.slerp(lastCam, initialCam, countForReset / 30); - * } else { - * // if the count is 30, - * // you can freely move the main camera with orbitControl(). - * orbitControl(); - * } + * background(200); * - * background(255); - * box(40); - * } - * // A double-click sets countForReset to 0 and initiates a reset. - * function doubleClicked() { - * if (countForReset === 30) { - * countForReset = 0; - * lastCam.set(cam); - * } + * // Calculate the amount to interpolate between cam0 and cam1. + * let amt = 0.5 * sin(frameCount * 0.01) + 0.5; + * + * // Update the main camera's position and orientation. + * cam.slerp(cam0, cam1, amt); + * + * box(); * } * *
- * @alt - * There is a camera, drawing a cube. The camera can be moved freely with - * orbitControl(). Double-click to smoothly return the camera to its initial state. - * The camera cannot be moved during that time. */ }, @@ -110839,9 +131920,9 @@ // up vector. normalized camera's up vector. var up = new _main.default.Vector(this.upX, this.upY, this.upZ).normalize(); // y-axis // side vector. Right when viewed from the front - var side = new _main.default.Vector.cross(up, front).normalize(); // x-axis + var side = _main.default.Vector.cross(up, front).normalize(); // x-axis // vertical vector. normalized vector of projection of front vector. - var vertical = new _main.default.Vector.cross(side, up); // z-axis + var vertical = _main.default.Vector.cross(side, up); // z-axis // update camRadius camRadius *= Math.pow(10, dRadius); // prevent zooming through the center: @@ -110899,9 +131980,9 @@ // up vector. camera's up vector. var up = new _main.default.Vector(this.upX, this.upY, this.upZ); // side vector. Right when viewed from the front. (like x-axis) - var side = new _main.default.Vector.cross(up, front).normalize(); + var side = _main.default.Vector.cross(up, front).normalize(); // down vector. Bottom when viewed from the front. (like y-axis) - var down = new _main.default.Vector.cross(front, side); + var down = _main.default.Vector.cross(front, side); // side vector and down vector are no longer used as-is. // Create a vector representing the direction of rotation // in the form cos(direction)*side + sin(direction)*down. @@ -110913,7 +131994,7 @@ var rotAngle = Math.sqrt(dx * dx + dy * dy); // The vector that is orthogonal to both the front vector and // the rotation direction vector is the rotation axis vector. - var axis = new _main.default.Vector.cross(front, side); + var axis = _main.default.Vector.cross(front, side); // update camRadius camRadius *= Math.pow(10, dRadius); // prevent zooming through the center: @@ -110962,95 +132043,82 @@ }(); /** * Sets the current (active) camera of a 3D sketch. - * Allows for switching between multiple cameras. + * + * `setCamera()` allows for switching between multiple cameras created with + * createCamera(). + * + * Note: `setCamera()` can only be used in WebGL mode. + * * @method setCamera - * @param {p5.Camera} cam p5.Camera object + * @param {p5.Camera} cam camera that should be made active. * @for p5 + * * @example *
* - * let cam1, cam2; - * let currentCamera; + * // Double-click to toggle between cameras. + * + * let cam1; + * let cam2; + * let usingCam1 = true; * * function setup() { * createCanvas(100, 100, WEBGL); - * normalMaterial(); * + * // Create the first camera. + * // Keep its default settings. * cam1 = createCamera(); + * + * // Create the second camera. + * // Place it at the top-left. + * // Point it at the origin. * cam2 = createCamera(); - * cam2.setPosition(30, 0, 50); + * cam2.setPosition(400, -400, 800); * cam2.lookAt(0, 0, 0); - * cam2.ortho(); * - * // set variable for previously active camera: - * currentCamera = 1; + * // Set the current camera to cam1. + * setCamera(cam1); * - * describe( - * 'Canvas switches between two camera views, each showing a series of spinning 3D boxes.' - * ); + * describe('A white cube on a gray background. The camera toggles between frontal and aerial views when the user double-clicks.'); * } * * function draw() { * background(200); * - * // camera 1: - * cam1.lookAt(0, 0, 0); - * cam1.setPosition(sin(frameCount / 60) * 200, 0, 100); - * - * // every 100 frames, switch between the two cameras - * if (frameCount % 100 === 0) { - * if (currentCamera === 1) { - * setCamera(cam1); - * currentCamera = 0; - * } else { - * setCamera(cam2); - * currentCamera = 1; - * } - * } - * - * drawBoxes(); + * // Draw the box. + * box(); * } * - * function drawBoxes() { - * rotateX(frameCount * 0.01); - * translate(-100, 0, 0); - * box(20); - * translate(35, 0, 0); - * box(20); - * translate(35, 0, 0); - * box(20); - * translate(35, 0, 0); - * box(20); - * translate(35, 0, 0); - * box(20); - * translate(35, 0, 0); - * box(20); - * translate(35, 0, 0); - * box(20); + * // Toggle the current camera when the user double-clicks. + * function doubleClicked() { + * if (usingCam1 === true) { + * setCamera(cam2); + * usingCam1 = false; + * } else { + * setCamera(cam1); + * usingCam1 = true; + * } * } * *
- * - * @alt - * Canvas switches between two camera views, each showing a series of spinning - * 3D boxes. */ _main.default.prototype.setCamera = function (cam) { this._renderer._curCamera = cam; // set the projection matrix (which is not normally updated each frame) - this._renderer.uPMatrix.set(cam.projMatrix.mat4[0], cam.projMatrix.mat4[1], cam.projMatrix.mat4[2], cam.projMatrix.mat4[3], cam.projMatrix.mat4[4], cam.projMatrix.mat4[5], cam.projMatrix.mat4[6], cam.projMatrix.mat4[7], cam.projMatrix.mat4[8], cam.projMatrix.mat4[9], cam.projMatrix.mat4[10], cam.projMatrix.mat4[11], cam.projMatrix.mat4[12], cam.projMatrix.mat4[13], cam.projMatrix.mat4[14], cam.projMatrix.mat4[15]); + this._renderer.uPMatrix.set(cam.projMatrix); + this._renderer.uViewMatrix.set(cam.cameraMatrix); }; var _default = _main.default.Camera; exports.default = _default; }, { - '../core/main': 298, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.math.hypot': 188, - 'core-js/modules/es.string.sub': 218 + '../core/main': 306, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.math.hypot': 194, + 'core-js/modules/es.string.sub': 226 } ], - 348: [ + 356: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.array.iterator'); @@ -111273,38 +132341,38 @@ exports.default = _default; }, { - '../core/main': 298, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.math.log2': 189, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.typed-array.copy-within': 223, - 'core-js/modules/es.typed-array.every': 224, - 'core-js/modules/es.typed-array.fill': 225, - 'core-js/modules/es.typed-array.filter': 226, - 'core-js/modules/es.typed-array.find': 228, - 'core-js/modules/es.typed-array.find-index': 227, - 'core-js/modules/es.typed-array.float32-array': 229, - 'core-js/modules/es.typed-array.for-each': 231, - 'core-js/modules/es.typed-array.includes': 232, - 'core-js/modules/es.typed-array.index-of': 233, - 'core-js/modules/es.typed-array.iterator': 236, - 'core-js/modules/es.typed-array.join': 237, - 'core-js/modules/es.typed-array.last-index-of': 238, - 'core-js/modules/es.typed-array.map': 239, - 'core-js/modules/es.typed-array.reduce': 241, - 'core-js/modules/es.typed-array.reduce-right': 240, - 'core-js/modules/es.typed-array.reverse': 242, - 'core-js/modules/es.typed-array.set': 243, - 'core-js/modules/es.typed-array.slice': 244, - 'core-js/modules/es.typed-array.some': 245, - 'core-js/modules/es.typed-array.sort': 246, - 'core-js/modules/es.typed-array.subarray': 247, - 'core-js/modules/es.typed-array.to-locale-string': 248, - 'core-js/modules/es.typed-array.to-string': 249 + '../core/main': 306, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.math.log2': 195, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.typed-array.copy-within': 231, + 'core-js/modules/es.typed-array.every': 232, + 'core-js/modules/es.typed-array.fill': 233, + 'core-js/modules/es.typed-array.filter': 234, + 'core-js/modules/es.typed-array.find': 236, + 'core-js/modules/es.typed-array.find-index': 235, + 'core-js/modules/es.typed-array.float32-array': 237, + 'core-js/modules/es.typed-array.for-each': 239, + 'core-js/modules/es.typed-array.includes': 240, + 'core-js/modules/es.typed-array.index-of': 241, + 'core-js/modules/es.typed-array.iterator': 244, + 'core-js/modules/es.typed-array.join': 245, + 'core-js/modules/es.typed-array.last-index-of': 246, + 'core-js/modules/es.typed-array.map': 247, + 'core-js/modules/es.typed-array.reduce': 249, + 'core-js/modules/es.typed-array.reduce-right': 248, + 'core-js/modules/es.typed-array.reverse': 250, + 'core-js/modules/es.typed-array.set': 251, + 'core-js/modules/es.typed-array.slice': 252, + 'core-js/modules/es.typed-array.some': 253, + 'core-js/modules/es.typed-array.sort': 254, + 'core-js/modules/es.typed-array.subarray': 255, + 'core-js/modules/es.typed-array.to-locale-string': 256, + 'core-js/modules/es.typed-array.to-string': 257 } ], - 349: [ + 357: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -111698,15 +132766,33 @@ _main.default.FramebufferTexture = FramebufferTexture; var Framebuffer = /*#__PURE__*/ function () { /** - * An object that one can draw to and then read as a texture. While similar - * to a p5.Graphics, using a p5.Framebuffer as a texture will generally run - * much faster, as it lives within the same WebGL context as the canvas it - * is created on. It only works in WebGL mode. + * A class to describe a high-performance drawing surface for textures. + * + * Each `p5.Framebuffer` object provides a dedicated drawing surface called + * a *framebuffer*. They're similar to + * p5.Graphics objects but can run much faster. + * Performance is improved because the framebuffer shares the same WebGL + * context as the canvas used to create it. + * + * `p5.Framebuffer` objects have all the drawing features of the main + * canvas. Drawing instructions meant for the framebuffer must be placed + * between calls to + * myBuffer.begin() and + * myBuffer.end(). The resulting image + * can be applied as a texture by passing the `p5.Framebuffer` object to the + * texture() function, as in `texture(myBuffer)`. + * It can also be displayed on the main canvas by passing it to the + * image() function, as in `image(myBuffer, 0, 0)`. + * + * Note: createFramebuffer() is the + * recommended way to create an instance of this class. * * @class p5.Framebuffer * @constructor - * @param {p5.Graphics|p5} target A p5 global instance or p5.Graphics - * @param {Object} [settings] A settings object + * @param {p5.Graphics|p5} target sketch instance or + * p5.Graphics + * object. + * @param {Object} [settings] configuration options. */ function Framebuffer(target) { var _this2 = this; @@ -111717,20 +132803,56 @@ this.target._renderer.framebuffers.add(this); this._isClipApplied = false; /** - * A Uint8ClampedArray - * containing the values for all the pixels in the Framebuffer. + * An array containing the color of each pixel in the framebuffer. * - * Like the main canvas pixels property, call - * loadPixels() before reading - * it, and call updatePixels() - * afterwards to update its data. + * myBuffer.loadPixels() must be + * called before accessing the `myBuffer.pixels` array. + * myBuffer.updatePixels() + * must be called after any changes are made. * - * Note that updating pixels via this property will be slower than - * drawing to the framebuffer directly. - * Consider using a shader instead of looping over pixels. + * Note: Updating pixels via this property is slower than drawing to the + * framebuffer directly. Consider using a + * p5.Shader object instead of looping over + * `myBuffer.pixels`. * * @property {Number[]} pixels + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * background(200); + * + * // Create a p5.Framebuffer object. + * let myBuffer = createFramebuffer(); + * + * // Load the pixels array. + * myBuffer.loadPixels(); + * + * // Get the number of pixels in the + * // top half of the framebuffer. + * let numPixels = myBuffer.pixels.length / 2; + * + * // Set the framebuffer's top half to pink. + * for (let i = 0; i < numPixels; i += 4) { + * myBuffer.pixels[i] = 255; + * myBuffer.pixels[i + 1] = 102; + * myBuffer.pixels[i + 2] = 204; + * myBuffer.pixels[i + 3] = 255; + * } + * + * // Update the pixels array. + * myBuffer.updatePixels(); + * + * // Draw the p5.Framebuffer object to the canvas. + * image(myBuffer, -50, -50); + * + * describe('A pink rectangle above a gray rectangle.'); + * } + * + *
*/ this.pixels = [ ]; @@ -111751,21 +132873,22 @@ console.warn('Antialiasing is unsupported in a WebGL 1 context'); this.antialias = false; } + this.density = settings.density || target.pixelDensity(); + var gl = target._renderer.GL; + this.gl = gl; if (settings.width && settings.height) { - this.width = settings.width; - this.height = settings.height; - this.autoSized = false; + var dimensions = target._renderer._adjustDimensions(settings.width, settings.height); + this.width = dimensions.adjustedWidth; + this.height = dimensions.adjustedHeight; + this._autoSized = false; } else { if (settings.width === undefined !== (settings.height === undefined)) { console.warn('Please supply both width and height for a framebuffer to give it a ' + 'size. Only one was given, so the framebuffer will match the size ' + 'of its canvas.'); } this.width = target.width; this.height = target.height; - this.autoSized = true; + this._autoSized = true; } - this.density = settings.density || target.pixelDensity(); - var gl = target._renderer.GL; - this.gl = gl; this._checkIfFormatsAvailable(); if (settings.stencil && !this.useDepth) { console.warn('A stencil buffer can only be used if also using depth. Since the framebuffer has no depth buffer, the stencil buffer will be ignored.'); @@ -111784,74 +132907,165 @@ this._recreateTextures(); var prevCam = this.target._renderer._curCamera; this.defaultCamera = this.createCamera(); + this.filterCamera = this.createCamera(); this.target._renderer._curCamera = prevCam; this.draw(function () { return _this2.target.clear(); }); } /** - * Resizes the framebuffer to the given width and height. + * Resizes the framebuffer to a given width and height. + * + * The parameters, `width` and `height`, set the dimensions of the + * framebuffer. For example, calling `myBuffer.resize(300, 500)` resizes + * the framebuffer to 300×500 pixels, then sets `myBuffer.width` to 300 + * and `myBuffer.height` 500. * * @method resize - * @param {Number} width - * @param {Number} height + * @param {Number} width width of the framebuffer. + * @param {Number} height height of the framebuffer. * * @example *
* - * let framebuffer; + * let myBuffer; + * * function setup() { * createCanvas(100, 100, WEBGL); - * framebuffer = createFramebuffer(); - * noStroke(); - * } * - * function mouseMoved() { - * framebuffer.resize( - * max(20, mouseX), - * max(20, mouseY) - * ); + * // Create a p5.Framebuffer object. + * myBuffer = createFramebuffer(); + * + * describe('A multicolor sphere on a white surface. The image grows larger or smaller when the user moves the mouse, revealing a gray background.'); * } * * function draw() { - * // Draw to the framebuffer - * framebuffer.begin(); + * background(200); + * + * // Draw to the p5.Framebuffer object. + * myBuffer.begin(); * background(255); * normalMaterial(); * sphere(20); - * framebuffer.end(); + * myBuffer.end(); + * + * // Display the p5.Framebuffer object. + * image(myBuffer, -50, -50); + * } * - * background(100); - * // Draw the framebuffer to the main canvas - * image(framebuffer, -width/2, -height/2); + * // Resize the p5.Framebuffer object when the + * // user moves the mouse. + * function mouseMoved() { + * myBuffer.resize(mouseX, mouseY); * } * *
- * - * @alt - * A red, green, and blue sphere is drawn in the middle of a white rectangle - * which starts in the top left of the canvas and whose bottom right is at - * the user's mouse */ _createClass(Framebuffer, [ { key: 'resize', value: function resize(width, height) { - this.autoSized = false; + this._autoSized = false; + var dimensions = this.target._renderer._adjustDimensions(width, height); + width = dimensions.adjustedWidth; + height = dimensions.adjustedHeight; this.width = width; this.height = height; this._handleResize(); } /** - * Gets or sets the pixel scaling for high pixel density displays. By - * default, the density will match that of the canvas the framebuffer was - * created on, which will match the display density. + * Sets the framebuffer's pixel density or returns its current density. + * + * Computer displays are grids of little lights called pixels. A display's + * pixel density describes how many pixels it packs into an area. Displays + * with smaller pixels have a higher pixel density and create sharper + * images. * - * Call this method with no arguments to get the current density, or pass - * in a number to set the density. + * The parameter, `density`, is optional. If a number is passed, as in + * `myBuffer.pixelDensity(1)`, it sets the framebuffer's pixel density. By + * default, the framebuffer's pixel density will match that of the canvas + * where it was created. All canvases default to match the display's pixel + * density. + * + * Calling `myBuffer.pixelDensity()` without an argument returns its current + * pixel density. * * @method pixelDensity - * @param {Number} [density] A scaling factor for the number of pixels per - * side of the framebuffer + * @param {Number} [density] pixel density to set. + * @returns {Number} current pixel density. + * + * @example + *
+ * + * let myBuffer; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Framebuffer object. + * myBuffer = createFramebuffer(); + * + * describe("A white circle on a gray canvas. The circle's edge become fuzzy while the user presses and holds the mouse."); + * } + * + * function draw() { + * // Draw to the p5.Framebuffer object. + * myBuffer.begin(); + * background(200); + * circle(0, 0, 40); + * myBuffer.end(); + * + * // Display the p5.Framebuffer object. + * image(myBuffer, -50, -50); + * } + * + * // Decrease the pixel density when the user + * // presses the mouse. + * function mousePressed() { + * myBuffer.pixelDensity(1); + * } + * + * // Increase the pixel density when the user + * // releases the mouse. + * function mouseReleased() { + * myBuffer.pixelDensity(2); + * } + * + *
+ * + *
+ * + * let myBuffer; + * let myFont; + * + * // Load a font and create a p5.Font object. + * function preload() { + * myFont = loadFont('assets/inconsolata.otf'); + * } + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * background(200); + * + * // Create a p5.Framebuffer object. + * myBuffer = createFramebuffer(); + * + * // Get the p5.Framebuffer object's pixel density. + * let d = myBuffer.pixelDensity(); + * + * // Style the text. + * textAlign(CENTER, CENTER); + * textFont(myFont); + * textSize(16); + * fill(0); + * + * // Display the pixel density. + * text(`Density: ${d}`, 0, 0); + * + * describe(`The text "Density: ${d}" written in black on a gray background.`); + * } + * + *
*/ }, @@ -111859,22 +133073,71 @@ key: 'pixelDensity', value: function pixelDensity(density) { if (density) { - this.autoSized = false; + this._autoSized = false; this.density = density; this._handleResize(); } else { return this.density; } } /** - * Gets or sets whether or not this framebuffer will automatically resize - * along with the canvas it's attached to in order to match its size. + * Toggles the framebuffer's autosizing mode or returns the current mode. + * + * By default, the framebuffer automatically resizes to match the canvas + * that created it. Calling `myBuffer.autoSized(false)` disables this + * behavior and calling `myBuffer.autoSized(true)` re-enables it. * - * Call this method with no arguments to see if it is currently auto-sized, - * or pass in a boolean to set this property. + * Calling `myBuffer.autoSized()` without an argument returns `true` if + * the framebuffer automatically resizes and `false` if not. * * @method autoSized - * @param {Boolean} [autoSized] Whether or not the framebuffer should resize - * along with the canvas it's attached to + * @param {Boolean} [autoSized] whether to automatically resize the framebuffer to match the canvas. + * @returns {Boolean} current autosize setting. + * + * @example + *
+ * + * // Double-click to toggle the autosizing mode. + * + * let myBuffer; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Framebuffer object. + * myBuffer = createFramebuffer(); + * + * describe('A multicolor sphere on a gray background. The image resizes when the user moves the mouse.'); + * } + * + * function draw() { + * background(50); + * + * // Draw to the p5.Framebuffer object. + * myBuffer.begin(); + * background(200); + * normalMaterial(); + * sphere(width / 4); + * myBuffer.end(); + * + * // Display the p5.Framebuffer object. + * image(myBuffer, -width / 2, -height / 2); + * } + * + * // Resize the canvas when the user moves the mouse. + * function mouseMoved() { + * let w = constrain(mouseX, 0, 100); + * let h = constrain(mouseY, 0, 100); + * resizeCanvas(w, h); + * } + * + * // Toggle autoSizing when the user double-clicks. + * // Note: opened an issue to fix(?) this. + * function doubleClicked() { + * let isAuto = myBuffer.autoSized(); + * myBuffer.autoSized(!isAuto); + * } + * + *
*/ }, @@ -111882,9 +133145,9 @@ key: 'autoSized', value: function autoSized(_autoSized) { if (_autoSized === undefined) { - return this.autoSized; + return this._autoSized; } else { - this.autoSized = _autoSized; + this._autoSized = _autoSized; this._handleResize(); } } /** @@ -112144,7 +133407,7 @@ { key: '_updateSize', value: function _updateSize() { - if (this.autoSized) { + if (this._autoSized) { this.width = this.target.width; this.height = this.target.height; this.density = this.target.pixelDensity(); @@ -112161,7 +133424,7 @@ { key: '_canvasSizeChanged', value: function _canvasSizeChanged() { - if (this.autoSized) { + if (this._autoSized) { this._handleResize(); } } /** @@ -112189,13 +133452,121 @@ this._recreateTextures(); this.defaultCamera._resize(); } /** - * Creates and returns a new - * p5.FramebufferCamera to be used - * while drawing to this framebuffer. The camera will be set as the - * currently active camera. + * Creates a new + * p5.Camera object to use with the framebuffer. + * + * The new camera is initialized with a default position `(0, 0, 800)` and a + * default perspective projection. Its properties can be controlled with + * p5.Camera methods such as `myCamera.lookAt(0, 0, 0)`. + * + * Framebuffer cameras should be created between calls to + * myBuffer.begin() and + * myBuffer.end() like so: + * + * ```js + * let myCamera; + * + * myBuffer.begin(); + * + * // Create the camera for the framebuffer. + * myCamera = myBuffer.createCamera(); + * + * myBuffer.end(); + * ``` + * + * Calling setCamera() updates the + * framebuffer's projection using the camera. + * resetMatrix() must also be called for the + * view to change properly: + * + * ```js + * myBuffer.begin(); + * + * // Set the camera for the framebuffer. + * setCamera(myCamera); + * + * // Reset all transformations. + * resetMatrix(); + * + * // Draw stuff... + * + * myBuffer.end(); + * ``` * * @method createCamera - * @returns {p5.Camera} A new camera + * @returns {p5.Camera} new camera. + * + * @example + *
+ * + * // Double-click to toggle between cameras. + * + * let myBuffer; + * let cam1; + * let cam2; + * let usingCam1 = true; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Framebuffer object. + * myBuffer = createFramebuffer(); + * + * // Create the cameras between begin() and end(). + * myBuffer.begin(); + * + * // Create the first camera. + * // Keep its default settings. + * cam1 = myBuffer.createCamera(); + * + * // Create the second camera. + * // Place it at the top-left. + * // Point it at the origin. + * cam2 = myBuffer.createCamera(); + * cam2.setPosition(400, -400, 800); + * cam2.lookAt(0, 0, 0); + * + * myBuffer.end(); + * + * describe( + * 'A white cube on a gray background. The camera toggles between frontal and aerial views when the user double-clicks.' + * ); + * } + * + * function draw() { + * // Draw to the p5.Framebuffer object. + * myBuffer.begin(); + * background(200); + * + * // Set the camera. + * if (usingCam1 === true) { + * setCamera(cam1); + * } else { + * setCamera(cam2); + * } + * + * // Reset all transformations. + * resetMatrix(); + * + * // Draw the box. + * box(); + * + * myBuffer.end(); + * + * // Display the p5.Framebuffer object. + * image(myBuffer, -50, -50); + * } + * + * // Toggle the current camera when the user double-clicks. + * function doubleClicked() { + * if (usingCam1 === true) { + * usingCam1 = false; + * } else { + * usingCam1 = true; + * } + * } + * + *
*/ }, @@ -112223,48 +133594,74 @@ gl.deleteTexture(texture.rawTexture()); this.target._renderer.textures.delete(texture); } /** - * Removes the framebuffer and frees its resources. + * Deletes the framebuffer from GPU memory. + * + * Calling `myBuffer.remove()` frees the GPU memory used by the framebuffer. + * The framebuffer also uses a bit of memory on the CPU which can be freed + * like so: + * + * ```js + * // Delete the framebuffer from GPU memory. + * myBuffer.remove(); + * + * // Delete the framebuffer from CPU memory. + * myBuffer = undefined; + * ``` + * + * Note: All variables that reference the framebuffer must be assigned + * the value `undefined` to delete the framebuffer from CPU memory. If any + * variable still refers to the framebuffer, then it won't be garbage + * collected. * * @method remove * * @example *
* - * let framebuffer; + * // Double-click to remove the p5.Framebuffer object. + * + * let myBuffer; + * * function setup() { * createCanvas(100, 100, WEBGL); + * + * // Create an options object. + * let options = { width: 60, height: 60 }; + * + * // Create a p5.Framebuffer object and + * // configure it using options. + * myBuffer = createFramebuffer(options); + * + * describe('A white circle at the center of a dark gray square disappears when the user double-clicks.'); * } * * function draw() { - * const useFramebuffer = (frameCount % 120) > 60; - * if (useFramebuffer && !framebuffer) { - * // Create a new framebuffer for us to use - * framebuffer = createFramebuffer(); - * } else if (!useFramebuffer && framebuffer) { - * // Free the old framebuffer's resources - * framebuffer.remove(); - * framebuffer = undefined; - * } + * background(200); * - * background(255); - * if (useFramebuffer) { - * // Draw to the framebuffer - * framebuffer.begin(); - * background(255); - * rotateX(frameCount * 0.01); - * rotateY(frameCount * 0.01); - * fill(255, 0, 0); - * box(30); - * framebuffer.end(); - * - * image(framebuffer, -width/2, -height/2); + * // Display the p5.Framebuffer object if + * // it's available. + * if (myBuffer) { + * // Draw to the p5.Framebuffer object. + * myBuffer.begin(); + * background(100); + * circle(0, 0, 20); + * myBuffer.end(); + * + * image(myBuffer, -30, -30); * } * } + * + * // Remove the p5.Framebuffer object when the + * // the user double-clicks. + * function doubleClicked() { + * // Delete the framebuffer from GPU memory. + * myBuffer.remove(); + * + * // Delete the framebuffer from CPU memory. + * myBuffer = undefined; + * } * *
- * - * @alt - * A rotating red cube blinks on and off every second. */ }, @@ -112286,47 +133683,53 @@ } this.target._renderer.framebuffers.delete(this); } /** - * Begin drawing to this framebuffer. Subsequent drawing functions to the - * canvas the framebuffer is attached to will not be immediately visible, and - * will instead be drawn to the framebuffer's texture. Call - * end() when finished to make draw - * functions go right to the canvas again and to be able to read the - * contents of the framebuffer's texture. + * Begins drawing shapes to the framebuffer. + * + * `myBuffer.begin()` and myBuffer.end() + * allow shapes to be drawn to the framebuffer. `myBuffer.begin()` begins + * drawing to the framebuffer and + * myBuffer.end() stops drawing to the + * framebuffer. Changes won't be visible until the framebuffer is displayed + * as an image or texture. * * @method begin * * @example *
* - * let framebuffer; + * let myBuffer; + * * function setup() { * createCanvas(100, 100, WEBGL); - * framebuffer = createFramebuffer(); - * noStroke(); + * + * // Create a p5.Framebuffer object. + * myBuffer = createFramebuffer(); + * + * describe('An empty gray canvas. The canvas gets darker and a rotating, multicolor torus appears while the user presses and holds the mouse.'); * } * * function draw() { - * // Draw to the framebuffer - * framebuffer.begin(); - * background(255); - * translate(0, 10*sin(frameCount * 0.01), 0); - * rotateX(frameCount * 0.01); + * background(200); + * + * // Start drawing to the p5.Framebuffer object. + * myBuffer.begin(); + * + * background(50); * rotateY(frameCount * 0.01); - * fill(255, 0, 0); - * box(50); - * framebuffer.end(); + * normalMaterial(); + * torus(30); * - * background(100); - * // Draw the framebuffer to the main canvas - * image(framebuffer, -50, -50, 25, 25); - * image(framebuffer, 0, 0, 35, 35); + * // Stop drawing to the p5.Framebuffer object. + * myBuffer.end(); + * + * // Display the p5.Framebuffer object while + * // the user presses the mouse. + * if (mouseIsPressed === true) { + * image(myBuffer, -50, -50); + * } * } * *
- * - * @alt - * A video of a floating and rotating red cube is pasted twice on the - * canvas: once in the top left, and again, larger, in the bottom right. */ }, @@ -112344,7 +133747,10 @@ // RendererGL.reset() does, but this does not try to clear any buffers; // it only sets the camera. this.target.setCamera(this.defaultCamera); - this.target._renderer.uMVMatrix.set(this.target._renderer._curCamera.cameraMatrix.mat4[0], this.target._renderer._curCamera.cameraMatrix.mat4[1], this.target._renderer._curCamera.cameraMatrix.mat4[2], this.target._renderer._curCamera.cameraMatrix.mat4[3], this.target._renderer._curCamera.cameraMatrix.mat4[4], this.target._renderer._curCamera.cameraMatrix.mat4[5], this.target._renderer._curCamera.cameraMatrix.mat4[6], this.target._renderer._curCamera.cameraMatrix.mat4[7], this.target._renderer._curCamera.cameraMatrix.mat4[8], this.target._renderer._curCamera.cameraMatrix.mat4[9], this.target._renderer._curCamera.cameraMatrix.mat4[10], this.target._renderer._curCamera.cameraMatrix.mat4[11], this.target._renderer._curCamera.cameraMatrix.mat4[12], this.target._renderer._curCamera.cameraMatrix.mat4[13], this.target._renderer._curCamera.cameraMatrix.mat4[14], this.target._renderer._curCamera.cameraMatrix.mat4[15]); + this.target.resetMatrix(); + this.target._renderer.uViewMatrix.set(this.target._renderer._curCamera.cameraMatrix); + this.target._renderer.uModelMatrix.reset(); + this.target._renderer._applyStencilTestIfClipping(); } /** * When making a p5.Framebuffer active so that it may be drawn to, this method * returns the underlying WebGL framebuffer that needs to be active to @@ -112413,13 +133819,53 @@ } } } /** - * After having previously called - * begin(), this method stops drawing - * functions from going to the framebuffer's texture, allowing them to go - * right to the canvas again. After this, one can read from the framebuffer's - * texture. + * Stops drawing shapes to the framebuffer. + * + * myBuffer.begin() and `myBuffer.end()` + * allow shapes to be drawn to the framebuffer. + * myBuffer.begin() begins drawing to + * the framebuffer and `myBuffer.end()` stops drawing to the framebuffer. + * Changes won't be visible until the framebuffer is displayed as an image + * or texture. * * @method end + * + * @example + *
+ * + * let myBuffer; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Framebuffer object. + * myBuffer = createFramebuffer(); + * + * describe('An empty gray canvas. The canvas gets darker and a rotating, multicolor torus appears while the user presses and holds the mouse.'); + * } + * + * function draw() { + * background(200); + * + * // Start drawing to the p5.Framebuffer object. + * myBuffer.begin(); + * + * background(50); + * rotateY(frameCount * 0.01); + * normalMaterial(); + * torus(30); + * + * // Stop drawing to the p5.Framebuffer object. + * myBuffer.end(); + * + * // Display the p5.Framebuffer object while + * // the user presses the mouse. + * if (mouseIsPressed === true) { + * image(myBuffer, -50, -50); + * } + * } + * + *
*/ }, @@ -112441,48 +133887,61 @@ } this.target._renderer._applyStencilTestIfClipping(); } /** - * Run a function while drawing to the framebuffer rather than to its canvas. - * This is equivalent to calling `framebuffer.begin()`, running the function, - * and then calling `framebuffer.end()`, but ensures that one never - * accidentally forgets `begin` or `end`. + * Draws to the framebuffer by calling a function that contains drawing + * instructions. + * + * The parameter, `callback`, is a function with the drawing instructions + * for the framebuffer. For example, calling `myBuffer.draw(myFunction)` + * will call a function named `myFunction()` to draw to the framebuffer. + * Doing so has the same effect as the following: + * + * ```js + * myBuffer.begin(); + * myFunction(); + * myBuffer.end(); + * ``` * * @method draw - * @param {Function} callback A function to run that draws to the canvas. The - * function will immediately be run, but it will draw to the framebuffer - * instead of the canvas. + * @param {Function} callback function that draws to the framebuffer. * * @example *
* - * let framebuffer; + * // Click the canvas to display the framebuffer. + * + * let myBuffer; + * * function setup() { * createCanvas(100, 100, WEBGL); - * framebuffer = createFramebuffer(); - * noStroke(); + * + * // Create a p5.Framebuffer object. + * myBuffer = createFramebuffer(); + * + * describe('An empty gray canvas. The canvas gets darker and a rotating, multicolor torus appears while the user presses and holds the mouse.'); * } * * function draw() { - * // Draw to the framebuffer - * framebuffer.draw(function() { - * background(255); - * translate(0, 10*sin(frameCount * 0.01), 0); - * rotateX(frameCount * 0.01); - * rotateY(frameCount * 0.01); - * fill(255, 0, 0); - * box(50); - * }); + * background(200); + * + * // Draw to the p5.Framebuffer object. + * myBuffer.draw(bagel); + * + * // Display the p5.Framebuffer object while + * // the user presses the mouse. + * if (mouseIsPressed === true) { + * image(myBuffer, -50, -50); + * } + * } * - * background(100); - * // Draw the framebuffer to the main canvas - * image(framebuffer, -50, -50, 25, 25); - * image(framebuffer, 0, 0, 35, 35); + * // Draw a rotating, multicolor torus. + * function bagel() { + * background(50); + * rotateY(frameCount * 0.01); + * normalMaterial(); + * torus(30); * } * *
- * - * @alt - * A video of a floating and rotating red cube is pasted twice on the - * canvas: once in the top left, and again, larger, in the bottom right. */ }, @@ -112493,10 +133952,50 @@ callback(); this.end(); } /** - * Call this befpre updating pixels - * and calling updatePixels - * to replace the content of the framebuffer with the data in the pixels - * array. + * Loads the current value of each pixel in the framebuffer into its + * pixels array. + * + * `myBuffer.loadPixels()` must be called before reading from or writing to + * myBuffer.pixels. + * + * @method loadPixels + * + * @example + *
+ * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * background(200); + * + * // Create a p5.Framebuffer object. + * let myBuffer = createFramebuffer(); + * + * // Load the pixels array. + * myBuffer.loadPixels(); + * + * // Get the number of pixels in the + * // top half of the framebuffer. + * let numPixels = myBuffer.pixels.length / 2; + * + * // Set the framebuffer's top half to pink. + * for (let i = 0; i < numPixels; i += 4) { + * myBuffer.pixels[i] = 255; + * myBuffer.pixels[i + 1] = 102; + * myBuffer.pixels[i + 2] = 204; + * myBuffer.pixels[i + 3] = 255; + * } + * + * // Update the pixels array. + * myBuffer.updatePixels(); + * + * // Draw the p5.Framebuffer object to the canvas. + * image(myBuffer, -50, -50); + * + * describe('A pink rectangle above a gray rectangle.'); + * } + * + *
*/ }, @@ -112514,35 +134013,42 @@ gl.bindFramebuffer(gl.FRAMEBUFFER, null); } } /** - * Get a region of pixels from the canvas in the form of a - * p5.Image, or a single pixel as an array of - * numbers. - * - * Returns an array of [R,G,B,A] values for any pixel or grabs a section of - * an image. If the Framebuffer has been set up to not store alpha values, then - * only [R,G,B] will be returned. If no parameters are specified, the entire - * image is returned. - * Use the x and y parameters to get the value of one pixel. Get a section of - * the display window by specifying additional w and h parameters. When - * getting an image, the x and y parameters define the coordinates for the - * upper-left corner of the image, regardless of the current imageMode(). + * Gets a pixel or a region of pixels from the framebuffer. + * + * `myBuffer.get()` is easy to use but it's not as fast as + * myBuffer.pixels. Use + * myBuffer.pixels to read many pixel + * values. + * + * The version of `myBuffer.get()` with no parameters returns the entire + * framebuffer as a a p5.Image object. + * + * The version of `myBuffer.get()` with two parameters interprets them as + * coordinates. It returns an array with the `[R, G, B, A]` values of the + * pixel at the given point. + * + * The version of `myBuffer.get()` with four parameters interprets them as + * coordinates and dimensions. It returns a subsection of the framebuffer as + * a p5.Image object. The first two parameters are + * the coordinates for the upper-left corner of the subsection. The last two + * parameters are the width and height of the subsection. * * @method get - * @param {Number} x x-coordinate of the pixel - * @param {Number} y y-coordinate of the pixel - * @param {Number} w width of the section to be returned - * @param {Number} h height of the section to be returned - * @return {p5.Image} the rectangle p5.Image + * @param {Number} x x-coordinate of the pixel. Defaults to 0. + * @param {Number} y y-coordinate of the pixel. Defaults to 0. + * @param {Number} w width of the subsection to be returned. + * @param {Number} h height of the subsection to be returned. + * @return {p5.Image} subsection as a p5.Image object. */ /** * @method get - * @return {p5.Image} the whole p5.Image + * @return {p5.Image} entire framebuffer as a p5.Image object. */ /** * @method get - * @param {Number} x - * @param {Number} y - * @return {Number[]} color of pixel at x,y in array format [R, G, B, A] + * @param {Number} x + * @param {Number} y + * @return {Number[]} color of the pixel at `(x, y)` as an array of color values `[R, G, B, A]`. */ }, @@ -112603,65 +134109,52 @@ } return region; } /** - * Call this after initially calling - * loadPixels() and updating pixels - * to replace the content of the framebuffer with the data in the pixels - * array. + * Updates the framebuffer with the RGBA values in the + * pixels array. + * + * `myBuffer.updatePixels()` only needs to be called after changing values + * in the myBuffer.pixels array. Such + * changes can be made directly after calling + * myBuffer.loadPixels(). * - * This will also clear the depth buffer so that any future drawing done - * afterwards will go on top. + * @method updatePixels * * @example *
* - * let framebuffer; * function setup() { * createCanvas(100, 100, WEBGL); - * framebuffer = createFramebuffer(); - * } - * function draw() { - * noStroke(); - * lights(); * - * // Draw a sphere to the framebuffer - * framebuffer.begin(); - * background(0); - * sphere(25); - * framebuffer.end(); - * - * // Load its pixels and draw a gradient over the lower half of the canvas - * framebuffer.loadPixels(); - * for (let y = height/2; y < height; y++) { - * for (let x = 0; x < width; x++) { - * const idx = (y * width + x) * 4; - * framebuffer.pixels[idx] = (x / width) * 255; - * framebuffer.pixels[idx + 1] = (y / height) * 255; - * framebuffer.pixels[idx + 2] = 255; - * framebuffer.pixels[idx + 3] = 255; - * } + * background(200); + * + * // Create a p5.Framebuffer object. + * let myBuffer = createFramebuffer(); + * + * // Load the pixels array. + * myBuffer.loadPixels(); + * + * // Get the number of pixels in the + * // top half of the framebuffer. + * let numPixels = myBuffer.pixels.length / 2; + * + * // Set the framebuffer's top half to pink. + * for (let i = 0; i < numPixels; i += 4) { + * myBuffer.pixels[i] = 255; + * myBuffer.pixels[i + 1] = 102; + * myBuffer.pixels[i + 2] = 204; + * myBuffer.pixels[i + 3] = 255; * } - * framebuffer.updatePixels(); - * - * // Draw a cube on top of the pixels we just wrote - * framebuffer.begin(); - * push(); - * translate(20, 20); - * rotateX(0.5); - * rotateY(0.5); - * box(20); - * pop(); - * framebuffer.end(); - * - * image(framebuffer, -width/2, -height/2); - * noLoop(); + * + * // Update the pixels array. + * myBuffer.updatePixels(); + * + * // Draw the p5.Framebuffer object to the canvas. + * image(myBuffer, -50, -50); + * + * describe('A pink rectangle above a gray rectangle.'); * } * *
- * - * @alt - * A sphere partly occluded by a gradient from cyan to white to magenta on - * the lower half of the canvas, with a 3D cube drawn on top of that in the - * lower right corner. */ }, @@ -112719,15 +134212,20 @@ return Framebuffer; }(); /** - * A texture with the color information of the framebuffer. Pass this (or the - * framebuffer itself) to texture() to draw it to - * the canvas, or pass it to a shader with - * setUniform() to read its data. + * An object that stores the framebuffer's color data. + * + * Each framebuffer uses a + * WebGLTexture + * object internally to store its color data. The `myBuffer.color` property + * makes it possible to pass this data directly to other functions. For + * example, calling `texture(myBuffer.color)` or + * `myShader.setUniform('colorTexture', myBuffer.color)` may be helpful for + * advanced use cases. * - * Since Framebuffers are controlled by WebGL, their y coordinates are stored - * flipped compared to images and videos. When texturing with a framebuffer - * texture, you may want to flip vertically, e.g. with - * `plane(framebuffer.width, -framebuffer.height)`. + * Note: By default, a framebuffer's y-coordinates are flipped compared to + * images and videos. It's easy to flip a framebuffer's y-coordinates as + * needed when applying it as a texture. For example, calling + * `plane(myBuffer.width, -myBuffer.height)` will flip the framebuffer. * * @property {p5.FramebufferTexture} color * @for p5.Framebuffer @@ -112735,58 +134233,70 @@ * @example *
* - * let framebuffer; * function setup() { * createCanvas(100, 100, WEBGL); - * framebuffer = createFramebuffer(); + * + * background(200); + * + * // Create a p5.Framebuffer object. + * let myBuffer = createFramebuffer(); + * + * // Start drawing to the p5.Framebuffer object. + * myBuffer.begin(); + * + * triangle(-25, 25, 0, -25, 25, 25); + * + * // Stop drawing to the p5.Framebuffer object. + * myBuffer.end(); + * + * // Use the p5.Framebuffer object's WebGLTexture. + * texture(myBuffer.color); + * + * // Style the plane. * noStroke(); - * } * - * function draw() { - * // Draw to the framebuffer - * framebuffer.begin(); - * background(255); - * normalMaterial(); - * sphere(20); - * framebuffer.end(); + * // Draw the plane. + * plane(myBuffer.width, myBuffer.height); * - * // Draw the framebuffer to the main canvas - * image(framebuffer.color, -width/2, -height/2); + * describe('A white triangle on a gray background.'); * } * *
- * - * @alt - * A red, green, and blue sphere in the middle of the canvas */ /** - * A texture with the depth information of the framebuffer. If the framebuffer - * was created with `{ depth: false }` in its settings, then this property will - * be undefined. Pass this to texture() to draw it to - * the canvas, or pass it to a shader with - * setUniform() to read its data. + * An object that stores the framebuffer's dpeth data. + * + * Each framebuffer uses a + * WebGLTexture + * object internally to store its depth data. The `myBuffer.depth` property + * makes it possible to pass this data directly to other functions. For + * example, calling `texture(myBuffer.depth)` or + * `myShader.setUniform('depthTexture', myBuffer.depth)` may be helpful for + * advanced use cases. * - * Since Framebuffers are controlled by WebGL, their y coordinates are stored - * flipped compared to images and videos. When texturing with a framebuffer - * texture, you may want to flip vertically, e.g. with - * `plane(framebuffer.width, -framebuffer.height)`. + * Note: By default, a framebuffer's y-coordinates are flipped compared to + * images and videos. It's easy to flip a framebuffer's y-coordinates as + * needed when applying it as a texture. For example, calling + * `plane(myBuffer.width, -myBuffer.height)` will flip the framebuffer. * - * @property {p5.FramebufferTexture|undefined} depth + * @property {p5.FramebufferTexture} depth * @for p5.Framebuffer * * @example *
* - * let framebuffer; - * let depthShader; + * // Note: A "uniform" is a global variable within a shader program. * - * const vert = ` + * // Create a string with the vertex shader program. + * // The vertex shader is called for each vertex. + * let vertSrc = ` * precision highp float; * attribute vec3 aPosition; * attribute vec2 aTexCoord; * uniform mat4 uModelViewMatrix; * uniform mat4 uProjectionMatrix; * varying vec2 vTexCoord; + * * void main() { * vec4 viewModelPosition = uModelViewMatrix * vec4(aPosition, 1.0); * gl_Position = uProjectionMatrix * viewModelPosition; @@ -112794,114 +134304,136 @@ * } * `; * - * const frag = ` + * // Create a string with the fragment shader program. + * // The fragment shader is called for each pixel. + * let fragSrc = ` * precision highp float; * varying vec2 vTexCoord; * uniform sampler2D depth; + * * void main() { + * // Get the pixel's depth value. * float depthVal = texture2D(depth, vTexCoord).r; + * + * // Set the pixel's color based on its depth. * gl_FragColor = mix( - * vec4(1., 1., 0., 1.), // yellow - * vec4(0., 0., 1., 1.), // blue - * pow(depthVal, 6.) - * ); + * vec4(0., 0., 0., 1.), + * vec4(1., 0., 1., 1.), + * depthVal); * } * `; * + * let myBuffer; + * let myShader; + * * function setup() { * createCanvas(100, 100, WEBGL); - * framebuffer = createFramebuffer(); - * depthShader = createShader(vert, frag); - * noStroke(); + * + * // Create a p5.Framebuffer object. + * myBuffer = createFramebuffer(); + * + * // Create a p5.Shader object. + * myShader = createShader(vertSrc, fragSrc); + * + * // Compile and apply the shader. + * shader(myShader); + * + * describe('The shadow of a box rotates slowly against a magenta background.'); * } * * function draw() { - * // Draw to the framebuffer - * framebuffer.begin(); + * // Draw to the p5.Framebuffer object. + * myBuffer.begin(); * background(255); * rotateX(frameCount * 0.01); - * box(20, 20, 100); - * framebuffer.end(); + * box(20, 20, 80); + * myBuffer.end(); * - * push(); - * shader(depthShader); - * depthShader.setUniform('depth', framebuffer.depth); - * plane(framebuffer.width, framebuffer.height); - * pop(); + * // Set the shader's depth uniform using + * // the framebuffer's depth texture. + * myShader.setUniform('depth', myBuffer.depth); + * + * // Style the plane. + * noStroke(); + * + * // Draw the plane. + * plane(myBuffer.width, myBuffer.height); * } * *
- * - * @alt - * A video of a rectangular prism rotating, with parts closest to the camera - * appearing yellow and colors getting progressively more blue the farther - * from the camera they go */ _main.default.Framebuffer = Framebuffer; var _default = Framebuffer; exports.default = _default; }, { - '../core/constants': 286, - '../core/main': 298, - './p5.RendererGL': 355, - './p5.Texture': 357, - 'core-js/modules/es.array.fill': 172, - 'core-js/modules/es.array.includes': 177, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.get-prototype-of': 198, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.reflect.construct': 202, - 'core-js/modules/es.reflect.get': 203, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.string.includes': 209, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.typed-array.copy-within': 223, - 'core-js/modules/es.typed-array.every': 224, - 'core-js/modules/es.typed-array.fill': 225, - 'core-js/modules/es.typed-array.filter': 226, - 'core-js/modules/es.typed-array.find': 228, - 'core-js/modules/es.typed-array.find-index': 227, - 'core-js/modules/es.typed-array.float32-array': 229, - 'core-js/modules/es.typed-array.for-each': 231, - 'core-js/modules/es.typed-array.includes': 232, - 'core-js/modules/es.typed-array.index-of': 233, - 'core-js/modules/es.typed-array.iterator': 236, - 'core-js/modules/es.typed-array.join': 237, - 'core-js/modules/es.typed-array.last-index-of': 238, - 'core-js/modules/es.typed-array.map': 239, - 'core-js/modules/es.typed-array.reduce': 241, - 'core-js/modules/es.typed-array.reduce-right': 240, - 'core-js/modules/es.typed-array.reverse': 242, - 'core-js/modules/es.typed-array.set': 243, - 'core-js/modules/es.typed-array.slice': 244, - 'core-js/modules/es.typed-array.some': 245, - 'core-js/modules/es.typed-array.sort': 246, - 'core-js/modules/es.typed-array.subarray': 247, - 'core-js/modules/es.typed-array.to-locale-string': 248, - 'core-js/modules/es.typed-array.to-string': 249, - 'core-js/modules/es.typed-array.uint8-array': 252, - 'core-js/modules/es.typed-array.uint8-clamped-array': 253, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/constants': 294, + '../core/main': 306, + './p5.RendererGL': 364, + './p5.Texture': 366, + 'core-js/modules/es.array.fill': 174, + 'core-js/modules/es.array.includes': 181, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.get-prototype-of': 206, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.reflect.construct': 210, + 'core-js/modules/es.reflect.get': 211, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.string.includes': 217, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.typed-array.copy-within': 231, + 'core-js/modules/es.typed-array.every': 232, + 'core-js/modules/es.typed-array.fill': 233, + 'core-js/modules/es.typed-array.filter': 234, + 'core-js/modules/es.typed-array.find': 236, + 'core-js/modules/es.typed-array.find-index': 235, + 'core-js/modules/es.typed-array.float32-array': 237, + 'core-js/modules/es.typed-array.for-each': 239, + 'core-js/modules/es.typed-array.includes': 240, + 'core-js/modules/es.typed-array.index-of': 241, + 'core-js/modules/es.typed-array.iterator': 244, + 'core-js/modules/es.typed-array.join': 245, + 'core-js/modules/es.typed-array.last-index-of': 246, + 'core-js/modules/es.typed-array.map': 247, + 'core-js/modules/es.typed-array.reduce': 249, + 'core-js/modules/es.typed-array.reduce-right': 248, + 'core-js/modules/es.typed-array.reverse': 250, + 'core-js/modules/es.typed-array.set': 251, + 'core-js/modules/es.typed-array.slice': 252, + 'core-js/modules/es.typed-array.some': 253, + 'core-js/modules/es.typed-array.sort': 254, + 'core-js/modules/es.typed-array.subarray': 255, + 'core-js/modules/es.typed-array.to-locale-string': 256, + 'core-js/modules/es.typed-array.to-string': 257, + 'core-js/modules/es.typed-array.uint8-array': 260, + 'core-js/modules/es.typed-array.uint8-clamped-array': 261, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 350: [ + 358: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); _dereq_('core-js/modules/es.symbol.description'); _dereq_('core-js/modules/es.symbol.iterator'); _dereq_('core-js/modules/es.array.concat'); + _dereq_('core-js/modules/es.array.flat'); _dereq_('core-js/modules/es.array.for-each'); _dereq_('core-js/modules/es.array.from'); _dereq_('core-js/modules/es.array.iterator'); + _dereq_('core-js/modules/es.array.last-index-of'); + _dereq_('core-js/modules/es.array.map'); _dereq_('core-js/modules/es.array.slice'); + _dereq_('core-js/modules/es.array.unscopables.flat'); + _dereq_('core-js/modules/es.array-buffer.constructor'); _dereq_('core-js/modules/es.map'); + _dereq_('core-js/modules/es.number.constructor'); + _dereq_('core-js/modules/es.object.entries'); _dereq_('core-js/modules/es.object.get-own-property-descriptor'); _dereq_('core-js/modules/es.object.to-string'); _dereq_('core-js/modules/es.regexp.to-string'); @@ -112939,10 +134471,17 @@ _dereq_('core-js/modules/es.symbol.description'); _dereq_('core-js/modules/es.symbol.iterator'); _dereq_('core-js/modules/es.array.concat'); + _dereq_('core-js/modules/es.array.flat'); _dereq_('core-js/modules/es.array.for-each'); _dereq_('core-js/modules/es.array.iterator'); + _dereq_('core-js/modules/es.array.last-index-of'); + _dereq_('core-js/modules/es.array.map'); _dereq_('core-js/modules/es.array.slice'); + _dereq_('core-js/modules/es.array.unscopables.flat'); + _dereq_('core-js/modules/es.array-buffer.constructor'); _dereq_('core-js/modules/es.map'); + _dereq_('core-js/modules/es.number.constructor'); + _dereq_('core-js/modules/es.object.entries'); _dereq_('core-js/modules/es.object.to-string'); _dereq_('core-js/modules/es.set'); _dereq_('core-js/modules/es.string.iterator'); @@ -113019,6 +134558,41 @@ return arr2; } } + function _slicedToArray(arr, i) { + return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); + } + function _nonIterableRest() { + throw new TypeError('Invalid attempt to destructure non-iterable instance'); + } + function _iterableToArrayLimit(arr, i) { + if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === '[object Arguments]')) { + return; + } + var _arr = [ + ]; + var _n = true; + var _d = false; + var _e = undefined; + try { + for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { + _arr.push(_s.value); + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally { + try { + if (!_n && _i['return'] != null) _i['return'](); + } finally { + if (_d) throw _e; + } + } + return _arr; + } + function _arrayWithHoles(arr) { + if (Array.isArray(arr)) return arr; + } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); @@ -113046,21 +134620,350 @@ */ //some of the functions are adjusted from Three.js(http://threejs.org) /** - * p5 Geometry class + * A class to describe a 3D shape. + * + * Each `p5.Geometry` object represents a 3D shape as a set of connected + * points called *vertices*. All 3D shapes are made by connecting vertices to + * form triangles that are stitched together. Each triangular patch on the + * geometry's surface is called a *face*. The geometry stores information + * about its vertices and faces for use with effects such as lighting and + * texture mapping. + * + * The first parameter, `detailX`, is optional. If a number is passed, as in + * `new p5.Geometry(24)`, it sets the number of triangle subdivisions to use + * along the geometry's x-axis. By default, `detailX` is 1. + * + * The second parameter, `detailY`, is also optional. If a number is passed, + * as in `new p5.Geometry(24, 16)`, it sets the number of triangle + * subdivisions to use along the geometry's y-axis. By default, `detailX` is + * 1. + * + * The third parameter, `callback`, is also optional. If a function is passed, + * as in `new p5.Geometry(24, 16, createShape)`, it will be called once to add + * vertices to the new 3D shape. + * * @class p5.Geometry * @constructor * @param {Integer} [detailX] number of vertices along the x-axis. * @param {Integer} [detailY] number of vertices along the y-axis. - * @param {function} [callback] function to call upon object instantiation. + * @param {function} [callback] function to call once the geometry is created. + * + * @example + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * let myGeometry; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Geometry object. + * myGeometry = new p5.Geometry(); + * + * // Create p5.Vector objects to position the vertices. + * let v0 = createVector(-40, 0, 0); + * let v1 = createVector(0, -40, 0); + * let v2 = createVector(40, 0, 0); + * + * // Add the vertices to the p5.Geometry object's vertices array. + * myGeometry.vertices.push(v0, v1, v2); + * + * describe('A white triangle drawn on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the p5.Geometry object. + * model(myGeometry); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * let myGeometry; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Geometry object using a callback function. + * myGeometry = new p5.Geometry(1, 1, createShape); + * + * describe('A white triangle drawn on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the p5.Geometry object. + * model(myGeometry); + * } + * + * function createShape() { + * // Create p5.Vector objects to position the vertices. + * let v0 = createVector(-40, 0, 0); + * let v1 = createVector(0, -40, 0); + * let v2 = createVector(40, 0, 0); + * + * // "this" refers to the p5.Geometry object being created. + * + * // Add the vertices to the p5.Geometry object's vertices array. + * this.vertices.push(v0, v1, v2); + * + * // Add an array to list which vertices belong to the face. + * // Vertices are listed in clockwise "winding" order from + * // left to top to right. + * this.faces.push([0, 1, 2]); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * let myGeometry; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Geometry object using a callback function. + * myGeometry = new p5.Geometry(1, 1, createShape); + * + * describe('A white triangle drawn on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the p5.Geometry object. + * model(myGeometry); + * } + * + * function createShape() { + * // Create p5.Vector objects to position the vertices. + * let v0 = createVector(-40, 0, 0); + * let v1 = createVector(0, -40, 0); + * let v2 = createVector(40, 0, 0); + * + * // "this" refers to the p5.Geometry object being created. + * + * // Add the vertices to the p5.Geometry object's vertices array. + * this.vertices.push(v0, v1, v2); + * + * // Add an array to list which vertices belong to the face. + * // Vertices are listed in clockwise "winding" order from + * // left to top to right. + * this.faces.push([0, 1, 2]); + * + * // Compute the surface normals to help with lighting. + * this.computeNormals(); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * // Adapted from Paul Wheeler's wonderful p5.Geometry tutorial. + * // https://www.paulwheeler.us/articles/custom-3d-geometry-in-p5js/ + * // CC-BY-SA 4.0 + * + * let myGeometry; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create the p5.Geometry object. + * // Set detailX to 48 and detailY to 2. + * // >>> try changing them. + * myGeometry = new p5.Geometry(48, 2, createShape); + * } + * + * function draw() { + * background(50); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * lights(); + * + * // Style the p5.Geometry object. + * strokeWeight(0.2); + * + * // Draw the p5.Geometry object. + * model(myGeometry); + * } + * + * function createShape() { + * // "this" refers to the p5.Geometry object being created. + * + * // Define the Möbius strip with a few parameters. + * let spread = 0.1; + * let radius = 30; + * let stripWidth = 15; + * let xInterval = 4 * PI / this.detailX; + * let yOffset = -stripWidth / 2; + * let yInterval = stripWidth / this.detailY; + * + * for (let j = 0; j <= this.detailY; j += 1) { + * // Calculate the "vertical" point along the strip. + * let v = yOffset + yInterval * j; + * + * for (let i = 0; i <= this.detailX; i += 1) { + * // Calculate the angle of rotation around the strip. + * let u = i * xInterval; + * + * // Calculate the coordinates of the vertex. + * let x = (radius + v * cos(u / 2)) * cos(u) - sin(u / 2) * 2 * spread; + * let y = (radius + v * cos(u / 2)) * sin(u); + * if (u < TWO_PI) { + * y += sin(u) * spread; + * } else { + * y -= sin(u) * spread; + * } + * let z = v * sin(u / 2) + sin(u / 4) * 4 * spread; + * + * // Create a p5.Vector object to position the vertex. + * let vert = createVector(x, y, z); + * + * // Add the vertex to the p5.Geometry object's vertices array. + * this.vertices.push(vert); + * } + * } + * + * // Compute the faces array. + * this.computeFaces(); + * + * // Compute the surface normals to help with lighting. + * this.computeNormals(); + * } + * + *
*/ _main.default.Geometry = /*#__PURE__*/ function () { function Geometry(detailX, detailY, callback) { _classCallCheck(this, Geometry); - //an array containing every vertex - //@type [p5.Vector] + /** + * An array with the geometry's vertices. + * + * The geometry's vertices are stored as + * p5.Vector objects in the `myGeometry.vertices` + * array. The geometry's first vertex is the + * p5.Vector object at `myGeometry.vertices[0]`, + * its second vertex is `myGeometry.vertices[1]`, its third vertex is + * `myGeometry.vertices[2]`, and so on. + * + * @property vertices + * @name vertices + * + * @example + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * let myGeometry; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Geometry object. + * myGeometry = new p5.Geometry(); + * + * // Create p5.Vector objects to position the vertices. + * let v0 = createVector(-40, 0, 0); + * let v1 = createVector(0, -40, 0); + * let v2 = createVector(40, 0, 0); + * + * // Add the vertices to the p5.Geometry object's vertices array. + * myGeometry.vertices.push(v0, v1, v2); + * + * describe('A white triangle drawn on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Draw the p5.Geometry object. + * model(myGeometry); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * let myGeometry; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Geometry object. + * beginGeometry(); + * torus(30, 15, 10, 8); + * myGeometry = endGeometry(); + * + * describe('A white torus rotates slowly against a dark gray background. Red spheres mark its vertices.'); + * } + * + * function draw() { + * background(50); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * lights(); + * + * // Rotate the coordinate system. + * rotateY(frameCount * 0.01); + * + * // Style the p5.Geometry object. + * fill(255); + * stroke(0); + * + * // Display the p5.Geometry object. + * model(myGeometry); + * + * // Style the vertices. + * fill(255, 0, 0); + * noStroke(); + * + * // Iterate over the vertices array. + * for (let v of myGeometry.vertices) { + * // Draw a sphere to mark the vertex. + * push(); + * translate(v); + * sphere(2.5); + * pop(); + * } + * } + * + *
+ */ this.vertices = [ ]; + this.boundingBoxCache = null; //an array containing every vertex for stroke drawing this.lineVertices = new _main.default.DataArray(); // The tangents going into or out of a vertex on a line. Along a straight @@ -113075,17 +134978,291 @@ // used as an enum to determine which part of the cap or join each vertex // represents. See the doc comments for _addCap and _addJoin for diagrams. this.lineSides = new _main.default.DataArray(); - //an array containing 1 normal per vertex - //@type [p5.Vector] - //[p5.Vector, p5.Vector, p5.Vector,p5.Vector, p5.Vector, p5.Vector,...] + /** + * An array with the vectors that are normal to the geometry's vertices. + * + * A face's orientation is defined by its *normal vector* which points out + * of the face and is normal (perpendicular) to the surface. Calling + * `myGeometry.computeNormals()` first calculates each face's normal + * vector. Then it calculates the normal vector for each vertex by + * averaging the normal vectors of the faces surrounding the vertex. The + * vertex normals are stored as p5.Vector + * objects in the `myGeometry.vertexNormals` array. + * + * @property vertexNormals + * @name vertexNormals + * + * @example + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * let myGeometry; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Geometry object. + * beginGeometry(); + * torus(30, 15, 10, 8); + * myGeometry = endGeometry(); + * + * // Compute the vertex normals. + * myGeometry.computeNormals(); + * + * describe( + * 'A white torus rotates against a dark gray background. Red lines extend outward from its vertices.' + * ); + * } + * + * function draw() { + * background(50); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * lights(); + * + * // Rotate the coordinate system. + * rotateY(frameCount * 0.01); + * + * // Style the p5.Geometry object. + * stroke(0); + * + * // Display the p5.Geometry object. + * model(myGeometry); + * + * // Style the normal vectors. + * stroke(255, 0, 0); + * + * // Iterate over the vertices and vertexNormals arrays. + * for (let i = 0; i < myGeometry.vertices.length; i += 1) { + * + * // Get the vertex p5.Vector object. + * let v = myGeometry.vertices[i]; + * + * // Get the vertex normal p5.Vector object. + * let n = myGeometry.vertexNormals[i]; + * + * // Calculate a point along the vertex normal. + * let p = p5.Vector.mult(n, 8); + * + * // Draw the vertex normal as a red line. + * push(); + * translate(v); + * line(0, 0, 0, p.x, p.y, p.z); + * pop(); + * } + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * let myGeometry; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Geometry object. + * myGeometry = new p5.Geometry(); + * + * // Create p5.Vector objects to position the vertices. + * let v0 = createVector(-40, 0, 0); + * let v1 = createVector(0, -40, 0); + * let v2 = createVector(0, 40, 0); + * let v3 = createVector(40, 0, 0); + * + * // Add the vertices to the p5.Geometry object's vertices array. + * myGeometry.vertices.push(v0, v1, v2, v3); + * + * // Compute the faces array. + * myGeometry.computeFaces(); + * + * // Compute the surface normals. + * myGeometry.computeNormals(); + * + * describe('A red square drawn on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Add a white point light. + * pointLight(255, 255, 255, 0, 0, 10); + * + * // Style the p5.Geometry object. + * noStroke(); + * fill(255, 0, 0); + * + * // Display the p5.Geometry object. + * model(myGeometry); + * } + * + *
+ */ this.vertexNormals = [ ]; - //an array containing each three vertex indices that form a face - //[[0, 1, 2], [2, 1, 3], ...] + /** + * An array that lists which of the geometry's vertices form each of its + * faces. + * + * All 3D shapes are made by connecting sets of points called *vertices*. A + * geometry's surface is formed by connecting vertices to form triangles + * that are stitched together. Each triangular patch on the geometry's + * surface is called a *face*. + * + * The geometry's vertices are stored as + * p5.Vector objects in the + * myGeometry.vertices array. The + * geometry's first vertex is the p5.Vector + * object at `myGeometry.vertices[0]`, its second vertex is + * `myGeometry.vertices[1]`, its third vertex is `myGeometry.vertices[2]`, + * and so on. + * + * For example, a geometry made from a rectangle has two faces because a + * rectangle is made by joining two triangles. `myGeometry.faces` for a + * rectangle would be the two-dimensional array `[[0, 1, 2], [2, 1, 3]]`. + * The first face, `myGeometry.faces[0]`, is the array `[0, 1, 2]` because + * it's formed by connecting `myGeometry.vertices[0]`, + * `myGeometry.vertices[1]`,and `myGeometry.vertices[2]`. The second face, + * `myGeometry.faces[1]`, is the array `[2, 1, 3]` because it's formed by + * connecting `myGeometry.vertices[2]`, `myGeometry.vertices[1]`,and + * `myGeometry.vertices[3]`. + * + * @property faces + * @name faces + * + * @example + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * let myGeometry; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Geometry object. + * beginGeometry(); + * sphere(); + * myGeometry = endGeometry(); + * + * describe("A sphere drawn on a gray background. The sphere's surface is a grayscale patchwork of triangles."); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * lights(); + * + * // Style the p5.Geometry object. + * noStroke(); + * + * // Set a random seed. + * randomSeed(1234); + * + * // Iterate over the faces array. + * for (let face of myGeometry.faces) { + * + * // Style the face. + * let g = random(0, 255); + * fill(g); + * + * // Draw the face. + * beginShape(); + * // Iterate over the vertices that form the face. + * for (let f of face) { + * // Get the vertex's p5.Vector object. + * let v = myGeometry.vertices[f]; + * vertex(v.x, v.y, v.z); + * } + * endShape(); + * + * } + * } + * + *
+ */ this.faces = [ ]; - //a 2D array containing uvs for every vertex - //[[0.0,0.0],[1.0,0.0], ...] + /** + * An array that lists the texture coordinates for each of the geometry's + * vertices. + * + * In order for texture() to work, the geometry + * needs a way to map the points on its surface to the pixels in a + * rectangular image that's used as a texture. The geometry's vertex at + * coordinates `(x, y, z)` maps to the texture image's pixel at coordinates + * `(u, v)`. + * + * The `myGeometry.uvs` array stores the `(u, v)` coordinates for each + * vertex in the order it was added to the geometry. For example, the + * first vertex, `myGeometry.vertices[0]`, has its `(u, v)` coordinates + * stored at `myGeometry.uvs[0]` and `myGeometry.uvs[1]`. + * + * @property uvs + * @name uvs + * + * @example + *
+ * + * let img; + * + * // Load the image and create a p5.Image object. + * function preload() { + * img = loadImage('assets/laDefense.jpg'); + * } + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * background(200); + * + * // Create p5.Geometry objects. + * let geom1 = buildGeometry(createShape); + * let geom2 = buildGeometry(createShape); + * + * // Left (original). + * push(); + * translate(-25, 0, 0); + * texture(img); + * noStroke(); + * model(geom1); + * pop(); + * + * // Set geom2's texture coordinates. + * geom2.uvs = [0.25, 0.25, 0.75, 0.25, 0.25, 0.75, 0.75, 0.75]; + * + * // Right (zoomed in). + * push(); + * translate(25, 0, 0); + * texture(img); + * noStroke(); + * model(geom2); + * pop(); + * + * describe( + * 'Two photos of a ceiling on a gray background. The photo on the right zooms in to the center of the photo.' + * ); + * } + * + * function createShape() { + * plane(40); + * } + * + *
+ */ this.uvs = [ ]; // a 2D array containing edge connectivity pattern for create line vertices @@ -113104,15 +135281,147 @@ this.detailY = detailY !== undefined ? detailY : 1; this.dirtyFlags = { }; + this._hasFillTransparency = undefined; + this._hasStrokeTransparency = undefined; if (callback instanceof Function) { callback.call(this); } - return this; // TODO: is this a constructor? - } + } /** + * Calculates the position and size of the smallest box that contains the geometry. + * + * A bounding box is the smallest rectangular prism that contains the entire + * geometry. It's defined by the box's minimum and maximum coordinates along + * each axis, as well as the size (length) and offset (center). + * + * Calling `myGeometry.calculateBoundingBox()` returns an object with four + * properties that describe the bounding box: + * + * ```js + * // Get myGeometry's bounding box. + * let bbox = myGeometry.calculateBoundingBox(); + * + * // Print the bounding box to the console. + * console.log(bbox); + * + * // { + * // // The minimum coordinate along each axis. + * // min: { x: -1, y: -2, z: -3 }, + * // + * // // The maximum coordinate along each axis. + * // max: { x: 1, y: 2, z: 3}, + * // + * // // The size (length) along each axis. + * // size: { x: 2, y: 4, z: 6}, + * // + * // // The offset (center) along each axis. + * // offset: { x: 0, y: 0, z: 0} + * // } + * ``` + * + * @method calculateBoundingBox + * @returns {Object} bounding box of the geometry. + * + * @example + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * let particles; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a new p5.Geometry object with random spheres. + * particles = buildGeometry(createParticles); + * + * describe('Ten white spheres placed randomly against a gray background. A box encloses the spheres.'); + * } + * + * function draw() { + * background(50); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * lights(); + * + * // Style the particles. + * noStroke(); + * fill(255); + * + * // Draw the particles. + * model(particles); + * + * // Calculate the bounding box. + * let bbox = particles.calculateBoundingBox(); + * + * // Translate to the bounding box's center. + * translate(bbox.offset.x, bbox.offset.y, bbox.offset.z); + * + * // Style the bounding box. + * stroke(255); + * noFill(); + * + * // Draw the bounding box. + * box(bbox.size.x, bbox.size.y, bbox.size.z); + * } + * + * function createParticles() { + * for (let i = 0; i < 10; i += 1) { + * // Calculate random coordinates. + * let x = randomGaussian(0, 15); + * let y = randomGaussian(0, 15); + * let z = randomGaussian(0, 15); + * + * push(); + * // Translate to the particle's coordinates. + * translate(x, y, z); + * // Draw the particle. + * sphere(3); + * pop(); + * } + * } + * + *
+ */ + _createClass(Geometry, [ + { + key: 'calculateBoundingBox', + value: function calculateBoundingBox() { + if (this.boundingBoxCache) { + return this.boundingBoxCache; // Return cached result if available + } + var minVertex = new _main.default.Vector(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE); + var maxVertex = new _main.default.Vector(Number.MIN_VALUE, Number.MIN_VALUE, Number.MIN_VALUE); + for (var i = 0; i < this.vertices.length; i++) { + var vertex = this.vertices[i]; + minVertex.x = Math.min(minVertex.x, vertex.x); + minVertex.y = Math.min(minVertex.y, vertex.y); + minVertex.z = Math.min(minVertex.z, vertex.z); + maxVertex.x = Math.max(maxVertex.x, vertex.x); + maxVertex.y = Math.max(maxVertex.y, vertex.y); + maxVertex.z = Math.max(maxVertex.z, vertex.z); + } // Calculate size and offset properties + + var size = new _main.default.Vector(maxVertex.x - minVertex.x, maxVertex.y - minVertex.y, maxVertex.z - minVertex.z); + var offset = new _main.default.Vector((minVertex.x + maxVertex.x) / 2, (minVertex.y + maxVertex.y) / 2, (minVertex.z + maxVertex.z) / 2); + // Cache the result for future access + this.boundingBoxCache = { + min: minVertex, + max: maxVertex, + size: size, + offset: offset + }; + return this.boundingBoxCache; + } + }, { key: 'reset', value: function reset() { + this._hasFillTransparency = undefined; + this._hasStrokeTransparency = undefined; this.lineVertices.clear(); this.lineTangentsIn.clear(); this.lineTangentsOut.clear(); @@ -113126,52 +135435,259 @@ this.uvs.length = 0; this.dirtyFlags = { }; + } + }, + { + key: 'hasFillTransparency', + value: function hasFillTransparency() { + if (this._hasFillTransparency === undefined) { + this._hasFillTransparency = false; + for (var i = 0; i < this.vertexColors.length; i += 4) { + if (this.vertexColors[i + 3] < 1) { + this._hasFillTransparency = true; + break; + } + } + } + return this._hasFillTransparency; + } + }, + { + key: 'hasStrokeTransparency', + value: function hasStrokeTransparency() { + if (this._hasStrokeTransparency === undefined) { + this._hasStrokeTransparency = false; + for (var i = 0; i < this.lineVertexColors.length; i += 4) { + if (this.lineVertexColors[i + 3] < 1) { + this._hasStrokeTransparency = true; + break; + } + } + } + return this._hasStrokeTransparency; } /** - * Removes the internal colors of p5.Geometry. - * Using `clearColors()`, you can use `fill()` to supply new colors before drawing each shape. - * If `clearColors()` is not used, the shapes will use their internal colors by ignoring `fill()`. + * Removes the geometry’s internal colors. + * + * `p5.Geometry` objects can be created with "internal colors" assigned to + * vertices or the entire shape. When a geometry has internal colors, + * fill() has no effect. Calling + * `myGeometry.clearColors()` allows the + * fill() function to apply color to the geometry. * * @method clearColors * * @example *
* - * let shape01; - * let shape02; - * let points = []; + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * background(200); + * + * // Create a p5.Geometry object. + * // Set its internal color to red. + * beginGeometry(); + * fill(255, 0, 0); + * plane(20); + * let myGeometry = endGeometry(); + * + * // Style the shape. + * noStroke(); + * + * // Draw the p5.Geometry object (center). + * model(myGeometry); + * + * // Translate the origin to the bottom-right. + * translate(25, 25, 0); + * + * // Try to fill the geometry with green. + * fill(0, 255, 0); + * + * // Draw the geometry again (bottom-right). + * model(myGeometry); + * + * // Clear the geometry's colors. + * myGeometry.clearColors(); + * + * // Fill the geometry with blue. + * fill(0, 0, 255); + * + * // Translate the origin up. + * translate(0, -50, 0); + * + * // Draw the geometry again (top-right). + * model(myGeometry); * + * describe( + * 'Three squares drawn against a gray background. Red squares are at the center and the bottom-right. A blue square is at the top-right.' + * ); + * } + * + *
+ */ + + }, + { + key: 'clearColors', + value: function clearColors() { + this.vertexColors = [ + ]; + return this; + } /** + * The `saveObj()` function exports `p5.Geometry` objects as + * 3D models in the Wavefront .obj file format. + * This way, you can use the 3D shapes you create in p5.js in other software + * for rendering, animation, 3D printing, or more. + * + * The exported .obj file will include the faces and vertices of the `p5.Geometry`, + * as well as its texture coordinates and normals, if it has them. + * + * @method saveObj + * @param {String} [fileName='model.obj'] The name of the file to save the model as. + * If not specified, the default file name will be 'model.obj'. + * @example + *
+ * + * let myModel; + * let saveBtn; * function setup() { - * createCanvas(600, 600, WEBGL); - * points.push(new p5.Vector(-1, -1, 0), new p5.Vector(-1, 1, 0), - * new p5.Vector(1, -1, 0), new p5.Vector(-1, -1, 0)); - * buildShape01(); - * buildShape02(); + * createCanvas(200, 200, WEBGL); + * myModel = buildGeometry(() => { + * for (let i = 0; i < 5; i++) { + * push(); + * translate( + * random(-75, 75), + * random(-75, 75), + * random(-75, 75) + * ); + * sphere(random(5, 50)); + * pop(); + * } + * }); + * + * saveBtn = createButton('Save .obj'); + * saveBtn.mousePressed(() => myModel.saveObj()); + * + * describe('A few spheres rotating in space'); * } + * * function draw() { * background(0); - * fill('pink'); // shape01 retains its internal blue color, so it won't turn pink. - * model(shape01); - * fill('yellow'); // Now, shape02 is yellow. - * model(shape02); + * noStroke(); + * lights(); + * rotateX(millis() * 0.001); + * rotateY(millis() * 0.002); + * model(myModel); * } + * + *
+ */ + + }, + { + key: 'saveObj', + value: function saveObj() { + var _this = this; + var fileName = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'model.obj'; + var objStr = ''; + // Vertices + this.vertices.forEach(function (v) { + objStr += 'v '.concat(v.x, ' ').concat(v.y, ' ').concat(v.z, '\n'); + }); + // Texture Coordinates (UVs) + if (this.uvs && this.uvs.length > 0) { + for (var i = 0; i < this.uvs.length; i += 2) { + objStr += 'vt '.concat(this.uvs[i], ' ').concat(this.uvs[i + 1], '\n'); + } + } // Vertex Normals + + if (this.vertexNormals && this.vertexNormals.length > 0) { + this.vertexNormals.forEach(function (n) { + objStr += 'vn '.concat(n.x, ' ').concat(n.y, ' ').concat(n.z, '\n'); + }); + } // Faces, obj vertex indices begin with 1 and not 0 + // texture coordinate (uvs) and vertexNormal indices + // are indicated with trailing ints vertex/normal/uv + // ex 1/1/1 or 2//2 for vertices without uvs + + this.faces.forEach(function (face) { + var faceStr = 'f'; + face.forEach(function (index) { + faceStr += ' '; + faceStr += index + 1; + if (_this.vertexNormals.length > 0 || _this.uvs.length > 0) { + faceStr += '/'; + if (_this.uvs.length > 0) { + faceStr += index + 1; + } + faceStr += '/'; + if (_this.vertexNormals.length > 0) { + faceStr += index + 1; + } + } + }); + objStr += faceStr + '\n'; + }); + var blob = new Blob([objStr], { + type: 'text/plain' + }); + _main.default.prototype.downloadFile(blob, fileName, 'obj'); + } /** + * The `saveStl()` function exports `p5.Geometry` objects as + * 3D models in the STL stereolithography file format. + * This way, you can use the 3D shapes you create in p5.js in other software + * for rendering, animation, 3D printing, or more. * - * function buildShape01() { - * beginGeometry(); - * fill('blue'); // shape01's color is blue because its internal colors remain. - * beginShape(); - * for (let vec of points) vertex(vec.x * 100, vec.y * 100, vec.z * 100); - * endShape(CLOSE); - * shape01 = endGeometry(); + * The exported .stl file will include the faces, vertices, and normals of the `p5.Geometry`. + * + * By default, this method saves a text-based .stl file. Alternatively, you can save a more compact + * but less human-readable binary .stl file by passing `{ binary: true }` as a second parameter. + * + * @method saveStl + * @param {String} [fileName='model.stl'] The name of the file to save the model as. + * If not specified, the default file name will be 'model.stl'. + * @param {Object} [options] Optional settings. Options can include a boolean `binary` property, which + * controls whether or not a binary .stl file is saved. It defaults to false. + * @example + *
+ * + * let myModel; + * let saveBtn1; + * let saveBtn2; + * function setup() { + * createCanvas(200, 200, WEBGL); + * myModel = buildGeometry(() => { + * for (let i = 0; i < 5; i++) { + * push(); + * translate( + * random(-75, 75), + * random(-75, 75), + * random(-75, 75) + * ); + * sphere(random(5, 50)); + * pop(); + * } + * }); + * + * saveBtn1 = createButton('Save .stl'); + * saveBtn1.mousePressed(function() { + * myModel.saveStl(); + * }); + * saveBtn2 = createButton('Save binary .stl'); + * saveBtn2.mousePressed(function() { + * myModel.saveStl('model.stl', { binary: true }); + * }); + * + * describe('A few spheres rotating in space'); * } * - * function buildShape02() { - * beginGeometry(); - * fill('red'); // shape02.clearColors() removes its internal colors. Now, shape02 is red. - * beginShape(); - * for (let vec of points) vertex(vec.x * 200, vec.y * 200, vec.z * 200); - * endShape(CLOSE); - * shape02 = endGeometry(); - * shape02.clearColors(); // Resets shape02's colors. + * function draw() { + * background(0); + * noStroke(); + * lights(); + * rotateX(millis() * 0.001); + * rotateY(millis() * 0.002); + * model(myModel); * } * *
@@ -113179,15 +135695,457 @@ }, { - key: 'clearColors', - value: function clearColors() { - this.vertexColors = [ + key: 'saveStl', + value: function saveStl() { + var fileName = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'model.stl'; + var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { + }, + _ref$binary = _ref.binary, + binary = _ref$binary === void 0 ? false : _ref$binary; + var modelOutput; + var name = fileName.substring(0, fileName.lastIndexOf('.')); + var faceNormals = [ ]; - return this; + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + try { + for (var _iterator = this.faces[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var _f2 = _step.value; + var U = _main.default.Vector.sub(this.vertices[_f2[1]], this.vertices[_f2[0]]); + var V = _main.default.Vector.sub(this.vertices[_f2[2]], this.vertices[_f2[0]]); + var nx = U.y * V.z - U.z * V.y; + var ny = U.z * V.x - U.x * V.z; + var nz = U.x * V.y - U.y * V.x; + faceNormals.push(new _main.default.Vector(nx, ny, nz).normalize()); + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return != null) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + if (binary) { + var offset = 80; + var bufferLength = this.faces.length * 2 + this.faces.length * 3 * 4 * 4 + 80 + 4; + var arrayBuffer = new ArrayBuffer(bufferLength); + modelOutput = new DataView(arrayBuffer); + modelOutput.setUint32(offset, this.faces.length, true); + offset += 4; + for (var _i = 0, _Object$entries = Object.entries(this.faces); _i < _Object$entries.length; _i++) { + var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2), + key = _Object$entries$_i[0], + f = _Object$entries$_i[1]; + var norm = faceNormals[key]; + modelOutput.setFloat32(offset, norm.x, true); + offset += 4; + modelOutput.setFloat32(offset, norm.y, true); + offset += 4; + modelOutput.setFloat32(offset, norm.z, true); + offset += 4; + var _iteratorNormalCompletion2 = true; + var _didIteratorError2 = false; + var _iteratorError2 = undefined; + try { + for (var _iterator2 = f[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { + var vertexIndex = _step2.value; + var vert = this.vertices[vertexIndex]; + modelOutput.setFloat32(offset, vert.x, true); + offset += 4; + modelOutput.setFloat32(offset, vert.y, true); + offset += 4; + modelOutput.setFloat32(offset, vert.z, true); + offset += 4; + } + } catch (err) { + _didIteratorError2 = true; + _iteratorError2 = err; + } finally { + try { + if (!_iteratorNormalCompletion2 && _iterator2.return != null) { + _iterator2.return(); + } + } finally { + if (_didIteratorError2) { + throw _iteratorError2; + } + } + } + modelOutput.setUint16(offset, 0, true); + offset += 2; + } + } else { + modelOutput = 'solid ' + name + '\n'; + for (var _i2 = 0, _Object$entries2 = Object.entries(this.faces); _i2 < _Object$entries2.length; _i2++) { + var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i2], 2), + _key = _Object$entries2$_i[0], + _f = _Object$entries2$_i[1]; + var _norm = faceNormals[_key]; + modelOutput += ' facet norm ' + _norm.x + ' ' + _norm.y + ' ' + _norm.z + '\n'; + modelOutput += ' outer loop' + '\n'; + var _iteratorNormalCompletion3 = true; + var _didIteratorError3 = false; + var _iteratorError3 = undefined; + try { + for (var _iterator3 = _f[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { + var _vertexIndex = _step3.value; + var _vert = this.vertices[_vertexIndex]; + modelOutput += ' vertex ' + _vert.x + ' ' + _vert.y + ' ' + _vert.z + '\n'; + } + } catch (err) { + _didIteratorError3 = true; + _iteratorError3 = err; + } finally { + try { + if (!_iteratorNormalCompletion3 && _iterator3.return != null) { + _iterator3.return(); + } + } finally { + if (_didIteratorError3) { + throw _iteratorError3; + } + } + } + modelOutput += ' endloop' + '\n'; + modelOutput += ' endfacet' + '\n'; + } + modelOutput += 'endsolid ' + name + '\n'; + } + var blob = new Blob([modelOutput], { + type: 'text/plain' + }); + _main.default.prototype.downloadFile(blob, fileName, 'stl'); + } /** + * Flips the geometry’s texture u-coordinates. + * + * In order for texture() to work, the geometry + * needs a way to map the points on its surface to the pixels in a rectangular + * image that's used as a texture. The geometry's vertex at coordinates + * `(x, y, z)` maps to the texture image's pixel at coordinates `(u, v)`. + * + * The myGeometry.uvs array stores the + * `(u, v)` coordinates for each vertex in the order it was added to the + * geometry. Calling `myGeometry.flipU()` flips a geometry's u-coordinates + * so that the texture appears mirrored horizontally. + * + * For example, a plane's four vertices are added clockwise starting from the + * top-left corner. Here's how calling `myGeometry.flipU()` would change a + * plane's texture coordinates: + * + * ```js + * // Print the original texture coordinates. + * // Output: [0, 0, 1, 0, 0, 1, 1, 1] + * console.log(myGeometry.uvs); + * + * // Flip the u-coordinates. + * myGeometry.flipU(); + * + * // Print the flipped texture coordinates. + * // Output: [1, 0, 0, 0, 1, 1, 0, 1] + * console.log(myGeometry.uvs); + * + * // Notice the swaps: + * // Top vertices: [0, 0, 1, 0] --> [1, 0, 0, 0] + * // Bottom vertices: [0, 1, 1, 1] --> [1, 1, 0, 1] + * ``` + * + * @method flipU + * @for p5.Geometry + * + * @example + *
+ * + * let img; + * + * function preload() { + * img = loadImage('assets/laDefense.jpg'); + * } + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * background(200); + * + * // Create p5.Geometry objects. + * let geom1 = buildGeometry(createShape); + * let geom2 = buildGeometry(createShape); + * + * // Flip geom2's U texture coordinates. + * geom2.flipU(); + * + * // Left (original). + * push(); + * translate(-25, 0, 0); + * texture(img); + * noStroke(); + * model(geom1); + * pop(); + * + * // Right (flipped). + * push(); + * translate(25, 0, 0); + * texture(img); + * noStroke(); + * model(geom2); + * pop(); + * + * describe( + * 'Two photos of a ceiling on a gray background. The photos are mirror images of each other.' + * ); + * } + * + * function createShape() { + * plane(40); + * } + * + *
+ */ + + }, + { + key: 'flipU', + value: function flipU() { + this.uvs = this.uvs.flat().map(function (val, index) { + if (index % 2 === 0) { + return 1 - val; + } else { + return val; + } + }); + } /** + * Flips the geometry’s texture v-coordinates. + * + * In order for texture() to work, the geometry + * needs a way to map the points on its surface to the pixels in a rectangular + * image that's used as a texture. The geometry's vertex at coordinates + * `(x, y, z)` maps to the texture image's pixel at coordinates `(u, v)`. + * + * The myGeometry.uvs array stores the + * `(u, v)` coordinates for each vertex in the order it was added to the + * geometry. Calling `myGeometry.flipV()` flips a geometry's v-coordinates + * so that the texture appears mirrored vertically. + * + * For example, a plane's four vertices are added clockwise starting from the + * top-left corner. Here's how calling `myGeometry.flipV()` would change a + * plane's texture coordinates: + * + * ```js + * // Print the original texture coordinates. + * // Output: [0, 0, 1, 0, 0, 1, 1, 1] + * console.log(myGeometry.uvs); + * + * // Flip the v-coordinates. + * myGeometry.flipV(); + * + * // Print the flipped texture coordinates. + * // Output: [0, 1, 1, 1, 0, 0, 1, 0] + * console.log(myGeometry.uvs); + * + * // Notice the swaps: + * // Left vertices: [0, 0] <--> [1, 0] + * // Right vertices: [1, 0] <--> [1, 1] + * ``` + * + * @method flipV + * @for p5.Geometry + * + * @example + *
+ * + * let img; + * + * function preload() { + * img = loadImage('assets/laDefense.jpg'); + * } + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * background(200); + * + * // Create p5.Geometry objects. + * let geom1 = buildGeometry(createShape); + * let geom2 = buildGeometry(createShape); + * + * // Flip geom2's V texture coordinates. + * geom2.flipV(); + * + * // Left (original). + * push(); + * translate(-25, 0, 0); + * texture(img); + * noStroke(); + * model(geom1); + * pop(); + * + * // Right (flipped). + * push(); + * translate(25, 0, 0); + * texture(img); + * noStroke(); + * model(geom2); + * pop(); + * + * describe( + * 'Two photos of a ceiling on a gray background. The photos are mirror images of each other.' + * ); + * } + * + * function createShape() { + * plane(40); + * } + * + *
+ */ + + }, + { + key: 'flipV', + value: function flipV() { + this.uvs = this.uvs.flat().map(function (val, index) { + if (index % 2 === 0) { + return val; + } else { + return 1 - val; + } + }); } /** - * computes faces for geometry objects based on the vertices. + * Computes the geometry's faces using its vertices. + * + * All 3D shapes are made by connecting sets of points called *vertices*. A + * geometry's surface is formed by connecting vertices to form triangles that + * are stitched together. Each triangular patch on the geometry's surface is + * called a *face*. `myGeometry.computeFaces()` performs the math needed to + * define each face based on the distances between vertices. + * + * The geometry's vertices are stored as p5.Vector + * objects in the myGeometry.vertices + * array. The geometry's first vertex is the + * p5.Vector object at `myGeometry.vertices[0]`, + * its second vertex is `myGeometry.vertices[1]`, its third vertex is + * `myGeometry.vertices[2]`, and so on. + * + * Calling `myGeometry.computeFaces()` fills the + * myGeometry.faces array with three-element + * arrays that list the vertices that form each face. For example, a geometry + * made from a rectangle has two faces because a rectangle is made by joining + * two triangles. myGeometry.faces for a + * rectangle would be the two-dimensional array + * `[[0, 1, 2], [2, 1, 3]]`. The first face, `myGeometry.faces[0]`, is the + * array `[0, 1, 2]` because it's formed by connecting + * `myGeometry.vertices[0]`, `myGeometry.vertices[1]`,and + * `myGeometry.vertices[2]`. The second face, `myGeometry.faces[1]`, is the + * array `[2, 1, 3]` because it's formed by connecting + * `myGeometry.vertices[2]`, `myGeometry.vertices[1]`, and + * `myGeometry.vertices[3]`. + * + * Note: `myGeometry.computeFaces()` only works when geometries have four or more vertices. + * * @method computeFaces * @chainable + * + * @example + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * let myGeometry; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Geometry object. + * myGeometry = new p5.Geometry(); + * + * // Create p5.Vector objects to position the vertices. + * let v0 = createVector(-40, 0, 0); + * let v1 = createVector(0, -40, 0); + * let v2 = createVector(0, 40, 0); + * let v3 = createVector(40, 0, 0); + * + * // Add the vertices to myGeometry's vertices array. + * myGeometry.vertices.push(v0, v1, v2, v3); + * + * // Compute myGeometry's faces array. + * myGeometry.computeFaces(); + * + * describe('A red square drawn on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * lights(); + * + * // Style the shape. + * noStroke(); + * fill(255, 0, 0); + * + * // Draw the p5.Geometry object. + * model(myGeometry); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * let myGeometry; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Geometry object using a callback function. + * myGeometry = new p5.Geometry(1, 1, createShape); + * + * describe('A red square drawn on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * lights(); + * + * // Style the shape. + * noStroke(); + * fill(255, 0, 0); + * + * // Draw the p5.Geometry object. + * model(myGeometry); + * } + * + * function createShape() { + * // Create p5.Vector objects to position the vertices. + * let v0 = createVector(-40, 0, 0); + * let v1 = createVector(0, -40, 0); + * let v2 = createVector(0, 40, 0); + * let v3 = createVector(40, 0, 0); + * + * // Add the vertices to the p5.Geometry object's vertices array. + * this.vertices.push(v0, v1, v2, v3); + * + * // Compute the faces array. + * this.computeFaces(); + * } + * + *
*/ }, @@ -113237,112 +136195,324 @@ if (sinAlpha > 1) sinAlpha = 1; // handle float rounding error return n.mult(Math.asin(sinAlpha) / ln); } /** - * This function calculates normals for each face, where each vertex's normal is the average of the normals of all faces it's connected to. - * i.e computes smooth normals per vertex as an average of each face. - * - * When using `FLAT` shading, vertices are disconnected/duplicated i.e each face has its own copy of vertices. - * When using `SMOOTH` shading, vertices are connected/deduplicated i.e each face has its vertices shared with other faces. - * - * Options can include: - * - `roundToPrecision`: Precision value for rounding computations. Defaults to 3. + * Calculates the normal vector for each vertex on the geometry. + * + * All 3D shapes are made by connecting sets of points called *vertices*. A + * geometry's surface is formed by connecting vertices to create triangles + * that are stitched together. Each triangular patch on the geometry's + * surface is called a *face*. `myGeometry.computeNormals()` performs the + * math needed to orient each face. Orientation is important for lighting + * and other effects. + * + * A face's orientation is defined by its *normal vector* which points out + * of the face and is normal (perpendicular) to the surface. Calling + * `myGeometry.computeNormals()` first calculates each face's normal vector. + * Then it calculates the normal vector for each vertex by averaging the + * normal vectors of the faces surrounding the vertex. The vertex normals + * are stored as p5.Vector objects in the + * myGeometry.vertexNormals array. + * + * The first parameter, `shadingType`, is optional. Passing the constant + * `FLAT`, as in `myGeometry.computeNormals(FLAT)`, provides neighboring + * faces with their own copies of the vertices they share. Surfaces appear + * tiled with flat shading. Passing the constant `SMOOTH`, as in + * `myGeometry.computeNormals(SMOOTH)`, makes neighboring faces reuse their + * shared vertices. Surfaces appear smoother with smooth shading. By + * default, `shadingType` is `FLAT`. + * + * The second parameter, `options`, is also optional. If an object with a + * `roundToPrecision` property is passed, as in + * `myGeometry.computeNormals(SMOOTH, { roundToPrecision: 5 })`, it sets the + * number of decimal places to use for calculations. By default, + * `roundToPrecision` uses 3 decimal places. * * @method computeNormals - * @param {String} [shadingType] shading type (`FLAT` for flat shading or `SMOOTH` for smooth shading) for buildGeometry() outputs. Defaults to `FLAT`. - * @param {Object} [options] An optional object with configuration. + * @param {String} [shadingType] shading type. either FLAT or SMOOTH. Defaults to `FLAT`. + * @param {Object} [options] shading options. * @chainable * * @example *
* - * let helix; + * // Click and drag the mouse to view the scene from different angles. + * + * let myGeometry; * * function setup() { * createCanvas(100, 100, WEBGL); * - * helix = buildGeometry(() => { - * beginShape(); + * // Create a p5.Geometry object. + * beginGeometry(); + * torus(); + * myGeometry = endGeometry(); * - * for (let i = 0; i < TWO_PI * 3; i += 0.6) { - * let radius = 20; - * let x = cos(i) * radius; - * let y = sin(i) * radius; - * let z = map(i, 0, TWO_PI * 3, -30, 30); - * vertex(x, y, z); - * } - * endShape(); - * }); - * helix.computeNormals(); + * // Compute the vertex normals. + * myGeometry.computeNormals(); + * + * describe( + * "A white torus drawn on a dark gray background. Red lines extend outward from the torus' vertices." + * ); * } + * * function draw() { - * background(255); - * stroke(0); - * fill(150, 200, 250); - * lights(); - * rotateX(PI*0.2); + * background(50); + * + * // Enable orbiting with the mouse. * orbitControl(); - * model(helix); + * + * // Turn on the lights. + * lights(); + * + * // Rotate the coordinate system. + * rotateX(1); + * + * // Style the helix. + * stroke(0); + * + * // Display the helix. + * model(myGeometry); + * + * // Style the normal vectors. + * stroke(255, 0, 0); + * + * // Iterate over the vertices and vertexNormals arrays. + * for (let i = 0; i < myGeometry.vertices.length; i += 1) { + * + * // Get the vertex p5.Vector object. + * let v = myGeometry.vertices[i]; + * + * // Get the vertex normal p5.Vector object. + * let n = myGeometry.vertexNormals[i]; + * + * // Calculate a point along the vertex normal. + * let p = p5.Vector.mult(n, 5); + * + * // Draw the vertex normal as a red line. + * push(); + * translate(v); + * line(0, 0, 0, p.x, p.y, p.z); + * pop(); + * } * } * *
* - * @alt - * A 3D helix using the computeNormals() function by default uses `FLAT` to create a flat shading effect on the helix. + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * let myGeometry; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Geometry object using a callback function. + * myGeometry = new p5.Geometry(); + * + * // Create p5.Vector objects to position the vertices. + * let v0 = createVector(-40, 0, 0); + * let v1 = createVector(0, -40, 0); + * let v2 = createVector(0, 40, 0); + * let v3 = createVector(40, 0, 0); + * + * // Add the vertices to the p5.Geometry object's vertices array. + * myGeometry.vertices.push(v0, v1, v2, v3); + * + * // Compute the faces array. + * myGeometry.computeFaces(); + * + * // Compute the surface normals. + * myGeometry.computeNormals(); + * + * describe('A red square drawn on a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Add a white point light. + * pointLight(255, 255, 255, 0, 0, 10); + * + * // Style the p5.Geometry object. + * noStroke(); + * fill(255, 0, 0); + * + * // Draw the p5.Geometry object. + * model(myGeometry); + * } + * + *
* - * @example *
* - * let star; + * // Click and drag the mouse to view the scene from different angles. + * + * let myGeometry; * * function setup() { * createCanvas(100, 100, WEBGL); * - * star = buildGeometry(() => { - * beginShape(); - * for (let i = 0; i < TWO_PI; i += PI / 5) { - * let outerRadius = 60; - * let innerRadius = 30; - * let xOuter = cos(i) * outerRadius; - * let yOuter = sin(i) * outerRadius; - * let zOuter = random(-20, 20); - * vertex(xOuter, yOuter, zOuter); - * - * let nextI = i + PI / 5 / 2; - * let xInner = cos(nextI) * innerRadius; - * let yInner = sin(nextI) * innerRadius; - * let zInner = random(-20, 20); - * vertex(xInner, yInner, zInner); - * } - * endShape(CLOSE); - * }); - * star.computeNormals(SMOOTH); + * // Create a p5.Geometry object. + * myGeometry = buildGeometry(createShape); + * + * // Compute normals using default (FLAT) shading. + * myGeometry.computeNormals(FLAT); + * + * describe('A white, helical structure drawn on a dark gray background. Its faces appear faceted.'); * } + * * function draw() { - * background(255); - * stroke(0); - * fill(150, 200, 250); + * background(50); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. * lights(); - * rotateX(PI*0.2); + * + * // Rotate the coordinate system. + * rotateX(1); + * + * // Style the helix. + * noStroke(); + * + * // Display the helix. + * model(myGeometry); + * } + * + * function createShape() { + * // Create a helical shape. + * beginShape(); + * for (let i = 0; i < TWO_PI * 3; i += 0.5) { + * let x = 30 * cos(i); + * let y = 30 * sin(i); + * let z = map(i, 0, TWO_PI * 3, -40, 40); + * vertex(x, y, z); + * } + * endShape(); + * } + * + *
+ * + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * let myGeometry; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Geometry object. + * myGeometry = buildGeometry(createShape); + * + * // Compute normals using smooth shading. + * myGeometry.computeNormals(SMOOTH); + * + * describe('A white, helical structure drawn on a dark gray background.'); + * } + * + * function draw() { + * background(50); + * + * // Enable orbiting with the mouse. * orbitControl(); - * model(star); + * + * // Turn on the lights. + * lights(); + * + * // Rotate the coordinate system. + * rotateX(1); + * + * // Style the helix. + * noStroke(); + * + * // Display the helix. + * model(myGeometry); + * } + * + * function createShape() { + * // Create a helical shape. + * beginShape(); + * for (let i = 0; i < TWO_PI * 3; i += 0.5) { + * let x = 30 * cos(i); + * let y = 30 * sin(i); + * let z = map(i, 0, TWO_PI * 3, -40, 40); + * vertex(x, y, z); + * } + * endShape(); * } * *
* - * @alt - * A star-like geometry, here the computeNormals(SMOOTH) is applied for a smooth shading effect. - * This helps to avoid the faceted appearance that can occur with flat shading. + *
+ * + * // Click and drag the mouse to view the scene from different angles. + * + * let myGeometry; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Geometry object. + * myGeometry = buildGeometry(createShape); + * + * // Create an options object. + * let options = { roundToPrecision: 5 }; + * + * // Compute normals using smooth shading. + * myGeometry.computeNormals(SMOOTH, options); + * + * describe('A white, helical structure drawn on a dark gray background.'); + * } + * + * function draw() { + * background(50); + * + * // Enable orbiting with the mouse. + * orbitControl(); + * + * // Turn on the lights. + * lights(); + * + * // Rotate the coordinate system. + * rotateX(1); + * + * // Style the helix. + * noStroke(); + * + * // Display the helix. + * model(myGeometry); + * } + * + * function createShape() { + * // Create a helical shape. + * beginShape(); + * for (let i = 0; i < TWO_PI * 3; i += 0.5) { + * let x = 30 * cos(i); + * let y = 30 * sin(i); + * let z = map(i, 0, TWO_PI * 3, -40, 40); + * vertex(x, y, z); + * } + * endShape(); + * } + * + *
*/ }, { key: 'computeNormals', value: function computeNormals() { - var _this = this; + var _this2 = this; var shadingType = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : constants.FLAT; - var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { + var _ref2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { }, - _ref$roundToPrecision = _ref.roundToPrecision, - roundToPrecision = _ref$roundToPrecision === void 0 ? 3 : _ref$roundToPrecision; + _ref2$roundToPrecisio = _ref2.roundToPrecision, + roundToPrecision = _ref2$roundToPrecisio === void 0 ? 3 : _ref2$roundToPrecisio; var vertexNormals = this.vertexNormals; var vertices = this.vertices; var faces = this.faces; @@ -113373,8 +136543,8 @@ for (var fv = 0; fv < 3; ++fv) { var originalVertexIndex = face[fv]; var originalVertex = vertices[originalVertexIndex]; - var _key = getKey(originalVertex); - face[fv] = vertexIndices[_key]; + var _key2 = getKey(originalVertex); + face[fv] = vertexIndices[_key2]; } }); // update edge indices to use the deduplicated vertex indices @@ -113382,8 +136552,8 @@ for (var ev = 0; ev < 2; ++ev) { var originalVertexIndex = edge[ev]; var originalVertex = vertices[originalVertexIndex]; - var _key2 = getKey(originalVertex); - edge[ev] = vertexIndices[_key2]; + var _key3 = getKey(originalVertex); + edge[ev] = vertexIndices[_key3]; } }); // update the deduplicated vertices @@ -113397,7 +136567,7 @@ // of each of its vertices faces.forEach(function (face, f) { - var faceNormal = _this._getFaceNormal(f); + var faceNormal = _this2._getFaceNormal(f); // all three vertices get the normal added for (var fv = 0; fv < 3; ++fv) { var vertexIndex = face[fv]; @@ -113412,7 +136582,7 @@ } /** * Averages the vertex normals. Used in curved * surfaces - * @method averageNormals + * @private * @chainable */ @@ -113430,7 +136600,7 @@ return this; } /** * Averages pole normals. Used in spherical primitives - * @method averagePoleNormals + * @private * @chainable */ @@ -113444,17 +136614,17 @@ sum.add(this.vertexNormals[i]); } sum = _main.default.Vector.div(sum, this.detailX); - for (var _i = 0; _i < this.detailX; _i++) { - this.vertexNormals[_i] = sum; + for (var _i3 = 0; _i3 < this.detailX; _i3++) { + this.vertexNormals[_i3] = sum; } //average the south pole sum = new _main.default.Vector(0, 0, 0); - for (var _i2 = this.vertices.length - 1; _i2 > this.vertices.length - 1 - this.detailX; _i2--) { - sum.add(this.vertexNormals[_i2]); + for (var _i4 = this.vertices.length - 1; _i4 > this.vertices.length - 1 - this.detailX; _i4--) { + sum.add(this.vertexNormals[_i4]); } sum = _main.default.Vector.div(sum, this.detailX); - for (var _i3 = this.vertices.length - 1; _i3 > this.vertices.length - 1 - this.detailX; _i3--) { - this.vertexNormals[_i3] = sum; + for (var _i5 = this.vertices.length - 1; _i5 > this.vertices.length - 1 - this.detailX; _i5--) { + this.vertexNormals[_i5] = sum; } return this; } /** @@ -113591,28 +136761,28 @@ lastValidDir = dir; } } - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; + var _iteratorNormalCompletion4 = true; + var _didIteratorError4 = false; + var _iteratorError4 = undefined; try { - for (var _iterator = potentialCaps.values() [Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var _step$value = _step.value, - point = _step$value.point, - _dir = _step$value.dir, - color = _step$value.color; + for (var _iterator4 = potentialCaps.values() [Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { + var _step4$value = _step4.value, + point = _step4$value.point, + _dir = _step4$value.dir, + color = _step4$value.color; this._addCap(point, _dir, color); } } catch (err) { - _didIteratorError = true; - _iteratorError = err; + _didIteratorError4 = true; + _iteratorError4 = err; } finally { try { - if (!_iteratorNormalCompletion && _iterator.return != null) { - _iterator.return(); + if (!_iteratorNormalCompletion4 && _iterator4.return != null) { + _iterator4.return(); } } finally { - if (_didIteratorError) { - throw _iteratorError; + if (_didIteratorError4) { + throw _iteratorError4; } } } @@ -113644,11 +136814,11 @@ var b = end.array(); var dirArr = dir.array(); this.lineSides.push(1, 1, - 1, 1, - 1, - 1); - for (var _i4 = 0, _arr = [ + for (var _i6 = 0, _arr2 = [ this.lineTangentsIn, this.lineTangentsOut - ]; _i4 < _arr.length; _i4++) { - var tangents = _arr[_i4]; + ]; _i6 < _arr2.length; _i6++) { + var tangents = _arr2[_i6]; for (var i = 0; i < 6; i++) { tangents.push.apply(tangents, _toConsumableArray(dirArr)); } @@ -113740,9 +136910,57 @@ this.lineSides.push(3, 1, 2, 3, 0, 1); return this; } /** - * Modifies all vertices to be centered within the range -100 to 100. + * Transforms the geometry's vertices to fit snugly within a 100×100×100 box + * centered at the origin. + * + * Calling `myGeometry.normalize()` translates the geometry's vertices so that + * they're centered at the origin `(0, 0, 0)`. Then it scales the vertices so + * that they fill a 100×100×100 box. As a result, small geometries will grow + * and large geometries will shrink. + * + * Note: `myGeometry.normalize()` only works when called in the + * setup() function. + * * @method normalize * @chainable + * + * @example + *
+ * + * let myGeometry; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a very small torus. + * beginGeometry(); + * torus(1, 0.25); + * myGeometry = endGeometry(); + * + * // Normalize the torus so its vertices fill + * // the range [-100, 100]. + * myGeometry.normalize(); + * + * describe('A white torus rotates slowly against a dark gray background.'); + * } + * + * function draw() { + * background(50); + * + * // Turn on the lights. + * lights(); + * + * // Rotate around the y-axis. + * rotateY(frameCount * 0.01); + * + * // Style the torus. + * noStroke(); + * + * // Draw the torus. + * model(myGeometry); + * } + * + *
*/ }, @@ -113765,9 +136983,9 @@ var dist = _main.default.Vector.sub(maxPosition, minPosition); var longestDist = Math.max(Math.max(dist.x, dist.y), dist.z); var scale = 200 / longestDist; - for (var _i5 = 0; _i5 < this.vertices.length; _i5++) { - this.vertices[_i5].sub(center); - this.vertices[_i5].mult(scale); + for (var _i7 = 0; _i7 < this.vertices.length; _i7++) { + this.vertices[_i7].sub(center); + this.vertices[_i7].mult(scale); } } return this; @@ -113780,29 +136998,36 @@ exports.default = _default; }, { - '../core/constants': 286, - '../core/main': 298, - 'core-js/modules/es.array.concat': 169, - 'core-js/modules/es.array.for-each': 175, - 'core-js/modules/es.array.from': 176, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.map': 187, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.set': 207, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.string.sub': 218, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.for-each': 255, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/constants': 294, + '../core/main': 306, + 'core-js/modules/es.array-buffer.constructor': 170, + 'core-js/modules/es.array.concat': 171, + 'core-js/modules/es.array.flat': 178, + 'core-js/modules/es.array.for-each': 179, + 'core-js/modules/es.array.from': 180, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.last-index-of': 185, + 'core-js/modules/es.array.map': 186, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.array.unscopables.flat': 191, + 'core-js/modules/es.map': 193, + 'core-js/modules/es.number.constructor': 197, + 'core-js/modules/es.object.entries': 202, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.set': 215, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.string.sub': 226, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.for-each': 263, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 351: [ + 359: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.array.iterator'); @@ -113953,49 +137178,74 @@ 1]); } return this; - } /** - * Sets the x, y, and z component of the vector using two or three separate - * variables, the data from a p5.Matrix, or the values from a float array. - * - * @method set - * @param {p5.Matrix|Float32Array|Number[]} [inMatrix] the input p5.Matrix or - * an Array of length 16 - * @chainable - */ - /** - * @method set - * @param {Number[]} elements 16 numbers passed by value to avoid - * array copying. - * @chainable - */ - + } _createClass(_class, [ + { + key: 'reset', + value: function reset() { + if (this.mat3) { + this.mat3.set([1, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 1]); + } else if (this.mat4) { + this.mat4.set([1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1]); + } + return this; + } /** + * Replace the entire contents of a 4x4 matrix. + * If providing an array or a p5.Matrix, the values will be copied without + * referencing the source object. + * Can also provide 16 numbers as individual arguments. + * + * @method set + * @param {p5.Matrix|Float32Array|Number[]} [inMatrix] the input p5.Matrix or + * an Array of length 16 + * @chainable + */ + /** + * @method set + * @param {Number[]} elements 16 numbers passed by value to avoid + * array copying. + * @chainable + */ + + }, { key: 'set', value: function set(inMatrix) { + var refArray = arguments; if (inMatrix instanceof _main.default.Matrix) { - this.mat4 = inMatrix.mat4; - return this; + refArray = inMatrix.mat4; } else if (isMatrixArray(inMatrix)) { - this.mat4 = inMatrix; + refArray = inMatrix; + } + if (refArray.length !== 16) { + _main.default._friendlyError('Expected 16 values but received '.concat(refArray.length, '.'), 'p5.Matrix.set'); return this; - } else if (arguments.length === 16) { - this.mat4[0] = arguments[0]; - this.mat4[1] = arguments[1]; - this.mat4[2] = arguments[2]; - this.mat4[3] = arguments[3]; - this.mat4[4] = arguments[4]; - this.mat4[5] = arguments[5]; - this.mat4[6] = arguments[6]; - this.mat4[7] = arguments[7]; - this.mat4[8] = arguments[8]; - this.mat4[9] = arguments[9]; - this.mat4[10] = arguments[10]; - this.mat4[11] = arguments[11]; - this.mat4[12] = arguments[12]; - this.mat4[13] = arguments[13]; - this.mat4[14] = arguments[14]; - this.mat4[15] = arguments[15]; + } + for (var i = 0; i < 16; i++) { + this.mat4[i] = refArray[i]; } return this; } /** @@ -114961,36 +138211,172 @@ exports.default = _default; }, { - '../core/main': 298, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.typed-array.copy-within': 223, - 'core-js/modules/es.typed-array.every': 224, - 'core-js/modules/es.typed-array.fill': 225, - 'core-js/modules/es.typed-array.filter': 226, - 'core-js/modules/es.typed-array.find': 228, - 'core-js/modules/es.typed-array.find-index': 227, - 'core-js/modules/es.typed-array.float32-array': 229, - 'core-js/modules/es.typed-array.for-each': 231, - 'core-js/modules/es.typed-array.includes': 232, - 'core-js/modules/es.typed-array.index-of': 233, - 'core-js/modules/es.typed-array.iterator': 236, - 'core-js/modules/es.typed-array.join': 237, - 'core-js/modules/es.typed-array.last-index-of': 238, - 'core-js/modules/es.typed-array.map': 239, - 'core-js/modules/es.typed-array.reduce': 241, - 'core-js/modules/es.typed-array.reduce-right': 240, - 'core-js/modules/es.typed-array.reverse': 242, - 'core-js/modules/es.typed-array.set': 243, - 'core-js/modules/es.typed-array.slice': 244, - 'core-js/modules/es.typed-array.some': 245, - 'core-js/modules/es.typed-array.sort': 246, - 'core-js/modules/es.typed-array.subarray': 247, - 'core-js/modules/es.typed-array.to-locale-string': 248, - 'core-js/modules/es.typed-array.to-string': 249 + '../core/main': 306, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.typed-array.copy-within': 231, + 'core-js/modules/es.typed-array.every': 232, + 'core-js/modules/es.typed-array.fill': 233, + 'core-js/modules/es.typed-array.filter': 234, + 'core-js/modules/es.typed-array.find': 236, + 'core-js/modules/es.typed-array.find-index': 235, + 'core-js/modules/es.typed-array.float32-array': 237, + 'core-js/modules/es.typed-array.for-each': 239, + 'core-js/modules/es.typed-array.includes': 240, + 'core-js/modules/es.typed-array.index-of': 241, + 'core-js/modules/es.typed-array.iterator': 244, + 'core-js/modules/es.typed-array.join': 245, + 'core-js/modules/es.typed-array.last-index-of': 246, + 'core-js/modules/es.typed-array.map': 247, + 'core-js/modules/es.typed-array.reduce': 249, + 'core-js/modules/es.typed-array.reduce-right': 248, + 'core-js/modules/es.typed-array.reverse': 250, + 'core-js/modules/es.typed-array.set': 251, + 'core-js/modules/es.typed-array.slice': 252, + 'core-js/modules/es.typed-array.some': 253, + 'core-js/modules/es.typed-array.sort': 254, + 'core-js/modules/es.typed-array.subarray': 255, + 'core-js/modules/es.typed-array.to-locale-string': 256, + 'core-js/modules/es.typed-array.to-string': 257 } ], - 352: [ + 360: [ + function (_dereq_, module, exports) { + 'use strict'; + Object.defineProperty(exports, '__esModule', { + value: true + }); + exports.default = void 0; + var _main = _interopRequireDefault(_dereq_('../core/main')); + function _interopRequireDefault(obj) { + return obj && obj.__esModule ? obj : { + default: + obj + }; + } + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError('Cannot call a class as a function'); + } + } + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ('value' in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; + } /** + * @module Math + * @submodule Quaternion + */ + /** + * A class to describe a Quaternion + * for vector rotations in the p5js webgl renderer. + * Please refer the following link for details on the implementation + * https://danceswithcode.net/engineeringnotes/quaternions/quaternions.html + * @class p5.Quat + * @constructor + * @param {Number} [w] Scalar part of the quaternion + * @param {Number} [x] x component of imaginary part of quaternion + * @param {Number} [y] y component of imaginary part of quaternion + * @param {Number} [z] z component of imaginary part of quaternion + * @private + */ + + _main.default.Quat = /*#__PURE__*/ function () { + function _class(w, x, y, z) { + _classCallCheck(this, _class); + this.w = w; + this.vec = new _main.default.Vector(x, y, z); + } /** + * Returns a Quaternion for the + * axis angle representation of the rotation + * + * @method fromAxisAngle + * @param {Number} [angle] Angle with which the points needs to be rotated + * @param {Number} [x] x component of the axis vector + * @param {Number} [y] y component of the axis vector + * @param {Number} [z] z component of the axis vector + * @chainable + */ + + _createClass(_class, [ + { + key: 'conjugate', + value: function conjugate() { + return new _main.default.Quat(this.w, - this.vec.x, - this.vec.y, - this.vec.z); + } /** + * Multiplies a quaternion with other quaternion. + * @method mult + * @param {p5.Quat} [quat] quaternion to multiply with the quaternion calling the method. + * @chainable + */ + + }, + { + key: 'multiply', + value: function multiply(quat) { + /* eslint-disable max-len */ + return new _main.default.Quat(this.w * quat.w - this.vec.x * quat.vec.x - this.vec.y * quat.vec.y - this.vec.z - quat.vec.z, this.w * quat.vec.x + this.vec.x * quat.w + this.vec.y * quat.vec.z - this.vec.z * quat.vec.y, this.w * quat.vec.y - this.vec.x * quat.vec.z + this.vec.y * quat.w + this.vec.z * quat.vec.x, this.w * quat.vec.z + this.vec.x * quat.vec.y - this.vec.y * quat.vec.x + this.vec.z * quat.w); + /* eslint-enable max-len */ + } /** + * This is similar to quaternion multiplication + * but when multipying vector with quaternion + * the multiplication can be simplified to the below formula. + * This was taken from the below stackexchange link + * https://gamedev.stackexchange.com/questions/28395/rotating-vector3-by-a-quaternion/50545#50545 + * @param {p5.Vector} [p] vector to rotate on the axis quaternion + */ + + }, + { + key: 'rotateVector', + value: function rotateVector(p) { + return new _main.default.Vector.mult(p, this.w * this.w - this.vec.dot(this.vec)).add(_main.default.Vector.mult(this.vec, 2 * p.dot(this.vec))).add(_main.default.Vector.mult(this.vec, 2 * this.w).cross(p)).clampToZero(); + } /** + * Rotates the Quaternion by the quaternion passed + * which contains the axis of roation and angle of rotation + * + * @method rotateBy + * @param {p5.Quat} [axesQuat] axis quaternion which contains + * the axis of rotation and angle of rotation + * @chainable + */ + + }, + { + key: 'rotateBy', + value: function rotateBy(axesQuat) { + return axesQuat.multiply(this).multiply(axesQuat.conjugate()).vec.clampToZero(); + } + } + ], [ + { + key: 'fromAxisAngle', + value: function fromAxisAngle(angle, x, y, z) { + var w = Math.cos(angle / 2); + var vec = new _main.default.Vector(x, y, z).normalize().mult(Math.sin(angle / 2)); + return new _main.default.Quat(w, vec.x, vec.y, vec.z); + } + } + ]); + return _class; + }(); + var _default = _main.default.Quat; + exports.default = _default; + }, + { + '../core/main': 306 + } + ], + 361: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.array.map'); @@ -115102,11 +138488,11 @@ exports.default = _default; }, { - '../core/main': 298, - 'core-js/modules/es.array.map': 182 + '../core/main': 306, + 'core-js/modules/es.array.map': 186 } ], - 353: [ + 362: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -115371,13 +138757,14 @@ }; /** * Sets the normal to use for subsequent vertices. - * @method vertexNormal + * @private + * @method normal * @param {Number} x * @param {Number} y * @param {Number} z * @chainable * - * @method vertexNormal + * @method normal * @param {Vector} v * @chainable */ @@ -115410,8 +138797,10 @@ this.isProcessingVertices = false; // LINE_STRIP and LINES are not used for rendering, instead // they only indicate a way to modify vertices during the _processVertices() step + var is_line = false; if (this.immediateMode.shapeMode === constants.LINE_STRIP || this.immediateMode.shapeMode === constants.LINES) { this.immediateMode.shapeMode = constants.TRIANGLE_FAN; + is_line = true; } // WebGL doesn't support the QUADS and QUAD_STRIP modes, so we // need to convert them to a supported format. In `vertex()`, we reformat // the input data into the formats specified below. @@ -115421,7 +138810,7 @@ } else if (this.immediateMode.shapeMode === constants.QUAD_STRIP) { this.immediateMode.shapeMode = constants.TRIANGLE_STRIP; } - if (this._doFill) { + if (this._doFill && !is_line) { if (!this.geometryBuilder && this.immediateMode.geometry.vertices.length >= 3) { this._drawImmediateFill(count); } @@ -115476,7 +138865,7 @@ * Called from _processVertices(). This function calculates the stroke vertices for custom shapes and * tesselates shapes when applicable. * @private - * @returns {Array[Number]} indices for custom shape vertices indicating edges. + * @returns {Number[]} indices for custom shape vertices indicating edges. */ _main.default.RendererGL.prototype._calculateEdges = function (shapeMode, verts, shouldClose) { var res = [ @@ -115689,7 +139078,7 @@ } } shader.disableRemainingAttributes(); - this._applyColorBlend(this.curFillColor); + this._applyColorBlend(this.curFillColor, this.immediateMode.geometry.hasFillTransparency()); if (count === 1) { gl.drawArrays(this.immediateMode.shapeMode, 0, this.immediateMode.geometry.vertices.length); } else { @@ -115734,7 +139123,7 @@ } } shader.disableRemainingAttributes(); - this._applyColorBlend(this.curStrokeColor); + this._applyColorBlend(this.curStrokeColor, this.immediateMode.geometry.hasFillTransparency()); gl.drawArrays(gl.TRIANGLES, 0, this.immediateMode.geometry.lineVertices.length / 3); shader.unbindShader(); }; @@ -115742,29 +139131,29 @@ exports.default = _default; }, { - '../core/constants': 286, - '../core/main': 298, - './p5.RenderBuffer': 352, - 'core-js/modules/es.array.concat': 169, - 'core-js/modules/es.array.fill': 172, - 'core-js/modules/es.array.find-index': 174, - 'core-js/modules/es.array.from': 176, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.map': 182, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.map': 187, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/constants': 294, + '../core/main': 306, + './p5.RenderBuffer': 361, + 'core-js/modules/es.array.concat': 171, + 'core-js/modules/es.array.fill': 174, + 'core-js/modules/es.array.find-index': 176, + 'core-js/modules/es.array.from': 180, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.map': 186, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.map': 193, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 354: [ + 363: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -116075,7 +139464,7 @@ //vertex index buffer this._bindBuffer(geometry.indexBuffer, gl.ELEMENT_ARRAY_BUFFER); } - this._applyColorBlend(this.curFillColor); + this._applyColorBlend(this.curFillColor, geometry.model.hasFillTransparency()); this._drawElements(gl.TRIANGLES, gId); fillShader.unbindShader(); } @@ -116106,7 +139495,7 @@ } } strokeShader.disableRemainingAttributes(); - this._applyColorBlend(this.curStrokeColor); + this._applyColorBlend(this.curStrokeColor, geometry.model.hasStrokeTransparency()); this._drawArrays(gl.TRIANGLES, gId); strokeShader.unbindShader(); } @@ -116131,12 +139520,12 @@ * @param {Number} scaleZ the amount to scale in the Z direction */ _main.default.RendererGL.prototype.drawBuffersScaled = function (gId, scaleX, scaleY, scaleZ) { - var uMVMatrix = this.uMVMatrix.copy(); + var originalModelMatrix = this.uModelMatrix.copy(); try { - this.uMVMatrix.scale(scaleX, scaleY, scaleZ); + this.uModelMatrix.scale(scaleX, scaleY, scaleZ); this.drawBuffers(gId); } finally { - this.uMVMatrix = uMVMatrix; + this.uModelMatrix = originalModelMatrix; } }; _main.default.RendererGL.prototype._drawArrays = function (drawMode, gId) { @@ -116176,51 +139565,51 @@ exports.default = _default; }, { - '../core/constants': 286, - '../core/main': 298, - './p5.RenderBuffer': 352, - './p5.RendererGL': 355, - 'core-js/modules/es.array.fill': 172, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.some': 184, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.keys': 199, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.typed-array.copy-within': 223, - 'core-js/modules/es.typed-array.every': 224, - 'core-js/modules/es.typed-array.fill': 225, - 'core-js/modules/es.typed-array.filter': 226, - 'core-js/modules/es.typed-array.find': 228, - 'core-js/modules/es.typed-array.find-index': 227, - 'core-js/modules/es.typed-array.float32-array': 229, - 'core-js/modules/es.typed-array.for-each': 231, - 'core-js/modules/es.typed-array.includes': 232, - 'core-js/modules/es.typed-array.index-of': 233, - 'core-js/modules/es.typed-array.iterator': 236, - 'core-js/modules/es.typed-array.join': 237, - 'core-js/modules/es.typed-array.last-index-of': 238, - 'core-js/modules/es.typed-array.map': 239, - 'core-js/modules/es.typed-array.reduce': 241, - 'core-js/modules/es.typed-array.reduce-right': 240, - 'core-js/modules/es.typed-array.reverse': 242, - 'core-js/modules/es.typed-array.set': 243, - 'core-js/modules/es.typed-array.slice': 244, - 'core-js/modules/es.typed-array.some': 245, - 'core-js/modules/es.typed-array.sort': 246, - 'core-js/modules/es.typed-array.subarray': 247, - 'core-js/modules/es.typed-array.to-locale-string': 248, - 'core-js/modules/es.typed-array.to-string': 249, - 'core-js/modules/es.typed-array.uint16-array': 250, - 'core-js/modules/es.typed-array.uint32-array': 251, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/constants': 294, + '../core/main': 306, + './p5.RenderBuffer': 361, + './p5.RendererGL': 364, + 'core-js/modules/es.array.fill': 174, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.some': 188, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.keys': 207, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.typed-array.copy-within': 231, + 'core-js/modules/es.typed-array.every': 232, + 'core-js/modules/es.typed-array.fill': 233, + 'core-js/modules/es.typed-array.filter': 234, + 'core-js/modules/es.typed-array.find': 236, + 'core-js/modules/es.typed-array.find-index': 235, + 'core-js/modules/es.typed-array.float32-array': 237, + 'core-js/modules/es.typed-array.for-each': 239, + 'core-js/modules/es.typed-array.includes': 240, + 'core-js/modules/es.typed-array.index-of': 241, + 'core-js/modules/es.typed-array.iterator': 244, + 'core-js/modules/es.typed-array.join': 245, + 'core-js/modules/es.typed-array.last-index-of': 246, + 'core-js/modules/es.typed-array.map': 247, + 'core-js/modules/es.typed-array.reduce': 249, + 'core-js/modules/es.typed-array.reduce-right': 248, + 'core-js/modules/es.typed-array.reverse': 250, + 'core-js/modules/es.typed-array.set': 251, + 'core-js/modules/es.typed-array.slice': 252, + 'core-js/modules/es.typed-array.some': 253, + 'core-js/modules/es.typed-array.sort': 254, + 'core-js/modules/es.typed-array.subarray': 255, + 'core-js/modules/es.typed-array.to-locale-string': 256, + 'core-js/modules/es.typed-array.to-string': 257, + 'core-js/modules/es.typed-array.uint16-array': 258, + 'core-js/modules/es.typed-array.uint32-array': 259, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 355: [ + 364: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -116230,11 +139619,16 @@ _dereq_('core-js/modules/es.array.copy-within'); _dereq_('core-js/modules/es.array.every'); _dereq_('core-js/modules/es.array.fill'); + _dereq_('core-js/modules/es.array.flat'); + _dereq_('core-js/modules/es.array.flat-map'); _dereq_('core-js/modules/es.array.from'); _dereq_('core-js/modules/es.array.includes'); _dereq_('core-js/modules/es.array.iterator'); + _dereq_('core-js/modules/es.array.map'); _dereq_('core-js/modules/es.array.slice'); _dereq_('core-js/modules/es.array.some'); + _dereq_('core-js/modules/es.array.unscopables.flat'); + _dereq_('core-js/modules/es.array.unscopables.flat-map'); _dereq_('core-js/modules/es.map'); _dereq_('core-js/modules/es.object.assign'); _dereq_('core-js/modules/es.object.get-own-property-descriptor'); @@ -116308,11 +139702,16 @@ _dereq_('core-js/modules/es.array.copy-within'); _dereq_('core-js/modules/es.array.every'); _dereq_('core-js/modules/es.array.fill'); + _dereq_('core-js/modules/es.array.flat'); + _dereq_('core-js/modules/es.array.flat-map'); _dereq_('core-js/modules/es.array.from'); _dereq_('core-js/modules/es.array.includes'); _dereq_('core-js/modules/es.array.iterator'); + _dereq_('core-js/modules/es.array.map'); _dereq_('core-js/modules/es.array.slice'); _dereq_('core-js/modules/es.array.some'); + _dereq_('core-js/modules/es.array.unscopables.flat'); + _dereq_('core-js/modules/es.array.unscopables.flat-map'); _dereq_('core-js/modules/es.map'); _dereq_('core-js/modules/es.object.assign'); _dereq_('core-js/modules/es.object.to-string'); @@ -116571,9 +139970,10 @@ defineStrokeJoinEnum('ROUND', 0); defineStrokeJoinEnum('MITER', 1); defineStrokeJoinEnum('BEVEL', 2); - var lightingShader = '#define PI 3.141592\n\nprecision highp float;\nprecision highp int;\n\nuniform mat4 uViewMatrix;\n\nuniform bool uUseLighting;\n\nuniform int uAmbientLightCount;\nuniform vec3 uAmbientColor[5];\n\nuniform int uDirectionalLightCount;\nuniform vec3 uLightingDirection[5];\nuniform vec3 uDirectionalDiffuseColors[5];\nuniform vec3 uDirectionalSpecularColors[5];\n\nuniform int uPointLightCount;\nuniform vec3 uPointLightLocation[5];\nuniform vec3 uPointLightDiffuseColors[5];\t\nuniform vec3 uPointLightSpecularColors[5];\n\nuniform int uSpotLightCount;\nuniform float uSpotLightAngle[5];\nuniform float uSpotLightConc[5];\nuniform vec3 uSpotLightDiffuseColors[5];\nuniform vec3 uSpotLightSpecularColors[5];\nuniform vec3 uSpotLightLocation[5];\nuniform vec3 uSpotLightDirection[5];\n\nuniform bool uSpecular;\nuniform float uShininess;\n\nuniform float uConstantAttenuation;\nuniform float uLinearAttenuation;\nuniform float uQuadraticAttenuation;\n\n// setting from _setImageLightUniforms()\n// boolean to initiate the calculateImageDiffuse and calculateImageSpecular\nuniform bool uUseImageLight;\n// texture for use in calculateImageDiffuse\nuniform sampler2D environmentMapDiffused;\n// texture for use in calculateImageSpecular\nuniform sampler2D environmentMapSpecular;\n// roughness for use in calculateImageSpecular\nuniform float levelOfDetail;\n\nconst float specularFactor = 2.0;\nconst float diffuseFactor = 0.73;\n\nstruct LightResult {\n float specular;\n float diffuse;\n};\n\nfloat _phongSpecular(\n vec3 lightDirection,\n vec3 viewDirection,\n vec3 surfaceNormal,\n float shininess) {\n\n vec3 R = reflect(lightDirection, surfaceNormal);\n return pow(max(0.0, dot(R, viewDirection)), shininess);\n}\n\nfloat _lambertDiffuse(vec3 lightDirection, vec3 surfaceNormal) {\n return max(0.0, dot(-lightDirection, surfaceNormal));\n}\n\nLightResult _light(vec3 viewDirection, vec3 normal, vec3 lightVector) {\n\n vec3 lightDir = normalize(lightVector);\n\n //compute our diffuse & specular terms\n LightResult lr;\n if (uSpecular)\n lr.specular = _phongSpecular(lightDir, viewDirection, normal, uShininess);\n lr.diffuse = _lambertDiffuse(lightDir, normal);\n return lr;\n}\n\n// converts the range of "value" from [min1 to max1] to [min2 to max2]\nfloat map(float value, float min1, float max1, float min2, float max2) {\n return min2 + (value - min1) * (max2 - min2) / (max1 - min1);\n}\n\nvec2 mapTextureToNormal( vec3 v ){\n // x = r sin(phi) cos(theta) \n // y = r cos(phi) \n // z = r sin(phi) sin(theta)\n float phi = acos( v.y );\n // if phi is 0, then there are no x, z components\n float theta = 0.0;\n // else \n theta = acos(v.x / sin(phi));\n float sinTheta = v.z / sin(phi);\n if (sinTheta < 0.0) {\n // Turn it into -theta, but in the 0-2PI range\n theta = 2.0 * PI - theta;\n }\n theta = theta / (2.0 * 3.14159);\n phi = phi / 3.14159 ;\n \n vec2 angles = vec2( fract(theta + 0.25), 1.0 - phi );\n return angles;\n}\n\n\nvec3 calculateImageDiffuse( vec3 vNormal, vec3 vViewPosition ){\n // make 2 seperate builds \n vec3 worldCameraPosition = vec3(0.0, 0.0, 0.0); // hardcoded world camera position\n vec3 worldNormal = normalize(vNormal);\n vec2 newTexCoor = mapTextureToNormal( worldNormal );\n vec4 texture = TEXTURE( environmentMapDiffused, newTexCoor );\n // this is to make the darker sections more dark\n // png and jpg usually flatten the brightness so it is to reverse that\n return smoothstep(vec3(0.0), vec3(0.8), texture.xyz);\n}\n\nvec3 calculateImageSpecular( vec3 vNormal, vec3 vViewPosition ){\n vec3 worldCameraPosition = vec3(0.0, 0.0, 0.0);\n vec3 worldNormal = normalize(vNormal);\n vec3 lightDirection = normalize( vViewPosition - worldCameraPosition );\n vec3 R = reflect(lightDirection, worldNormal);\n vec2 newTexCoor = mapTextureToNormal( R );\n#ifdef WEBGL2\n vec4 outColor = textureLod(environmentMapSpecular, newTexCoor, levelOfDetail);\n#else\n vec4 outColor = TEXTURE(environmentMapSpecular, newTexCoor);\n#endif\n // this is to make the darker sections more dark\n // png and jpg usually flatten the brightness so it is to reverse that\n return pow(outColor.xyz, vec3(10.0));\n}\n\nvoid totalLight(\n vec3 modelPosition,\n vec3 normal,\n out vec3 totalDiffuse,\n out vec3 totalSpecular\n) {\n\n totalSpecular = vec3(0.0);\n\n if (!uUseLighting) {\n totalDiffuse = vec3(1.0);\n return;\n }\n\n totalDiffuse = vec3(0.0);\n\n vec3 viewDirection = normalize(-modelPosition);\n\n for (int j = 0; j < 5; j++) {\n if (j < uDirectionalLightCount) {\n vec3 lightVector = (uViewMatrix * vec4(uLightingDirection[j], 0.0)).xyz;\n vec3 lightColor = uDirectionalDiffuseColors[j];\n vec3 specularColor = uDirectionalSpecularColors[j];\n LightResult result = _light(viewDirection, normal, lightVector);\n totalDiffuse += result.diffuse * lightColor;\n totalSpecular += result.specular * lightColor * specularColor;\n }\n\n if (j < uPointLightCount) {\n vec3 lightPosition = (uViewMatrix * vec4(uPointLightLocation[j], 1.0)).xyz;\n vec3 lightVector = modelPosition - lightPosition;\n \n //calculate attenuation\n float lightDistance = length(lightVector);\n float lightFalloff = 1.0 / (uConstantAttenuation + lightDistance * uLinearAttenuation + (lightDistance * lightDistance) * uQuadraticAttenuation);\n vec3 lightColor = lightFalloff * uPointLightDiffuseColors[j];\n vec3 specularColor = lightFalloff * uPointLightSpecularColors[j];\n\n LightResult result = _light(viewDirection, normal, lightVector);\n totalDiffuse += result.diffuse * lightColor;\n totalSpecular += result.specular * lightColor * specularColor;\n }\n\n if(j < uSpotLightCount) {\n vec3 lightPosition = (uViewMatrix * vec4(uSpotLightLocation[j], 1.0)).xyz;\n vec3 lightVector = modelPosition - lightPosition;\n \n float lightDistance = length(lightVector);\n float lightFalloff = 1.0 / (uConstantAttenuation + lightDistance * uLinearAttenuation + (lightDistance * lightDistance) * uQuadraticAttenuation);\n\n vec3 lightDirection = (uViewMatrix * vec4(uSpotLightDirection[j], 0.0)).xyz;\n float spotDot = dot(normalize(lightVector), normalize(lightDirection));\n float spotFalloff;\n if(spotDot < uSpotLightAngle[j]) {\n spotFalloff = 0.0;\n }\n else {\n spotFalloff = pow(spotDot, uSpotLightConc[j]);\n }\n lightFalloff *= spotFalloff;\n\n vec3 lightColor = uSpotLightDiffuseColors[j];\n vec3 specularColor = uSpotLightSpecularColors[j];\n \n LightResult result = _light(viewDirection, normal, lightVector);\n \n totalDiffuse += result.diffuse * lightColor * lightFalloff;\n totalSpecular += result.specular * lightColor * specularColor * lightFalloff;\n }\n }\n\n if( uUseImageLight ){\n totalDiffuse += calculateImageDiffuse(normal, modelPosition);\n totalSpecular += calculateImageSpecular(normal, modelPosition);\n }\n\n totalDiffuse *= diffuseFactor;\n totalSpecular *= specularFactor;\n}\n'; + var lightingShader = '#define PI 3.141592\n\nprecision highp float;\nprecision highp int;\n\nuniform mat4 uViewMatrix;\n\nuniform bool uUseLighting;\n\nuniform int uAmbientLightCount;\nuniform vec3 uAmbientColor[5];\nuniform mat3 uCameraRotation;\nuniform int uDirectionalLightCount;\nuniform vec3 uLightingDirection[5];\nuniform vec3 uDirectionalDiffuseColors[5];\nuniform vec3 uDirectionalSpecularColors[5];\n\nuniform int uPointLightCount;\nuniform vec3 uPointLightLocation[5];\nuniform vec3 uPointLightDiffuseColors[5];\t\nuniform vec3 uPointLightSpecularColors[5];\n\nuniform int uSpotLightCount;\nuniform float uSpotLightAngle[5];\nuniform float uSpotLightConc[5];\nuniform vec3 uSpotLightDiffuseColors[5];\nuniform vec3 uSpotLightSpecularColors[5];\nuniform vec3 uSpotLightLocation[5];\nuniform vec3 uSpotLightDirection[5];\n\nuniform bool uSpecular;\nuniform float uShininess;\nuniform float metallic;\n\nuniform float uConstantAttenuation;\nuniform float uLinearAttenuation;\nuniform float uQuadraticAttenuation;\n\n// setting from _setImageLightUniforms()\n// boolean to initiate the calculateImageDiffuse and calculateImageSpecular\nuniform bool uUseImageLight;\n// texture for use in calculateImageDiffuse\nuniform sampler2D environmentMapDiffused;\n// texture for use in calculateImageSpecular\nuniform sampler2D environmentMapSpecular;\n// roughness for use in calculateImageSpecular\nuniform float levelOfDetail;\n\nconst float specularFactor = 2.0;\nconst float diffuseFactor = 0.73;\n\nstruct LightResult {\n float specular;\n float diffuse;\n};\n\nfloat _phongSpecular(\n vec3 lightDirection,\n vec3 viewDirection,\n vec3 surfaceNormal,\n float shininess) {\n\n vec3 R = reflect(lightDirection, surfaceNormal);\n return pow(max(0.0, dot(R, viewDirection)), shininess);\n}\n\nfloat _lambertDiffuse(vec3 lightDirection, vec3 surfaceNormal) {\n return max(0.0, dot(-lightDirection, surfaceNormal));\n}\n\nLightResult _light(vec3 viewDirection, vec3 normal, vec3 lightVector) {\n\n vec3 lightDir = normalize(lightVector);\n\n //compute our diffuse & specular terms\n LightResult lr;\n float specularIntensity = mix(1.0, 0.4, metallic);\n float diffuseIntensity = mix(1.0, 0.1, metallic);\n if (uSpecular)\n lr.specular = (_phongSpecular(lightDir, viewDirection, normal, uShininess)) * specularIntensity;\n lr.diffuse = _lambertDiffuse(lightDir, normal) * diffuseIntensity;\n return lr;\n}\n\n// converts the range of "value" from [min1 to max1] to [min2 to max2]\nfloat map(float value, float min1, float max1, float min2, float max2) {\n return min2 + (value - min1) * (max2 - min2) / (max1 - min1);\n}\n\nvec2 mapTextureToNormal( vec3 v ){\n // x = r sin(phi) cos(theta) \n // y = r cos(phi) \n // z = r sin(phi) sin(theta)\n float phi = acos( v.y );\n // if phi is 0, then there are no x, z components\n float theta = 0.0;\n // else \n theta = acos(v.x / sin(phi));\n float sinTheta = v.z / sin(phi);\n if (sinTheta < 0.0) {\n // Turn it into -theta, but in the 0-2PI range\n theta = 2.0 * PI - theta;\n }\n theta = theta / (2.0 * 3.14159);\n phi = phi / 3.14159 ;\n \n vec2 angles = vec2( fract(theta + 0.25), 1.0 - phi );\n return angles;\n}\n\n\nvec3 calculateImageDiffuse( vec3 vNormal, vec3 vViewPosition ){\n // make 2 seperate builds \n vec3 worldCameraPosition = vec3(0.0, 0.0, 0.0); // hardcoded world camera position\n vec3 worldNormal = normalize(vNormal * uCameraRotation);\n vec2 newTexCoor = mapTextureToNormal( worldNormal );\n vec4 texture = TEXTURE( environmentMapDiffused, newTexCoor );\n // this is to make the darker sections more dark\n // png and jpg usually flatten the brightness so it is to reverse that\n return mix(smoothstep(vec3(0.0), vec3(1.0), texture.xyz), vec3(0.0), metallic);\n}\n\nvec3 calculateImageSpecular( vec3 vNormal, vec3 vViewPosition ){\n vec3 worldCameraPosition = vec3(0.0, 0.0, 0.0);\n vec3 worldNormal = normalize(vNormal);\n vec3 lightDirection = normalize( vViewPosition - worldCameraPosition );\n vec3 R = reflect(lightDirection, worldNormal) * uCameraRotation;\n vec2 newTexCoor = mapTextureToNormal( R );\n#ifdef WEBGL2\n vec4 outColor = textureLod(environmentMapSpecular, newTexCoor, levelOfDetail);\n#else\n vec4 outColor = TEXTURE(environmentMapSpecular, newTexCoor);\n#endif\n // this is to make the darker sections more dark\n // png and jpg usually flatten the brightness so it is to reverse that\n return mix(\n pow(outColor.xyz, vec3(10)),\n pow(outColor.xyz, vec3(1.2)),\n metallic \n );\n}\n\nvoid totalLight(\n vec3 modelPosition,\n vec3 normal,\n out vec3 totalDiffuse,\n out vec3 totalSpecular\n) {\n\n totalSpecular = vec3(0.0);\n\n if (!uUseLighting) {\n totalDiffuse = vec3(1.0);\n return;\n }\n\n totalDiffuse = vec3(0.0);\n\n vec3 viewDirection = normalize(-modelPosition);\n\n for (int j = 0; j < 5; j++) {\n if (j < uDirectionalLightCount) {\n vec3 lightVector = (uViewMatrix * vec4(uLightingDirection[j], 0.0)).xyz;\n vec3 lightColor = uDirectionalDiffuseColors[j];\n vec3 specularColor = uDirectionalSpecularColors[j];\n LightResult result = _light(viewDirection, normal, lightVector);\n totalDiffuse += result.diffuse * lightColor;\n totalSpecular += result.specular * lightColor * specularColor;\n }\n\n if (j < uPointLightCount) {\n vec3 lightPosition = (uViewMatrix * vec4(uPointLightLocation[j], 1.0)).xyz;\n vec3 lightVector = modelPosition - lightPosition;\n //calculate attenuation\n float lightDistance = length(lightVector);\n float lightFalloff = 1.0 / (uConstantAttenuation + lightDistance * uLinearAttenuation + (lightDistance * lightDistance) * uQuadraticAttenuation);\n vec3 lightColor = lightFalloff * uPointLightDiffuseColors[j];\n vec3 specularColor = lightFalloff * uPointLightSpecularColors[j];\n\n LightResult result = _light(viewDirection, normal, lightVector);\n totalDiffuse += result.diffuse * lightColor;\n totalSpecular += result.specular * lightColor * specularColor;\n }\n\n if(j < uSpotLightCount) {\n vec3 lightPosition = (uViewMatrix * vec4(uSpotLightLocation[j], 1.0)).xyz;\n vec3 lightVector = modelPosition - lightPosition;\n \n float lightDistance = length(lightVector);\n float lightFalloff = 1.0 / (uConstantAttenuation + lightDistance * uLinearAttenuation + (lightDistance * lightDistance) * uQuadraticAttenuation);\n\n vec3 lightDirection = (uViewMatrix * vec4(uSpotLightDirection[j], 0.0)).xyz;\n float spotDot = dot(normalize(lightVector), normalize(lightDirection));\n float spotFalloff;\n if(spotDot < uSpotLightAngle[j]) {\n spotFalloff = 0.0;\n }\n else {\n spotFalloff = pow(spotDot, uSpotLightConc[j]);\n }\n lightFalloff *= spotFalloff;\n\n vec3 lightColor = uSpotLightDiffuseColors[j];\n vec3 specularColor = uSpotLightSpecularColors[j];\n \n LightResult result = _light(viewDirection, normal, lightVector);\n \n totalDiffuse += result.diffuse * lightColor * lightFalloff;\n totalSpecular += result.specular * lightColor * specularColor * lightFalloff;\n }\n }\n\n if( uUseImageLight ){\n totalDiffuse += calculateImageDiffuse(normal, modelPosition);\n totalSpecular += calculateImageSpecular(normal, modelPosition);\n }\n\n totalDiffuse *= diffuseFactor;\n totalSpecular *= specularFactor;\n}\n'; var webgl2CompatibilityShader = '#ifdef WEBGL2\n\n#define IN in\n#define OUT out\n\n#ifdef FRAGMENT_SHADER\nout vec4 outColor;\n#define OUT_COLOR outColor\n#endif\n#define TEXTURE texture\n\n#else\n\n#ifdef FRAGMENT_SHADER\n#define IN varying\n#else\n#define IN attribute\n#endif\n#define OUT varying\n#define TEXTURE texture2D\n\n#ifdef FRAGMENT_SHADER\n#define OUT_COLOR gl_FragColor\n#endif\n\n#endif\n'; var defaultShaders = { + sphereMappingFrag: '#define PI 3.141592\n\nprecision highp float;\n \nuniform sampler2D uSampler;\nuniform mat3 uNewNormalMatrix;\nuniform float uFovY;\nuniform float uAspect;\n\nvarying vec2 vTexCoord;\n \nvoid main() {\n float uFovX = uFovY * uAspect; \n vec4 newTexColor = texture2D(uSampler, vTexCoord);\n float angleY = mix(uFovY/2.0, -uFovY/2.0, vTexCoord.y);\n float angleX = mix(uFovX/2.0, -uFovX/2.0, vTexCoord.x);\n vec3 rotatedNormal = vec3( angleX, angleY, 1.0 );\n rotatedNormal = uNewNormalMatrix * normalize(rotatedNormal);\n vec2 suv;\n suv.y = 0.5 + 0.5 * (-rotatedNormal.y);\n suv.x = atan(rotatedNormal.z, rotatedNormal.x) / (2.0 * PI) + 0.5;\n newTexColor = texture2D(uSampler, suv.xy);\n gl_FragColor = newTexColor;\n}\n', immediateVert: 'IN vec3 aPosition;\nIN vec4 aVertexColor;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform float uResolution;\nuniform float uPointSize;\n\nOUT vec4 vColor;\nvoid main(void) {\n vec4 positionVec4 = vec4(aPosition, 1.0);\n gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n vColor = aVertexColor;\n gl_PointSize = uPointSize;\n}\n', vertexColorVert: 'IN vec3 aPosition;\nIN vec4 aVertexColor;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\n\nOUT vec4 vColor;\n\nvoid main(void) {\n vec4 positionVec4 = vec4(aPosition, 1.0);\n gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n vColor = aVertexColor;\n}\n', vertexColorFrag: 'IN vec4 vColor;\nvoid main(void) {\n OUT_COLOR = vec4(vColor.rgb, 1.) * vColor.a;\n}\n', @@ -116586,14 +139986,15 @@ phongFrag: lightingShader + '// include lighting.glsl\nprecision highp int;\n\nuniform bool uHasSetAmbient;\nuniform vec4 uSpecularMatColor;\nuniform vec4 uAmbientMatColor;\nuniform vec4 uEmissiveMatColor;\n\nuniform vec4 uTint;\nuniform sampler2D uSampler;\nuniform bool isTexture;\n\nIN vec3 vNormal;\nIN vec2 vTexCoord;\nIN vec3 vViewPosition;\nIN vec3 vAmbientColor;\nIN vec4 vColor;\n\nvoid main(void) {\n\n vec3 diffuse;\n vec3 specular;\n totalLight(vViewPosition, normalize(vNormal), diffuse, specular);\n\n // Calculating final color as result of all lights (plus emissive term).\n\n vec4 baseColor = isTexture\n // Textures come in with premultiplied alpha. To apply tint and still have\n // premultiplied alpha output, we need to multiply the RGB channels by the\n // tint RGB, and all channels by the tint alpha.\n ? TEXTURE(uSampler, vTexCoord) * vec4(uTint.rgb/255., 1.) * (uTint.a/255.)\n // Colors come in with unmultiplied alpha, so we need to multiply the RGB\n // channels by alpha to convert it to premultiplied alpha.\n : vec4(vColor.rgb * vColor.a, vColor.a);\n OUT_COLOR = vec4(diffuse * baseColor.rgb + \n vAmbientColor * (\n uHasSetAmbient ? uAmbientMatColor.rgb : baseColor.rgb\n ) + \n specular * uSpecularMatColor.rgb + \n uEmissiveMatColor.rgb, baseColor.a);\n}\n', fontVert: 'IN vec3 aPosition;\nIN vec2 aTexCoord;\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\n\nuniform vec4 uGlyphRect;\nuniform float uGlyphOffset;\n\nOUT vec2 vTexCoord;\nOUT float w;\n\nvoid main() {\n vec4 positionVec4 = vec4(aPosition, 1.0);\n\n // scale by the size of the glyph\'s rectangle\n positionVec4.xy *= uGlyphRect.zw - uGlyphRect.xy;\n\n // Expand glyph bounding boxes by 1px on each side to give a bit of room\n // for antialiasing\n vec3 newOrigin = (uModelViewMatrix * vec4(0., 0., 0., 1.)).xyz;\n vec3 newDX = (uModelViewMatrix * vec4(1., 0., 0., 1.)).xyz;\n vec3 newDY = (uModelViewMatrix * vec4(0., 1., 0., 1.)).xyz;\n vec2 pixelScale = vec2(\n 1. / length(newOrigin - newDX),\n 1. / length(newOrigin - newDY)\n );\n vec2 offset = pixelScale * normalize(aTexCoord - vec2(0.5, 0.5)) * vec2(1., -1.);\n vec2 textureOffset = offset * (1. / vec2(\n uGlyphRect.z - uGlyphRect.x,\n uGlyphRect.w - uGlyphRect.y\n ));\n\n // move to the corner of the glyph\n positionVec4.xy += uGlyphRect.xy;\n\n // move to the letter\'s line offset\n positionVec4.x += uGlyphOffset;\n\n positionVec4.xy += offset;\n \n gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n vTexCoord = aTexCoord + textureOffset;\n w = gl_Position.w;\n}\n', fontFrag: '#ifndef WEBGL2\n#extension GL_OES_standard_derivatives : enable\n#endif\n\n#if 0\n // simulate integer math using floats\n\t#define int float\n\t#define ivec2 vec2\n\t#define INT(x) float(x)\n\n\tint ifloor(float v) { return floor(v); }\n\tivec2 ifloor(vec2 v) { return floor(v); }\n\n#else\n // use native integer math\n\tprecision highp int;\n\t#define INT(x) x\n\n\tint ifloor(float v) { return int(v); }\n\tint ifloor(int v) { return v; }\n\tivec2 ifloor(vec2 v) { return ivec2(v); }\n\n#endif\n\nuniform sampler2D uSamplerStrokes;\nuniform sampler2D uSamplerRowStrokes;\nuniform sampler2D uSamplerRows;\nuniform sampler2D uSamplerColStrokes;\nuniform sampler2D uSamplerCols;\n\nuniform ivec2 uStrokeImageSize;\nuniform ivec2 uCellsImageSize;\nuniform ivec2 uGridImageSize;\n\nuniform ivec2 uGridOffset;\nuniform ivec2 uGridSize;\nuniform vec4 uMaterialColor;\n\nIN vec2 vTexCoord;\n\n// some helper functions\nint ROUND(float v) { return ifloor(v + 0.5); }\nivec2 ROUND(vec2 v) { return ifloor(v + 0.5); }\nfloat saturate(float v) { return clamp(v, 0.0, 1.0); }\nvec2 saturate(vec2 v) { return clamp(v, 0.0, 1.0); }\n\nint mul(float v1, int v2) {\n return ifloor(v1 * float(v2));\n}\n\nivec2 mul(vec2 v1, ivec2 v2) {\n return ifloor(v1 * vec2(v2) + 0.5);\n}\n\n// unpack a 16-bit integer from a float vec2\nint getInt16(vec2 v) {\n ivec2 iv = ROUND(v * 255.0);\n return iv.x * INT(128) + iv.y;\n}\n\nvec2 pixelScale;\nvec2 coverage = vec2(0.0);\nvec2 weight = vec2(0.5);\nconst float minDistance = 1.0/8192.0;\nconst float hardness = 1.05; // amount of antialias\n\n// the maximum number of curves in a glyph\nconst int N = INT(250);\n\n// retrieves an indexed pixel from a sampler\nvec4 getTexel(sampler2D sampler, int pos, ivec2 size) {\n int width = size.x;\n int y = ifloor(pos / width);\n int x = pos - y * width; // pos % width\n\n return TEXTURE(sampler, (vec2(x, y) + 0.5) / vec2(size));\n}\n\nvoid calulateCrossings(vec2 p0, vec2 p1, vec2 p2, out vec2 C1, out vec2 C2) {\n\n // get the coefficients of the quadratic in t\n vec2 a = p0 - p1 * 2.0 + p2;\n vec2 b = p0 - p1;\n vec2 c = p0 - vTexCoord;\n\n // found out which values of \'t\' it crosses the axes\n vec2 surd = sqrt(max(vec2(0.0), b * b - a * c));\n vec2 t1 = ((b - surd) / a).yx;\n vec2 t2 = ((b + surd) / a).yx;\n\n // approximate straight lines to avoid rounding errors\n if (abs(a.y) < 0.001)\n t1.x = t2.x = c.y / (2.0 * b.y);\n\n if (abs(a.x) < 0.001)\n t1.y = t2.y = c.x / (2.0 * b.x);\n\n // plug into quadratic formula to find the corrdinates of the crossings\n C1 = ((a * t1 - b * 2.0) * t1 + c) * pixelScale;\n C2 = ((a * t2 - b * 2.0) * t2 + c) * pixelScale;\n}\n\nvoid coverageX(vec2 p0, vec2 p1, vec2 p2) {\n\n vec2 C1, C2;\n calulateCrossings(p0, p1, p2, C1, C2);\n\n // determine on which side of the x-axis the points lie\n bool y0 = p0.y > vTexCoord.y;\n bool y1 = p1.y > vTexCoord.y;\n bool y2 = p2.y > vTexCoord.y;\n\n // could web be under the curve (after t1)?\n if (y1 ? !y2 : y0) {\n // add the coverage for t1\n coverage.x += saturate(C1.x + 0.5);\n // calculate the anti-aliasing for t1\n weight.x = min(weight.x, abs(C1.x));\n }\n\n // are we outside the curve (after t2)?\n if (y1 ? !y0 : y2) {\n // subtract the coverage for t2\n coverage.x -= saturate(C2.x + 0.5);\n // calculate the anti-aliasing for t2\n weight.x = min(weight.x, abs(C2.x));\n }\n}\n\n// this is essentially the same as coverageX, but with the axes swapped\nvoid coverageY(vec2 p0, vec2 p1, vec2 p2) {\n\n vec2 C1, C2;\n calulateCrossings(p0, p1, p2, C1, C2);\n\n bool x0 = p0.x > vTexCoord.x;\n bool x1 = p1.x > vTexCoord.x;\n bool x2 = p2.x > vTexCoord.x;\n\n if (x1 ? !x2 : x0) {\n coverage.y -= saturate(C1.y + 0.5);\n weight.y = min(weight.y, abs(C1.y));\n }\n\n if (x1 ? !x0 : x2) {\n coverage.y += saturate(C2.y + 0.5);\n weight.y = min(weight.y, abs(C2.y));\n }\n}\n\nvoid main() {\n\n // calculate the pixel scale based on screen-coordinates\n pixelScale = hardness / fwidth(vTexCoord);\n\n // which grid cell is this pixel in?\n ivec2 gridCoord = ifloor(vTexCoord * vec2(uGridSize));\n\n // intersect curves in this row\n {\n // the index into the row info bitmap\n int rowIndex = gridCoord.y + uGridOffset.y;\n // fetch the info texel\n vec4 rowInfo = getTexel(uSamplerRows, rowIndex, uGridImageSize);\n // unpack the rowInfo\n int rowStrokeIndex = getInt16(rowInfo.xy);\n int rowStrokeCount = getInt16(rowInfo.zw);\n\n for (int iRowStroke = INT(0); iRowStroke < N; iRowStroke++) {\n if (iRowStroke >= rowStrokeCount)\n break;\n\n // each stroke is made up of 3 points: the start and control point\n // and the start of the next curve.\n // fetch the indices of this pair of strokes:\n vec4 strokeIndices = getTexel(uSamplerRowStrokes, rowStrokeIndex++, uCellsImageSize);\n\n // unpack the stroke index\n int strokePos = getInt16(strokeIndices.xy);\n\n // fetch the two strokes\n vec4 stroke0 = getTexel(uSamplerStrokes, strokePos + INT(0), uStrokeImageSize);\n vec4 stroke1 = getTexel(uSamplerStrokes, strokePos + INT(1), uStrokeImageSize);\n\n // calculate the coverage\n coverageX(stroke0.xy, stroke0.zw, stroke1.xy);\n }\n }\n\n // intersect curves in this column\n {\n int colIndex = gridCoord.x + uGridOffset.x;\n vec4 colInfo = getTexel(uSamplerCols, colIndex, uGridImageSize);\n int colStrokeIndex = getInt16(colInfo.xy);\n int colStrokeCount = getInt16(colInfo.zw);\n \n for (int iColStroke = INT(0); iColStroke < N; iColStroke++) {\n if (iColStroke >= colStrokeCount)\n break;\n\n vec4 strokeIndices = getTexel(uSamplerColStrokes, colStrokeIndex++, uCellsImageSize);\n\n int strokePos = getInt16(strokeIndices.xy);\n vec4 stroke0 = getTexel(uSamplerStrokes, strokePos + INT(0), uStrokeImageSize);\n vec4 stroke1 = getTexel(uSamplerStrokes, strokePos + INT(1), uStrokeImageSize);\n coverageY(stroke0.xy, stroke0.zw, stroke1.xy);\n }\n }\n\n weight = saturate(1.0 - weight * 2.0);\n float distance = max(weight.x + weight.y, minDistance); // manhattan approx.\n float antialias = abs(dot(coverage, weight) / distance);\n float cover = min(abs(coverage.x), abs(coverage.y));\n OUT_COLOR = vec4(uMaterialColor.rgb, 1.) * uMaterialColor.a;\n OUT_COLOR *= saturate(max(antialias, cover));\n}\n', - lineVert: lineDefs + '/*\n Part of the Processing project - http://processing.org\n Copyright (c) 2012-15 The Processing Foundation\n Copyright (c) 2004-12 Ben Fry and Casey Reas\n Copyright (c) 2001-04 Massachusetts Institute of Technology\n This library is free software; you can redistribute it and/or\n modify it under the terms of the GNU Lesser General Public\n License as published by the Free Software Foundation, version 2.1.\n This library is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n Lesser General Public License for more details.\n You should have received a copy of the GNU Lesser General\n Public License along with this library; if not, write to the\n Free Software Foundation, Inc., 59 Temple Place, Suite 330,\n Boston, MA 02111-1307 USA\n*/\n\n#define PROCESSING_LINE_SHADER\n\nprecision mediump int;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform float uStrokeWeight;\n\nuniform bool uUseLineColor;\nuniform vec4 uMaterialColor;\n\nuniform vec4 uViewport;\nuniform int uPerspective;\nuniform int uStrokeJoin;\n\nIN vec4 aPosition;\nIN vec3 aTangentIn;\nIN vec3 aTangentOut;\nIN float aSide;\nIN vec4 aVertexColor;\n\nOUT vec4 vColor;\nOUT vec2 vTangent;\nOUT vec2 vCenter;\nOUT vec2 vPosition;\nOUT float vMaxDist;\nOUT float vCap;\nOUT float vJoin;\n\nvec2 lineIntersection(vec2 aPoint, vec2 aDir, vec2 bPoint, vec2 bDir) {\n // Rotate and translate so a starts at the origin and goes out to the right\n bPoint -= aPoint;\n vec2 rotatedBFrom = vec2(\n bPoint.x*aDir.x + bPoint.y*aDir.y,\n bPoint.y*aDir.x - bPoint.x*aDir.y\n );\n vec2 bTo = bPoint + bDir;\n vec2 rotatedBTo = vec2(\n bTo.x*aDir.x + bTo.y*aDir.y,\n bTo.y*aDir.x - bTo.x*aDir.y\n );\n float intersectionDistance =\n rotatedBTo.x + (rotatedBFrom.x - rotatedBTo.x) * rotatedBTo.y /\n (rotatedBTo.y - rotatedBFrom.y);\n return aPoint + aDir * intersectionDistance;\n}\n\nvoid main() {\n // Caps have one of either the in or out tangent set to 0\n vCap = (aTangentIn == vec3(0.)) != (aTangentOut == (vec3(0.)))\n ? 1. : 0.;\n\n // Joins have two unique, defined tangents\n vJoin = (\n aTangentIn != vec3(0.) &&\n aTangentOut != vec3(0.) &&\n aTangentIn != aTangentOut\n ) ? 1. : 0.;\n\n vec4 posp = uModelViewMatrix * aPosition;\n vec4 posqIn = uModelViewMatrix * (aPosition + vec4(aTangentIn, 0));\n vec4 posqOut = uModelViewMatrix * (aPosition + vec4(aTangentOut, 0));\n\n float facingCamera = pow(\n // The word space tangent\'s z value is 0 if it\'s facing the camera\n abs(normalize(posqIn-posp).z),\n\n // Using pow() here to ramp `facingCamera` up from 0 to 1 really quickly\n // so most lines get scaled and don\'t get clipped\n 0.25\n );\n\n // using a scale <1 moves the lines towards the camera\n // in order to prevent popping effects due to half of\n // the line disappearing behind the geometry faces.\n float scale = mix(1., 0.995, facingCamera);\n\n // Moving vertices slightly toward the camera\n // to avoid depth-fighting with the fill triangles.\n // Discussed here:\n // http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=252848 \n posp.xyz = posp.xyz * scale;\n posqIn.xyz = posqIn.xyz * scale;\n posqOut.xyz = posqOut.xyz * scale;\n\n vec4 p = uProjectionMatrix * posp;\n vec4 qIn = uProjectionMatrix * posqIn;\n vec4 qOut = uProjectionMatrix * posqOut;\n vCenter = p.xy;\n\n // formula to convert from clip space (range -1..1) to screen space (range 0..[width or height])\n // screen_p = (p.xy/p.w + <1,1>) * 0.5 * uViewport.zw\n\n // prevent division by W by transforming the tangent formula (div by 0 causes\n // the line to disappear, see https://github.com/processing/processing/issues/5183)\n // t = screen_q - screen_p\n //\n // tangent is normalized and we don\'t care which aDirection it points to (+-)\n // t = +- normalize( screen_q - screen_p )\n // t = +- normalize( (q.xy/q.w+<1,1>)*0.5*uViewport.zw - (p.xy/p.w+<1,1>)*0.5*uViewport.zw )\n //\n // extract common factor, <1,1> - <1,1> cancels out\n // t = +- normalize( (q.xy/q.w - p.xy/p.w) * 0.5 * uViewport.zw )\n //\n // convert to common divisor\n // t = +- normalize( ((q.xy*p.w - p.xy*q.w) / (p.w*q.w)) * 0.5 * uViewport.zw )\n //\n // remove the common scalar divisor/factor, not needed due to normalize and +-\n // (keep uViewport - can\'t remove because it has different components for x and y\n // and corrects for aspect ratio, see https://github.com/processing/processing/issues/5181)\n // t = +- normalize( (q.xy*p.w - p.xy*q.w) * uViewport.zw )\n\n vec2 tangentIn = normalize((qIn.xy*p.w - p.xy*qIn.w) * uViewport.zw);\n vec2 tangentOut = normalize((qOut.xy*p.w - p.xy*qOut.w) * uViewport.zw);\n\n vec2 curPerspScale;\n if(uPerspective == 1) {\n // Perspective ---\n // convert from world to clip by multiplying with projection scaling factor\n // to get the right thickness (see https://github.com/processing/processing/issues/5182)\n\n // The y value of the projection matrix may be flipped if rendering to a Framebuffer.\n // Multiplying again by its sign here negates the flip to get just the scale.\n curPerspScale = (uProjectionMatrix * vec4(1, sign(uProjectionMatrix[1][1]), 0, 0)).xy;\n } else {\n // No Perspective ---\n // multiply by W (to cancel out division by W later in the pipeline) and\n // convert from screen to clip (derived from clip to screen above)\n curPerspScale = p.w / (0.5 * uViewport.zw);\n }\n\n vec2 offset;\n if (vJoin == 1.) {\n vTangent = normalize(tangentIn + tangentOut);\n vec2 normalIn = vec2(-tangentIn.y, tangentIn.x);\n vec2 normalOut = vec2(-tangentOut.y, tangentOut.x);\n float side = sign(aSide);\n float sideEnum = abs(aSide);\n\n // We generate vertices for joins on either side of the centerline, but\n // the "elbow" side is the only one needing a join. By not setting the\n // offset for the other side, all its vertices will end up in the same\n // spot and not render, effectively discarding it.\n if (sign(dot(tangentOut, vec2(-tangentIn.y, tangentIn.x))) != side) {\n // Side enums:\n // 1: the side going into the join\n // 2: the middle of the join\n // 3: the side going out of the join\n if (sideEnum == 2.) {\n // Calculate the position + tangent on either side of the join, and\n // find where the lines intersect to find the elbow of the join\n vec2 c = (posp.xy/posp.w + vec2(1.,1.)) * 0.5 * uViewport.zw;\n vec2 intersection = lineIntersection(\n c + (side * normalIn * uStrokeWeight / 2.),\n tangentIn,\n c + (side * normalOut * uStrokeWeight / 2.),\n tangentOut\n );\n offset = (intersection - c);\n\n // When lines are thick and the angle of the join approaches 180, the\n // elbow might be really far from the center. We\'ll apply a limit to\n // the magnitude to avoid lines going across the whole screen when this\n // happens.\n float mag = length(offset);\n float maxMag = 3. * uStrokeWeight;\n if (mag > maxMag) {\n offset *= maxMag / mag;\n }\n } else if (sideEnum == 1.) {\n offset = side * normalIn * uStrokeWeight / 2.;\n } else if (sideEnum == 3.) {\n offset = side * normalOut * uStrokeWeight / 2.;\n }\n }\n if (uStrokeJoin == STROKE_JOIN_BEVEL) {\n vec2 avgNormal = vec2(-vTangent.y, vTangent.x);\n vMaxDist = abs(dot(avgNormal, normalIn * uStrokeWeight / 2.));\n } else {\n vMaxDist = uStrokeWeight / 2.;\n }\n } else {\n vec2 tangent = aTangentIn == vec3(0.) ? tangentOut : tangentIn;\n vTangent = tangent;\n vec2 normal = vec2(-tangent.y, tangent.x);\n\n float normalOffset = sign(aSide);\n // Caps will have side values of -2 or 2 on the edge of the cap that\n // extends out from the line\n float tangentOffset = abs(aSide) - 1.;\n offset = (normal * normalOffset + tangent * tangentOffset) *\n uStrokeWeight * 0.5;\n vMaxDist = uStrokeWeight / 2.;\n }\n vPosition = vCenter + offset;\n\n gl_Position.xy = p.xy + offset.xy * curPerspScale;\n gl_Position.zw = p.zw;\n \n vColor = (uUseLineColor ? aVertexColor : uMaterialColor);\n}\n', + lineVert: lineDefs + '/*\n Part of the Processing project - http://processing.org\n Copyright (c) 2012-15 The Processing Foundation\n Copyright (c) 2004-12 Ben Fry and Casey Reas\n Copyright (c) 2001-04 Massachusetts Institute of Technology\n This library is free software; you can redistribute it and/or\n modify it under the terms of the GNU Lesser General Public\n License as published by the Free Software Foundation, version 2.1.\n This library is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n Lesser General Public License for more details.\n You should have received a copy of the GNU Lesser General\n Public License along with this library; if not, write to the\n Free Software Foundation, Inc., 59 Temple Place, Suite 330,\n Boston, MA 02111-1307 USA\n*/\n\n#define PROCESSING_LINE_SHADER\n\nprecision mediump int;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform float uStrokeWeight;\n\nuniform bool uUseLineColor;\nuniform vec4 uMaterialColor;\n\nuniform vec4 uViewport;\nuniform int uPerspective;\nuniform int uStrokeJoin;\n\nIN vec4 aPosition;\nIN vec3 aTangentIn;\nIN vec3 aTangentOut;\nIN float aSide;\nIN vec4 aVertexColor;\n\nOUT vec4 vColor;\nOUT vec2 vTangent;\nOUT vec2 vCenter;\nOUT vec2 vPosition;\nOUT float vMaxDist;\nOUT float vCap;\nOUT float vJoin;\n\nvec2 lineIntersection(vec2 aPoint, vec2 aDir, vec2 bPoint, vec2 bDir) {\n // Rotate and translate so a starts at the origin and goes out to the right\n bPoint -= aPoint;\n vec2 rotatedBFrom = vec2(\n bPoint.x*aDir.x + bPoint.y*aDir.y,\n bPoint.y*aDir.x - bPoint.x*aDir.y\n );\n vec2 bTo = bPoint + bDir;\n vec2 rotatedBTo = vec2(\n bTo.x*aDir.x + bTo.y*aDir.y,\n bTo.y*aDir.x - bTo.x*aDir.y\n );\n float intersectionDistance =\n rotatedBTo.x + (rotatedBFrom.x - rotatedBTo.x) * rotatedBTo.y /\n (rotatedBTo.y - rotatedBFrom.y);\n return aPoint + aDir * intersectionDistance;\n}\n\nvoid main() {\n // Caps have one of either the in or out tangent set to 0\n vCap = (aTangentIn == vec3(0.)) != (aTangentOut == (vec3(0.)))\n ? 1. : 0.;\n\n // Joins have two unique, defined tangents\n vJoin = (\n aTangentIn != vec3(0.) &&\n aTangentOut != vec3(0.) &&\n aTangentIn != aTangentOut\n ) ? 1. : 0.;\n\n vec4 posp = uModelViewMatrix * aPosition;\n vec4 posqIn = uModelViewMatrix * (aPosition + vec4(aTangentIn, 0));\n vec4 posqOut = uModelViewMatrix * (aPosition + vec4(aTangentOut, 0));\n\n float facingCamera = pow(\n // The word space tangent\'s z value is 0 if it\'s facing the camera\n abs(normalize(posqIn-posp).z),\n\n // Using pow() here to ramp `facingCamera` up from 0 to 1 really quickly\n // so most lines get scaled and don\'t get clipped\n 0.25\n );\n\n // Moving vertices slightly toward the camera\n // to avoid depth-fighting with the fill triangles.\n // This prevents popping effects due to half of\n // the line disappearing behind the geometry faces.\n \n float zOffset = mix(-0.00045, -1., facingCamera);\n posp.z -= zOffset;\n posqIn.z -= zOffset;\n posqOut.z -= zOffset;\n \n vec4 p = uProjectionMatrix * posp;\n vec4 qIn = uProjectionMatrix * posqIn;\n vec4 qOut = uProjectionMatrix * posqOut;\n vCenter = p.xy;\n\n // formula to convert from clip space (range -1..1) to screen space (range 0..[width or height])\n // screen_p = (p.xy/p.w + <1,1>) * 0.5 * uViewport.zw\n\n // prevent division by W by transforming the tangent formula (div by 0 causes\n // the line to disappear, see https://github.com/processing/processing/issues/5183)\n // t = screen_q - screen_p\n //\n // tangent is normalized and we don\'t care which aDirection it points to (+-)\n // t = +- normalize( screen_q - screen_p )\n // t = +- normalize( (q.xy/q.w+<1,1>)*0.5*uViewport.zw - (p.xy/p.w+<1,1>)*0.5*uViewport.zw )\n //\n // extract common factor, <1,1> - <1,1> cancels out\n // t = +- normalize( (q.xy/q.w - p.xy/p.w) * 0.5 * uViewport.zw )\n //\n // convert to common divisor\n // t = +- normalize( ((q.xy*p.w - p.xy*q.w) / (p.w*q.w)) * 0.5 * uViewport.zw )\n //\n // remove the common scalar divisor/factor, not needed due to normalize and +-\n // (keep uViewport - can\'t remove because it has different components for x and y\n // and corrects for aspect ratio, see https://github.com/processing/processing/issues/5181)\n // t = +- normalize( (q.xy*p.w - p.xy*q.w) * uViewport.zw )\n\n vec2 tangentIn = normalize((qIn.xy*p.w - p.xy*qIn.w) * uViewport.zw);\n vec2 tangentOut = normalize((qOut.xy*p.w - p.xy*qOut.w) * uViewport.zw);\n\n vec2 curPerspScale;\n if(uPerspective == 1) {\n // Perspective ---\n // convert from world to clip by multiplying with projection scaling factor\n // to get the right thickness (see https://github.com/processing/processing/issues/5182)\n\n // The y value of the projection matrix may be flipped if rendering to a Framebuffer.\n // Multiplying again by its sign here negates the flip to get just the scale.\n curPerspScale = (uProjectionMatrix * vec4(1, sign(uProjectionMatrix[1][1]), 0, 0)).xy;\n } else {\n // No Perspective ---\n // multiply by W (to cancel out division by W later in the pipeline) and\n // convert from screen to clip (derived from clip to screen above)\n curPerspScale = p.w / (0.5 * uViewport.zw);\n }\n\n vec2 offset;\n if (vJoin == 1.) {\n vTangent = normalize(tangentIn + tangentOut);\n vec2 normalIn = vec2(-tangentIn.y, tangentIn.x);\n vec2 normalOut = vec2(-tangentOut.y, tangentOut.x);\n float side = sign(aSide);\n float sideEnum = abs(aSide);\n\n // We generate vertices for joins on either side of the centerline, but\n // the "elbow" side is the only one needing a join. By not setting the\n // offset for the other side, all its vertices will end up in the same\n // spot and not render, effectively discarding it.\n if (sign(dot(tangentOut, vec2(-tangentIn.y, tangentIn.x))) != side) {\n // Side enums:\n // 1: the side going into the join\n // 2: the middle of the join\n // 3: the side going out of the join\n if (sideEnum == 2.) {\n // Calculate the position + tangent on either side of the join, and\n // find where the lines intersect to find the elbow of the join\n vec2 c = (posp.xy/posp.w + vec2(1.,1.)) * 0.5 * uViewport.zw;\n vec2 intersection = lineIntersection(\n c + (side * normalIn * uStrokeWeight / 2.),\n tangentIn,\n c + (side * normalOut * uStrokeWeight / 2.),\n tangentOut\n );\n offset = (intersection - c);\n\n // When lines are thick and the angle of the join approaches 180, the\n // elbow might be really far from the center. We\'ll apply a limit to\n // the magnitude to avoid lines going across the whole screen when this\n // happens.\n float mag = length(offset);\n float maxMag = 3. * uStrokeWeight;\n if (mag > maxMag) {\n offset *= maxMag / mag;\n }\n } else if (sideEnum == 1.) {\n offset = side * normalIn * uStrokeWeight / 2.;\n } else if (sideEnum == 3.) {\n offset = side * normalOut * uStrokeWeight / 2.;\n }\n }\n if (uStrokeJoin == STROKE_JOIN_BEVEL) {\n vec2 avgNormal = vec2(-vTangent.y, vTangent.x);\n vMaxDist = abs(dot(avgNormal, normalIn * uStrokeWeight / 2.));\n } else {\n vMaxDist = uStrokeWeight / 2.;\n }\n } else {\n vec2 tangent = aTangentIn == vec3(0.) ? tangentOut : tangentIn;\n vTangent = tangent;\n vec2 normal = vec2(-tangent.y, tangent.x);\n\n float normalOffset = sign(aSide);\n // Caps will have side values of -2 or 2 on the edge of the cap that\n // extends out from the line\n float tangentOffset = abs(aSide) - 1.;\n offset = (normal * normalOffset + tangent * tangentOffset) *\n uStrokeWeight * 0.5;\n vMaxDist = uStrokeWeight / 2.;\n }\n vPosition = vCenter + offset;\n\n gl_Position.xy = p.xy + offset.xy * curPerspScale;\n gl_Position.zw = p.zw;\n \n vColor = (uUseLineColor ? aVertexColor : uMaterialColor);\n}\n', lineFrag: lineDefs + 'precision mediump int;\n\nuniform vec4 uMaterialColor;\nuniform int uStrokeCap;\nuniform int uStrokeJoin;\nuniform float uStrokeWeight;\n\nIN vec4 vColor;\nIN vec2 vTangent;\nIN vec2 vCenter;\nIN vec2 vPosition;\nIN float vMaxDist;\nIN float vCap;\nIN float vJoin;\n\nfloat distSquared(vec2 a, vec2 b) {\n vec2 aToB = b - a;\n return dot(aToB, aToB);\n}\n\nvoid main() {\n if (vCap > 0.) {\n if (\n uStrokeCap == STROKE_CAP_ROUND &&\n distSquared(vPosition, vCenter) > uStrokeWeight * uStrokeWeight * 0.25\n ) {\n discard;\n } else if (\n uStrokeCap == STROKE_CAP_SQUARE &&\n dot(vPosition - vCenter, vTangent) > 0.\n ) {\n discard;\n }\n // Use full area for PROJECT\n } else if (vJoin > 0.) {\n if (\n uStrokeJoin == STROKE_JOIN_ROUND &&\n distSquared(vPosition, vCenter) > uStrokeWeight * uStrokeWeight * 0.25\n ) {\n discard;\n } else if (uStrokeJoin == STROKE_JOIN_BEVEL) {\n vec2 normal = vec2(-vTangent.y, vTangent.x);\n if (abs(dot(vPosition - vCenter, normal)) > vMaxDist) {\n discard;\n }\n }\n // Use full area for MITER\n }\n OUT_COLOR = vec4(vColor.rgb, 1.) * vColor.a;\n}\n', pointVert: 'IN vec3 aPosition;\nuniform float uPointSize;\nOUT float vStrokeWeight;\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nvoid main() {\n\tvec4 positionVec4 = vec4(aPosition, 1.0);\n\tgl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n\tgl_PointSize = uPointSize;\n\tvStrokeWeight = uPointSize;\n}\n', pointFrag: 'precision mediump int;\nuniform vec4 uMaterialColor;\nIN float vStrokeWeight;\n\nvoid main(){\n float mask = 0.0;\n\n // make a circular mask using the gl_PointCoord (goes from 0 - 1 on a point)\n // might be able to get a nicer edge on big strokeweights with smoothstep but slightly less performant\n\n mask = step(0.98, length(gl_PointCoord * 2.0 - 1.0));\n\n // if strokeWeight is 1 or less lets just draw a square\n // this prevents weird artifacting from carving circles when our points are really small\n // if strokeWeight is larger than 1, we just use it as is\n\n mask = mix(0.0, mask, clamp(floor(vStrokeWeight - 0.5),0.0,1.0));\n\n // throw away the borders of the mask\n // otherwise we get weird alpha blending issues\n\n if(mask > 0.98){\n discard;\n }\n\n OUT_COLOR = vec4(uMaterialColor.rgb, 1.) * uMaterialColor.a;\n}\n', imageLightVert: 'precision highp float;\nattribute vec3 aPosition;\nattribute vec3 aNormal;\nattribute vec2 aTexCoord;\n\nvarying vec3 localPos;\nvarying vec3 vWorldNormal;\nvarying vec3 vWorldPosition;\nvarying vec2 vTexCoord;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform mat3 uNormalMatrix;\n\nvoid main() {\n // Multiply the position by the matrix.\n vec4 viewModelPosition = uModelViewMatrix * vec4(aPosition, 1.0);\n gl_Position = uProjectionMatrix * viewModelPosition; \n \n // orient the normals and pass to the fragment shader\n vWorldNormal = uNormalMatrix * aNormal;\n \n // send the view position to the fragment shader\n vWorldPosition = (uModelViewMatrix * vec4(aPosition, 1.0)).xyz;\n \n localPos = vWorldPosition;\n vTexCoord = aTexCoord;\n}\n\n\n/*\nin the vertex shader we\'ll compute the world position and world oriented normal of the vertices and pass those to the fragment shader as varyings.\n*/\n', - imageLightDiffusedFrag: 'precision highp float;\nvarying vec3 localPos;\n\n// the HDR cubemap converted (can be from an equirectangular environment map.)\nuniform sampler2D environmentMap;\nvarying vec2 vTexCoord;\n\nconst float PI = 3.14159265359;\n\nvec2 nTOE( vec3 v ){\n // x = r sin(phi) cos(theta) \n // y = r cos(phi) \n // z = r sin(phi) sin(theta)\n float phi = acos( v.y );\n // if phi is 0, then there are no x, z components\n float theta = 0.0;\n // else \n theta = acos(v.x / sin(phi));\n float sinTheta = v.z / sin(phi);\n if (sinTheta < 0.0) {\n // Turn it into -theta, but in the 0-2PI range\n theta = 2.0 * PI - theta;\n }\n theta = theta / (2.0 * 3.14159);\n phi = phi / 3.14159 ;\n \n vec2 angles = vec2( phi, theta );\n return angles;\n}\n\nvoid main()\n{ \t \n\t// the sample direction equals the hemisphere\'s orientation\n float phi = vTexCoord.x * 2.0 * PI;\n float theta = vTexCoord.y * PI;\n float x = sin(theta) * cos(phi);\n float y = sin(theta) * sin(phi);\n float z = cos(theta);\n vec3 normal = vec3( x, y, z);\n\n\t// Discretely sampling the hemisphere given the integral\'s\n // spherical coordinates translates to the following fragment code:\n\tvec3 irradiance = vec3(0.0); \n\tvec3 up\t= vec3(0.0, 1.0, 0.0);\n\tvec3 right = normalize(cross(up, normal));\n\tup = normalize(cross(normal, right));\n\n\t// We specify a fixed sampleDelta delta value to traverse\n // the hemisphere; decreasing or increasing the sample delta\n // will increase or decrease the accuracy respectively.\n\tconst float sampleDelta = 0.025;\n\tfloat nrSamples = 0.0;\n \n\tfor(float phi = 0.0; phi < 2.0 * PI; phi += sampleDelta)\n\t{\n for(float theta = 0.0; theta < ( 0.5 ) * PI; theta += sampleDelta)\n {\n // spherical to cartesian (in tangent space) // tangent space to world // add each sample result to irradiance\n float x = sin(theta) * cos(phi);\n float y = sin(theta) * sin(phi);\n float z = cos(theta);\n vec3 tangentSample = vec3( x, y, z);\n \n vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * normal;\n irradiance += (texture2D(environmentMap, nTOE(sampleVec)).xyz) * cos(theta) * sin(theta);\n nrSamples++;\n }\n\t}\n\t// divide by the total number of samples taken, giving us the average sampled irradiance.\n\tirradiance = PI * irradiance * (1.0 / float(nrSamples )) ;\n \n \n\tgl_FragColor = vec4(irradiance, 1.0);\n}', - imageLightSpecularFrag: 'precision highp float;\r\nvarying vec3 localPos;\r\nvarying vec2 vTexCoord;\r\n\r\n// our texture\r\nuniform sampler2D environmentMap;\r\nuniform float roughness;\r\n\r\nconst float PI = 3.14159265359;\r\n\r\nfloat VanDerCorput(int bits);\r\nvec2 HammersleyNoBitOps(int i, int N);\r\nvec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness);\r\n\r\n\r\nvec2 nTOE( vec3 v ){\r\n // x = r sin(phi) cos(theta) \r\n // y = r cos(phi) \r\n // z = r sin(phi) sin(theta)\r\n float phi = acos( v.y );\r\n // if phi is 0, then there are no x, z components\r\n float theta = 0.0;\r\n // else \r\n theta = acos(v.x / sin(phi));\r\n float sinTheta = v.z / sin(phi);\r\n if (sinTheta < 0.0) {\r\n // Turn it into -theta, but in the 0-2PI range\r\n theta = 2.0 * PI - theta;\r\n }\r\n theta = theta / (2.0 * 3.14159);\r\n phi = phi / 3.14159 ;\r\n \r\n vec2 angles = vec2( phi, theta );\r\n return angles;\r\n}\r\n\r\n\r\nvoid main(){\r\n const int SAMPLE_COUNT = 1024; // 4096\r\n float totalWeight = 0.0;\r\n vec3 prefilteredColor = vec3(0.0);\r\n float phi = vTexCoord.x * 2.0 * PI;\r\n float theta = vTexCoord.y * PI;\r\n float x = sin(theta) * cos(phi);\r\n float y = sin(theta) * sin(phi);\r\n float z = cos(theta);\r\n vec3 N = vec3(x,y,z);\r\n vec3 V = N;\r\n for (int i = 0; i < SAMPLE_COUNT; ++i)\r\n {\r\n vec2 Xi = HammersleyNoBitOps(i, SAMPLE_COUNT);\r\n vec3 H = ImportanceSampleGGX(Xi, N, roughness);\r\n vec3 L = normalize(2.0 * dot(V, H) * H - V);\r\n\r\n float NdotL = max(dot(N, L), 0.0);\r\n if (NdotL > 0.0)\r\n {\r\n prefilteredColor += texture2D(environmentMap, nTOE(L)).xyz * NdotL;\r\n totalWeight += NdotL;\r\n }\r\n }\r\n prefilteredColor = prefilteredColor / totalWeight;\r\n\r\n gl_FragColor = vec4(prefilteredColor, 1.0);\r\n}\r\n\r\nvec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness){\r\n float a = roughness * roughness;\r\n\r\n float phi = 2.0 * PI * Xi.x;\r\n float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y));\r\n float sinTheta = sqrt(1.0 - cosTheta * cosTheta);\r\n // from spherical coordinates to cartesian coordinates\r\n vec3 H;\r\n H.x = cos(phi) * sinTheta;\r\n H.y = sin(phi) * sinTheta;\r\n H.z = cosTheta;\r\n\r\n // from tangent-space vector to world-space sample vector\r\n vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);\r\n vec3 tangent = normalize(cross(up, N));\r\n vec3 bitangent = cross(N, tangent);\r\n\r\n vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;\r\n return normalize(sampleVec);\r\n}\r\n\r\n\r\nfloat VanDerCorput(int n, int base)\r\n{\r\n float invBase = 1.0 / float(base);\r\n float denom = 1.0;\r\n float result = 0.0;\r\n\r\n for (int i = 0; i < 32; ++i)\r\n {\r\n\tif (n > 0)\r\n\t{\r\n \tdenom = mod(float(n), 2.0);\r\n \tresult += denom * invBase;\r\n \tinvBase = invBase / 2.0;\r\n \tn = int(float(n) / 2.0);\r\n\t}\r\n }\r\n\r\n return result;\r\n}\r\n\r\nvec2 HammersleyNoBitOps(int i, int N)\r\n{\r\n return vec2(float(i) / float(N), VanDerCorput(i, 2));\r\n}\r\n' + imageLightDiffusedFrag: 'precision highp float;\nvarying vec3 localPos;\n\n// the HDR cubemap converted (can be from an equirectangular environment map.)\nuniform sampler2D environmentMap;\nvarying vec2 vTexCoord;\n\nconst float PI = 3.14159265359;\n\nvec2 nTOE( vec3 v ){\n // x = r sin(phi) cos(theta) \n // y = r cos(phi) \n // z = r sin(phi) sin(theta)\n float phi = acos( v.y );\n // if phi is 0, then there are no x, z components\n float theta = 0.0;\n // else \n theta = acos(v.x / sin(phi));\n float sinTheta = v.z / sin(phi);\n if (sinTheta < 0.0) {\n // Turn it into -theta, but in the 0-2PI range\n theta = 2.0 * PI - theta;\n }\n theta = theta / (2.0 * 3.14159);\n phi = phi / 3.14159 ;\n \n vec2 angles = vec2( phi, theta );\n return angles;\n}\n\nfloat random(vec2 p) {\n vec3 p3 = fract(vec3(p.xyx) * .1031);\n p3 += dot(p3, p3.yzx + 33.33);\n return fract((p3.x + p3.y) * p3.z);\n}\n\nvoid main()\n{ \t \n\t// the sample direction equals the hemisphere\'s orientation\n float phi = vTexCoord.x * 2.0 * PI;\n float theta = vTexCoord.y * PI;\n float x = sin(theta) * cos(phi);\n float y = sin(theta) * sin(phi);\n float z = cos(theta);\n vec3 normal = vec3( x, y, z);\n\n\t// Discretely sampling the hemisphere given the integral\'s\n // spherical coordinates translates to the following fragment code:\n\tvec3 irradiance = vec3(0.0); \n\tvec3 up\t= vec3(0.0, 1.0, 0.0);\n\tvec3 right = normalize(cross(up, normal));\n\tup = normalize(cross(normal, right));\n\n\t// We specify a fixed sampleDelta delta value to traverse\n // the hemisphere; decreasing or increasing the sample delta\n // will increase or decrease the accuracy respectively.\n\tconst float sampleDelta = 0.100;\n\tfloat nrSamples = 0.0;\n float randomOffset = random(gl_FragCoord.xy) * sampleDelta;\n\tfor(float rawPhi = 0.0; rawPhi < 2.0 * PI; rawPhi += sampleDelta)\n\t{\n float phi = rawPhi + randomOffset;\n for(float rawTheta = 0.0; rawTheta < ( 0.5 ) * PI; rawTheta += sampleDelta)\n {\n float theta = rawTheta + randomOffset;\n // spherical to cartesian (in tangent space) // tangent space to world // add each sample result to irradiance\n float x = sin(theta) * cos(phi);\n float y = sin(theta) * sin(phi);\n float z = cos(theta);\n vec3 tangentSample = vec3( x, y, z);\n \n vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * normal;\n irradiance += (texture2D(environmentMap, nTOE(sampleVec)).xyz) * cos(theta) * sin(theta);\n nrSamples++;\n }\n\t}\n\t// divide by the total number of samples taken, giving us the average sampled irradiance.\n\tirradiance = PI * irradiance * (1.0 / float(nrSamples )) ;\n \n \n\tgl_FragColor = vec4(irradiance, 1.0);\n}', + imageLightSpecularFrag: 'precision highp float;\r\nvarying vec3 localPos;\r\nvarying vec2 vTexCoord;\r\n\r\n// our texture\r\nuniform sampler2D environmentMap;\r\nuniform float roughness;\r\n\r\nconst float PI = 3.14159265359;\r\n\r\nfloat VanDerCorput(int bits);\r\nvec2 HammersleyNoBitOps(int i, int N);\r\nvec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness);\r\n\r\n\r\nvec2 nTOE( vec3 v ){\r\n // x = r sin(phi) cos(theta) \r\n // y = r cos(phi) \r\n // z = r sin(phi) sin(theta)\r\n float phi = acos( v.y );\r\n // if phi is 0, then there are no x, z components\r\n float theta = 0.0;\r\n // else \r\n theta = acos(v.x / sin(phi));\r\n float sinTheta = v.z / sin(phi);\r\n if (sinTheta < 0.0) {\r\n // Turn it into -theta, but in the 0-2PI range\r\n theta = 2.0 * PI - theta;\r\n }\r\n theta = theta / (2.0 * 3.14159);\r\n phi = phi / 3.14159 ;\r\n \r\n vec2 angles = vec2( phi, theta );\r\n return angles;\r\n}\r\n\r\n\r\nvoid main(){\r\n const int SAMPLE_COUNT = 400; // 4096\r\n int lowRoughnessLimit = int(pow(2.0,(roughness+0.1)*20.0));\r\n float totalWeight = 0.0;\r\n vec3 prefilteredColor = vec3(0.0);\r\n float phi = vTexCoord.x * 2.0 * PI;\r\n float theta = vTexCoord.y * PI;\r\n float x = sin(theta) * cos(phi);\r\n float y = sin(theta) * sin(phi);\r\n float z = cos(theta);\r\n vec3 N = vec3(x,y,z);\r\n vec3 V = N;\r\n for (int i = 0; i < SAMPLE_COUNT; ++i)\r\n {\r\n // break at smaller sample numbers for low roughness levels\r\n if(i == lowRoughnessLimit)\r\n {\r\n break;\r\n }\r\n vec2 Xi = HammersleyNoBitOps(i, SAMPLE_COUNT);\r\n vec3 H = ImportanceSampleGGX(Xi, N, roughness);\r\n vec3 L = normalize(2.0 * dot(V, H) * H - V);\r\n\r\n float NdotL = max(dot(N, L), 0.0);\r\n if (NdotL > 0.0)\r\n {\r\n prefilteredColor += texture2D(environmentMap, nTOE(L)).xyz * NdotL;\r\n totalWeight += NdotL;\r\n }\r\n }\r\n prefilteredColor = prefilteredColor / totalWeight;\r\n\r\n gl_FragColor = vec4(prefilteredColor, 1.0);\r\n}\r\n\r\nvec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness){\r\n float a = roughness * roughness;\r\n\r\n float phi = 2.0 * PI * Xi.x;\r\n float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y));\r\n float sinTheta = sqrt(1.0 - cosTheta * cosTheta);\r\n // from spherical coordinates to cartesian coordinates\r\n vec3 H;\r\n H.x = cos(phi) * sinTheta;\r\n H.y = sin(phi) * sinTheta;\r\n H.z = cosTheta;\r\n\r\n // from tangent-space vector to world-space sample vector\r\n vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);\r\n vec3 tangent = normalize(cross(up, N));\r\n vec3 bitangent = cross(N, tangent);\r\n\r\n vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;\r\n return normalize(sampleVec);\r\n}\r\n\r\n\r\nfloat VanDerCorput(int n, int base)\r\n{\r\n#ifdef WEBGL2\r\n\r\n uint bits = uint(n);\r\n bits = (bits << 16u) | (bits >> 16u);\r\n bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);\r\n bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);\r\n bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);\r\n bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);\r\n return float(bits) * 2.3283064365386963e-10; // / 0x100000000\r\n\r\n#else\r\n\r\n float invBase = 1.0 / float(base);\r\n float denom = 1.0;\r\n float result = 0.0;\r\n\r\n\r\n for (int i = 0; i < 32; ++i)\r\n {\r\n if (n > 0)\r\n {\r\n denom = mod(float(n), 2.0);\r\n result += denom * invBase;\r\n invBase = invBase / 2.0;\r\n n = int(float(n) / 2.0);\r\n }\r\n }\r\n\r\n\r\n return result;\r\n\r\n#endif\r\n}\r\n\r\nvec2 HammersleyNoBitOps(int i, int N)\r\n{\r\n return vec2(float(i) / float(N), VanDerCorput(i, 2));\r\n}\r\n' }; + var sphereMapping = defaultShaders.sphereMappingFrag; for (var key in defaultShaders) { defaultShaders[key] = webgl2CompatibilityShader + defaultShaders[key]; } @@ -116902,6 +140303,10 @@ _this._enableLighting = false; _this.ambientLightColors = [ ]; + _this.mixedAmbientLight = [ + ]; + _this.mixedSpecularColor = [ + ]; _this.specularColors = [ 1, 1, @@ -116938,10 +140343,10 @@ _this.activeImageLight = null; // If activeImageLight property is Null, diffusedTextures, // specularTextures are Empty. - // Else, it maps a p5.Image used by imageLight() to a p5.Graphics. - // p5.Graphics for this are calculated in getDiffusedTexture function + // Else, it maps a p5.Image used by imageLight() to a p5.framebuffer. + // p5.framebuffer for this are calculated in getDiffusedTexture function _this.diffusedTextures = new Map(); - // p5.Graphics for this are calculated in getSpecularTexture function + // p5.framebuffer for this are calculated in getSpecularTexture function _this.specularTextures = new Map(); _this.drawMode = constants.FILL; _this.curFillColor = _this._cachedFillStyle = [ @@ -116975,6 +140380,7 @@ 1 ]; _this.curBlendMode = constants.BLEND; + _this.preEraseBlend = undefined; _this._cachedBlendMode = undefined; if (_this.webglVersion === constants.WEBGL2) { _this.blendExt = _this.GL; @@ -116987,6 +140393,7 @@ _this._useEmissiveMaterial = false; _this._useNormalMaterial = false; _this._useShininess = 1; + _this._useMetalness = 0; _this._useLineColor = false; _this._useVertexColor = false; _this.registerEnabled = new Set(); @@ -117004,9 +140411,12 @@ * model view, projection, & normal * matrices */ + _this.uModelMatrix = new _main.default.Matrix(); + _this.uViewMatrix = new _main.default.Matrix(); _this.uMVMatrix = new _main.default.Matrix(); _this.uPMatrix = new _main.default.Matrix(); _this.uNMatrix = new _main.default.Matrix('mat3'); + _this.curMatrix = new _main.default.Matrix('mat3'); // Current vertex normal _this._currentNormal = new _main.default.Vector(0, 0, 1); // Camera @@ -117028,6 +140438,9 @@ // Flags for recording the state of zooming, rotation and moving _this.executeZoom = false; _this.executeRotateAndMove = false; + _this.specularShader = undefined; + _this.sphereMapping = undefined; + _this.diffusedShader = undefined; _this._defaultLightShader = undefined; _this._defaultImmediateModeShader = undefined; _this._defaultNormalShader = undefined; @@ -117259,6 +140672,33 @@ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); this._viewport = this.drawingContext.getParameter(this.drawingContext.VIEWPORT); } + } + }, + { + key: '_getParam', + value: function _getParam() { + var gl = this.drawingContext; + return gl.getParameter(gl.MAX_TEXTURE_SIZE); + } + }, + { + key: '_adjustDimensions', + value: function _adjustDimensions(width, height) { + if (!this._maxTextureSize) { + this._maxTextureSize = this._getParam(); + } + var maxTextureSize = this._maxTextureSize; + var maxAllowedPixelDimensions = _main.default.prototype._maxAllowedPixelDimensions; + maxAllowedPixelDimensions = Math.floor(maxTextureSize / this.pixelDensity()); + var adjustedWidth = Math.min(width, maxAllowedPixelDimensions); + var adjustedHeight = Math.min(height, maxAllowedPixelDimensions); + if (adjustedWidth !== width || adjustedHeight !== height) { + console.warn('Warning: The requested width/height exceeds hardware limits. ' + 'Adjusting dimensions to width: '.concat(adjustedWidth, ', height: ').concat(adjustedHeight, '.')); + } + return { + adjustedWidth: adjustedWidth, + adjustedHeight: adjustedHeight + }; } //This is helper function to reset the context anytime the attributes //are changed with setAttributes() @@ -117318,7 +140758,8 @@ value: function _update() { // reset model view and apply initial camera transform // (containing only look at info; no projection). - this.uMVMatrix.set(this._curCamera.cameraMatrix.mat4[0], this._curCamera.cameraMatrix.mat4[1], this._curCamera.cameraMatrix.mat4[2], this._curCamera.cameraMatrix.mat4[3], this._curCamera.cameraMatrix.mat4[4], this._curCamera.cameraMatrix.mat4[5], this._curCamera.cameraMatrix.mat4[6], this._curCamera.cameraMatrix.mat4[7], this._curCamera.cameraMatrix.mat4[8], this._curCamera.cameraMatrix.mat4[9], this._curCamera.cameraMatrix.mat4[10], this._curCamera.cameraMatrix.mat4[11], this._curCamera.cameraMatrix.mat4[12], this._curCamera.cameraMatrix.mat4[13], this._curCamera.cameraMatrix.mat4[14], this._curCamera.cameraMatrix.mat4[15]); + this.uModelMatrix.reset(); + this.uViewMatrix.set(this._curCamera.cameraMatrix); // reset light data for new frame. this.ambientLightColors.length = 0; this.specularColors = [ @@ -117521,10 +140962,6 @@ var target = this.activeFramebuffer() || this; // Resize the framebuffer 'fbo' and adjust its pixel density if it doesn't match the target. this.matchSize(fbo, target); - // Set filterCamera for framebuffers. - if (target !== this) { - this.filterCamera = this.getFilterLayer().createCamera(); - } fbo.draw(function () { return _this2._pInst.clear(); }); // prevent undesirable feedback effects accumulating secretly. @@ -117541,6 +140978,7 @@ // setup this._pInst.push(); this._pInst.noStroke(); + this._pInst.blendMode(constants.BLEND); // draw main to temp buffer this._pInst.shader(this.filterShader); this.filterShader.setUniform('texelSize', texelSize); @@ -117558,7 +140996,8 @@ _this2.filterShader.setUniform('tex0', target); _this2._pInst.clear(); _this2._pInst.shader(_this2.filterShader); - _this2._pInst.rect( - target.width / 2, - target.height / 2, target.width, target.height); + _this2._pInst.noLights(); + _this2._pInst.plane(target.width, target.height); }); // Vert pass: draw `tmp` to `fbo` fbo.draw(function () { @@ -117569,13 +141008,15 @@ _this2.filterShader.setUniform('tex0', tmp); _this2._pInst.clear(); _this2._pInst.shader(_this2.filterShader); - _this2._pInst.rect( - target.width / 2, - target.height / 2, target.width, target.height); + _this2._pInst.noLights(); + _this2._pInst.plane(target.width, target.height); }); this._pInst.pop(); } // every other non-blur shader uses single pass else { fbo.draw(function () { _this2._pInst.noStroke(); + _this2._pInst.blendMode(constants.BLEND); _this2._pInst.shader(_this2.filterShader); _this2.filterShader.setUniform('tex0', target); _this2.filterShader.setUniform('texelSize', texelSize); @@ -117586,7 +141027,8 @@ // filterParameter uniform only used for POSTERIZE, and THRESHOLD // but shouldn't hurt to always set _this2.filterShader.setUniform('filterParameter', filterParameter); - _this2._pInst.rect( - target.width / 2, - target.height / 2, target.width, target.height); + _this2._pInst.noLights(); + _this2._pInst.plane(target.width, target.height); }); } // draw fbo contents onto main renderer. @@ -117596,10 +141038,11 @@ this._pInst.push(); this._pInst.imageMode(constants.CORNER); this._pInst.blendMode(constants.BLEND); - this.filterCamera._resize(); - this._pInst.setCamera(this.filterCamera); + target.filterCamera._resize(); + this._pInst.setCamera(target.filterCamera); this._pInst.resetMatrix(); - this._pInst.image(fbo, - this.width / 2, - this.height / 2, this.width, this.height); + this._pInst.image(fbo, - target.width / 2, - target.height / 2, target.width, target.height); + this._pInst.clearDepth(); this._pInst.pop(); this._pInst.pop(); } // Pass this off to the host instance so that we can treat a renderer and a @@ -117628,7 +141071,7 @@ key: 'erase', value: function erase(opacityFill, opacityStroke) { if (!this._isErasing) { - this._cachedBlendMode = this.curBlendMode; + this.preEraseBlend = this.curBlendMode; this._isErasing = true; this.blendMode(constants.REMOVE); this._cachedFillStyle = this.curFillColor.slice(); @@ -117652,14 +141095,15 @@ key: 'noErase', value: function noErase() { if (this._isErasing) { + // Restore colors this.curFillColor = this._cachedFillStyle.slice(); this.curStrokeColor = this._cachedStrokeStyle.slice(); - // It's necessary to restore post-erase state. Needs rework - var temp = this.curBlendMode; - this.blendMode(this._cachedBlendMode); - this._cachedBlendMode = temp; // If we don't do this, applyBlendMode() returns null + // Restore blend mode + this.curBlendMode = this.preEraseBlend; + this.blendMode(this.preEraseBlend); + // Ensure that _applyBlendMode() sets preEraseBlend back to the original blend mode this._isErasing = false; - this._applyBlendMode(); // This sets _cachedBlendMode back to the original blendmode + this._applyBlendMode(); } } }, @@ -117937,15 +141381,27 @@ this.GL.clearColor(_r * _a, _g * _a, _b * _a, _a); this.GL.clearDepth(1); this.GL.clear(this.GL.COLOR_BUFFER_BIT | this.GL.DEPTH_BUFFER_BIT); + } /** + * Resets all depth information so that nothing previously drawn will + * occlude anything subsequently drawn. + */ + + }, + { + key: 'clearDepth', + value: function clearDepth() { + var depth = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; + this.GL.clearDepth(depth); + this.GL.clear(this.GL.DEPTH_BUFFER_BIT); } }, { key: 'applyMatrix', value: function applyMatrix(a, b, c, d, e, f) { if (arguments.length === 16) { - _main.default.Matrix.prototype.apply.apply(this.uMVMatrix, arguments); + _main.default.Matrix.prototype.apply.apply(this.uModelMatrix, arguments); } else { - this.uMVMatrix.apply([a, + this.uModelMatrix.apply([a, b, 0, 0, @@ -117981,7 +141437,7 @@ y = x.y; x = x.x; } - this.uMVMatrix.translate([x, + this.uModelMatrix.translate([x, y, z]); return this; @@ -117998,7 +141454,7 @@ { key: 'scale', value: function scale(x, y, z) { - this.uMVMatrix.scale(x, y, z); + this.uModelMatrix.scale(x, y, z); return this; } }, @@ -118008,7 +141464,7 @@ if (typeof axis === 'undefined') { return this.rotateZ(rad); } - _main.default.Matrix.prototype.rotate.apply(this.uMVMatrix, arguments); + _main.default.Matrix.prototype.rotate.apply(this.uModelMatrix, arguments); return this; } }, @@ -118040,7 +141496,8 @@ var style = _main.default.Renderer.prototype.push.apply(this); // add webgl-specific style properties var properties = style.properties; - properties.uMVMatrix = this.uMVMatrix.copy(); + properties.uModelMatrix = this.uModelMatrix.copy(); + properties.uViewMatrix = this.uViewMatrix.copy(); properties.uPMatrix = this.uPMatrix.copy(); properties._curCamera = this._curCamera; // make a copy of the current camera for the push state @@ -118074,6 +141531,7 @@ properties._useSpecularMaterial = this._useSpecularMaterial; properties._useEmissiveMaterial = this._useEmissiveMaterial; properties._useShininess = this._useShininess; + properties._useMetalness = this._useMetalness; properties.constantAttenuation = this.constantAttenuation; properties.linearAttenuation = this.linearAttenuation; properties.quadraticAttenuation = this.quadraticAttenuation; @@ -118121,7 +141579,8 @@ { key: 'resetMatrix', value: function resetMatrix() { - this.uMVMatrix.set(this._curCamera.cameraMatrix.mat4[0], this._curCamera.cameraMatrix.mat4[1], this._curCamera.cameraMatrix.mat4[2], this._curCamera.cameraMatrix.mat4[3], this._curCamera.cameraMatrix.mat4[4], this._curCamera.cameraMatrix.mat4[5], this._curCamera.cameraMatrix.mat4[6], this._curCamera.cameraMatrix.mat4[7], this._curCamera.cameraMatrix.mat4[8], this._curCamera.cameraMatrix.mat4[9], this._curCamera.cameraMatrix.mat4[10], this._curCamera.cameraMatrix.mat4[11], this._curCamera.cameraMatrix.mat4[12], this._curCamera.cameraMatrix.mat4[13], this._curCamera.cameraMatrix.mat4[14], this._curCamera.cameraMatrix.mat4[15]); + this.uModelMatrix.reset(); + this.uViewMatrix.set(this._curCamera.cameraMatrix); return this; } ////////////////////////////////////////////// // SHADER @@ -118148,6 +141607,21 @@ key: '_getRetainedStrokeShader', value: function _getRetainedStrokeShader() { return this._getImmediateStrokeShader(); + } + }, + { + key: '_getSphereMapping', + value: function _getSphereMapping(img) { + if (!this.sphereMapping) { + this.sphereMapping = this._pInst.createFilterShader(sphereMapping); + } + this.uNMatrix.inverseTranspose(this.uViewMatrix); + this.uNMatrix.invert3x3(this.uNMatrix); + this.sphereMapping.setUniform('uFovY', this._curCamera.cameraFOV); + this.sphereMapping.setUniform('uAspect', this._curCamera.aspectRatio); + this.sphereMapping.setUniform('uNewNormalMatrix', this.uNMatrix.mat3); + this.sphereMapping.setUniform('uSampler', img); + return this.sphereMapping; } /* * selects which fill shader should be used based on renderer state, * for use with begin/endShape and immediate vertex mode. @@ -118338,34 +141812,44 @@ * To create a blurry image from the input non blurry img, if it doesn't already exist * Add it to the diffusedTexture map, * Returns the blurry image - * maps a p5.Image used by imageLight() to a p5.Graphics + * maps a p5.Image used by imageLight() to a p5.Framebuffer */ }, { key: 'getDiffusedTexture', value: function getDiffusedTexture(input) { + var _this3 = this; // if one already exists for a given input image if (this.diffusedTextures.get(input) != null) { return this.diffusedTextures.get(input); } // if not, only then create one - var newGraphic; // maybe switch to framebuffer + var newFramebuffer; // hardcoded to 200px, because it's going to be blurry and smooth var smallWidth = 200; var width = smallWidth; var height = Math.floor(smallWidth * (input.height / input.width)); - newGraphic = this._pInst.createGraphics(width, height, constants.WEBGL); - // create graphics is like making a new sketch, all functions on main - // sketch it would be available on graphics - var irradiance = newGraphic.createShader(defaultShaders.imageLightVert, defaultShaders.imageLightDiffusedFrag); - newGraphic.shader(irradiance); - irradiance.setUniform('environmentMap', input); - newGraphic.noStroke(); - newGraphic.rectMode(newGraphic.CENTER); - newGraphic.rect(0, 0, newGraphic.width, newGraphic.height); - this.diffusedTextures.set(input, newGraphic); - return newGraphic; + newFramebuffer = this._pInst.createFramebuffer({ + width: width, + height: height, + density: 1 + }); + // create framebuffer is like making a new sketch, all functions on main + // sketch it would be available on framebuffer + if (!this.diffusedShader) { + this.diffusedShader = this._pInst.createShader(defaultShaders.imageLightVert, defaultShaders.imageLightDiffusedFrag); + } + newFramebuffer.draw(function () { + _this3._pInst.shader(_this3.diffusedShader); + _this3.diffusedShader.setUniform('environmentMap', input); + _this3._pInst.noStroke(); + _this3._pInst.rectMode(constants.CENTER); + _this3._pInst.noLights(); + _this3._pInst.rect(0, 0, width, height); + }); + this.diffusedTextures.set(input, newFramebuffer); + return newFramebuffer; } /* * used in imageLight, * To create a texture from the input non blurry image, if it doesn't already exist @@ -118380,6 +141864,7 @@ { key: 'getSpecularTexture', value: function getSpecularTexture(input) { + var _this4 = this; // check if already exits (there are tex of diff resolution so which one to check) // currently doing the whole array if (this.specularTextures.get(input) != null) { @@ -118390,28 +141875,40 @@ var tex; var levels = [ ]; - var graphic = this._pInst.createGraphics(size, size, constants.WEBGL); + var framebuffer = this._pInst.createFramebuffer({ + width: size, + height: size, + density: 1 + }); var count = Math.log(size) / Math.log(2); - graphic.pixelDensity(1); - // currently only 8 levels - // This loop calculates 8 graphics of varying size of canvas + if (!this.specularShader) { + this.specularShader = this._pInst.createShader(defaultShaders.imageLightVert, defaultShaders.imageLightSpecularFrag); + } // currently only 8 levels + // This loop calculates 8 framebuffers of varying size of canvas // and corresponding different roughness levels. // Roughness increases with the decrease in canvas size, // because rougher surfaces have less detailed/more blurry reflections. - for (var w = size; w >= 1; w /= 2) { - graphic.resizeCanvas(w, w); + + var _loop = function _loop(w) { + framebuffer.resize(w, w); var currCount = Math.log(w) / Math.log(2); var roughness = 1 - currCount / count; - var myShader = graphic.createShader(defaultShaders.imageLightVert, defaultShaders.imageLightSpecularFrag); - graphic.shader(myShader); - graphic.clear(); - myShader.setUniform('environmentMap', input); - myShader.setUniform('roughness', roughness); - graphic.noStroke(); - graphic.plane(w, w); - levels.push(graphic.get().drawingContext.getImageData(0, 0, w, w)); - } - graphic.remove(); + framebuffer.draw(function () { + _this4._pInst.shader(_this4.specularShader); + _this4._pInst.clear(); + _this4.specularShader.setUniform('environmentMap', input); + _this4.specularShader.setUniform('roughness', roughness); + _this4._pInst.noStroke(); + _this4._pInst.noLights(); + _this4._pInst.plane(w, w); + }); + levels.push(framebuffer.get().drawingContext.getImageData(0, 0, w, w)); + }; + for (var w = size; w >= 1; w /= 2) { + _loop(w); + } // Free the Framebuffer + + framebuffer.remove(); tex = new _p6.MipmapTexture(this, levels, { }); this.specularTextures.set(input, tex); @@ -118451,8 +141948,15 @@ { key: '_setFillUniforms', value: function _setFillUniforms(fillShader) { + var _this5 = this; fillShader.bindShader(); - // TODO: optimize + this.mixedSpecularColor = _toConsumableArray(this.curSpecularColor); + if (this._useMetalness > 0) { + this.mixedSpecularColor = this.mixedSpecularColor.map(function (mixedSpecularColor, index) { + return _this5.curFillColor[index] * _this5._useMetalness + mixedSpecularColor * (1 - _this5._useMetalness); + }); + } // TODO: optimize + fillShader.setUniform('uUseVertexColor', this._useVertexColor); fillShader.setUniform('uMaterialColor', this.curFillColor); fillShader.setUniform('isTexture', !!this._tex); @@ -118462,11 +141966,12 @@ fillShader.setUniform('uTint', this._tint); fillShader.setUniform('uHasSetAmbient', this._hasSetAmbient); fillShader.setUniform('uAmbientMatColor', this.curAmbientColor); - fillShader.setUniform('uSpecularMatColor', this.curSpecularColor); + fillShader.setUniform('uSpecularMatColor', this.mixedSpecularColor); fillShader.setUniform('uEmissiveMatColor', this.curEmissiveColor); fillShader.setUniform('uSpecular', this._useSpecularMaterial); fillShader.setUniform('uEmissive', this._useEmissiveMaterial); fillShader.setUniform('uShininess', this._useShininess); + fillShader.setUniform('metallic', this._useMetalness); this._setImageLightUniforms(fillShader); fillShader.setUniform('uUseLighting', this._enableLighting); var pointLightCount = this.pointLightDiffuseColors.length / 3; @@ -118481,8 +141986,15 @@ fillShader.setUniform('uDirectionalSpecularColors', this.directionalLightSpecularColors); // TODO: sum these here... var ambientLightCount = this.ambientLightColors.length / 3; + this.mixedAmbientLight = _toConsumableArray(this.ambientLightColors); + if (this._useMetalness > 0) { + this.mixedAmbientLight = this.mixedAmbientLight.map(function (ambientColors) { + var mixing = ambientColors - _this5._useMetalness; + return Math.max(0, mixing); + }); + } fillShader.setUniform('uAmbientLightCount', ambientLightCount); - fillShader.setUniform('uAmbientColor', this.ambientLightColors); + fillShader.setUniform('uAmbientColor', this.mixedAmbientLight); var spotLightCount = this.spotLightDiffuseColors.length / 3; fillShader.setUniform('uSpotLightCount', spotLightCount); fillShader.setUniform('uSpotLightAngle', this.spotLightAngle); @@ -118532,9 +142044,9 @@ // should be they be same var? pointShader.setUniform('uPointSize', this.pointSize * this._pInst._pixelDensity); } /* Binds a buffer to the drawing context - * when passed more than two arguments it also updates or initializes - * the data associated with the buffer - */ + * when passed more than two arguments it also updates or initializes + * the data associated with the buffer + */ }, { @@ -118588,34 +142100,7 @@ { key: '_flatten', value: function _flatten(arr) { - //when empty, return empty - if (arr.length === 0) { - return []; - } else if (arr.length > 20000) { - //big models , load slower to avoid stack overflow - //faster non-recursive flatten via axelduch - //stackoverflow.com/questions/27266550/how-to-flatten-nested-array-in-javascript - var result = [ - ]; - var nodes = arr.slice(); - var node; - node = nodes.pop(); - do { - if (Array.isArray(node)) { - nodes.push.apply(nodes, _toConsumableArray(node)); - } else { - result.push(node); - } - } while (nodes.length && (node = nodes.pop()) !== undefined); - result.reverse(); // we reverse result to restore the original order - return result; - } else { - var _ref; - //otherwise if model within limits for browser - //use faster recursive loading - return (_ref = [ - ]).concat.apply(_ref, _toConsumableArray(arr)); - } + return arr.flat(); } /** * turn a p5.Vector Array into a one dimensional number array * @private @@ -118629,31 +142114,11 @@ { key: '_vToNArray', value: function _vToNArray(arr) { - var ret = [ - ]; - var _iteratorNormalCompletion2 = true; - var _didIteratorError2 = false; - var _iteratorError2 = undefined; - try { - for (var _iterator2 = arr[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { - var item = _step2.value; - ret.push(item.x, item.y, item.z); - } - } catch (err) { - _didIteratorError2 = true; - _iteratorError2 = err; - } finally { - try { - if (!_iteratorNormalCompletion2 && _iterator2.return != null) { - _iterator2.return(); - } - } finally { - if (_didIteratorError2) { - throw _iteratorError2; - } - } - } - return ret; + return arr.flatMap(function (item) { + return [item.x, + item.y, + item.z]; + }); } // function to calculate BezierVertex Coefficients }, @@ -118705,8 +142170,27 @@ value: function _initTessy() { // function called for each vertex of tesselator output function vertexCallback(data, polyVertArray) { - for (var i = 0; i < data.length; i++) { - polyVertArray.push(data[i]); + var _iteratorNormalCompletion2 = true; + var _didIteratorError2 = false; + var _iteratorError2 = undefined; + try { + for (var _iterator2 = data[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { + var element = _step2.value; + polyVertArray.push(element); + } + } catch (err) { + _didIteratorError2 = true; + _iteratorError2 = err; + } finally { + try { + if (!_iteratorNormalCompletion2 && _iterator2.return != null) { + _iterator2.return(); + } + } finally { + if (_didIteratorError2) { + throw _iteratorError2; + } + } } } function begincallback(type) { @@ -118835,74 +142319,79 @@ exports.default = _default; }, { - '../core/constants': 286, - '../core/main': 298, - '../core/p5.Renderer': 301, - './GeometryBuilder': 342, - './p5.Camera': 347, - './p5.Framebuffer': 349, - './p5.Matrix': 351, - './p5.Shader': 356, - './p5.Texture': 357, - 'core-js/modules/es.array.concat': 169, - 'core-js/modules/es.array.copy-within': 170, - 'core-js/modules/es.array.every': 171, - 'core-js/modules/es.array.fill': 172, - 'core-js/modules/es.array.from': 176, - 'core-js/modules/es.array.includes': 177, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.array.some': 184, - 'core-js/modules/es.map': 187, - 'core-js/modules/es.object.assign': 194, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.get-prototype-of': 198, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.reflect.construct': 202, - 'core-js/modules/es.reflect.get': 203, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.set': 207, - 'core-js/modules/es.string.includes': 209, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.typed-array.copy-within': 223, - 'core-js/modules/es.typed-array.every': 224, - 'core-js/modules/es.typed-array.fill': 225, - 'core-js/modules/es.typed-array.filter': 226, - 'core-js/modules/es.typed-array.find': 228, - 'core-js/modules/es.typed-array.find-index': 227, - 'core-js/modules/es.typed-array.float32-array': 229, - 'core-js/modules/es.typed-array.float64-array': 230, - 'core-js/modules/es.typed-array.for-each': 231, - 'core-js/modules/es.typed-array.includes': 232, - 'core-js/modules/es.typed-array.index-of': 233, - 'core-js/modules/es.typed-array.int16-array': 234, - 'core-js/modules/es.typed-array.iterator': 236, - 'core-js/modules/es.typed-array.join': 237, - 'core-js/modules/es.typed-array.last-index-of': 238, - 'core-js/modules/es.typed-array.map': 239, - 'core-js/modules/es.typed-array.reduce': 241, - 'core-js/modules/es.typed-array.reduce-right': 240, - 'core-js/modules/es.typed-array.reverse': 242, - 'core-js/modules/es.typed-array.set': 243, - 'core-js/modules/es.typed-array.slice': 244, - 'core-js/modules/es.typed-array.some': 245, - 'core-js/modules/es.typed-array.sort': 246, - 'core-js/modules/es.typed-array.subarray': 247, - 'core-js/modules/es.typed-array.to-locale-string': 248, - 'core-js/modules/es.typed-array.to-string': 249, - 'core-js/modules/es.typed-array.uint16-array': 250, - 'core-js/modules/es.typed-array.uint32-array': 251, - 'core-js/modules/es.typed-array.uint8-array': 252, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256, - 'libtess': 269, - 'path': 272 + '../core/constants': 294, + '../core/main': 306, + '../core/p5.Renderer': 309, + './GeometryBuilder': 350, + './p5.Camera': 355, + './p5.Framebuffer': 357, + './p5.Matrix': 359, + './p5.Shader': 365, + './p5.Texture': 366, + 'core-js/modules/es.array.concat': 171, + 'core-js/modules/es.array.copy-within': 172, + 'core-js/modules/es.array.every': 173, + 'core-js/modules/es.array.fill': 174, + 'core-js/modules/es.array.flat': 178, + 'core-js/modules/es.array.flat-map': 177, + 'core-js/modules/es.array.from': 180, + 'core-js/modules/es.array.includes': 181, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.map': 186, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.array.some': 188, + 'core-js/modules/es.array.unscopables.flat': 191, + 'core-js/modules/es.array.unscopables.flat-map': 190, + 'core-js/modules/es.map': 193, + 'core-js/modules/es.object.assign': 201, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.get-prototype-of': 206, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.reflect.construct': 210, + 'core-js/modules/es.reflect.get': 211, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.set': 215, + 'core-js/modules/es.string.includes': 217, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.typed-array.copy-within': 231, + 'core-js/modules/es.typed-array.every': 232, + 'core-js/modules/es.typed-array.fill': 233, + 'core-js/modules/es.typed-array.filter': 234, + 'core-js/modules/es.typed-array.find': 236, + 'core-js/modules/es.typed-array.find-index': 235, + 'core-js/modules/es.typed-array.float32-array': 237, + 'core-js/modules/es.typed-array.float64-array': 238, + 'core-js/modules/es.typed-array.for-each': 239, + 'core-js/modules/es.typed-array.includes': 240, + 'core-js/modules/es.typed-array.index-of': 241, + 'core-js/modules/es.typed-array.int16-array': 242, + 'core-js/modules/es.typed-array.iterator': 244, + 'core-js/modules/es.typed-array.join': 245, + 'core-js/modules/es.typed-array.last-index-of': 246, + 'core-js/modules/es.typed-array.map': 247, + 'core-js/modules/es.typed-array.reduce': 249, + 'core-js/modules/es.typed-array.reduce-right': 248, + 'core-js/modules/es.typed-array.reverse': 250, + 'core-js/modules/es.typed-array.set': 251, + 'core-js/modules/es.typed-array.slice': 252, + 'core-js/modules/es.typed-array.some': 253, + 'core-js/modules/es.typed-array.sort': 254, + 'core-js/modules/es.typed-array.subarray': 255, + 'core-js/modules/es.typed-array.to-locale-string': 256, + 'core-js/modules/es.typed-array.to-string': 257, + 'core-js/modules/es.typed-array.uint16-array': 258, + 'core-js/modules/es.typed-array.uint32-array': 259, + 'core-js/modules/es.typed-array.uint8-array': 260, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264, + 'libtess': 277, + 'path': 280 } ], - 356: [ + 365: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -118966,13 +142455,118 @@ * @requires core */ /** - * Shader class for WEBGL Mode + * A class to describe a shader program. + * + * Each `p5.Shader` object contains a shader program that runs on the graphics + * processing unit (GPU). Shaders can process many pixels or vertices at the + * same time, making them fast for many graphics tasks. They’re written in a + * language called + * GLSL + * and run along with the rest of the code in a sketch. + * + * A shader program consists of two files, a vertex shader and a fragment + * shader. The vertex shader affects where 3D geometry is drawn on the screen + * and the fragment shader affects color. Once the `p5.Shader` object is + * created, it can be used with the shader() + * function, as in `shader(myShader)`. + * + * Note: createShader(), + * createFilterShader(), and + * loadShader() are the recommended ways to + * create an instance of this class. + * * @class p5.Shader * @constructor - * @param {p5.RendererGL} renderer an instance of p5.RendererGL that - * will provide the GL context for this new p5.Shader - * @param {String} vertSrc source code for the vertex shader (as a string) - * @param {String} fragSrc source code for the fragment shader (as a string) + * @param {p5.RendererGL} renderer WebGL context for this shader. + * @param {String} vertSrc source code for the vertex shader program. + * @param {String} fragSrc source code for the fragment shader program. + * + * @example + *
+ * + * // Note: A "uniform" is a global variable within a shader program. + * + * // Create a string with the vertex shader program. + * // The vertex shader is called for each vertex. + * let vertSrc = ` + * precision highp float; + * uniform mat4 uModelViewMatrix; + * uniform mat4 uProjectionMatrix; + * + * attribute vec3 aPosition; + * attribute vec2 aTexCoord; + * varying vec2 vTexCoord; + * + * void main() { + * vTexCoord = aTexCoord; + * vec4 positionVec4 = vec4(aPosition, 1.0); + * gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4; + * } + * `; + * + * // Create a string with the fragment shader program. + * // The fragment shader is called for each pixel. + * let fragSrc = ` + * precision highp float; + * + * void main() { + * // Set each pixel's RGBA value to yellow. + * gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0); + * } + * `; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Shader object. + * let myShader = createShader(vertSrc, fragSrc); + * + * // Apply the p5.Shader object. + * shader(myShader); + * + * // Style the drawing surface. + * noStroke(); + * + * // Add a plane as a drawing surface. + * plane(100, 100); + * + * describe('A yellow square.'); + * } + * + *
+ * + *
+ * + * // Note: A "uniform" is a global variable within a shader program. + * + * let mandelbrot; + * + * // Load the shader and create a p5.Shader object. + * function preload() { + * mandelbrot = loadShader('assets/shader.vert', 'assets/shader.frag'); + * } + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Use the p5.Shader object. + * shader(mandelbrot); + * + * // Set the shader uniform p to an array. + * mandelbrot.setUniform('p', [-0.74364388703, 0.13182590421]); + * + * describe('A fractal image zooms in and out of focus.'); + * } + * + * function draw() { + * // Set the shader uniform r to a value that oscillates between 0 and 2. + * mandelbrot.setUniform('r', sin(frameCount * 0.01) + 1); + * + * // Add a quad as a display surface for the shader. + * quad(-1, -1, 1, -1, 1, 1, -1, 1); + * } + * + *
*/ _main.default.Shader = /*#__PURE__*/ function () { @@ -119049,26 +142643,182 @@ } return this; } /** - * Shaders belong to the main canvas or a p5.Graphics. Once they are compiled, - * they can only be used in the context they were compiled on. - * - * Use this method to make a new copy of a shader that gets compiled on a - * different context. + * Copies the shader from one drawing context to another. + * + * Each `p5.Shader` object must be compiled by calling + * shader() before it can run. Compilation happens + * in a drawing context which is usually the main canvas or an instance of + * p5.Graphics. A shader can only be used in the + * context where it was compiled. The `copyToContext()` method compiles the + * shader again and copies it to another drawing context where it can be + * reused. + * + * The parameter, `context`, is the drawing context where the shader will be + * used. The shader can be copied to an instance of + * p5.Graphics, as in + * `myShader.copyToContext(pg)`. The shader can also be copied from a + * p5.Graphics object to the main canvas using + * the `window` variable, as in `myShader.copyToContext(window)`. + * + * Note: A p5.Shader object created with + * createShader(), + * createFilterShader(), or + * loadShader() + * can be used directly with a p5.Framebuffer + * object created with + * createFramebuffer(). Both objects + * have the same context as the main canvas. * * @method copyToContext - * @param {p5|p5.Graphics} context The graphic or instance to copy this shader to. - * Pass `window` if you need to copy to the main canvas. - * @returns {p5.Shader} A new shader on the target context. + * @param {p5|p5.Graphics} context WebGL context for the copied shader. + * @returns {p5.Shader} new shader compiled for the target context. * * @example - *
+ *
* - * let graphic = createGraphics(200, 200, WEBGL); - * let graphicShader = graphic.createShader(vert, frag); - * graphic.shader(graphicShader); // Use graphicShader on the graphic + * // Note: A "uniform" is a global variable within a shader program. + * + * // Create a string with the vertex shader program. + * // The vertex shader is called for each vertex. + * let vertSrc = ` + * precision highp float; + * uniform mat4 uModelViewMatrix; + * uniform mat4 uProjectionMatrix; + * + * attribute vec3 aPosition; + * attribute vec2 aTexCoord; + * varying vec2 vTexCoord; + * + * void main() { + * vTexCoord = aTexCoord; + * vec4 positionVec4 = vec4(aPosition, 1.0); + * gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4; + * } + * `; + * + * // Create a string with the fragment shader program. + * // The fragment shader is called for each pixel. + * let fragSrc = ` + * precision mediump float; + * varying vec2 vTexCoord; + * + * void main() { + * vec2 uv = vTexCoord; + * vec3 color = vec3(uv.x, uv.y, min(uv.x + uv.y, 1.0)); + * gl_FragColor = vec4(color, 1.0);\ + * } + * `; + * + * let pg; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * background(200); + * + * // Create a p5.Shader object. + * let original = createShader(vertSrc, fragSrc); + * + * // Compile the p5.Shader object. + * shader(original); + * + * // Create a p5.Graphics object. + * pg = createGraphics(50, 50, WEBGL); * - * let mainShader = graphicShader.copyToContext(window); - * shader(mainShader); // Use `mainShader` on the main canvas + * // Copy the original shader to the p5.Graphics object. + * let copied = original.copyToContext(pg); + * + * // Apply the copied shader to the p5.Graphics object. + * pg.shader(copied); + * + * // Style the display surface. + * pg.noStroke(); + * + * // Add a display surface for the shader. + * pg.plane(50, 50); + * + * describe('A square with purple-blue gradient on its surface drawn against a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Draw the p5.Graphics object to the main canvas. + * image(pg, -25, -25); + * } + * + *
+ * + *
+ * + * // Note: A "uniform" is a global variable within a shader program. + * + * // Create a string with the vertex shader program. + * // The vertex shader is called for each vertex. + * let vertSrc = ` + * precision highp float; + * uniform mat4 uModelViewMatrix; + * uniform mat4 uProjectionMatrix; + * + * attribute vec3 aPosition; + * attribute vec2 aTexCoord; + * varying vec2 vTexCoord; + * + * void main() { + * vTexCoord = aTexCoord; + * vec4 positionVec4 = vec4(aPosition, 1.0); + * gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4; + * } + * `; + * + * // Create a string with the fragment shader program. + * // The fragment shader is called for each pixel. + * let fragSrc = ` + * precision mediump float; + * + * varying vec2 vTexCoord; + * + * void main() { + * vec2 uv = vTexCoord; + * vec3 color = vec3(uv.x, uv.y, min(uv.x + uv.y, 1.0)); + * gl_FragColor = vec4(color, 1.0); + * } + * `; + * + * let copied; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Graphics object. + * let pg = createGraphics(25, 25, WEBGL); + * + * // Create a p5.Shader object. + * let original = pg.createShader(vertSrc, fragSrc); + * + * // Compile the p5.Shader object. + * pg.shader(original); + * + * // Copy the original shader to the main canvas. + * copied = original.copyToContext(window); + * + * // Apply the copied shader to the main canvas. + * shader(copied); + * + * describe('A rotating cube with a purple-blue gradient on its surface drawn against a gray background.'); + * } + * + * function draw() { + * background(200); + * + * // Rotate around the x-, y-, and z-axes. + * rotateX(frameCount * 0.01); + * rotateY(frameCount * 0.01); + * rotateZ(frameCount * 0.01); + * + * // Draw the box. + * box(50); + * } * *
*/ @@ -119151,7 +142901,7 @@ uniform.location = gl.getUniformLocation(this._glProgram, uniformInfo.name); uniform.size = uniformInfo.size; var uniformName = uniformInfo.name; - //uniforms thats are arrays have their name returned as + //uniforms that are arrays have their name returned as //someUniform[0] which is a bit silly so we trim it //off here. The size property tells us that its an array //so we dont lose any information by doing this @@ -119309,28 +143059,29 @@ { key: '_setMatrixUniforms', value: function _setMatrixUniforms() { - var viewMatrix = this._renderer._curCamera.cameraMatrix; + var modelMatrix = this._renderer.uModelMatrix; + var viewMatrix = this._renderer.uViewMatrix; var projectionMatrix = this._renderer.uPMatrix; - var modelViewMatrix = this._renderer.uMVMatrix; + var modelViewMatrix = modelMatrix.copy().mult(viewMatrix); + this._renderer.uMVMatrix = modelViewMatrix; var modelViewProjectionMatrix = modelViewMatrix.copy(); modelViewProjectionMatrix.mult(projectionMatrix); if (this.isStrokeShader()) { - if (this._renderer._curCamera.cameraType === 'default') { - // strokes scale up as they approach camera, default - this.setUniform('uPerspective', 1); - } else { - // strokes have uniform scale regardless of distance from camera - this.setUniform('uPerspective', 0); - } + this.setUniform('uPerspective', this._renderer._curCamera.useLinePerspective ? 1 : 0); } this.setUniform('uViewMatrix', viewMatrix.mat4); this.setUniform('uProjectionMatrix', projectionMatrix.mat4); + this.setUniform('uModelMatrix', modelMatrix.mat4); this.setUniform('uModelViewMatrix', modelViewMatrix.mat4); this.setUniform('uModelViewProjectionMatrix', modelViewProjectionMatrix.mat4); if (this.uniforms.uNormalMatrix) { this._renderer.uNMatrix.inverseTranspose(this._renderer.uMVMatrix); this.setUniform('uNormalMatrix', this._renderer.uNMatrix.mat3); } + if (this.uniforms.uCameraRotation) { + this._renderer.curMatrix.inverseTranspose(this._renderer.uViewMatrix); + this.setUniform('uCameraRotation', this._renderer.curMatrix.mat3); + } } /** * @method useProgram * @chainable @@ -119348,84 +143099,239 @@ } return this; } /** - * Used to set the uniforms of a - * p5.Shader object. - * - * Uniforms are used as a way to provide shader programs - * (which run on the GPU) with values from a sketch - * (which runs on the CPU). - * - * Here are some examples of uniforms you can make: - * - booleans - * - Example: `setUniform('x', true)` becomes `uniform float x` with the value `1.0` - * - numbers - * - Example: `setUniform('x', -2)` becomes `uniform float x` with the value `-2.0` - * - arrays of numbers - * - Example: `setUniform('x', [0, 0.5, 1])` becomes `uniform vec3 x` with the value `vec3(0.0, 0.5, 1.0)` - * - a p5.Image, p5.Graphics, p5.MediaElement, or p5.Texture - * - Example: `setUniform('x', img)` becomes `uniform sampler2D x` + * Sets the shader’s uniform (global) variables. + * + * Shader programs run on the computer’s graphics processing unit (GPU). + * They live in part of the computer’s memory that’s completely separate + * from the sketch that runs them. Uniforms are global variables within a + * shader program. They provide a way to pass values from a sketch running + * on the CPU to a shader program running on the GPU. + * + * The first parameter, `uniformName`, is a string with the uniform’s name. + * For the shader above, `uniformName` would be `'r'`. + * + * The second parameter, `data`, is the value that should be used to set the + * uniform. For example, calling `myShader.setUniform('r', 0.5)` would set + * the `r` uniform in the shader above to `0.5`. data should match the + * uniform’s type. Numbers, strings, booleans, arrays, and many types of + * images can all be passed to a shader with `setUniform()`. * * @method setUniform * @chainable - * @param {String} uniformName the name of the uniform. - * Must correspond to the name used in the vertex and fragment shaders + * @param {String} uniformName name of the uniform. Must match the name + * used in the vertex and fragment shaders. * @param {Boolean|Number|Number[]|p5.Image|p5.Graphics|p5.MediaElement|p5.Texture} - * data the data to associate with the uniform. The type can be - * a boolean (true/false), a number, an array of numbers, or - * an image (p5.Image, p5.Graphics, p5.MediaElement, p5.Texture) + * data value to assign to the uniform. Must match the uniform’s data type. * * @example - *
+ *
* - * // Click within the image to toggle the value of uniforms - * // Note: for an alternative approach to the same example, - * // involving toggling between shaders please refer to: - * // https://p5js.org/reference/#/p5/shader + * // Note: A "uniform" is a global variable within a shader program. + * + * // Create a string with the vertex shader program. + * // The vertex shader is called for each vertex. + * let vertSrc = ` + * precision highp float; + * uniform mat4 uModelViewMatrix; + * uniform mat4 uProjectionMatrix; + * + * attribute vec3 aPosition; + * attribute vec2 aTexCoord; + * varying vec2 vTexCoord; + * + * void main() { + * vTexCoord = aTexCoord; + * vec4 positionVec4 = vec4(aPosition, 1.0); + * gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4; + * } + * `; * - * let grad; - * let showRedGreen = false; + * // Create a string with the fragment shader program. + * // The fragment shader is called for each pixel. + * let fragSrc = ` + * precision mediump float; * - * function preload() { - * // note that we are using two instances - * // of the same vertex and fragment shaders - * grad = loadShader('assets/shader.vert', 'assets/shader-gradient.frag'); + * uniform float r; + * + * void main() { + * gl_FragColor = vec4(r, 1.0, 1.0, 1.0); * } + * `; * * function setup() { * createCanvas(100, 100, WEBGL); - * shader(grad); + * + * // Create a p5.Shader object. + * let myShader = createShader(vertSrc, fragSrc); + * + * // Apply the p5.Shader object. + * shader(myShader); + * + * // Set the r uniform to 0.5. + * myShader.setUniform('r', 0.5); + * + * // Style the drawing surface. * noStroke(); * - * describe( - * 'canvas toggles between a circular gradient of orange and blue vertically. and a circular gradient of red and green moving horizontally when mouse is clicked/pressed.' - * ); + * // Add a plane as a drawing surface for the shader. + * plane(100, 100); + * + * describe('A cyan square.'); + * } + * + *
+ * + *
+ * + * // Note: A "uniform" is a global variable within a shader program. + * + * // Create a string with the vertex shader program. + * // The vertex shader is called for each vertex. + * let vertSrc = ` + * precision highp float; + * uniform mat4 uModelViewMatrix; + * uniform mat4 uProjectionMatrix; + * + * attribute vec3 aPosition; + * attribute vec2 aTexCoord; + * varying vec2 vTexCoord; + * + * void main() { + * vTexCoord = aTexCoord; + * vec4 positionVec4 = vec4(aPosition, 1.0); + * gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4; + * } + * `; + * + * // Create a string with the fragment shader program. + * // The fragment shader is called for each pixel. + * let fragSrc = ` + * precision mediump float; + * + * uniform float r; + * + * void main() { + * gl_FragColor = vec4(r, 1.0, 1.0, 1.0); + * } + * `; + * + * let myShader; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Shader object. + * myShader = createShader(vertSrc, fragSrc); + * + * // Compile and apply the p5.Shader object. + * shader(myShader); + * + * describe('A square oscillates color between cyan and white.'); * } * * function draw() { - * // update the offset values for each scenario, - * // moving the "grad" shader in either vertical or - * // horizontal direction each with differing colors - * - * if (showRedGreen === true) { - * grad.setUniform('colorCenter', [1, 0, 0]); - * grad.setUniform('colorBackground', [0, 1, 0]); - * grad.setUniform('offset', [sin(millis() / 2000), 1]); - * } else { - * grad.setUniform('colorCenter', [1, 0.5, 0]); - * grad.setUniform('colorBackground', [0.226, 0, 0.615]); - * grad.setUniform('offset', [0, sin(millis() / 2000) + 1]); + * background(200); + * + * // Style the drawing surface. + * noStroke(); + * + * // Update the r uniform. + * let nextR = 0.5 * (sin(frameCount * 0.01) + 1); + * myShader.setUniform('r', nextR); + * + * // Add a plane as a drawing surface. + * plane(100, 100); + * } + * + *
+ * + *
+ * + * // Note: A "uniform" is a global variable within a shader program. + * + * // Create a string with the vertex shader program. + * // The vertex shader is called for each vertex. + * let vertSrc = ` + * precision highp float; + * uniform mat4 uModelViewMatrix; + * uniform mat4 uProjectionMatrix; + * + * attribute vec3 aPosition; + * attribute vec2 aTexCoord; + * varying vec2 vTexCoord; + * + * void main() { + * vTexCoord = aTexCoord; + * vec4 positionVec4 = vec4(aPosition, 1.0); + * gl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4; + * } + * `; + * + * // Create a string with the fragment shader program. + * // The fragment shader is called for each pixel. + * let fragSrc = ` + * precision highp float; + * uniform vec2 p; + * uniform float r; + * const int numIterations = 500; + * varying vec2 vTexCoord; + * + * void main() { + * vec2 c = p + gl_FragCoord.xy * r; + * vec2 z = c; + * float n = 0.0; + * + * for (int i = numIterations; i > 0; i--) { + * if (z.x * z.x + z.y * z.y > 4.0) { + * n = float(i) / float(numIterations); + * break; + * } + * + * z = vec2(z.x * z.x - z.y * z.y, 2.0 * z.x * z.y) + c; * } - * quad(-1, -1, 1, -1, 1, 1, -1, 1); + * + * gl_FragColor = vec4( + * 0.5 - cos(n * 17.0) / 2.0, + * 0.5 - cos(n * 13.0) / 2.0, + * 0.5 - cos(n * 23.0) / 2.0, + * 1.0 + * ); + * } + * `; + * + * let mandelbrot; + * + * function setup() { + * createCanvas(100, 100, WEBGL); + * + * // Create a p5.Shader object. + * mandelbrot = createShader(vertSrc, fragSrc); + * + * // Compile and apply the p5.Shader object. + * shader(mandelbrot); + * + * // Set the shader uniform p to an array. + * // p is the center point of the Mandelbrot image. + * mandelbrot.setUniform('p', [-0.74364388703, 0.13182590421]); + * + * describe('A fractal image zooms in and out of focus.'); * } * - * function mouseClicked() { - * showRedGreen = !showRedGreen; + * function draw() { + * // Set the shader uniform r to a value that oscillates + * // between 0 and 0.005. + * // r is the size of the image in Mandelbrot-space. + * let radius = 0.005 * (sin(frameCount * 0.01) + 1); + * mandelbrot.setUniform('r', radius); + * + * // Style the drawing surface. + * noStroke(); + * + * // Add a plane as a drawing surface. + * plane(100, 100); * } * *
- * - * @alt - * canvas toggles between a circular gradient of orange and blue vertically. and a circular gradient of red and green moving horizontally when mouse is clicked/pressed. */ }, @@ -119549,7 +143455,21 @@ { key: 'isLightShader', value: function isLightShader() { - return this.attributes.aNormal !== undefined || this.uniforms.uUseLighting !== undefined || this.uniforms.uAmbientLightCount !== undefined || this.uniforms.uDirectionalLightCount !== undefined || this.uniforms.uPointLightCount !== undefined || this.uniforms.uAmbientColor !== undefined || this.uniforms.uDirectionalDiffuseColors !== undefined || this.uniforms.uDirectionalSpecularColors !== undefined || this.uniforms.uPointLightLocation !== undefined || this.uniforms.uPointLightDiffuseColors !== undefined || this.uniforms.uPointLightSpecularColors !== undefined || this.uniforms.uLightingDirection !== undefined || this.uniforms.uSpecular !== undefined; + return [this.attributes.aNormal, + this.uniforms.uUseLighting, + this.uniforms.uAmbientLightCount, + this.uniforms.uDirectionalLightCount, + this.uniforms.uPointLightCount, + this.uniforms.uAmbientColor, + this.uniforms.uDirectionalDiffuseColors, + this.uniforms.uDirectionalSpecularColors, + this.uniforms.uPointLightLocation, + this.uniforms.uPointLightDiffuseColors, + this.uniforms.uPointLightSpecularColors, + this.uniforms.uLightingDirection, + this.uniforms.uSpecular].some(function (x) { + return x !== undefined; + }); } }, { @@ -119659,22 +143579,22 @@ exports.default = _default; }, { - '../core/main': 298, - 'core-js/modules/es.array.index-of': 178, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.array.slice': 183, - 'core-js/modules/es.array.some': 184, - 'core-js/modules/es.function.name': 186, - 'core-js/modules/es.object.keys': 199, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/main': 306, + 'core-js/modules/es.array.index-of': 182, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.array.slice': 187, + 'core-js/modules/es.array.some': 188, + 'core-js/modules/es.function.name': 192, + 'core-js/modules/es.object.keys': 207, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 357: [ + 366: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -120350,47 +144270,47 @@ exports.default = _default; }, { - '../core/constants': 286, - '../core/main': 298, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.get-prototype-of': 198, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.reflect.construct': 202, - 'core-js/modules/es.regexp.to-string': 206, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.typed-array.copy-within': 223, - 'core-js/modules/es.typed-array.every': 224, - 'core-js/modules/es.typed-array.fill': 225, - 'core-js/modules/es.typed-array.filter': 226, - 'core-js/modules/es.typed-array.find': 228, - 'core-js/modules/es.typed-array.find-index': 227, - 'core-js/modules/es.typed-array.for-each': 231, - 'core-js/modules/es.typed-array.includes': 232, - 'core-js/modules/es.typed-array.index-of': 233, - 'core-js/modules/es.typed-array.iterator': 236, - 'core-js/modules/es.typed-array.join': 237, - 'core-js/modules/es.typed-array.last-index-of': 238, - 'core-js/modules/es.typed-array.map': 239, - 'core-js/modules/es.typed-array.reduce': 241, - 'core-js/modules/es.typed-array.reduce-right': 240, - 'core-js/modules/es.typed-array.reverse': 242, - 'core-js/modules/es.typed-array.set': 243, - 'core-js/modules/es.typed-array.slice': 244, - 'core-js/modules/es.typed-array.some': 245, - 'core-js/modules/es.typed-array.sort': 246, - 'core-js/modules/es.typed-array.subarray': 247, - 'core-js/modules/es.typed-array.to-locale-string': 248, - 'core-js/modules/es.typed-array.to-string': 249, - 'core-js/modules/es.typed-array.uint8-array': 252, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/constants': 294, + '../core/main': 306, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.get-prototype-of': 206, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.reflect.construct': 210, + 'core-js/modules/es.regexp.to-string': 214, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.typed-array.copy-within': 231, + 'core-js/modules/es.typed-array.every': 232, + 'core-js/modules/es.typed-array.fill': 233, + 'core-js/modules/es.typed-array.filter': 234, + 'core-js/modules/es.typed-array.find': 236, + 'core-js/modules/es.typed-array.find-index': 235, + 'core-js/modules/es.typed-array.for-each': 239, + 'core-js/modules/es.typed-array.includes': 240, + 'core-js/modules/es.typed-array.index-of': 241, + 'core-js/modules/es.typed-array.iterator': 244, + 'core-js/modules/es.typed-array.join': 245, + 'core-js/modules/es.typed-array.last-index-of': 246, + 'core-js/modules/es.typed-array.map': 247, + 'core-js/modules/es.typed-array.reduce': 249, + 'core-js/modules/es.typed-array.reduce-right': 248, + 'core-js/modules/es.typed-array.reverse': 250, + 'core-js/modules/es.typed-array.set': 251, + 'core-js/modules/es.typed-array.slice': 252, + 'core-js/modules/es.typed-array.some': 253, + 'core-js/modules/es.typed-array.sort': 254, + 'core-js/modules/es.typed-array.subarray': 255, + 'core-js/modules/es.typed-array.to-locale-string': 256, + 'core-js/modules/es.typed-array.to-string': 257, + 'core-js/modules/es.typed-array.uint8-array': 260, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 358: [ + 367: [ function (_dereq_, module, exports) { 'use strict'; _dereq_('core-js/modules/es.symbol'); @@ -121351,25 +145271,25 @@ }; }, { - '../core/constants': 286, - '../core/main': 298, - './p5.RendererGL.Retained': 354, - './p5.Shader': 356, - 'core-js/modules/es.array.iterator': 179, - 'core-js/modules/es.object.get-own-property-descriptor': 196, - 'core-js/modules/es.object.to-string': 200, - 'core-js/modules/es.regexp.exec': 205, - 'core-js/modules/es.string.iterator': 210, - 'core-js/modules/es.string.split': 216, - 'core-js/modules/es.string.sub': 218, - 'core-js/modules/es.symbol': 222, - 'core-js/modules/es.symbol.description': 220, - 'core-js/modules/es.symbol.iterator': 221, - 'core-js/modules/es.weak-map': 254, - 'core-js/modules/web.dom-collections.iterator': 256 + '../core/constants': 294, + '../core/main': 306, + './p5.RendererGL.Retained': 363, + './p5.Shader': 365, + 'core-js/modules/es.array.iterator': 183, + 'core-js/modules/es.object.get-own-property-descriptor': 204, + 'core-js/modules/es.object.to-string': 208, + 'core-js/modules/es.regexp.exec': 213, + 'core-js/modules/es.string.iterator': 218, + 'core-js/modules/es.string.split': 224, + 'core-js/modules/es.string.sub': 226, + 'core-js/modules/es.symbol': 230, + 'core-js/modules/es.symbol.description': 228, + 'core-js/modules/es.symbol.iterator': 229, + 'core-js/modules/es.weak-map': 262, + 'core-js/modules/web.dom-collections.iterator': 264 } ], - 359: [ + 368: [ function (_dereq_, module, exports) { module.exports = { 'fes': { @@ -121447,7 +145367,7 @@ { } ], - 360: [ + 369: [ function (_dereq_, module, exports) { 'use strict'; Object.defineProperty(exports, '__esModule', { @@ -121486,16 +145406,17 @@ 'es', 'ko', 'zh', - 'hi' + 'hi', + 'ja' ]; exports.languages = languages; }, { - './en/translation': 359 + './en/translation': 368 } ] }, { }, [ - 281 - ]) (281) + 289 + ]) (289) }); diff --git a/public/lib/p5.min.js b/public/lib/p5.min.js index 7b436a7..d14c00d 100644 --- a/public/lib/p5.min.js +++ b/public/lib/p5.min.js @@ -1,2 +1,2 @@ -/*! p5.js v1.9.0 November 28, 2023 */ -!function(e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).p5=e()}(function(){var s,t,r;return function o(n,s,i){function a(t,e){if(!s[t]){if(!n[t]){var r="function"==typeof require&&require;if(!e&&r)return r(t,!0);if(l)return l(t,!0);throw(e=new Error("Cannot find module '"+t+"'")).code="MODULE_NOT_FOUND",e}r=s[t]={exports:{}},n[t][0].call(r.exports,function(e){return a(n[t][1][e]||e)},r,r.exports,o,n,s,i)}return s[t].exports}for(var l="function"==typeof require&&require,e=0;e>16&255,s[i++]=t>>8&255,s[i++]=255&t;2===o&&(t=l[e.charCodeAt(r)]<<2|l[e.charCodeAt(r+1)]>>4,s[i++]=255&t);1===o&&(t=l[e.charCodeAt(r)]<<10|l[e.charCodeAt(r+1)]<<4|l[e.charCodeAt(r+2)]>>2,s[i++]=t>>8&255,s[i++]=255&t);return s},r.fromByteArray=function(e){for(var t,r=e.length,o=r%3,n=[],s=0,i=r-o;s>18&63]+a[e>>12&63]+a[e>>6&63]+a[63&e]}(o));return n.join("")}(e,s,i>2]+a[t<<4&63]+"==")):2==o&&(t=(e[r-2]<<8)+e[r-1],n.push(a[t>>10]+a[t>>4&63]+a[t<<2&63]+"="));return n.join("")};for(var a=[],l=[],u="undefined"!=typeof Uint8Array?Uint8Array:Array,o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",n=0,s=o.length;n>>1;case"base64":return E(e).length;default:if(n)return o?-1:M(e).length;t=(""+t).toLowerCase(),n=!0}}function r(e,t,r){var o,n=!1;if((t=void 0===t||t<0?0:t)>this.length)return"";if((r=void 0===r||r>this.length?this.length:r)<=0)return"";if((r>>>=0)<=(t>>>=0))return"";for(e=e||"utf8";;)switch(e){case"hex":var s=this,i=t,a=r,l=s.length;(!a||a<0||l=e.length){if(n)return-1;r=e.length-1}else if(r<0){if(!n)return-1;r=0}if("string"==typeof t&&(t=d.from(t,o)),d.isBuffer(t))return 0===t.length?-1:p(e,t,r,o,n);if("number"==typeof t)return t&=255,"function"==typeof Uint8Array.prototype.indexOf?(n?Uint8Array.prototype.indexOf:Uint8Array.prototype.lastIndexOf).call(e,t,r):p(e,[t],r,o,n);throw new TypeError("val must be string, number or Buffer")}function p(e,t,r,o,n){var s=1,i=e.length,a=t.length;if(void 0!==o&&("ucs2"===(o=String(o).toLowerCase())||"ucs-2"===o||"utf16le"===o||"utf-16le"===o)){if(e.length<2||t.length<2)return-1;i/=s=2,a/=2,r/=2}function l(e,t){return 1===s?e[t]:e.readUInt16BE(t*s)}if(n)for(var u=-1,c=r;c>8,o=o%256,n.push(o),n.push(r);return n}(t,e.length-r),e,r,o)}function T(e,t,r){r=Math.min(e.length,r);for(var o=[],n=t;n>>10&1023|55296),c=56320|1023&c),o.push(c),n+=d}var h=o,f=h.length;if(f<=v)return String.fromCharCode.apply(String,h);for(var p="",m=0;mt&&(e+=" ... "),""},e&&(d.prototype[e]=d.prototype.inspect),d.prototype.compare=function(e,t,r,o,n){if(C(e,Uint8Array)&&(e=d.from(e,e.offset,e.byteLength)),!d.isBuffer(e))throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. Received type '+typeof e);if(void 0===r&&(r=e?e.length:0),void 0===o&&(o=0),void 0===n&&(n=this.length),(t=void 0===t?0:t)<0||r>e.length||o<0||n>this.length)throw new RangeError("out of range index");if(n<=o&&r<=t)return 0;if(n<=o)return-1;if(r<=t)return 1;if(this===e)return 0;for(var s=(n>>>=0)-(o>>>=0),i=(r>>>=0)-(t>>>=0),a=Math.min(s,i),l=this.slice(o,n),u=e.slice(t,r),c=0;c>>=0,isFinite(r)?(r>>>=0,void 0===o&&(o="utf8")):(o=r,r=void 0)}var n=this.length-t;if((void 0===r||nthis.length)throw new RangeError("Attempt to write outside buffer bounds");o=o||"utf8";for(var s,i,a,l=!1;;)switch(o){case"hex":var u=this,c=e,d=t,h=r,f=(d=Number(d)||0,u.length-d);(!h||f<(h=Number(h)))&&(h=f),(f=c.length)/2e.length)throw new RangeError("Index out of range")}function j(e,t,r,o){if(r+o>e.length)throw new RangeError("Index out of range");if(r<0)throw new RangeError("Index out of range")}function _(e,t,r,o,n){return t=+t,r>>>=0,n||j(e,0,r,4),s.write(e,t,r,o,23,4),r+4}function x(e,t,r,o,n){return t=+t,r>>>=0,n||j(e,0,r,8),s.write(e,t,r,o,52,8),r+8}d.prototype.slice=function(e,t){var r=this.length,r=((e=~~e)<0?(e+=r)<0&&(e=0):r>>=0,t>>>=0,r||m(e,t,this.length);for(var o=this[e],n=1,s=0;++s>>=0,t>>>=0,r||m(e,t,this.length);for(var o=this[e+--t],n=1;0>>=0,t||m(e,1,this.length),this[e]},d.prototype.readUInt16LE=function(e,t){return e>>>=0,t||m(e,2,this.length),this[e]|this[e+1]<<8},d.prototype.readUInt16BE=function(e,t){return e>>>=0,t||m(e,2,this.length),this[e]<<8|this[e+1]},d.prototype.readUInt32LE=function(e,t){return e>>>=0,t||m(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},d.prototype.readUInt32BE=function(e,t){return e>>>=0,t||m(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},d.prototype.readIntLE=function(e,t,r){e>>>=0,t>>>=0,r||m(e,t,this.length);for(var o=this[e],n=1,s=0;++s>>=0,t>>>=0,r||m(e,t,this.length);for(var o=t,n=1,s=this[e+--o];0>>=0,t||m(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},d.prototype.readInt16LE=function(e,t){e>>>=0,t||m(e,2,this.length);t=this[e]|this[e+1]<<8;return 32768&t?4294901760|t:t},d.prototype.readInt16BE=function(e,t){e>>>=0,t||m(e,2,this.length);t=this[e+1]|this[e]<<8;return 32768&t?4294901760|t:t},d.prototype.readInt32LE=function(e,t){return e>>>=0,t||m(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},d.prototype.readInt32BE=function(e,t){return e>>>=0,t||m(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},d.prototype.readFloatLE=function(e,t){return e>>>=0,t||m(e,4,this.length),s.read(this,e,!0,23,4)},d.prototype.readFloatBE=function(e,t){return e>>>=0,t||m(e,4,this.length),s.read(this,e,!1,23,4)},d.prototype.readDoubleLE=function(e,t){return e>>>=0,t||m(e,8,this.length),s.read(this,e,!0,52,8)},d.prototype.readDoubleBE=function(e,t){return e>>>=0,t||m(e,8,this.length),s.read(this,e,!1,52,8)},d.prototype.writeUIntLE=function(e,t,r,o){e=+e,t>>>=0,r>>>=0,o||b(this,e,t,r,Math.pow(2,8*r)-1,0);var n=1,s=0;for(this[t]=255&e;++s>>=0,r>>>=0,o||b(this,e,t,r,Math.pow(2,8*r)-1,0);var n=r-1,s=1;for(this[t+n]=255&e;0<=--n&&(s*=256);)this[t+n]=e/s&255;return t+r},d.prototype.writeUInt8=function(e,t,r){return e=+e,t>>>=0,r||b(this,e,t,1,255,0),this[t]=255&e,t+1},d.prototype.writeUInt16LE=function(e,t,r){return e=+e,t>>>=0,r||b(this,e,t,2,65535,0),this[t]=255&e,this[t+1]=e>>>8,t+2},d.prototype.writeUInt16BE=function(e,t,r){return e=+e,t>>>=0,r||b(this,e,t,2,65535,0),this[t]=e>>>8,this[t+1]=255&e,t+2},d.prototype.writeUInt32LE=function(e,t,r){return e=+e,t>>>=0,r||b(this,e,t,4,4294967295,0),this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e,t+4},d.prototype.writeUInt32BE=function(e,t,r){return e=+e,t>>>=0,r||b(this,e,t,4,4294967295,0),this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e,t+4},d.prototype.writeIntLE=function(e,t,r,o){e=+e,t>>>=0,o||b(this,e,t,r,(o=Math.pow(2,8*r-1))-1,-o);var n=0,s=1,i=0;for(this[t]=255&e;++n>0)-i&255;return t+r},d.prototype.writeIntBE=function(e,t,r,o){e=+e,t>>>=0,o||b(this,e,t,r,(o=Math.pow(2,8*r-1))-1,-o);var n=r-1,s=1,i=0;for(this[t+n]=255&e;0<=--n&&(s*=256);)e<0&&0===i&&0!==this[t+n+1]&&(i=1),this[t+n]=(e/s>>0)-i&255;return t+r},d.prototype.writeInt8=function(e,t,r){return e=+e,t>>>=0,r||b(this,e,t,1,127,-128),this[t]=255&(e=e<0?255+e+1:e),t+1},d.prototype.writeInt16LE=function(e,t,r){return e=+e,t>>>=0,r||b(this,e,t,2,32767,-32768),this[t]=255&e,this[t+1]=e>>>8,t+2},d.prototype.writeInt16BE=function(e,t,r){return e=+e,t>>>=0,r||b(this,e,t,2,32767,-32768),this[t]=e>>>8,this[t+1]=255&e,t+2},d.prototype.writeInt32LE=function(e,t,r){return e=+e,t>>>=0,r||b(this,e,t,4,2147483647,-2147483648),this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24,t+4},d.prototype.writeInt32BE=function(e,t,r){return e=+e,t>>>=0,r||b(this,e,t,4,2147483647,-2147483648),this[t]=(e=e<0?4294967295+e+1:e)>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e,t+4},d.prototype.writeFloatLE=function(e,t,r){return _(this,e,t,!0,r)},d.prototype.writeFloatBE=function(e,t,r){return _(this,e,t,!1,r)},d.prototype.writeDoubleLE=function(e,t,r){return x(this,e,t,!0,r)},d.prototype.writeDoubleBE=function(e,t,r){return x(this,e,t,!1,r)},d.prototype.copy=function(e,t,r,o){if(!d.isBuffer(e))throw new TypeError("argument should be a Buffer");if(r=r||0,o||0===o||(o=this.length),t>=e.length&&(t=e.length),(o=0=this.length)throw new RangeError("Index out of range");if(o<0)throw new RangeError("sourceEnd out of bounds");o>this.length&&(o=this.length);var n=(o=e.length-t>>=0,r=void 0===r?this.length:r>>>0,"number"==typeof(e=e||0))for(s=t;s>6|192,63&r|128)}else if(r<65536){if((t-=3)<0)break;s.push(r>>12|224,r>>6&63|128,63&r|128)}else{if(!(r<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;s.push(r>>18|240,r>>12&63|128,r>>6&63|128,63&r|128)}}return s}function E(e){return S.toByteArray(function(e){if((e=(e=e.split("=")[0]).trim().replace(w,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function k(e,t,r,o){for(var n=0;n=t.length||n>=e.length);++n)t[n+r]=e[n];return n}function C(e,t){return e instanceof t||null!=e&&null!=e.constructor&&null!=e.constructor.name&&e.constructor.name===t.name}function O(e){return e!=e}var P=function(){for(var e="0123456789abcdef",t=new Array(256),r=0;r<16;++r)for(var o=16*r,n=0;n<16;++n)t[o+n]=e[r]+e[n];return t}()}.call(this,A("buffer").Buffer)},{"base64-js":1,buffer:4,ieee754:246}],5:[function(e,t,r){t.exports=function(e){if("function"!=typeof e)throw TypeError(String(e)+" is not a function");return e}},{}],6:[function(e,t,r){var o=e("../internals/is-object");t.exports=function(e){if(o(e)||null===e)return e;throw TypeError("Can't set "+String(e)+" as a prototype")}},{"../internals/is-object":74}],7:[function(e,t,r){var o=e("../internals/well-known-symbol"),n=e("../internals/object-create"),e=e("../internals/object-define-property"),s=o("unscopables"),i=Array.prototype;null==i[s]&&e.f(i,s,{configurable:!0,value:n(null)}),t.exports=function(e){i[s][e]=!0}},{"../internals/object-create":90,"../internals/object-define-property":92,"../internals/well-known-symbol":148}],8:[function(e,t,r){"use strict";var o=e("../internals/string-multibyte").charAt;t.exports=function(e,t,r){return t+(r?o(e,t).length:1)}},{"../internals/string-multibyte":123}],9:[function(e,t,r){t.exports=function(e,t,r){if(e instanceof t)return e;throw TypeError("Incorrect "+(r?r+" ":"")+"invocation")}},{}],10:[function(e,t,r){var o=e("../internals/is-object");t.exports=function(e){if(o(e))return e;throw TypeError(String(e)+" is not an object")}},{"../internals/is-object":74}],11:[function(e,t,r){t.exports="undefined"!=typeof ArrayBuffer&&"undefined"!=typeof DataView},{}],12:[function(e,t,r){"use strict";function o(e){return l(e)&&u(M,c(e))}var n,s=e("../internals/array-buffer-native"),i=e("../internals/descriptors"),a=e("../internals/global"),l=e("../internals/is-object"),u=e("../internals/has"),c=e("../internals/classof"),d=e("../internals/create-non-enumerable-property"),h=e("../internals/redefine"),f=e("../internals/object-define-property").f,p=e("../internals/object-get-prototype-of"),m=e("../internals/object-set-prototype-of"),y=e("../internals/well-known-symbol"),e=e("../internals/uid"),g=a.Int8Array,v=g&&g.prototype,b=a.Uint8ClampedArray,b=b&&b.prototype,j=g&&p(g),_=v&&p(v),x=Object.prototype,w=x.isPrototypeOf,y=y("toStringTag"),S=e("TYPED_ARRAY_TAG"),T=s&&!!m&&"Opera"!==c(a.opera),e=!1,M={Int8Array:1,Uint8Array:1,Uint8ClampedArray:1,Int16Array:2,Uint16Array:2,Int32Array:4,Uint32Array:4,Float32Array:4,Float64Array:8};for(n in M)a[n]||(T=!1);if((!T||"function"!=typeof j||j===Function.prototype)&&(j=function(){throw TypeError("Incorrect invocation")},T))for(n in M)a[n]&&m(a[n],j);if((!T||!_||_===x)&&(_=j.prototype,T))for(n in M)a[n]&&m(a[n].prototype,_);if(T&&p(b)!==_&&m(b,_),i&&!u(_,y))for(n in e=!0,f(_,y,{get:function(){return l(this)?this[S]:void 0}}),M)a[n]&&d(a[n],S,n);t.exports={NATIVE_ARRAY_BUFFER_VIEWS:T,TYPED_ARRAY_TAG:e&&S,aTypedArray:function(e){if(o(e))return e;throw TypeError("Target is not a typed array")},aTypedArrayConstructor:function(e){if(m){if(w.call(j,e))return e}else for(var t in M)if(u(M,n)){t=a[t];if(t&&(e===t||w.call(t,e)))return e}throw TypeError("Target is not a typed array constructor")},exportTypedArrayMethod:function(e,t,r){if(i){if(r)for(var o in M){o=a[o];o&&u(o.prototype,e)&&delete o.prototype[e]}_[e]&&!r||h(_,e,!r&&T&&v[e]||t)}},exportTypedArrayStaticMethod:function(e,t,r){var o,n;if(i){if(m){if(r)for(o in M)(n=a[o])&&u(n,e)&&delete n[e];if(j[e]&&!r)return;try{return h(j,e,!r&&T&&g[e]||t)}catch(e){}}for(o in M)!(n=a[o])||n[e]&&!r||h(n,e,t)}},isView:function(e){e=c(e);return"DataView"===e||u(M,e)},isTypedArray:o,TypedArray:j,TypedArrayPrototype:_}},{"../internals/array-buffer-native":11,"../internals/classof":29,"../internals/create-non-enumerable-property":38,"../internals/descriptors":43,"../internals/global":59,"../internals/has":60,"../internals/is-object":74,"../internals/object-define-property":92,"../internals/object-get-prototype-of":97,"../internals/object-set-prototype-of":101,"../internals/redefine":108,"../internals/uid":145,"../internals/well-known-symbol":148}],13:[function(e,t,D){"use strict";function r(e){return[255&e]}function o(e){return[255&e,e>>8&255]}function n(e){return[255&e,e>>8&255,e>>16&255,e>>24&255]}function s(e){return e[3]<<24|e[2]<<16|e[1]<<8|e[0]}function i(e){return O(e,23,4)}function F(e){return O(e,52,8)}function a(e,t){H(e[w],t,{get:function(){return b(this)[t]}})}function l(e,t,r,o){if(r=m(r),e=b(e),r+t>e.byteLength)throw C(S);var n=b(e.buffer).bytes,r=r+e.byteOffset,e=n.slice(r,r+t);return o?e:e.reverse()}function u(e,t,r,o,n,s){if(r=m(r),e=b(e),r+t>e.byteLength)throw C(S);for(var i=b(e.buffer).bytes,a=r+e.byteOffset,l=o(+n),u=0;uR;)(A=L[R++])in M||N(M,A,T[A]);c.constructor=M}g&&V(e)!==k&&g(e,k);var y=new E(new M(2)),I=e.setInt8;y.setInt8(0,2147483648),y.setInt8(1,2147483649),!y.getInt8(0)&&y.getInt8(1)||h(e,{setInt8:function(e,t){I.call(this,e,t<<24>>24)},setUint8:function(e,t){I.call(this,e,t<<24>>24)}},{unsafe:!0})}else M=function(e){p(this,M,_);e=m(e);j(this,{bytes:W.call(new Array(e),0),byteLength:e}),d||(this.byteLength=e)},E=function(e,t,r){p(this,E,x),p(e,M,x);var o=b(e).byteLength,t=B(t);if(t<0||o>24},getUint8:function(e){return l(this,1,e)[0]},getInt16:function(e){e=l(this,2,e,1>16},getUint16:function(e){e=l(this,2,e,1>>0},getFloat32:function(e){return P(l(this,4,e,1"+e+""}},{"../internals/require-object-coercible":113}],37:[function(e,t,r){"use strict";function o(){return this}var n=e("../internals/iterators-core").IteratorPrototype,s=e("../internals/object-create"),i=e("../internals/create-property-descriptor"),a=e("../internals/set-to-string-tag"),l=e("../internals/iterators");t.exports=function(e,t,r){t+=" Iterator";return e.prototype=s(n,{next:i(1,r)}),a(e,t,!1,!0),l[t]=o,e}},{"../internals/create-property-descriptor":39,"../internals/iterators":79,"../internals/iterators-core":78,"../internals/object-create":90,"../internals/set-to-string-tag":117}],38:[function(e,t,r){var o=e("../internals/descriptors"),n=e("../internals/object-define-property"),s=e("../internals/create-property-descriptor");t.exports=o?function(e,t,r){return n.f(e,t,s(1,r))}:function(e,t,r){return e[t]=r,e}},{"../internals/create-property-descriptor":39,"../internals/descriptors":43,"../internals/object-define-property":92}],39:[function(e,t,r){t.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},{}],40:[function(e,t,r){"use strict";var o=e("../internals/to-primitive"),n=e("../internals/object-define-property"),s=e("../internals/create-property-descriptor");t.exports=function(e,t,r){t=o(t);t in e?n.f(e,t,s(0,r)):e[t]=r}},{"../internals/create-property-descriptor":39,"../internals/object-define-property":92,"../internals/to-primitive":140}],41:[function(e,t,r){"use strict";function m(){return this}var y=e("../internals/export"),g=e("../internals/create-iterator-constructor"),v=e("../internals/object-get-prototype-of"),b=e("../internals/object-set-prototype-of"),j=e("../internals/set-to-string-tag"),_=e("../internals/create-non-enumerable-property"),x=e("../internals/redefine"),o=e("../internals/well-known-symbol"),w=e("../internals/is-pure"),S=e("../internals/iterators"),e=e("../internals/iterators-core"),T=e.IteratorPrototype,M=e.BUGGY_SAFARI_ITERATORS,E=o("iterator"),k="values",C="entries";t.exports=function(e,t,r,o,n,s,i){g(r,t,o);function a(e){if(e===n&&f)return f;if(!M&&e in d)return d[e];switch(e){case"keys":case k:case C:return function(){return new r(this,e)}}return function(){return new r(this)}}var l,u,o=t+" Iterator",c=!1,d=e.prototype,h=d[E]||d["@@iterator"]||n&&d[n],f=!M&&h||a(n),p="Array"==t&&d.entries||h;if(p&&(p=v(p.call(new e)),T!==Object.prototype&&p.next&&(w||v(p)===T||(b?b(p,T):"function"!=typeof p[E]&&_(p,E,m)),j(p,o,!0,!0),w&&(S[o]=m))),n==k&&h&&h.name!==k&&(c=!0,f=function(){return h.call(this)}),w&&!i||d[E]===f||_(d,E,f),S[t]=f,n)if(l={values:a(k),keys:s?f:a("keys"),entries:a(C)},i)for(u in l)!M&&!c&&u in d||x(d,u,l[u]);else y({target:t,proto:!0,forced:M||c},l);return l}},{"../internals/create-iterator-constructor":37,"../internals/create-non-enumerable-property":38,"../internals/export":50,"../internals/is-pure":75,"../internals/iterators":79,"../internals/iterators-core":78,"../internals/object-get-prototype-of":97,"../internals/object-set-prototype-of":101,"../internals/redefine":108,"../internals/set-to-string-tag":117,"../internals/well-known-symbol":148}],42:[function(e,t,r){var o=e("../internals/path"),n=e("../internals/has"),s=e("../internals/well-known-symbol-wrapped"),i=e("../internals/object-define-property").f;t.exports=function(e){var t=o.Symbol||(o.Symbol={});n(t,e)||i(t,e,{value:s.f(e)})}},{"../internals/has":60,"../internals/object-define-property":92,"../internals/path":104,"../internals/well-known-symbol-wrapped":147}],43:[function(e,t,r){e=e("../internals/fails");t.exports=!e(function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]})},{"../internals/fails":51}],44:[function(e,t,r){var o=e("../internals/global"),e=e("../internals/is-object"),n=o.document,s=e(n)&&e(n.createElement);t.exports=function(e){return s?n.createElement(e):{}}},{"../internals/global":59,"../internals/is-object":74}],45:[function(e,t,r){t.exports={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0}},{}],46:[function(e,t,r){e=e("../internals/engine-user-agent");t.exports=/(iphone|ipod|ipad).*applewebkit/i.test(e)},{"../internals/engine-user-agent":47}],47:[function(e,t,r){e=e("../internals/get-built-in");t.exports=e("navigator","userAgent")||""},{"../internals/get-built-in":56}],48:[function(e,t,r){var o,n,s=e("../internals/global"),e=e("../internals/engine-user-agent"),s=s.process,s=s&&s.versions,s=s&&s.v8;s?n=(o=s.split("."))[0]+o[1]:e&&(!(o=e.match(/Edge\/(\d+)/))||74<=o[1])&&(o=e.match(/Chrome\/(\d+)/))&&(n=o[1]),t.exports=n&&+n},{"../internals/engine-user-agent":47,"../internals/global":59}],49:[function(e,t,r){t.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},{}],50:[function(e,t,r){var u=e("../internals/global"),c=e("../internals/object-get-own-property-descriptor").f,d=e("../internals/create-non-enumerable-property"),h=e("../internals/redefine"),f=e("../internals/set-global"),p=e("../internals/copy-constructor-properties"),m=e("../internals/is-forced");t.exports=function(e,t){var r,o,n,s=e.target,i=e.global,a=e.stat,l=i?u:a?u[s]||f(s,{}):(u[s]||{}).prototype;if(l)for(r in t){if(o=t[r],n=e.noTargetGet?(n=c(l,r))&&n.value:l[r],!m(i?r:s+(a?".":"#")+r,e.forced)&&void 0!==n){if(typeof o==typeof n)continue;p(o,n)}(e.sham||n&&n.sham)&&d(o,"sham",!0),h(l,r,o,e)}}},{"../internals/copy-constructor-properties":33,"../internals/create-non-enumerable-property":38,"../internals/global":59,"../internals/is-forced":73,"../internals/object-get-own-property-descriptor":93,"../internals/redefine":108,"../internals/set-global":115}],51:[function(e,t,r){t.exports=function(e){try{return!!e()}catch(e){return!0}}},{}],52:[function(e,t,r){"use strict";e("../modules/es.regexp.exec");var u=e("../internals/redefine"),c=e("../internals/fails"),d=e("../internals/well-known-symbol"),h=e("../internals/regexp-exec"),f=e("../internals/create-non-enumerable-property"),p=d("species"),m=!c(function(){var e=/./;return e.exec=function(){var e=[];return e.groups={a:"7"},e},"7"!=="".replace(e,"$")}),y="$0"==="a".replace(/./,"$0"),e=d("replace"),g=!!/./[e]&&""===/./[e]("a","$0"),v=!c(function(){var e=/(?:)/,t=e.exec,e=(e.exec=function(){return t.apply(this,arguments)},"ab".split(e));return 2!==e.length||"a"!==e[0]||"b"!==e[1]});t.exports=function(r,e,t,o){var s,n,i=d(r),a=!c(function(){var e={};return e[i]=function(){return 7},7!=""[r](e)}),l=a&&!c(function(){var e=!1,t=/a/;return"split"===r&&((t={constructor:{}}).constructor[p]=function(){return t},t.flags="",t[i]=/./[i]),t.exec=function(){return e=!0,null},t[i](""),!e});a&&l&&("replace"!==r||m&&y&&!g)&&("split"!==r||v)||(s=/./[i],t=(l=t(i,""[r],function(e,t,r,o,n){return t.exec===h?a&&!n?{done:!0,value:s.call(t,r,o)}:{done:!0,value:e.call(r,t,o)}:{done:!1}},{REPLACE_KEEPS_$0:y,REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE:g}))[0],n=l[1],u(String.prototype,r,t),u(RegExp.prototype,i,2==e?function(e,t){return n.call(e,this,t)}:function(e){return n.call(e,this)})),o&&f(RegExp.prototype[i],"sham",!0)}},{"../internals/create-non-enumerable-property":38,"../internals/fails":51,"../internals/redefine":108,"../internals/regexp-exec":110,"../internals/well-known-symbol":148,"../modules/es.regexp.exec":187}],53:[function(e,t,r){e=e("../internals/fails");t.exports=!e(function(){return Object.isExtensible(Object.preventExtensions({}))})},{"../internals/fails":51}],54:[function(e,t,r){var s=e("../internals/a-function");t.exports=function(o,n,e){if(s(o),void 0===n)return o;switch(e){case 0:return function(){return o.call(n)};case 1:return function(e){return o.call(n,e)};case 2:return function(e,t){return o.call(n,e,t)};case 3:return function(e,t,r){return o.call(n,e,t,r)}}return function(){return o.apply(n,arguments)}}},{"../internals/a-function":5}],55:[function(e,t,r){"use strict";var o=e("../internals/a-function"),n=e("../internals/is-object"),c=[].slice,d={};t.exports=Function.bind||function(i){var a=o(this),l=c.call(arguments,1),u=function(){var e=l.concat(c.call(arguments));if(this instanceof u){var t=a,r=e.length,o=e;if(!(r in d)){for(var n=[],s=0;s>1,u=23===t?f(2,-24)-f(2,-77):0,c=e<0||0===e&&1/e<0?1:0,d=0;for((e=h(e))!=e||e===1/0?(n=e!=e?1:0,o=r):(o=p(m(e)/y),e*(s=f(2,-o))<1&&(o--,s*=2),2<=(e+=1<=o+l?u/s:u*f(2,1-l))*s&&(o++,s/=2),r<=o+l?(n=0,o=r):1<=o+l?(n=(e*s-1)*f(2,t),o+=l):(n=e*f(2,l-1)*f(2,t),o=0));8<=t;i[d++]=255&n,n/=256,t-=8);for(o=o<>1,a=n-7,l=o-1,n=e[l--],u=127&n;for(n>>=7;0>=-a,a+=t;0"+e+""},m=function(){try{n=document.domain&&new ActiveXObject("htmlfile")}catch(e){}m=n?((e=n).write(p("")),e.close(),t=e.parentWindow.Object,e=null,t):(e=c("iframe"),t="java"+h+":",e.style.display="none",u.appendChild(e),e.src=String(t),(t=e.contentWindow.document).open(),t.write(p("document.F=Object")),t.close(),t.F);for(var e,t,r=a.length;r--;)delete m[d][a[r]];return m()};l[f]=!0,t.exports=Object.create||function(e,t){var r;return null!==e?(o[d]=s(e),r=new o,o[d]=null,r[f]=e):r=m(),void 0===t?r:i(r,t)}},{"../internals/an-object":10,"../internals/document-create-element":44,"../internals/enum-bug-keys":49,"../internals/hidden-keys":61,"../internals/html":63,"../internals/object-define-properties":91,"../internals/shared-key":118}],91:[function(e,t,r){var o=e("../internals/descriptors"),i=e("../internals/object-define-property"),a=e("../internals/an-object"),l=e("../internals/object-keys");t.exports=o?Object.defineProperties:function(e,t){a(e);for(var r,o=l(t),n=o.length,s=0;sn;)!i(o,r=t[n++])||~l(s,r)||s.push(r);return s}},{"../internals/array-includes":18,"../internals/has":60,"../internals/hidden-keys":61,"../internals/to-indexed-object":134}],99:[function(e,t,r){var o=e("../internals/object-keys-internal"),n=e("../internals/enum-bug-keys");t.exports=Object.keys||function(e){return o(e,n)}},{"../internals/enum-bug-keys":49,"../internals/object-keys-internal":98}],100:[function(e,t,r){"use strict";var o={}.propertyIsEnumerable,n=Object.getOwnPropertyDescriptor,s=n&&!o.call({1:2},1);r.f=s?function(e){e=n(this,e);return!!e&&e.enumerable}:o},{}],101:[function(e,t,r){var n=e("../internals/an-object"),s=e("../internals/a-possible-prototype");t.exports=Object.setPrototypeOf||("__proto__"in{}?function(){var r,o=!1,e={};try{(r=Object.getOwnPropertyDescriptor(Object.prototype,"__proto__").set).call(e,[]),o=e instanceof Array}catch(e){}return function(e,t){return n(e),s(t),o?r.call(e,t):e.__proto__=t,e}}():void 0)},{"../internals/a-possible-prototype":6,"../internals/an-object":10}],102:[function(e,t,r){"use strict";var o=e("../internals/to-string-tag-support"),n=e("../internals/classof");t.exports=o?{}.toString:function(){return"[object "+n(this)+"]"}},{"../internals/classof":29,"../internals/to-string-tag-support":141}],103:[function(e,t,r){var o=e("../internals/get-built-in"),n=e("../internals/object-get-own-property-names"),s=e("../internals/object-get-own-property-symbols"),i=e("../internals/an-object");t.exports=o("Reflect","ownKeys")||function(e){var t=n.f(i(e)),r=s.f;return r?t.concat(r(e)):t}},{"../internals/an-object":10,"../internals/get-built-in":56,"../internals/object-get-own-property-names":95,"../internals/object-get-own-property-symbols":96}],104:[function(e,t,r){e=e("../internals/global");t.exports=e},{"../internals/global":59}],105:[function(e,t,r){t.exports=function(e){try{return{error:!1,value:e()}}catch(e){return{error:!0,value:e}}}},{}],106:[function(e,t,r){var o=e("../internals/an-object"),n=e("../internals/is-object"),s=e("../internals/new-promise-capability");t.exports=function(e,t){return o(e),n(t)&&t.constructor===e?t:((0,(e=s.f(e)).resolve)(t),e.promise)}},{"../internals/an-object":10,"../internals/is-object":74,"../internals/new-promise-capability":86}],107:[function(e,t,r){var n=e("../internals/redefine");t.exports=function(e,t,r){for(var o in t)n(e,o,t[o],r);return e}},{"../internals/redefine":108}],108:[function(e,t,r){var i=e("../internals/global"),a=e("../internals/create-non-enumerable-property"),l=e("../internals/has"),u=e("../internals/set-global"),o=e("../internals/inspect-source"),e=e("../internals/internal-state"),n=e.get,c=e.enforce,d=String(String).split("String");(t.exports=function(e,t,r,o){var n=!!o&&!!o.unsafe,s=!!o&&!!o.enumerable,o=!!o&&!!o.noTargetGet;"function"==typeof r&&("string"!=typeof t||l(r,"name")||a(r,"name",t),c(r).source=d.join("string"==typeof t?t:"")),e===i?s?e[t]=r:u(t,r):(n?!o&&e[t]&&(s=!0):delete e[t],s?e[t]=r:a(e,t,r))})(Function.prototype,"toString",function(){return"function"==typeof this&&n(this).source||o(this)})},{"../internals/create-non-enumerable-property":38,"../internals/global":59,"../internals/has":60,"../internals/inspect-source":68,"../internals/internal-state":70,"../internals/set-global":115}],109:[function(e,t,r){var o=e("./classof-raw"),n=e("./regexp-exec");t.exports=function(e,t){var r=e.exec;if("function"==typeof r){r=r.call(e,t);if("object"!=typeof r)throw TypeError("RegExp exec method returned something other than an Object or null");return r}if("RegExp"!==o(e))throw TypeError("RegExp#exec called on incompatible receiver");return n.call(e,t)}},{"./classof-raw":28,"./regexp-exec":110}],110:[function(e,t,r){"use strict";var o,n,d=e("./regexp-flags"),e=e("./regexp-sticky-helpers"),h=RegExp.prototype.exec,f=String.prototype.replace,s=h,p=(o=/a/,n=/b*/g,h.call(o,"a"),h.call(n,"a"),0!==o.lastIndex||0!==n.lastIndex),m=e.UNSUPPORTED_Y||e.BROKEN_CARET,y=void 0!==/()??/.exec("")[1];t.exports=s=p||y||m?function(e){var t,r,o,n,s=this,i=m&&s.sticky,a=d.call(s),l=s.source,u=0,c=e;return i&&(-1===(a=a.replace("y","")).indexOf("g")&&(a+="g"),c=String(e).slice(s.lastIndex),0t&&(o=o.slice(0,t)),n?e+o:o+e)}}var s=e("../internals/to-length"),i=e("../internals/string-repeat"),a=e("../internals/require-object-coercible"),l=Math.ceil;t.exports={start:o(!1),end:o(!0)}},{"../internals/require-object-coercible":113,"../internals/string-repeat":127,"../internals/to-length":136}],126:[function(e,t,r){"use strict";function g(e){return e+22+75*(e<26)}function s(e){var t,r=[],o=(e=function(e){for(var t=[],r=0,o=e.length;rT((v-s)/d))throw RangeError(w);for(s+=(u-n)*d,n=u,c=0;cv)throw RangeError(w);if(t==n){for(var h=s,f=b;;f+=b){var p=f<=i?1:i+j<=f?j:f-i;if(h>1,e+=T(e/t);S*j>>1>>=1)&&(t+=t))1&o&&(r+=t);return r}},{"../internals/require-object-coercible":113,"../internals/to-integer":135}],128:[function(e,t,r){var o=e("../internals/fails"),n=e("../internals/whitespaces");t.exports=function(e){return o(function(){return!!n[e]()||"​…᠎"!="​…᠎"[e]()||n[e].name!==e})}},{"../internals/fails":51,"../internals/whitespaces":149}],129:[function(e,t,r){function o(t){return function(e){e=String(n(e));return 1&t&&(e=e.replace(s,"")),e=2&t?e.replace(i,""):e}}var n=e("../internals/require-object-coercible"),e="["+e("../internals/whitespaces")+"]",s=RegExp("^"+e+e+"*"),i=RegExp(e+e+"*$");t.exports={start:o(1),end:o(2),trim:o(3)}},{"../internals/require-object-coercible":113,"../internals/whitespaces":149}],130:[function(e,t,r){function o(e){return function(){x(e)}}function n(e){x(e.data)}function s(e){a.postMessage(e+"",f.protocol+"//"+f.host)}var i,a=e("../internals/global"),l=e("../internals/fails"),u=e("../internals/classof-raw"),c=e("../internals/function-bind-context"),d=e("../internals/html"),h=e("../internals/document-create-element"),e=e("../internals/engine-is-ios"),f=a.location,p=a.setImmediate,m=a.clearImmediate,y=a.process,g=a.MessageChannel,v=a.Dispatch,b=0,j={},_="onreadystatechange",x=function(e){var t;j.hasOwnProperty(e)&&(t=j[e],delete j[e],t())};p&&m||(p=function(e){for(var t=[],r=1;r=t.length?{value:e.target=void 0,done:!0}:"keys"==r?{value:o,done:!1}:"values"==r?{value:t[o],done:!1}:{value:[o,t[o]],done:!1}},"values"),s.Arguments=s.Array,n("keys"),n("values"),n("entries")},{"../internals/add-to-unscopables":7,"../internals/define-iterator":41,"../internals/internal-state":70,"../internals/iterators":79,"../internals/to-indexed-object":134}],162:[function(e,t,r){"use strict";var o=e("../internals/export"),n=e("../internals/indexed-object"),s=e("../internals/to-indexed-object"),e=e("../internals/array-method-is-strict"),i=[].join,n=n!=Object,e=e("join",",");o({target:"Array",proto:!0,forced:n||!e},{join:function(e){return i.call(s(this),void 0===e?",":e)}})},{"../internals/array-method-is-strict":22,"../internals/export":50,"../internals/indexed-object":66,"../internals/to-indexed-object":134}],163:[function(e,t,r){var o=e("../internals/export"),e=e("../internals/array-last-index-of");o({target:"Array",proto:!0,forced:e!==[].lastIndexOf},{lastIndexOf:e})},{"../internals/array-last-index-of":20,"../internals/export":50}],164:[function(e,t,r){"use strict";var o=e("../internals/export"),n=e("../internals/array-iteration").map,s=e("../internals/array-method-has-species-support"),e=e("../internals/array-method-uses-to-length"),s=s("map"),e=e("map");o({target:"Array",proto:!0,forced:!s||!e},{map:function(e){return n(this,e,1T;T++)l(b,x=S[T])&&!l(w,x)&&y(w,x,m(b,x));(w.prototype=j).constructor=w,a(s,v,w)}},{"../internals/classof-raw":28,"../internals/descriptors":43,"../internals/fails":51,"../internals/global":59,"../internals/has":60,"../internals/inherit-if-required":67,"../internals/is-forced":73,"../internals/object-create":90,"../internals/object-define-property":92,"../internals/object-get-own-property-descriptor":93,"../internals/object-get-own-property-names":95,"../internals/redefine":108,"../internals/string-trim":129,"../internals/to-primitive":140}],174:[function(e,t,r){e("../internals/export")({target:"Number",stat:!0},{isFinite:e("../internals/number-is-finite")})},{"../internals/export":50,"../internals/number-is-finite":88}],175:[function(e,t,r){"use strict";function c(e,t,r){return 0===t?r:t%2==1?c(e,t-1,r*e):c(e*e,t/2,r)}var o=e("../internals/export"),d=e("../internals/to-integer"),h=e("../internals/this-number-value"),f=e("../internals/string-repeat"),e=e("../internals/fails"),n=1..toFixed,p=Math.floor;o({target:"Number",proto:!0,forced:n&&("0.000"!==8e-5.toFixed(3)||"1"!==.9.toFixed(0)||"1.25"!==1.255.toFixed(2)||"1000000000000000128"!==0xde0b6b3a7640080.toFixed(0))||!e(function(){n.call({})})},{toFixed:function(e){function t(e,t){for(var r=-1,o=t;++r<6;)o+=e*a[r],a[r]=o%1e7,o=p(o/1e7)}function r(e){for(var t=6,r=0;0<=--t;)r+=a[t],a[t]=p(r/e),r=r%e*1e7}function o(){for(var e,t=6,r="";0<=--t;)""===r&&0!==t&&0===a[t]||(e=String(a[t]),r=""===r?e:r+f.call("0",7-e.length)+e);return r}var n,s,i=h(this),e=d(e),a=[0,0,0,0,0,0],l="",u="0";if(e<0||20n;){var s,i,a,l=y[n++],u=t?l.ok:l.fail,c=l.resolve,d=l.reject,h=l.domain;try{u?(t||(p.rejection===oe&&function(e,t){v.call(g,function(){if(k)T.emit("rejectionHandled",e);else se(te,e,t.value)})}(f,p),p.rejection=P),!0===u?s=e:(h&&h.enter(),s=u(e),h&&(h.exit(),a=!0)),s===l.promise?d(w("Promise-chain cycle")):(i=ne(s))?i.call(s,c,d):c(s)):d(e)}catch(e){h&&!a&&h.exit(),d(e)}}p.reactions=[],p.notified=!1,m&&!p.rejection&&(r=f,o=p,v.call(g,function(){var e=o.value,t=ie(o);if(t&&(t=b(function(){k?T.emit("unhandledRejection",e,r):se(C,r,e)}),o.rejection=k||ie(o)?oe:P,t.error))throw t.value}))}))},se=function(e,t,r){var o;ee?((o=S.createEvent("Event")).promise=t,o.reason=r,o.initEvent(e,!1,!0),g.dispatchEvent(o)):o={promise:t,reason:r},(t=g["on"+e])?t(o):e===C&&Y("Unhandled promise rejection",r)},ie=function(e){return e.rejection!==P&&!e.parent},L=function(t,r,o,n){return function(e){t(r,o,e,n)}},R=function(e,t,r,o){t.done||(t.done=!0,(t=o?o:t).value=r,t.state=re,A(e,t,!0))},I=function(r,o,e,t){if(!o.done){o.done=!0,t&&(o=t);try{if(r===e)throw w("Promise can't be resolved itself");var n=ne(e);n?u(function(){var t={done:!1};try{n.call(e,L(I,r,t,o),L(R,r,t,o))}catch(e){R(r,t,e,o)}}):(o.value=e,o.state=O,A(r,o,!1))}catch(e){R(r,{done:!1},e,o)}}};e&&(x=function(e){z(this,x,j),c(e),r.call(this);var t=_(this);try{e(L(I,this,t),L(R,this,t))}catch(e){R(this,t,e)}},(r=function(e){J(this,{type:j,done:!1,notified:!1,parent:!1,reactions:[],rejection:!1,state:0,value:void 0})}).prototype=N(x.prototype,{then:function(e,t){var r=K(this),o=E(X(this,x));return o.ok="function"!=typeof e||e,o.fail="function"==typeof t&&t,o.domain=k?T.domain:void 0,r.parent=!0,r.reactions.push(o),0!=r.state&&A(this,r,!1),o.promise},catch:function(e){return this.then(void 0,e)}}),t=function(){var e=new r,t=_(e);this.promise=e,this.resolve=L(I,e,t),this.reject=L(R,e,t)},f.f=E=function(e){return e===x||e===o?new t:$(e)},i||"function"!=typeof l||(n=l.prototype.then,U(l.prototype,"then",function(e,t){var r=this;return new x(function(e,t){n.call(r,e,t)}).then(e,t)},{unsafe:!0}),"function"==typeof M&&s({global:!0,enumerable:!0,forced:!0},{fetch:function(e){return h(x,M.apply(g,arguments))}}))),s({global:!0,wrap:!0,forced:e},{Promise:x}),B(x,j,!1,!0),G(j),o=a(j),s({target:j,stat:!0,forced:e},{reject:function(e){var t=E(this);return t.reject.call(void 0,e),t.promise}}),s({target:j,stat:!0,forced:i||e},{resolve:function(e){return h(i&&this===o?x:this,e)}}),s({target:j,stat:!0,forced:m},{all:function(e){var a=this,t=E(a),l=t.resolve,u=t.reject,r=b(function(){var o=c(a.resolve),n=[],s=0,i=1;d(e,function(e){var t=s++,r=!1;n.push(void 0),i++,o.call(a,e).then(function(e){r||(r=!0,n[t]=e,--i||l(n))},u)}),--i||l(n)});return r.error&&u(r.value),t.promise},race:function(e){var r=this,o=E(r),n=o.reject,t=b(function(){var t=c(r.resolve);d(e,function(e){t.call(r,e).then(o.resolve,n)})});return t.error&&n(t.value),o.promise}})},{"../internals/a-function":5,"../internals/an-instance":9,"../internals/check-correctness-of-iteration":27,"../internals/classof-raw":28,"../internals/engine-v8-version":48,"../internals/export":50,"../internals/get-built-in":56,"../internals/global":59,"../internals/host-report-errors":62,"../internals/inspect-source":68,"../internals/internal-state":70,"../internals/is-forced":73,"../internals/is-object":74,"../internals/is-pure":75,"../internals/iterate":77,"../internals/microtask":81,"../internals/native-promise-constructor":82,"../internals/new-promise-capability":86,"../internals/perform":105,"../internals/promise-resolve":106,"../internals/redefine":108,"../internals/redefine-all":107,"../internals/set-species":116,"../internals/set-to-string-tag":117,"../internals/species-constructor":121,"../internals/task":130,"../internals/well-known-symbol":148}],184:[function(e,t,r){var o=e("../internals/export"),n=e("../internals/get-built-in"),s=e("../internals/a-function"),i=e("../internals/an-object"),a=e("../internals/is-object"),l=e("../internals/object-create"),u=e("../internals/function-bind"),e=e("../internals/fails"),c=n("Reflect","construct"),d=e(function(){function e(){}return!(c(function(){},[],e)instanceof e)}),h=!e(function(){c(function(){})}),n=d||h;o({target:"Reflect",stat:!0,forced:n,sham:n},{construct:function(e,t){s(e),i(t);var r=arguments.length<3?e:s(arguments[2]);if(h&&!d)return c(e,t,r);if(e==r){switch(t.length){case 0:return new e;case 1:return new e(t[0]);case 2:return new e(t[0],t[1]);case 3:return new e(t[0],t[1],t[2]);case 4:return new e(t[0],t[1],t[2],t[3])}var o=[null];return o.push.apply(o,t),new(u.apply(e,o))}o=r.prototype,r=l(a(o)?o:Object.prototype),o=Function.apply.call(e,r,t);return a(o)?o:r}})},{"../internals/a-function":5,"../internals/an-object":10,"../internals/export":50,"../internals/fails":51,"../internals/function-bind":55,"../internals/get-built-in":56,"../internals/is-object":74,"../internals/object-create":90}],185:[function(e,t,r){var o=e("../internals/export"),s=e("../internals/is-object"),i=e("../internals/an-object"),a=e("../internals/has"),l=e("../internals/object-get-own-property-descriptor"),u=e("../internals/object-get-prototype-of");o({target:"Reflect",stat:!0},{get:function e(t,r){var o,n=arguments.length<3?t:arguments[2];return i(t)===n?t[r]:(o=l.f(t,r))?a(o,"value")?o.value:void 0===o.get?void 0:o.get.call(n):s(o=u(t))?e(o,r,n):void 0}})},{"../internals/an-object":10,"../internals/export":50,"../internals/has":60,"../internals/is-object":74,"../internals/object-get-own-property-descriptor":93,"../internals/object-get-prototype-of":97}],186:[function(e,t,r){var o=e("../internals/descriptors"),n=e("../internals/global"),s=e("../internals/is-forced"),i=e("../internals/inherit-if-required"),a=e("../internals/object-define-property").f,l=e("../internals/object-get-own-property-names").f,u=e("../internals/is-regexp"),c=e("../internals/regexp-flags"),d=e("../internals/regexp-sticky-helpers"),h=e("../internals/redefine"),f=e("../internals/fails"),p=e("../internals/internal-state").set,m=e("../internals/set-species"),y=e("../internals/well-known-symbol")("match"),g=n.RegExp,v=g.prototype,b=/a/g,j=/a/g,_=new g(b)!==b,x=d.UNSUPPORTED_Y;if(o&&s("RegExp",!_||x||f(function(){return j[y]=!1,g(b)!=b||g(j)==j||"/a/i"!=g(b,"i")}))){for(var w=function(e,t){var r,o=this instanceof w,n=u(e),s=void 0===t;if(!o&&n&&e.constructor===w&&s)return e;_?n&&!s&&(e=e.source):e instanceof w&&(s&&(t=c.call(e)),e=e.source),x&&(r=!!t&&-1T;)!function(t){t in w||a(w,t,{configurable:!0,get:function(){return g[t]},set:function(e){g[t]=e}})}(S[T++]);(v.constructor=w).prototype=v,h(n,"RegExp",w)}m("RegExp")},{"../internals/descriptors":43,"../internals/fails":51,"../internals/global":59,"../internals/inherit-if-required":67,"../internals/internal-state":70,"../internals/is-forced":73,"../internals/is-regexp":76,"../internals/object-define-property":92,"../internals/object-get-own-property-names":95,"../internals/redefine":108,"../internals/regexp-flags":111,"../internals/regexp-sticky-helpers":112,"../internals/set-species":116,"../internals/well-known-symbol":148}],187:[function(e,t,r){"use strict";var o=e("../internals/export"),e=e("../internals/regexp-exec");o({target:"RegExp",proto:!0,forced:/./.exec!==e},{exec:e})},{"../internals/export":50,"../internals/regexp-exec":110}],188:[function(e,t,r){"use strict";var o=e("../internals/redefine"),n=e("../internals/an-object"),s=e("../internals/fails"),i=e("../internals/regexp-flags"),e="toString",a=RegExp.prototype,l=a[e],s=s(function(){return"/a/b"!=l.call({source:"a",flags:"b"})}),u=l.name!=e;(s||u)&&o(RegExp.prototype,e,function(){var e=n(this),t=String(e.source),r=e.flags;return"/"+t+"/"+String(void 0===r&&e instanceof RegExp&&!("flags"in a)?i.call(e):r)},{unsafe:!0})},{"../internals/an-object":10,"../internals/fails":51,"../internals/redefine":108,"../internals/regexp-flags":111}],189:[function(e,t,r){"use strict";var o=e("../internals/collection"),e=e("../internals/collection-strong");t.exports=o("Set",function(e){return function(){return e(this,arguments.length?arguments[0]:void 0)}},e)},{"../internals/collection":32,"../internals/collection-strong":30}],190:[function(e,t,r){"use strict";var o=e("../internals/export"),n=e("../internals/object-get-own-property-descriptor").f,s=e("../internals/to-length"),i=e("../internals/not-a-regexp"),a=e("../internals/require-object-coercible"),l=e("../internals/correct-is-regexp-logic"),e=e("../internals/is-pure"),u="".endsWith,c=Math.min,l=l("endsWith");o({target:"String",proto:!0,forced:!!(e||l||(!(o=n(String.prototype,"endsWith"))||o.writable))&&!l},{endsWith:function(e){var t=String(a(this)),r=(i(e),1=t.length?{value:void 0,done:!0}:(t=o(t,r),e.index+=t.length,{value:t,done:!1})})},{"../internals/define-iterator":41,"../internals/internal-state":70,"../internals/string-multibyte":123}],193:[function(e,t,r){"use strict";var o=e("../internals/fix-regexp-well-known-symbol-logic"),c=e("../internals/an-object"),d=e("../internals/to-length"),n=e("../internals/require-object-coercible"),h=e("../internals/advance-string-index"),f=e("../internals/regexp-exec-abstract");o("match",1,function(o,l,u){return[function(e){var t=n(this),r=null==e?void 0:e[o];return void 0!==r?r.call(e,t):new RegExp(e)[o](String(t))},function(e){var t=u(l,e,this);if(t.done)return t.value;var r=c(e),o=String(this);if(!r.global)return f(r,o);for(var n=r.unicode,s=[],i=r.lastIndex=0;null!==(a=f(r,o));){var a=String(a[0]);""===(s[i]=a)&&(r.lastIndex=h(o,d(r.lastIndex),n)),i++}return 0===i?null:s}]})},{"../internals/advance-string-index":8,"../internals/an-object":10,"../internals/fix-regexp-well-known-symbol-logic":52,"../internals/regexp-exec-abstract":109,"../internals/require-object-coercible":113,"../internals/to-length":136}],194:[function(e,t,r){"use strict";var o=e("../internals/export"),n=e("../internals/string-pad").start;o({target:"String",proto:!0,forced:e("../internals/string-pad-webkit-bug")},{padStart:function(e){return n(this,e,1]*>)/g,I=/\$([$&'`]|\d\d?)/g;o("replace",2,function(n,j,_,e){var x=e.REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE,w=e.REPLACE_KEEPS_$0,S=x?"$":"$0";return[function(e,t){var r=s(this),o=null==e?void 0:e[n];return void 0!==o?o.call(e,r,t):j.call(String(r),e,t)},function(e,t){if(!x&&w||"string"==typeof t&&-1===t.indexOf(S)){var r=_(j,e,this,t);if(r.done)return r.value}for(var o,n=T(e),s=String(this),i="function"==typeof t,a=(i||(t=String(t)),n.global),l=(a&&(o=n.unicode,n.lastIndex=0),[]);null!==(f=O(n,s))&&(l.push(f),a);)""===String(f[0])&&(n.lastIndex=C(s,E(n.lastIndex),o));for(var u,c="",d=0,h=0;h>>0;if(0==o)return[];if(void 0===e)return[r];if(!c(e))return p.call(r,e,o);for(var n,s,i,a=[],t=(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.unicode?"u":"")+(e.sticky?"y":""),l=0,u=new RegExp(e.source,t+"g");(n=h.call(u,r))&&!(l<(s=u.lastIndex)&&(a.push(r.slice(l,n.index)),1=o));)u.lastIndex===n.index&&u.lastIndex++;return l===r.length?!i&&u.test("")||a.push(""):a.push(r.slice(l)),a.length>o?a.slice(0,o):a}:"0".split(void 0,0).length?function(e,t){return void 0===e&&0===t?[]:p.call(this,e,t)}:p;return[function(e,t){var r=d(this),o=null==e?void 0:e[n];return void 0!==o?o.call(e,r,t):y.call(String(r),e,t)},function(e,t){var r=m(y,e,this,t,y!==p);if(r.done)return r.value;var r=g(e),o=String(this),e=v(r,RegExp),n=r.unicode,s=(r.ignoreCase?"i":"")+(r.multiline?"m":"")+(r.unicode?"u":"")+(S?"y":"g"),i=new e(S?r:"^(?:"+r.source+")",s),a=void 0===t?w:t>>>0;if(0==a)return[];if(0===o.length)return null===_(i,o)?[o]:[];for(var l=0,u=0,c=[];ue.key){o.splice(t,0,e);break}t===s&&o.push(e)}r.updateURL()},forEach:function(e){for(var t,r=P(this).entries,o=v(e,16)return;a=0;while(h()){l=null;if(a>0)if(h()=="."&&a<4)n++;else return;if(!x.test(h()))return;while(x.test(h())){u=parseInt(h(),10);if(l===null)l=u;else if(l==0)return;else l=l*10+u;if(l>255)return;n++}t[r]=t[r]*256+l;a++;if(a==2||a==4)r++}if(a!=4)return;break}else if(h()==":"){n++;if(!h())return}else if(h())return;t[r++]=s}if(o!==null){c=r-o;r=7;while(r!=0&&c>0){d=t[r];t[r--]=t[o+c-1];t[o+--c]=d}}else if(r!=8)return;return t}(t.slice(1,-1)))?void(e.host=r):_;if(k(e))return t=z(t),ne.test(t)||null===(r=function(e){var t=e.split("."),r,o,n,s,i,a,l;if(t.length&&t[t.length-1]=="")t.pop();if((r=t.length)>4)return e;for(o=[],n=0;n1&&s.charAt(0)=="0"){i=ee.test(s)?16:8;s=s.slice(i==8?1:2)}if(s==="")a=0;else{if(!(i==10?re:i==8?te:oe).test(s))return e;a=parseInt(s,i)}o.push(a)}for(n=0;n=Z(256,5-r))return null}else if(a>255)return null}for(l=o.pop(),n=0;n":1,"`":1}),ce=d({},ue,{"#":1,"?":1,"{":1,"}":1}),T=d({},ce,{"/":1,":":1,";":1,"=":1,"@":1,"[":1,"\\":1,"]":1,"^":1,"|":1}),M=function(e,t){var r=V(e,0);return 32h,applyPalette:()=>function(e,t,r="rgb565"){if(!e||!e.buffer)throw new Error("quantize() expected RGBA Uint8Array data");if(!(e instanceof Uint8Array||e instanceof Uint8ClampedArray))throw new Error("quantize() expected RGBA Uint8Array data");if(256>24&255,c=l>>16&255,d=l>>8&255,l=255&l,h=P(l,d,c,u),h=h in a?a[h]:a[h]=function(t,r,o,n,s){let i=0,a=1e100;for(let e=0;ea||(l=u[0],(c+=v(l-t))>a||(l=u[1],(c+=v(l-r))>a||(l=u[2],(c+=v(l-o))>a||(a=c,i=e))))}return i}(l,d,c,u,t);i[e]=h}else{const g="rgb444"===r?A:O;for(let e=0;e>16&255,m=f>>8&255,f=255&f,y=g(f,m,p),y=y in a?a[y]:a[y]=function(t,r,o,n){let s=0,i=1e100;for(let e=0;ei||(a=l[1],(u+=v(a-r))>i||(a=l[2],(u+=v(a-o))>i||(i=u,s=e)))}return s}(f,m,p,t);i[e]=y}}return i},default:()=>f,nearestColor:()=>function(e,t,r=u){return e[l(e,t,r)]},nearestColorIndex:()=>l,nearestColorIndexWithDistance:()=>d,prequantize:()=>function(e,{roundRGB:r=5,roundAlpha:o=10,oneBitAlpha:n=null}={}){const s=new Uint32Array(e.buffer);for(let t=0;t>24&255;var a,l=i>>16&255,u=i>>8&255,i=255&i;e=c(e,o),n&&(a="number"==typeof n?n:127,e=e<=a?0:255),i=c(i,r),u=c(u,r),l=c(l,r),s[t]=e<<24|l<<16|u<<8|i<<0}},quantize:()=>function(e,t,r={}){var{format:o="rgb565",clearAlpha:n=!0,clearAlphaColor:s=0,clearAlphaThreshold:i=0,oneBitAlpha:a=!1}=r;if(!e||!e.buffer)throw new Error("quantize() expected RGBA Uint8Array data");if(!(e instanceof Uint8Array||e instanceof Uint8ClampedArray))throw new Error("quantize() expected RGBA Uint8Array data");e=new Uint32Array(e.buffer);let l=!1!==r.useSqrt;const u="rgba4444"===o,c=function(r,e){const t="rgb444"===e?4096:65536,o=new Array(t),n=r.length;if("rgba4444"===e)for(let t=0;t>24&255,a=s>>16&255,l=s>>8&255,s=255&s,u=P(s,l,a,i);let e=u in o?o[u]:o[u]=D();e.rc+=s,e.gc+=l,e.bc+=a,e.ac+=i,e.cnt++}else if("rgb444"===e)for(let t=0;t>16&255,h=c>>8&255,c=255&c,f=A(c,h,d);let e=f in o?o[f]:o[f]=D();e.rc+=c,e.gc+=h,e.bc+=d,e.cnt++}else for(let t=0;t>16&255,y=p>>8&255,p=255&p,g=O(p,y,m);let e=g in o?o[g]:o[g]=D();e.rc+=p,e.gc+=y,e.bc+=m,e.cnt++}return o}(e,o),d=c.length,h=d-1,f=new Uint32Array(d+1);for(var p=0,m=0;m>1,!(c[y=f[v]].err<=b));g=v)f[g]=y;f[g]=m}var j,_=p-t;for(m=0;m<_;){for(;;){var x=f[1];if((j=c[x]).tm>=j.mtm&&c[j.nn].mtm<=j.tm)break;j.mtm==h?x=f[1]=f[f[0]--]:(I(c,x,!1),j.tm=m);b=c[x].err;for(g=1;(v=g+g)<=f[0]&&(vc[f[v+1]].err&&v++,!(b<=c[y=f[v]].err));g=v)f[g]=y;f[g]=x}var w=c[j.nn],S=j.cnt,T=w.cnt,M=1/(S+T);u&&(j.ac=M*(S*j.ac+T*w.ac)),j.rc=M*(S*j.rc+T*w.rc),j.gc=M*(S*j.gc+T*w.gc),j.bc=M*(S*j.bc+T*w.bc),j.cnt+=w.cnt,j.mtm=++m,c[w.bk].fw=w.fw,c[w.fw].bk=w.bk,w.mtm=h}let E=[];for(m=0;;0){let e=L(Math.round(c[m].rc),0,255),t=L(Math.round(c[m].gc),0,255),r=L(Math.round(c[m].bc),0,255),o=255;u&&(o=L(Math.round(c[m].ac),0,255),a&&(k="number"==typeof a?a:127,o=o<=k?0:255),n&&o<=i&&(e=t=r=s,o=0));var k=u?[e,t,r,o]:[e,t,r];if(function(t,r){for(let e=0;efunction(r,o,e=5){if(r.length&&o.length){var n=r.map(e=>e.slice(0,3)),s=e*e,i=r[0].length;for(let t=0;ti?e.slice(0,3):e.slice();var a=d(n,e.slice(0,3),u),l=a[0],a=a[1];0>>0),0!=t&&(e=Math.max(e,256));const r=s;s=new Uint8Array(e),0>=8,c-=8;if((v>m||f)&&(f?(p=h,m=(1<>=8,c-=8;0>3}function P(e,t,r,o){return e>>4|240&t|(240&r)<<4|(240&o)<<8}function A(e,t,r){return e>>4<<8|240&t|r>>4}function L(e,t,r){return e>8&255)}function C(e,t){for(var r=0;r>1,c=-7,d=r?n-1:0,h=r?-1:1,n=e[t+d];for(d+=h,s=n&(1<<-c)-1,n>>=-c,c+=a;0>=-c,c+=o;0>1,d=23===n?Math.pow(2,-24)-Math.pow(2,-77):0,h=o?0:s-1,f=o?1:-1,s=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(a=isNaN(t)?1:0,i=u):(i=Math.floor(Math.log(t)/Math.LN2),t*(o=Math.pow(2,-i))<1&&(i--,o*=2),2<=(t+=1<=i+c?d/o:d*Math.pow(2,1-c))*o&&(i++,o/=2),u<=i+c?(a=0,i=u):1<=i+c?(a=(t*o-1)*Math.pow(2,n),i+=c):(a=t*Math.pow(2,c-1)*Math.pow(2,n),i=0));8<=n;e[r+h]=255&a,h+=f,a/=256,n-=8);for(i=i<Math.abs(e[0])&&(t=1),t=Math.abs(e[2])>Math.abs(e[t])?2:t}function E(e,t){e.f+=t.f,e.b.f+=t.b.f}function h(e,t,r){return e=e.a,t=t.a,r=r.a,t.b.a===e?r.b.a===e?g(t.a,r.a)?b(r.b.a,t.a,r.a)<=0:0<=b(t.b.a,r.a,t.a):b(r.b.a,e,r.a)<=0:r.b.a===e?0<=b(t.b.a,e,t.a):(t=v(t.b.a,e,t.a),(e=v(r.b.a,e,r.a))<=t)}function k(e){e.a.i=null;var t=e.e;t.a.c=t.c,t.c.a=t.a,e.e=null}function C(e,t){m(e.a),e.c=!1,(e.a=t).i=e}function O(e){for(var t=e.a.a;(e=G(e)).a.a===t;);return e.c&&(C(e,t=S(B(e).a.b,e.a.e)),e=G(e)),e}function q(e,t,r){var o=new N;return o.a=r,o.e=p(e.f,t.e,o),r.i=o}function X(e,t){switch(e.s){case 100130:return 0!=(1&t);case 100131:return 0!==t;case 100132:return 0>1]],a[i[u]])?U:ue)(r,u),a[s]=null,l[s]=r.b,r.b=s}else for(r.c[-(s+1)]=null;0Math.max(i.a,l.a))){if(g(s,i)){if(0r.f&&(r.f*=2,r.c=ae(r.c,r.f+1)),0===r.b?n=o:(n=r.b,r.b=r.c[r.b]),r.e[n]=t,r.c[n]=o,r.d[o]=n,r.h&&ue(r,o),n):(r=e.a++,e.c[r]=t,-(r+1))}function se(e){if(0===e.a)return le(e.b);var t=e.c[e.d[e.a-1]];if(0!==e.b.a&&g(F(e.b),t))return le(e.b);for(;--e.a,0e.a||g(o[i],o[l])){n[r[s]=i]=s;break}n[r[s]=l]=s,s=a}}function ue(e,t){for(var r=e.d,o=e.e,n=e.c,s=t,i=r[s];;){var a=s>>1,l=r[a];if(0==a||g(o[l],o[i])){n[r[s]=i]=s;break}n[r[s]=l]=s,s=a}}function N(){this.e=this.a=null,this.f=0,this.c=this.b=this.h=this.d=!1}function B(e){return e.e.c.b}function G(e){return e.e.a.b}(t=r.prototype).x=function(){I(this,0)},t.B=function(e,t){switch(e){case 100142:return;case 100140:switch(t){case 100130:case 100131:case 100132:case 100133:case 100134:return void(this.s=t)}break;case 100141:return void(this.m=!!t);default:return void l(this,100900)}l(this,100901)},t.y=function(e){switch(e){case 100142:return 0;case 100140:return this.s;case 100141:return this.m;default:l(this,100900)}return!1},t.A=function(e,t,r){this.j[0]=e,this.j[1]=t,this.j[2]=r},t.z=function(e,t){var r=t||null;switch(e){case 100100:case 100106:this.h=r;break;case 100104:case 100110:this.l=r;break;case 100101:case 100107:this.k=r;break;case 100102:case 100108:this.i=r;break;case 100103:case 100109:this.p=r;break;case 100105:case 100111:this.o=r;break;case 100112:this.r=r;break;default:l(this,100900)}},t.C=function(e,t){var r=!1,o=[0,0,0];I(this,2);for(var n=0;n<3;++n){var s=e[n];s<-1e150&&(s=-1e150,r=!0),1e150o[u]&&(o[u]=c,n[u]=r)}if(o[1]-a[1]>o[r=0]-a[0]&&(r=1),a[r=o[2]-a[2]>o[r]-a[r]?2:r]>=o[r])i[0]=0,i[1]=0,i[2]=1;else{for(a=l[r],n=n[r],l=[o=0,0,0],a=[a.g[0]-n.g[0],a.g[1]-n.g[1],a.g[2]-n.g[2]],u=[0,0,0],r=s.e;r!==s;r=r.e)u[0]=r.g[0]-n.g[0],u[1]=r.g[1]-n.g[1],u[2]=r.g[2]-n.g[2],l[0]=a[1]*u[2]-a[2]*u[1],l[1]=a[2]*u[0]-a[0]*u[2],l[2]=a[0]*u[1]-a[1]*u[0],o<(c=l[0]*l[0]+l[1]*l[1]+l[2]*l[2])&&(o=c,i[0]=l[0],i[1]=l[1],i[2]=l[2]);o<=0&&(i[0]=i[1]=i[2]=0,i[W(a)]=1)}s=!0}for(l=W(i),r=this.b.c,o=(l+1)%3,n=(l+2)%3,l=0>=1;)++n;if(i=1<>8&255,g[v++]=255&t,g[v++]=t>>8&255,g[v++]=(null!==b?128:0)|n,g[v++]=s,g[v++]=0,null!==b)for(var a=0,l=b.length;a>16&255,g[v++]=u>>8&255,g[v++]=255&u}if(null!==o){if(o<0||65535>8&255,g[v++]=0}var _=!1;this.addFrame=function(e,t,r,o,n,s){if(!0===_&&(--v,_=!1),s=void 0===s?{}:s,e<0||t<0||65535>=1;)++u;var l=1<>8&255,g[v++]=f,g[v++]=0),g[v++]=44,g[v++]=255&e,g[v++]=e>>8&255,g[v++]=255&t,g[v++]=t>>8&255,g[v++]=255&r,g[v++]=r>>8&255,g[v++]=255&o,g[v++]=o>>8&255,g[v++]=!0===i?128|u-1:0,!0===i)for(var p=0,m=a.length;p>16&255,g[v++]=y>>8&255,g[v++]=255&y}return v=function(t,r,e,o){t[r++]=e;var n=r++,s=1<>=8,c-=8,r===n+256&&(t[n]=255,n=r++)}function f(e){d|=e<>=8,c-=8,r===n+256&&(t[n]=255,n=r++);4096===l?(f(s),l=1+a,u=e+1,m={}):(1<>=l,c-=l,y==s)a=1+i,u=(1<<(l=n+1))-1,m=null;else{if(y==i)break;for(var g=y>8,++v;var j=b;if(o>=8;null!==m&&a<4096&&(p[a++]=m<<8|j,u+1<=a&&l<12&&(++l,u=u<<1|1)),m=y}}h!==o&&console.log("Warning, gif stream shorter than expected.")}try{r.GifWriter=o,r.GifReader=function(b){var e=0;if(71!==b[e++]||73!==b[e++]||70!==b[e++]||56!==b[e++]||56!=(b[e++]+1&253)||97!==b[e++])throw new Error("Invalid GIF 87a/89a header.");var j=b[e++]|b[e++]<<8,t=b[e++]|b[e++]<<8,r=b[e++],o=1<<1+(7&r),n=(b[e++],b[e++],null),s=null,i=(r>>7&&(n=e,e+=3*(s=o)),!0),a=[],l=0,u=null,c=0,d=null;for(this.width=j,this.height=t;i&&e>2&7,e++;break;case 254:for(;;){if(!(0<=(f=b[e++])))throw Error("Invalid block size");if(0===f)break;e+=f}break;default:throw new Error("Unknown graphic control label: 0x"+b[e-1].toString(16))}break;case 44:var f,p=b[e++]|b[e++]<<8,m=b[e++]|b[e++]<<8,y=b[e++]|b[e++]<<8,g=b[e++]|b[e++]<<8,v=b[e++],_=v>>6&1,x=1<<1+(7&v),w=n,S=s,T=!1,v=(v>>7&&(T=!0,w=e,e+=3*(S=x)),e);for(e++;;){if(!(0<=(f=b[e++])))throw Error("Invalid block size");if(0===f)break;e+=f}a.push({x:p,y:m,width:y,height:g,has_local_palette:T,palette_offset:w,palette_size:S,data_offset:v,data_length:e-v,transparent_index:u,interlaced:!!_,delay:l,disposal:c});break;case 59:i=!1;break;default:throw new Error("Unknown gif block: 0x"+b[e-1].toString(16))}this.numFrames=function(){return a.length},this.loopCount=function(){return d},this.frameInfo=function(e){if(e<0||e>=a.length)throw new Error("Frame index out of range.");return a[e]},this.decodeAndBlitFrameBGRA=function(e,t){for(var e=this.frameInfo(e),r=e.width*e.height,o=new Uint8Array(r),n=(M(b,e.data_offset,o,r),e.palette_offset),s=e.transparent_index,i=(null===s&&(s=256),e.width),a=j-i,l=i,u=4*(e.y*j+e.x),c=4*((e.y+e.height)*j+e.x),d=u,h=4*a,f=(!0===e.interlaced&&(h+=4*j*7),8),p=0,m=o.length;p>=1)),v===s?d+=4:(y=b[n+3*v],g=b[n+3*v+1],v=b[n+3*v+2],t[d++]=v,t[d++]=g,t[d++]=y,t[d++]=255),--l}},this.decodeAndBlitFrameRGBA=function(e,t){for(var e=this.frameInfo(e),r=e.width*e.height,o=new Uint8Array(r),n=(M(b,e.data_offset,o,r),e.palette_offset),s=e.transparent_index,i=(null===s&&(s=256),e.width),a=j-i,l=i,u=4*(e.y*j+e.x),c=4*((e.y+e.height)*j+e.x),d=u,h=4*a,f=(!0===e.interlaced&&(h+=4*j*7),8),p=0,m=o.length;p>=1)),v===s?d+=4:(y=b[n+3*v],g=b[n+3*v+1],v=b[n+3*v+2],t[d++]=y,t[d++]=g,t[d++]=v,t[d++]=255),--l}}}}catch(e){}},{}],249:[function(Ar,r,o){!function(Pr){var e,t;e=this,t=function(j){"use strict";function D(e){if(null==this)throw TypeError();var t,r=String(this),o=r.length,e=e?Number(e):0;if(!((e=e!=e?0:e)<0||o<=e))return 55296<=(t=r.charCodeAt(e))&&t<=56319&&e+1>>16-t;return e.tag>>>=t,e.bitcount-=t,o+r}function $(e,t){for(;e.bitcount<24;)e.tag|=e.source[e.sourceIndex++]<>>=1,r+=t.table[++n],0<=(o-=t.table[n]););return e.tag=s,e.bitcount-=n,t.trans[r+o]}function ee(e,t,r){for(;;){var o=$(e,t);if(256===o)return U;if(o<256)e.dest[e.destLen++]=o;else for(var n,s=b(e,H[o-=257],W[o]),o=$(e,r),i=n=e.destLen-b(e,q[o],X[o]);i>>=1,o=n,b(s,2,0)){case 0:r=function(e){for(var t,r;8this.x2&&(this.x2=e)),"number"==typeof t&&((isNaN(this.y1)||isNaN(this.y2))&&(this.y1=t,this.y2=t),tthis.y2&&(this.y2=t))},a.prototype.addX=function(e){this.addPoint(e,null)},a.prototype.addY=function(e){this.addPoint(null,e)},a.prototype.addBezier=function(e,t,r,o,n,s,i,a){var l=[e,t],u=[r,o],c=[n,s],d=[i,a];this.addPoint(e,t),this.addPoint(i,a);for(var h=0;h<=1;h++){var f,p=6*l[h]-12*u[h]+6*c[h],m=-3*l[h]+9*u[h]-9*c[h]+3*d[h],y=3*u[h]-3*l[h];0==m?0==p||0<(f=-y/p)&&f<1&&(0===h&&this.addX(g(l[h],u[h],c[h],d[h],f)),1===h&&this.addY(g(l[h],u[h],c[h],d[h],f))):(f=Math.pow(p,2)-4*y*m)<0||(0<(y=(-p+Math.sqrt(f))/(2*m))&&y<1&&(0===h&&this.addX(g(l[h],u[h],c[h],d[h],y)),1===h&&this.addY(g(l[h],u[h],c[h],d[h],y))),0<(y=(-p-Math.sqrt(f))/(2*m))&&y<1&&(0===h&&this.addX(g(l[h],u[h],c[h],d[h],y)),1===h&&this.addY(g(l[h],u[h],c[h],d[h],y))))}},a.prototype.addQuad=function(e,t,r,o,n,s){r=e+2/3*(r-e),o=t+2/3*(o-t);this.addBezier(e,t,r,o,r+1/3*(n-e),o+1/3*(s-t),n,s)},h.prototype.moveTo=function(e,t){this.commands.push({type:"M",x:e,y:t})},h.prototype.lineTo=function(e,t){this.commands.push({type:"L",x:e,y:t})},h.prototype.curveTo=h.prototype.bezierCurveTo=function(e,t,r,o,n,s){this.commands.push({type:"C",x1:e,y1:t,x2:r,y2:o,x:n,y:s})},h.prototype.quadTo=h.prototype.quadraticCurveTo=function(e,t,r,o){this.commands.push({type:"Q",x1:e,y1:t,x:r,y:o})},h.prototype.close=h.prototype.closePath=function(){this.commands.push({type:"Z"})},h.prototype.extend=function(e){var t;if(e.commands)e=e.commands;else if(e instanceof a)return t=e,this.moveTo(t.x1,t.y1),this.lineTo(t.x2,t.y1),this.lineTo(t.x2,t.y2),this.lineTo(t.x1,t.y2),void this.close();Array.prototype.push.apply(this.commands,e)},h.prototype.getBoundingBox=function(){for(var e=new a,t=0,r=0,o=0,n=0,s=0;s>8&255,255&e]},l.USHORT=r(2),w.SHORT=function(e){return[(e=32768<=e?-(65536-e):e)>>8&255,255&e]},l.SHORT=r(2),w.UINT24=function(e){return[e>>16&255,e>>8&255,255&e]},l.UINT24=r(3),w.ULONG=function(e){return[e>>24&255,e>>16&255,e>>8&255,255&e]},l.ULONG=r(4),w.LONG=function(e){return[(e=2147483648<=e?-(4294967296-e):e)>>24&255,e>>16&255,e>>8&255,255&e]},l.LONG=r(4),w.FIXED=w.ULONG,l.FIXED=l.ULONG,w.FWORD=w.SHORT,l.FWORD=l.SHORT,w.UFWORD=w.USHORT,l.UFWORD=l.USHORT,w.LONGDATETIME=function(e){return[0,0,0,0,e>>24&255,e>>16&255,e>>8&255,255&e]},l.LONGDATETIME=r(8),w.TAG=function(e){return L.argument(4===e.length,"Tag should be exactly 4 ASCII characters."),[e.charCodeAt(0),e.charCodeAt(1),e.charCodeAt(2),e.charCodeAt(3)]},l.TAG=r(4),w.Card8=w.BYTE,l.Card8=l.BYTE,w.Card16=w.USHORT,l.Card16=l.USHORT,w.OffSize=w.BYTE,l.OffSize=l.BYTE,w.SID=w.USHORT,l.SID=l.USHORT,w.NUMBER=function(e){return-107<=e&&e<=107?[e+139]:108<=e&&e<=1131?[247+((e-=108)>>8),255&e]:-1131<=e&&e<=-108?[251+((e=-e-108)>>8),255&e]:-32768<=e&&e<=32767?w.NUMBER16(e):w.NUMBER32(e)},l.NUMBER=function(e){return w.NUMBER(e).length},w.NUMBER16=function(e){return[28,e>>8&255,255&e]},l.NUMBER16=r(3),w.NUMBER32=function(e){return[29,e>>24&255,e>>16&255,e>>8&255,255&e]},l.NUMBER32=r(5),w.REAL=function(e){for(var t=e.toString(),r=/\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/.exec(t),o=(r&&(r=parseFloat("1e"+((r[2]?+r[2]:0)+r[1].length)),t=(Math.round(e*r)/r).toString()),""),n=0,s=t.length;n>8&255,t[t.length]=255&o}return t},l.UTF16=function(e){return 2*e.length};var se,ie={"x-mac-croatian":"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®Š™´¨≠ŽØ∞±≤≥∆µ∂∑∏š∫ªºΩžø¿¡¬√ƒ≈Ć«Č… ÀÃÕŒœĐ—“”‘’÷◊©⁄€‹›Æ»–·‚„‰ÂćÁčÈÍÎÏÌÓÔđÒÚÛÙıˆ˜¯πË˚¸Êæˇ","x-mac-cyrillic":"АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ†°Ґ£§•¶І®©™Ђђ≠Ѓѓ∞±≤≥іµґЈЄєЇїЉљЊњјЅ¬√ƒ≈∆«»… ЋћЌќѕ–—“”‘’÷„ЎўЏџ№Ёёяабвгдежзийклмнопрстуфхцчшщъыьэю","x-mac-gaelic":"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØḂ±≤≥ḃĊċḊḋḞḟĠġṀæøṁṖṗɼƒſṠ«»… ÀÃÕŒœ–—“”‘’ṡẛÿŸṪ€‹›Ŷŷṫ·Ỳỳ⁊ÂÊÁËÈÍÎÏÌÓÔ♣ÒÚÛÙıÝýŴŵẄẅẀẁẂẃ","x-mac-greek":"Ĺ²É³ÖÜ΅àâä΄¨çéèê룙î‰ôö¦€ùûü†ΓΔΘΛΞΠß®©ΣΪ§≠°·Α±≤≥¥ΒΕΖΗΙΚΜΦΫΨΩάΝ¬ΟΡ≈Τ«»… ΥΧΆΈœ–―“”‘’÷ΉΊΌΎέήίόΏύαβψδεφγηιξκλμνοπώρστθωςχυζϊϋΐΰ­","x-mac-icelandic":"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûüÝ°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€ÐðÞþý·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ","x-mac-inuit":"ᐃᐄᐅᐆᐊᐋᐱᐲᐳᐴᐸᐹᑉᑎᑏᑐᑑᑕᑖᑦᑭᑮᑯᑰᑲᑳᒃᒋᒌᒍᒎᒐᒑ°ᒡᒥᒦ•¶ᒧ®©™ᒨᒪᒫᒻᓂᓃᓄᓅᓇᓈᓐᓯᓰᓱᓲᓴᓵᔅᓕᓖᓗᓘᓚᓛᓪᔨᔩᔪᔫᔭ… ᔮᔾᕕᕖᕗ–—“”‘’ᕘᕙᕚᕝᕆᕇᕈᕉᕋᕌᕐᕿᖀᖁᖂᖃᖄᖅᖏᖐᖑᖒᖓᖔᖕᙱᙲᙳᙴᙵᙶᖖᖠᖡᖢᖣᖤᖥᖦᕼŁł","x-mac-ce":"ÄĀāÉĄÖÜáąČäčĆć鏟ĎíďĒēĖóėôöõúĚěü†°Ę£§•¶ß®©™ę¨≠ģĮįĪ≤≥īĶ∂∑łĻļĽľĹĺŅņѬ√ńŇ∆«»… ňŐÕőŌ–—“”‘’÷◊ōŔŕŘ‹›řŖŗŠ‚„šŚśÁŤťÍŽžŪÓÔūŮÚůŰűŲųÝýķŻŁżĢˇ",macintosh:"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€‹›fifl‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ","x-mac-romanian":"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ĂȘ∞±≤≥¥µ∂∑∏π∫ªºΩăș¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€‹›Țț‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ","x-mac-turkish":"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸĞğİıŞş‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙˆ˜¯˘˙˚¸˝˛ˇ"},ae=(m.MACSTRING=function(e,t,r,o){var n=ie[o];if(void 0!==n){for(var s="",i=0;i>8&255,l+256&255)}return s})(e,t,r);return r},w.INDEX=function(e){for(var t=1,r=[t],o=[],n=0;n>8,t[c+1]=255&d,t=t.concat(o[u])}return t},l.TABLE=function(e){for(var t=0,r=e.fields.length,o=0;o>1,a.skip("uShort",3),y.glyphIndexMap={};for(var j,_=new R.Parser(g,v+b+14),x=new R.Parser(g,v+b+16+2*j),w=new R.Parser(g,v+b+16+4*j),S=new R.Parser(g,v+b+16+6*j),T=v+b+16+8*j,M=0;M>4,s=15&s;if(15==i)break;if(o+=n[i],15==s)break;o+=n[s]}return parseFloat(o)}if(32<=t&&t<=246)return t-139;if(247<=t&&t<=250)return 256*(t-247)+e.parseByte()+108;if(251<=t&&t<=254)return 256*-(t-251)-e.parseByte()-108;throw new Error("Invalid b0 "+t)}function Ie(e,t,r){var o=new R.Parser(e,t=void 0!==t?t:0),n=[],s=[];for(r=void 0!==r?r:e.length;o.relativeOffset>1,M.length=0,k=!0}return function e(t){for(var r,o,n,s,i,a,l,u,c,d,h,f,p=0;pMath.abs(f-P)?O=h+M.shift():P=f+M.shift(),T.curveTo(v,b,j,_,l,u),T.curveTo(c,d,h,f,O,P);break;default:console.log("Glyph "+g.index+": unknown operator 1200"+m),M.length=0}break;case 14:0>3;break;case 21:2>16),p+=2;break;case 29:i=M.pop()+y.gsubrsBias,(a=y.gsubrs[i])&&e(a);break;case 30:for(;0=r.begin&&e=c.length&&(s=o.parseChar(),r.names.push(o.parseString(s)));break;case 2.5:r.numberOfGlyphs=o.parseUShort(),r.offset=new Array(r.numberOfGlyphs);for(var a=0;at.value.tag?1:-1}),t.fields=t.fields.concat(o),t.fields=t.fields.concat(n),t}function xt(e,t,r){for(var o=0;o 123 are reserved for internal usage");f|=1<>>1,s=e[n].tag;if(s===t)return n;s>>1,s=e[n];if(s===t)return n;s>>1,i=(n=e[s]).start;if(i===t)return n;i(n=e[r-1]).end?0:n}function Et(e,t){this.font=e,this.tableName=t}function kt(e){Et.call(this,e,"gpos")}function i(e){Et.call(this,e,"gsub")}function Ct(e,t,r){for(var o=e.subtables,n=0;nt.points.length-1||o.matchedPoints[1]>n.points.length-1)throw Error("Matched points out of range in "+t.name);var i=t.points[o.matchedPoints[0]],a=n.points[o.matchedPoints[1]],o={xScale:o.xScale,scale01:o.scale01,scale10:o.scale10,yScale:o.yScale,dx:0,dy:0},a=Lt([a],o)[0];o.dx=i.x-a.x,o.dy=i.y-a.y,s=Lt(n.points,o)}t.points=t.points.concat(s)}}return Rt(t.points)}(kt.prototype=Et.prototype={searchTag:St,binSearch:Tt,getTable:function(e){var t=this.font.tables[this.tableName];return t=!t&&e?this.font.tables[this.tableName]=this.createDefaultTable():t},getScriptNames:function(){var e=this.getTable();return e?e.scripts.map(function(e){return e.tag}):[]},getDefaultScriptName:function(){var e=this.getTable();if(e){for(var t=!1,r=0;r=i[t-1].tag,"Features must be added in alphabetical order."),i.push(n={tag:r,feature:{params:0,lookupListIndexes:[]}}),s.push(t),n.feature}},getLookupTables:function(e,t,r,o,n){var e=this.getFeatureTable(e,t,r,n),s=[];if(e){for(var i,a=e.lookupListIndexes,l=this.font.tables[this.tableName].lookups,u=0;u",s),t.stack.push(Math.round(64*s))}function hr(e,t){var r=t.stack,o=r.pop(),n=t.fv,s=t.pv,i=t.ppem,a=t.deltaBase+16*(e-1),l=t.deltaShift,u=t.z0;j.DEBUG&&console.log(t.step,"DELTAP["+e+"]",o,r);for(var c=0;c>4)===i&&(0<=(h=(15&h)-8)&&h++,j.DEBUG&&console.log(t.step,"DELTAPFIX",d,"by",h*l),d=u[d],n.setRelative(d,d,h*l,s))}}function fr(e,t){var r=t.stack,o=r.pop();j.DEBUG&&console.log(t.step,"ROUND[]"),r.push(64*t.round(o/64))}function pr(e,t){var r=t.stack,o=r.pop(),n=t.ppem,s=t.deltaBase+16*(e-1),i=t.deltaShift;j.DEBUG&&console.log(t.step,"DELTAC["+e+"]",o,r);for(var a=0;a>4)===n&&(0<=(u=(15&u)-8)&&u++,u=u*i,j.DEBUG&&console.log(t.step,"DELTACFIX",l,"by",u),t.cvt[l]+=u)}}function mr(e,t){var r,o=t.stack,n=o.pop(),o=o.pop(),s=t.z2[n],i=t.z1[o];j.DEBUG&&console.log(t.step,"SDPVTL["+e+"]",n,o),n=e?(r=s.y-i.y,i.x-s.x):(r=i.x-s.x,i.y-s.y),t.dpv=qt(r,n)}function k(e,t){var r=t.stack,o=t.prog,n=t.ip;j.DEBUG&&console.log(t.step,"PUSHB["+e+"]");for(var s=0;s":"_")+(o?"R":"_")+(0===n?"Gr":1===n?"Bl":2===n?"Wh":"")+"]",e?u+"("+s.cvt[u]+","+a+")":"",l,"(d =",i,"->",y*m,")"),s.rp1=s.rp0,s.rp2=l,t&&(s.rp0=l)}Ft.prototype.exec=function(e,t){if("number"!=typeof t)throw new Error("Point size is not a number!");if(!(2",o),a.interpolate(d,s,i,l),a.touch(d)}e.loop=1},lr.bind(void 0,0),lr.bind(void 0,1),function(e){for(var t=e.stack,r=e.rp0,o=e.z0[r],n=e.loop,s=e.fv,i=e.pv,a=e.z1;n--;){var l=t.pop(),u=a[l];j.DEBUG&&console.log(e.step,(1'.concat(n,"").concat(t,""),this.dummyDOM||(this.dummyDOM=document.getElementById(o).parentNode),this.descriptions?this.descriptions.fallbackElements||(this.descriptions.fallbackElements={}):this.descriptions={fallbackElements:{}},this.descriptions.fallbackElements[e]?this.descriptions.fallbackElements[e].innerHTML!==n&&(this.descriptions.fallbackElements[e].innerHTML=n):this._describeElementHTML("fallback",e,n),r===this.LABEL&&(this.descriptions.labelElements||(this.descriptions.labelElements={}),this.descriptions.labelElements[e]?this.descriptions.labelElements[e].innerHTML!==n&&(this.descriptions.labelElements[e].innerHTML=n):this._describeElementHTML("label",e,n)))},s.default.prototype._describeHTML=function(e,t){var r,o=this.canvas.id;"fallback"===e?(this.dummyDOM.querySelector("#".concat(o+i))?this.dummyDOM.querySelector("#"+o+l).insertAdjacentHTML("beforebegin",'

')):(r='

'),this.dummyDOM.querySelector("#".concat(o,"accessibleOutput"))?this.dummyDOM.querySelector("#".concat(o,"accessibleOutput")).insertAdjacentHTML("beforebegin",r):this.dummyDOM.querySelector("#".concat(o)).innerHTML=r),this.descriptions.fallback=this.dummyDOM.querySelector("#".concat(o).concat(a)),this.descriptions.fallback.innerHTML=t):"label"===e&&(this.dummyDOM.querySelector("#".concat(o+u))?this.dummyDOM.querySelector("#".concat(o+d))&&this.dummyDOM.querySelector("#".concat(o+d)).insertAdjacentHTML("beforebegin",'

')):(r='

'),this.dummyDOM.querySelector("#".concat(o,"accessibleOutputLabel"))?this.dummyDOM.querySelector("#".concat(o,"accessibleOutputLabel")).insertAdjacentHTML("beforebegin",r):this.dummyDOM.querySelector("#"+o).insertAdjacentHTML("afterend",r)),this.descriptions.label=this.dummyDOM.querySelector("#"+o+c),this.descriptions.label.innerHTML=t)},s.default.prototype._describeElementHTML=function(e,t,r){var o,n=this.canvas.id;"fallback"===e?(this.dummyDOM.querySelector("#".concat(n+i))?this.dummyDOM.querySelector("#"+n+l)||this.dummyDOM.querySelector("#"+n+a).insertAdjacentHTML("afterend",'
Canvas elements and their descriptions
')):(o='
Canvas elements and their descriptions
'),this.dummyDOM.querySelector("#".concat(n,"accessibleOutput"))?this.dummyDOM.querySelector("#".concat(n,"accessibleOutput")).insertAdjacentHTML("beforebegin",o):this.dummyDOM.querySelector("#"+n).innerHTML=o),(o=document.createElement("tr")).id=n+"_fte_"+t,this.dummyDOM.querySelector("#"+n+l).appendChild(o),this.descriptions.fallbackElements[t]=this.dummyDOM.querySelector("#".concat(n).concat("_fte_").concat(t)),this.descriptions.fallbackElements[t].innerHTML=r):"label"===e&&(this.dummyDOM.querySelector("#".concat(n+u))?this.dummyDOM.querySelector("#".concat(n+d))||this.dummyDOM.querySelector("#"+n+c).insertAdjacentHTML("afterend",'
')):(o='
'),this.dummyDOM.querySelector("#".concat(n,"accessibleOutputLabel"))?this.dummyDOM.querySelector("#".concat(n,"accessibleOutputLabel")).insertAdjacentHTML("beforebegin",o):this.dummyDOM.querySelector("#"+n).insertAdjacentHTML("afterend",o)),(e=document.createElement("tr")).id=n+"_lte_"+t,this.dummyDOM.querySelector("#"+n+d).appendChild(e),this.descriptions.labelElements[t]=this.dummyDOM.querySelector("#".concat(n).concat("_lte_").concat(t)),this.descriptions.labelElements[t].innerHTML=r)};e=s.default;r.default=e},{"../core/main":275,"core-js/modules/es.array.concat":151,"core-js/modules/es.regexp.exec":187,"core-js/modules/es.string.ends-with":190,"core-js/modules/es.string.replace":196}],256:[function(e,t,r){"use strict";e("core-js/modules/es.array.concat"),e("core-js/modules/es.array.from"),e("core-js/modules/es.array.map"),e("core-js/modules/es.string.iterator"),e("core-js/modules/es.array.concat"),e("core-js/modules/es.array.from"),e("core-js/modules/es.array.map"),e("core-js/modules/es.string.iterator"),Object.defineProperty(r,"__esModule",{value:!0}),r.default=void 0;e=(e=e("../core/main"))&&e.__esModule?e:{default:e};e.default.prototype._updateGridOutput=function(e){var t,r,o,n;this.dummyDOM.querySelector("#".concat(e,"_summary"))&&(t=this._accessibleOutputs[e],o=function(e,t,r,o){t="".concat(t," canvas, ").concat(r," by ").concat(o," pixels, contains ").concat(e[0]);t=(1===e[0]?"".concat(t," shape: "):"".concat(t," shapes: ")).concat(e[1]);return t}((r=function(e,t){var r,o="",n="",s=0;for(r in t){var i,a=0;for(i in t[r]){var l='
  • ').concat(t[r][i].color," ").concat(r,",");"line"===r?l+=" location = ".concat(t[r][i].pos,", length = ").concat(t[r][i].length," pixels"):(l+=" location = ".concat(t[r][i].pos),"point"!==r&&(l+=", area = ".concat(t[r][i].area," %")),l+="
  • "),o+=l,a++,s++}n=1').concat(t[r][a].color," ").concat(r,"
    "):'').concat(t[r][a].color," ").concat(r," midpoint"),i[t[r][a].loc.locY][t[r][a].loc.locX]?i[t[r][a].loc.locY][t[r][a].loc.locX]=i[t[r][a].loc.locY][t[r][a].loc.locX]+" "+l:i[t[r][a].loc.locY][t[r][a].loc.locX]=l,n++}for(o in i){var u,c="";for(u in i[o])c+="",void 0!==i[o][u]&&(c+=i[o][u]),c+="";s=s+c+""}return s}(e,this.ingredients.shapes),o!==t.summary.innerHTML&&(t.summary.innerHTML=o),n!==t.map.innerHTML&&(t.map.innerHTML=n),r.details!==t.shapeDetails.innerHTML&&(t.shapeDetails.innerHTML=r.details),this._accessibleOutputs[e]=t)};e=e.default;r.default=e},{"../core/main":275,"core-js/modules/es.array.concat":151,"core-js/modules/es.array.from":158,"core-js/modules/es.array.map":164,"core-js/modules/es.string.iterator":192}],257:[function(e,t,r){"use strict";e("core-js/modules/es.symbol"),e("core-js/modules/es.symbol.description"),e("core-js/modules/es.symbol.iterator"),e("core-js/modules/es.array.concat"),e("core-js/modules/es.array.fill"),e("core-js/modules/es.array.from"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.map"),e("core-js/modules/es.number.to-fixed"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.regexp.to-string"),e("core-js/modules/es.string.iterator"),e("core-js/modules/web.dom-collections.iterator"),e("core-js/modules/es.array.concat"),e("core-js/modules/es.array.fill"),e("core-js/modules/es.array.map"),e("core-js/modules/es.number.to-fixed"),Object.defineProperty(r,"__esModule",{value:!0}),r.default=void 0;var o=(e=e("../core/main"))&&e.__esModule?e:{default:e};function l(e){return function(e){if(Array.isArray(e)){for(var t=0,r=new Array(e.length);t
    ')):this.dummyDOM.querySelector("#".concat(s)).innerHTML='
    '))):"Label"===t&&(r=s+e+(i=t),this.dummyDOM.querySelector("#".concat(o=s+"accessibleOutput"+t))||(this.dummyDOM.querySelector("#".concat(s,"_Label"))?this.dummyDOM.querySelector("#".concat(s,"_Label")):this.dummyDOM.querySelector("#".concat(s))).insertAdjacentHTML("afterend",'
    '))),this._accessibleOutputs[r]={},"textOutput"===e?(i="#".concat(s,"gridOutput").concat(i),n='
    Text Output

      '),this.dummyDOM.querySelector(i)?this.dummyDOM.querySelector(i).insertAdjacentHTML("beforebegin",n):this.dummyDOM.querySelector("#".concat(o)).innerHTML=n,this._accessibleOutputs[r].list=this.dummyDOM.querySelector("#".concat(r,"_list"))):"gridOutput"===e&&(i="#".concat(s,"textOutput").concat(i),n='
      Grid Output

        '),this.dummyDOM.querySelector(i)?this.dummyDOM.querySelector(i).insertAdjacentHTML("afterend",n):this.dummyDOM.querySelector("#".concat(o)).innerHTML=n,this._accessibleOutputs[r].map=this.dummyDOM.querySelector("#".concat(r,"_map"))),this._accessibleOutputs[r].shapeDetails=this.dummyDOM.querySelector("#".concat(r,"_shapeDetails")),this._accessibleOutputs[r].summary=this.dummyDOM.querySelector("#".concat(r,"_summary"))},o.default.prototype._updateAccsOutput=function(){var e=this.canvas.id;JSON.stringify(this.ingredients.shapes)!==this.ingredients.pShapes&&(this.ingredients.pShapes=JSON.stringify(this.ingredients.shapes),this._accessibleOutputs.text&&this._updateTextOutput(e+"textOutput"),this._accessibleOutputs.grid&&this._updateGridOutput(e+"gridOutput"),this._accessibleOutputs.textLabel&&this._updateTextOutput(e+"textOutputLabel"),this._accessibleOutputs.gridLabel&&this._updateGridOutput(e+"gridOutputLabel"))},o.default.prototype._accsBackground=function(e){this.ingredients.pShapes=JSON.stringify(this.ingredients.shapes),this.ingredients.shapes={},this.ingredients.colors.backgroundRGBA!==e&&(this.ingredients.colors.backgroundRGBA=e,this.ingredients.colors.background=this._rgbColorName(e))},o.default.prototype._accsCanvasColors=function(e,t){"fill"===e?this.ingredients.colors.fillRGBA!==t&&(this.ingredients.colors.fillRGBA=t,this.ingredients.colors.fill=this._rgbColorName(t)):"stroke"===e&&this.ingredients.colors.strokeRGBA!==t&&(this.ingredients.colors.strokeRGBA=t,this.ingredients.colors.stroke=this._rgbColorName(t))},o.default.prototype._accsOutput=function(e,t){"ellipse"===e&&t[2]===t[3]?e="circle":"rectangle"===e&&t[2]===t[3]&&(e="square");var r,o,n={},s=!0,i=function(e,t){var r;e="rectangle"===e||"ellipse"===e||"arc"===e||"circle"===e||"square"===e?(r=Math.round(t[0]+t[2]/2),Math.round(t[1]+t[3]/2)):"triangle"===e?(r=(t[0]+t[2]+t[4])/3,(t[1]+t[3]+t[5])/3):"quadrilateral"===e?(r=(t[0]+t[2]+t[4]+t[6])/4,(t[1]+t[3]+t[5]+t[7])/4):"line"===e?(r=(t[0]+t[2])/2,(t[1]+t[3])/2):(r=t[0],t[1]);return[r,e]}(e,t);if("line"===e?(n.color=this.ingredients.colors.stroke,n.length=Math.round(this.dist(t[0],t[1],t[2],t[3])),r=this._getPos(t[0],[1]),o=this._getPos(t[2],[3]),n.loc=u(i,this.width,this.height),n.pos=r===o?"at ".concat(r):"from ".concat(r," to ").concat(o)):("point"===e?n.color=this.ingredients.colors.stroke:(n.color=this.ingredients.colors.fill,n.area=this._getArea(e,t)),n.pos=this._getPos.apply(this,l(i)),n.loc=u(i,this.width,this.height)),this.ingredients.shapes[e]){if(this.ingredients.shapes[e]!==[n]){for(var a in this.ingredients.shapes[e])JSON.stringify(this.ingredients.shapes[e][a])===JSON.stringify(n)&&(s=!1);!0===s&&this.ingredients.shapes[e].push(n)}}else this.ingredients.shapes[e]=[n]},o.default.prototype._getPos=function(e,t){var e=new DOMPointReadOnly(e,t),t=this._renderer.isP3D?new DOMMatrix(this._renderer.uMVMatrix.mat4):this.drawingContext.getTransform(),e=e.matrixTransform(t),t=e.x,e=e.y,r=this.width,o=this.height;return t<.4*r?e<.4*o?"top left":.6*oMath.PI?n+=o:n-=o)):"ellipse"===e||"circle"===e?n=3.14*t[2]/2*t[3]/2:"line"===e||"point"===e?n=0:"quadrilateral"===e?n=Math.abs((t[6]+t[0])*(t[7]-t[1])+(t[0]+t[2])*(t[1]-t[3])+(t[2]+t[4])*(t[3]-t[5])+(t[4]+t[6])*(t[5]-t[7]))/2:"rectangle"===e||"square"===e?n=t[2]*t[3]:"triangle"===e&&(n=Math.abs(t[0]*(t[3]-t[5])+t[2]*(t[5]-t[1])+t[4]*(t[1]-t[3]))/2),this.width*this._pixelDensity),i=this.height*this._pixelDensity,a=[new DOMPoint(0,0),new DOMPoint(s,0),new DOMPoint(s,i),new DOMPoint(0,i)],l=(this._renderer.isP3D?new DOMMatrix(this._renderer.uMVMatrix.mat4):this.drawingContext.getTransform()).inverse(),u=a.map(function(e){return e.matrixTransform(l)}),c=Math.abs((u[3].x+u[0].x)*(u[3].y-u[0].y)+(u[0].x+u[1].x)*(u[0].y-u[1].y)+(u[1].x+u[2].x)*(u[1].y-u[2].y)+(u[2].x+u[3].x)*(u[2].y-u[3].y))/2;return Math.round(100*n/c)};e=o.default;r.default=e},{"../core/main":275,"core-js/modules/es.array.concat":151,"core-js/modules/es.array.fill":154,"core-js/modules/es.array.from":158,"core-js/modules/es.array.iterator":161,"core-js/modules/es.array.map":164,"core-js/modules/es.number.to-fixed":175,"core-js/modules/es.object.to-string":182,"core-js/modules/es.regexp.to-string":188,"core-js/modules/es.string.iterator":192,"core-js/modules/es.symbol":204,"core-js/modules/es.symbol.description":202,"core-js/modules/es.symbol.iterator":203,"core-js/modules/web.dom-collections.iterator":238}],258:[function(e,t,r){"use strict";e("core-js/modules/es.array.concat"),e("core-js/modules/es.array.concat"),Object.defineProperty(r,"__esModule",{value:!0}),r.default=void 0;e=(e=e("../core/main"))&&e.__esModule?e:{default:e};e.default.prototype._updateTextOutput=function(e){var t,r,o,n;this.dummyDOM.querySelector("#".concat(e,"_summary"))&&(t=this._accessibleOutputs[e],o=function(e,t,r,o){r="Your output is a, ".concat(r," by ").concat(o," pixels, ").concat(t," canvas containing the following");r=1===e?"".concat(r," shape:"):"".concat(r," ").concat(e," shapes:");return r}((r=function(e,t){var r,o="",n=0;for(r in t)for(var s in t[r]){var i='
      • ').concat(t[r][s].color," ").concat(r,"");"line"===r?i+=", ".concat(t[r][s].pos,", ").concat(t[r][s].length," pixels long.
      • "):(i+=", at ".concat(t[r][s].pos),"point"!==r&&(i+=", covering ".concat(t[r][s].area,"% of the canvas")),i+="."),o+=i,n++}return{numShapes:n,listShapes:o}}(e,this.ingredients.shapes)).numShapes,this.ingredients.colors.background,this.width,this.height),n=function(e,t){var r,o="",n=0;for(r in t)for(var s in t[r]){var i='').concat(t[r][s].color," ").concat(r,"");"line"===r?i+="location = ".concat(t[r][s].pos,"length = ").concat(t[r][s].length," pixels"):(i+="location = ".concat(t[r][s].pos,""),"point"!==r&&(i+=" area = ".concat(t[r][s].area,"%")),i+=""),o+=i,n++}return o}(e,this.ingredients.shapes),o!==t.summary.innerHTML&&(t.summary.innerHTML=o),r.listShapes!==t.list.innerHTML&&(t.list.innerHTML=r.listShapes),n!==t.shapeDetails.innerHTML&&(t.shapeDetails.innerHTML=n),this._accessibleOutputs[e]=t)};e=e.default;r.default=e},{"../core/main":275,"core-js/modules/es.array.concat":151}],259:[function(e,t,r){"use strict";var o=(o=e("./core/main"))&&o.__esModule?o:{default:o};e("./core/constants"),e("./core/environment"),e("./core/friendly_errors/stacktrace"),e("./core/friendly_errors/validate_params"),e("./core/friendly_errors/file_errors"),e("./core/friendly_errors/fes_core"),e("./core/friendly_errors/sketch_reader"),e("./core/helpers"),e("./core/legacy"),e("./core/preload"),e("./core/p5.Element"),e("./core/p5.Graphics"),e("./core/p5.Renderer"),e("./core/p5.Renderer2D"),e("./core/rendering"),e("./core/shim"),e("./core/structure"),e("./core/transform"),e("./core/shape/2d_primitives"),e("./core/shape/attributes"),e("./core/shape/curves"),e("./core/shape/vertex"),e("./accessibility/outputs"),e("./accessibility/textOutput"),e("./accessibility/gridOutput"),e("./accessibility/color_namer"),e("./color/color_conversion"),e("./color/creating_reading"),e("./color/p5.Color"),e("./color/setting"),e("./data/p5.TypedDict"),e("./data/local_storage.js"),e("./dom/dom"),e("./accessibility/describe"),e("./events/acceleration"),e("./events/keyboard"),e("./events/mouse"),e("./events/touch"),e("./image/filters"),e("./image/image"),e("./image/loading_displaying"),e("./image/p5.Image"),e("./image/pixels"),e("./io/files"),e("./io/p5.Table"),e("./io/p5.TableRow"),e("./io/p5.XML"),e("./math/calculation"),e("./math/math"),e("./math/noise"),e("./math/p5.Vector"),e("./math/random"),e("./math/trigonometry"),e("./typography/attributes"),e("./typography/loading_displaying"),e("./typography/p5.Font"),e("./utilities/array_functions"),e("./utilities/conversion"),e("./utilities/string_functions"),e("./utilities/time_date"),e("./webgl/3d_primitives"),e("./webgl/interaction"),e("./webgl/light"),e("./webgl/loading"),e("./webgl/material"),e("./webgl/p5.Camera"),e("./webgl/p5.DataArray"),e("./webgl/p5.Geometry"),e("./webgl/p5.Matrix"),e("./webgl/p5.RendererGL.Immediate"),e("./webgl/p5.RendererGL"),e("./webgl/p5.RendererGL.Retained"),e("./webgl/p5.Framebuffer"),e("./webgl/p5.Shader"),e("./webgl/p5.RenderBuffer"),e("./webgl/p5.Texture"),e("./webgl/text"),e("./core/init"),t.exports=o.default},{"./accessibility/color_namer":254,"./accessibility/describe":255,"./accessibility/gridOutput":256,"./accessibility/outputs":257,"./accessibility/textOutput":258,"./color/color_conversion":260,"./color/creating_reading":261,"./color/p5.Color":262,"./color/setting":263,"./core/constants":264,"./core/environment":265,"./core/friendly_errors/fes_core":266,"./core/friendly_errors/file_errors":267,"./core/friendly_errors/sketch_reader":268,"./core/friendly_errors/stacktrace":269,"./core/friendly_errors/validate_params":270,"./core/helpers":271,"./core/init":272,"./core/legacy":274,"./core/main":275,"./core/p5.Element":276,"./core/p5.Graphics":277,"./core/p5.Renderer":278,"./core/p5.Renderer2D":279,"./core/preload":280,"./core/rendering":281,"./core/shape/2d_primitives":282,"./core/shape/attributes":283,"./core/shape/curves":284,"./core/shape/vertex":285,"./core/shim":286,"./core/structure":287,"./core/transform":288,"./data/local_storage.js":289,"./data/p5.TypedDict":290,"./dom/dom":291,"./events/acceleration":292,"./events/keyboard":293,"./events/mouse":294,"./events/touch":295,"./image/filters":296,"./image/image":297,"./image/loading_displaying":298,"./image/p5.Image":299,"./image/pixels":300,"./io/files":301,"./io/p5.Table":302,"./io/p5.TableRow":303,"./io/p5.XML":304,"./math/calculation":305,"./math/math":306,"./math/noise":307,"./math/p5.Vector":308,"./math/random":309,"./math/trigonometry":310,"./typography/attributes":311,"./typography/loading_displaying":312,"./typography/p5.Font":313,"./utilities/array_functions":314,"./utilities/conversion":315,"./utilities/string_functions":316,"./utilities/time_date":317,"./webgl/3d_primitives":318,"./webgl/interaction":320,"./webgl/light":321,"./webgl/loading":322,"./webgl/material":323,"./webgl/p5.Camera":324,"./webgl/p5.DataArray":325,"./webgl/p5.Framebuffer":326,"./webgl/p5.Geometry":327,"./webgl/p5.Matrix":328,"./webgl/p5.RenderBuffer":329,"./webgl/p5.RendererGL":332,"./webgl/p5.RendererGL.Immediate":330,"./webgl/p5.RendererGL.Retained":331,"./webgl/p5.Shader":333,"./webgl/p5.Texture":334,"./webgl/text":335}],260:[function(e,t,r){"use strict";Object.defineProperty(r,"__esModule",{value:!0}),r.default=void 0;e=(e=e("../core/main"))&&e.__esModule?e:{default:e};e.default.ColorConversion={_hsbaToHSLA:function(e){var t=e[0],r=e[1],o=e[2],n=(2-r)*o/2;return 0!=n&&(1==n?r=0:n<.5?r/=2-r:r=r*o/(2-2*n)),[t,r,n,e[3]]},_hsbaToRGBA:function(e){var t,r,o,n,s,i=6*e[0],a=e[1],l=e[2];return 0===a?[l,l,l,e[3]]:(r=l*(1-a),o=l*(1-a*(i-(t=Math.floor(i)))),a=l*(1-a*(1+t-i)),i=1===t?(n=o,s=l,r):2===t?(n=r,s=l,a):3===t?(n=r,s=o,l):4===t?(n=a,s=r,l):5===t?(n=l,s=r,o):(n=l,s=a,r),[n,s,i,e[3]])},_hslaToHSBA:function(e){var t=e[0],r=e[1],o=e[2],n=o<.5?(1+r)*o:o+r-o*r;return[t,r=2*(n-o)/n,n,e[3]]},_hslaToRGBA:function(e){var t,r=6*e[0],o=e[1],n=e[2];return 0===o?[n,n,n,e[3]]:[(t=function(e,t,r){return e<0?e+=6:6<=e&&(e-=6),e<1?t+(r-t)*e:e<3?r:e<4?t+(r-t)*(4-e):t})(2+r,o=2*n-(n=n<.5?(1+o)*n:n+o-n*o),n),t(r,o,n),t(r-2,o,n),e[3]]},_rgbaToHSBA:function(e){var t,r,o=e[0],n=e[1],s=e[2],i=Math.max(o,n,s),a=i-Math.min(o,n,s);return 0==a?r=t=0:(r=a/i,o===i?t=(n-s)/a:n===i?t=2+(s-o)/a:s===i&&(t=4+(o-n)/a),t<0?t+=6:6<=t&&(t-=6)),[t/6,r,i,e[3]]},_rgbaToHSLA:function(e){var t,r,o=e[0],n=e[1],s=e[2],i=Math.max(o,n,s),a=Math.min(o,n,s),l=i+a,a=i-a;return 0==a?r=t=0:(r=l<1?a/l:a/(2-l),o===i?t=(n-s)/a:n===i?t=2+(s-o)/a:s===i&&(t=4+(o-n)/a),t<0?t+=6:6<=t&&(t-=6)),[t/6,r,l/2,e[3]]}};e=e.default.ColorConversion;r.default=e},{"../core/main":275}],261:[function(e,t,r){"use strict";function o(e){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function i(e){return(i="function"==typeof Symbol&&"symbol"===o(Symbol.iterator)?function(e){return o(e)}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":o(e)})(e)}e("core-js/modules/es.symbol"),e("core-js/modules/es.symbol.description"),e("core-js/modules/es.symbol.iterator"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.map"),e("core-js/modules/es.object.get-own-property-descriptor"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.string.iterator"),e("core-js/modules/es.weak-map"),e("core-js/modules/web.dom-collections.iterator"),e("core-js/modules/es.array.map"),Object.defineProperty(r,"__esModule",{value:!0}),r.default=void 0;var l=(n=e("../core/main"))&&n.__esModule?n:{default:n},u=function(e){if(e&&e.__esModule)return e;if(null===e||"object"!==i(e)&&"function"!=typeof e)return{default:e};var t=a();if(t&&t.has(e))return t.get(e);var r,o={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(r in e){var s;Object.prototype.hasOwnProperty.call(e,r)&&((s=n?Object.getOwnPropertyDescriptor(e,r):null)&&(s.get||s.set)?Object.defineProperty(o,r,s):o[r]=e[r])}o.default=e,t&&t.set(e,o);return o}(e("../core/constants"));function a(){var e;return"function"!=typeof WeakMap?null:(e=new WeakMap,a=function(){return e},e)}e("./p5.Color"),e("../core/friendly_errors/validate_params"),e("../core/friendly_errors/file_errors"),e("../core/friendly_errors/fes_core"),l.default.prototype.alpha=function(e){return l.default._validateParameters("alpha",arguments),this.color(e)._getAlpha()},l.default.prototype.blue=function(e){return l.default._validateParameters("blue",arguments),this.color(e)._getBlue()},l.default.prototype.brightness=function(e){return l.default._validateParameters("brightness",arguments),this.color(e)._getBrightness()},l.default.prototype.color=function(){var e;return l.default._validateParameters("color",arguments),arguments[0]instanceof l.default.Color?arguments[0]:(e=arguments[0]instanceof Array?arguments[0]:arguments,new l.default.Color(this,e))},l.default.prototype.green=function(e){return l.default._validateParameters("green",arguments),this.color(e)._getGreen()},l.default.prototype.hue=function(e){return l.default._validateParameters("hue",arguments),this.color(e)._getHue()},l.default.prototype.lerpColor=function(e,t,r){l.default._validateParameters("lerpColor",arguments);var o,n,s,i=this._colorMode,a=this._colorMaxes;if(i===u.RGB)n=e.levels.map(function(e){return e/255}),s=t.levels.map(function(e){return e/255});else if(i===u.HSB)e._getBrightness(),t._getBrightness(),n=e.hsba,s=t.hsba;else{if(i!==u.HSL)throw new Error("".concat(i,"cannot be used for interpolation."));e._getLightness(),t._getLightness(),n=e.hsla,s=t.hsla}return r=Math.max(Math.min(r,1),0),void 0===this.lerp&&(this.lerp=function(e,t,r){return r*(t-e)+e}),e=this.lerp(n[0],s[0],r),t=this.lerp(n[1],s[1],r),o=this.lerp(n[2],s[2],r),n=this.lerp(n[3],s[3],r),e*=a[i][0],t*=a[i][1],o*=a[i][2],n*=a[i][3],this.color(e,t,o,n)},l.default.prototype.lightness=function(e){return l.default._validateParameters("lightness",arguments),this.color(e)._getLightness()},l.default.prototype.red=function(e){return l.default._validateParameters("red",arguments),this.color(e)._getRed()},l.default.prototype.saturation=function(e){return l.default._validateParameters("saturation",arguments),this.color(e)._getSaturation()};var n=l.default;r.default=n},{"../core/constants":264,"../core/friendly_errors/fes_core":266,"../core/friendly_errors/file_errors":267,"../core/friendly_errors/validate_params":270,"../core/main":275,"./p5.Color":262,"core-js/modules/es.array.iterator":161,"core-js/modules/es.array.map":164,"core-js/modules/es.object.get-own-property-descriptor":178,"core-js/modules/es.object.to-string":182,"core-js/modules/es.string.iterator":192,"core-js/modules/es.symbol":204,"core-js/modules/es.symbol.description":202,"core-js/modules/es.symbol.iterator":203,"core-js/modules/es.weak-map":236,"core-js/modules/web.dom-collections.iterator":238}],262:[function(e,t,r){"use strict";function o(e){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function i(e){return(i="function"==typeof Symbol&&"symbol"===o(Symbol.iterator)?function(e){return o(e)}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":o(e)})(e)}e("core-js/modules/es.symbol"),e("core-js/modules/es.symbol.description"),e("core-js/modules/es.symbol.iterator"),e("core-js/modules/es.array.includes"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.join"),e("core-js/modules/es.array.map"),e("core-js/modules/es.array.slice"),e("core-js/modules/es.object.get-own-property-descriptor"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.regexp.constructor"),e("core-js/modules/es.regexp.exec"),e("core-js/modules/es.regexp.to-string"),e("core-js/modules/es.string.includes"),e("core-js/modules/es.string.iterator"),e("core-js/modules/es.string.trim"),e("core-js/modules/es.weak-map"),e("core-js/modules/web.dom-collections.iterator"),e("core-js/modules/es.array.includes"),e("core-js/modules/es.array.join"),e("core-js/modules/es.array.map"),e("core-js/modules/es.array.slice"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.regexp.constructor"),e("core-js/modules/es.regexp.exec"),e("core-js/modules/es.regexp.to-string"),e("core-js/modules/es.string.includes"),e("core-js/modules/es.string.trim"),Object.defineProperty(r,"__esModule",{value:!0}),r.default=void 0;var n=s(e("../core/main")),d=function(e){if(e&&e.__esModule)return e;if(null===e||"object"!==i(e)&&"function"!=typeof e)return{default:e};var t=a();if(t&&t.has(e))return t.get(e);var r,o={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(r in e){var s;Object.prototype.hasOwnProperty.call(e,r)&&((s=n?Object.getOwnPropertyDescriptor(e,r):null)&&(s.get||s.set)?Object.defineProperty(o,r,s):o[r]=e[r])}o.default=e,t&&t.set(e,o);return o}(e("../core/constants")),h=s(e("./color_conversion"));function a(){var e;return"function"!=typeof WeakMap?null:(e=new WeakMap,a=function(){return e},e)}function s(e){return e&&e.__esModule?e:{default:e}}function l(e,t){for(var r=0;r"].indexOf(r[0])?void 0:r[0],lineNumber:r[1],columnNumber:r[2],source:e}},this)},parseFFOrSafari:function(e){return e.stack.split("\n").filter(function(e){return!e.match(o)},this).map(function(e){var t,r;return-1===(e=-1 eval")?e.replace(/ line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g,":$1"):e).indexOf("@")&&-1===e.indexOf(":")?{functionName:e}:{functionName:(r=e.match(t=/((.*".+"[^@]*)?[^@]*)(?:@)/))&&r[1]?r[1]:void 0,fileName:(r=this.extractLocation(e.replace(t,"")))[0],lineNumber:r[1],columnNumber:r[2],source:e}},this)},parseOpera:function(e){return!e.stacktrace||-1e.stacktrace.split("\n").length?this.parseOpera9(e):e.stack?this.parseOpera11(e):this.parseOpera10(e)},parseOpera9:function(e){for(var t=/Line (\d+).*script (?:in )?(\S+)/i,r=e.message.split("\n"),o=[],n=2,s=r.length;n/,"$2").replace(/\([^)]*\)/g,"")||void 0,args:void 0===(t=r.match(/\(([^)]*)\)/)?r.replace(/^[^(]+\(([^)]*)\)$/,"$1"):t)||"[arguments not available]"===t?void 0:t.split(","),fileName:o[0],lineNumber:o[1],columnNumber:o[2],source:e}},this)}}}e.default._getErrorStackParser=function(){return new o};e=e.default;r.default=e},{"../main":275,"core-js/modules/es.array.filter":155,"core-js/modules/es.array.index-of":160,"core-js/modules/es.array.join":162,"core-js/modules/es.array.map":164,"core-js/modules/es.array.slice":165,"core-js/modules/es.regexp.exec":187,"core-js/modules/es.string.match":193,"core-js/modules/es.string.replace":196,"core-js/modules/es.string.split":198}],270:[function(e,t,r){"use strict";function o(e){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}e("core-js/modules/es.symbol"),e("core-js/modules/es.symbol.description"),e("core-js/modules/es.symbol.iterator"),e("core-js/modules/es.array.concat"),e("core-js/modules/es.array.for-each"),e("core-js/modules/es.array.includes"),e("core-js/modules/es.array.index-of"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.join"),e("core-js/modules/es.array.last-index-of"),e("core-js/modules/es.array.map"),e("core-js/modules/es.array.slice"),e("core-js/modules/es.function.name"),e("core-js/modules/es.map"),e("core-js/modules/es.number.constructor"),e("core-js/modules/es.object.get-own-property-descriptor"),e("core-js/modules/es.object.get-prototype-of"),e("core-js/modules/es.object.keys"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.reflect.construct"),e("core-js/modules/es.regexp.exec"),e("core-js/modules/es.regexp.to-string"),e("core-js/modules/es.set"),e("core-js/modules/es.string.includes"),e("core-js/modules/es.string.iterator"),e("core-js/modules/es.string.split"),e("core-js/modules/es.weak-map"),e("core-js/modules/web.dom-collections.for-each"),e("core-js/modules/web.dom-collections.iterator"),e("core-js/modules/es.symbol"),e("core-js/modules/es.symbol.description"),e("core-js/modules/es.symbol.iterator"),e("core-js/modules/es.array.concat"),e("core-js/modules/es.array.for-each"),e("core-js/modules/es.array.includes"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.join"),e("core-js/modules/es.array.last-index-of"),e("core-js/modules/es.array.map"),e("core-js/modules/es.array.slice"),e("core-js/modules/es.function.name"),e("core-js/modules/es.number.constructor"),e("core-js/modules/es.object.keys"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.regexp.exec"),e("core-js/modules/es.regexp.to-string"),e("core-js/modules/es.set"),e("core-js/modules/es.string.includes"),e("core-js/modules/es.string.iterator"),e("core-js/modules/es.string.split"),e("core-js/modules/web.dom-collections.for-each"),e("core-js/modules/web.dom-collections.iterator"),Object.defineProperty(r,"__esModule",{value:!0}),r.default=void 0;var n=(n=e("../main"))&&n.__esModule?n:{default:n};(function(e){if(e&&e.__esModule)return;if(null===e||"object"!==a(e)&&"function"!=typeof e)return;var t=i();if(t&&t.has(e))return t.get(e);var r,o={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(r in e){var s;Object.prototype.hasOwnProperty.call(e,r)&&((s=n?Object.getOwnPropertyDescriptor(e,r):null)&&(s.get||s.set)?Object.defineProperty(o,r,s):o[r]=e[r])}o.default=e,t&&t.set(e,o)})(e("../constants")),e("../internationalization");function i(){var e;return"function"!=typeof WeakMap?null:(e=new WeakMap,i=function(){return e},e)}function a(e){return(a="function"==typeof Symbol&&"symbol"===o(Symbol.iterator)?function(e){return o(e)}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":o(e)})(e)}n.default._validateParameters=n.default._clearValidateParamsCache=function(){};e=n.default;r.default=e},{"../../../docs/parameterData.json":void 0,"../constants":264,"../internationalization":273,"../main":275,"core-js/modules/es.array.concat":151,"core-js/modules/es.array.for-each":157,"core-js/modules/es.array.includes":159,"core-js/modules/es.array.index-of":160,"core-js/modules/es.array.iterator":161,"core-js/modules/es.array.join":162,"core-js/modules/es.array.last-index-of":163,"core-js/modules/es.array.map":164,"core-js/modules/es.array.slice":165,"core-js/modules/es.function.name":168,"core-js/modules/es.map":169,"core-js/modules/es.number.constructor":173,"core-js/modules/es.object.get-own-property-descriptor":178,"core-js/modules/es.object.get-prototype-of":180,"core-js/modules/es.object.keys":181,"core-js/modules/es.object.to-string":182,"core-js/modules/es.reflect.construct":184,"core-js/modules/es.regexp.exec":187,"core-js/modules/es.regexp.to-string":188,"core-js/modules/es.set":189,"core-js/modules/es.string.includes":191,"core-js/modules/es.string.iterator":192,"core-js/modules/es.string.split":198,"core-js/modules/es.symbol":204,"core-js/modules/es.symbol.description":202,"core-js/modules/es.symbol.iterator":203,"core-js/modules/es.weak-map":236,"core-js/modules/web.dom-collections.for-each":237,"core-js/modules/web.dom-collections.iterator":238}],271:[function(e,t,r){"use strict";function o(e){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function i(e){return(i="function"==typeof Symbol&&"symbol"===o(Symbol.iterator)?function(e){return o(e)}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":o(e)})(e)}e("core-js/modules/es.symbol"),e("core-js/modules/es.symbol.description"),e("core-js/modules/es.symbol.iterator"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.object.get-own-property-descriptor"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.string.iterator"),e("core-js/modules/es.weak-map"),e("core-js/modules/web.dom-collections.iterator"),Object.defineProperty(r,"__esModule",{value:!0}),r.default=void 0;var s=function(e){if(e&&e.__esModule)return e;if(null===e||"object"!==i(e)&&"function"!=typeof e)return{default:e};var t=a();if(t&&t.has(e))return t.get(e);var r,o={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(r in e){var s;Object.prototype.hasOwnProperty.call(e,r)&&((s=n?Object.getOwnPropertyDescriptor(e,r):null)&&(s.get||s.set)?Object.defineProperty(o,r,s):o[r]=e[r])}o.default=e,t&&t.set(e,o);return o}(e("./constants"));function a(){var e;return"function"!=typeof WeakMap?null:(e=new WeakMap,a=function(){return e},e)}r.default={modeAdjust:function(e,t,r,o,n){return n===s.CORNER?{x:e,y:t,w:r,h:o}:n===s.CORNERS?{x:e,y:t,w:r-e,h:o-t}:n===s.RADIUS?{x:e-r,y:t-o,w:2*r,h:2*o}:n===s.CENTER?{x:e-.5*r,y:t-.5*o,w:r,h:o}:void 0}}},{"./constants":264,"core-js/modules/es.array.iterator":161,"core-js/modules/es.object.get-own-property-descriptor":178,"core-js/modules/es.object.to-string":182,"core-js/modules/es.string.iterator":192,"core-js/modules/es.symbol":204,"core-js/modules/es.symbol.description":202,"core-js/modules/es.symbol.iterator":203,"core-js/modules/es.weak-map":236,"core-js/modules/web.dom-collections.iterator":238}],272:[function(e,t,r){"use strict";e("core-js/modules/es.array.iterator"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.promise"),e("core-js/modules/es.string.iterator"),e("core-js/modules/web.dom-collections.iterator"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.promise"),e("core-js/modules/es.string.iterator"),e("core-js/modules/web.dom-collections.iterator");var o=(n=e("../core/main"))&&n.__esModule?n:{default:n};e("./internationalization");var n=Promise.resolve();Promise.all([new Promise(function(e,t){"complete"===document.readyState?e():window.addEventListener("load",e,!1)}),n]).then(function(){void 0!==window._setupDone?console.warn("p5.js seems to have been imported multiple times. Please remove the duplicate import"):window.mocha||(window.setup&&"function"==typeof window.setup||window.draw&&"function"==typeof window.draw)&&!o.default.instance&&new o.default})},{"../core/main":275,"./internationalization":273,"core-js/modules/es.array.iterator":161,"core-js/modules/es.object.to-string":182,"core-js/modules/es.promise":183,"core-js/modules/es.string.iterator":192,"core-js/modules/web.dom-collections.iterator":238}],273:[function(e,t,r){"use strict";e("core-js/modules/es.array.includes"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.join"),e("core-js/modules/es.array.slice"),e("core-js/modules/es.object.keys"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.promise"),e("core-js/modules/es.regexp.exec"),e("core-js/modules/es.string.includes"),e("core-js/modules/es.string.iterator"),e("core-js/modules/es.string.split"),e("core-js/modules/web.dom-collections.iterator"),e("core-js/modules/es.array.includes"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.join"),e("core-js/modules/es.array.slice"),e("core-js/modules/es.object.keys"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.promise"),e("core-js/modules/es.regexp.exec"),e("core-js/modules/es.string.includes"),e("core-js/modules/es.string.iterator"),e("core-js/modules/es.string.split"),e("core-js/modules/web.dom-collections.iterator"),Object.defineProperty(r,"__esModule",{value:!0}),r.setTranslatorLanguage=r.currentTranslatorLanguage=r.availableTranslatorLanguages=r.initialize=r.translator=void 0;var n,s,o=a(e("i18next")),i=a(e("i18next-browser-languagedetector"));function a(e){return e&&e.__esModule?e:{default:e}}function l(e,t){for(var r=0;r=i.width||t>=i.height?[0,0,0,0]:this._getPixel(e,t);n=new a.default.Image(r*s,o*s);return n.pixelDensity(s),n.canvas.getContext("2d").drawImage(i,e,t,r*s,o*s,0,0,r*s,o*s),n}},{key:"textLeading",value:function(e){return"number"==typeof e?(this._setProperty("_leadingSet",!0),this._setProperty("_textLeading",e),this._pInst):this._textLeading}},{key:"textStyle",value:function(e){return e?(e!==P.NORMAL&&e!==P.ITALIC&&e!==P.BOLD&&e!==P.BOLDITALIC||this._setProperty("_textStyle",e),this._applyTextProperties()):this._textStyle}},{key:"textAscent",value:function(){return null===this._textAscent&&this._updateTextMetrics(),this._textAscent}},{key:"textDescent",value:function(){return null===this._textDescent&&this._updateTextMetrics(),this._textDescent}},{key:"textAlign",value:function(e,t){return void 0!==e?(this._setProperty("_textAlign",e),void 0!==t&&this._setProperty("_textBaseline",t),this._applyTextProperties()):{horizontal:this._textAlign,vertical:this._textBaseline}}},{key:"textWrap",value:function(e){return this._setProperty("_textWrap",e),this._textWrap}},{key:"text",value:function(e,t,r,o,n){var s,i,a,l,u=this._pInst,c=this._textWrap,d=Number.MAX_VALUE,h=r;if((this._doFill||this._doStroke)&&void 0!==e){if(s=(e=(e="string"!=typeof e?e.toString():e).replace(/(\t)/g," ")).split("\n"),void 0!==o){switch(this._rectMode===P.CENTER&&(t-=o/2),this._textAlign){case P.CENTER:t+=o/2;break;case P.RIGHT:t+=o}if(void 0!==n){this._rectMode===P.CENTER&&(r-=n/2,h-=n/2);var e=r,f=u.textAscent();switch(this._textBaseline){case P.BOTTOM:l=r+n,r=Math.max(l,r),h+=f;break;case P.CENTER:l=r+n/2,r=Math.max(l,r),h+=f/2}d=r+n-f,this._textBaseline===P.CENTER&&(d=e+n-f/2)}else this._textBaseline!==P.BOTTOM&&this._textBaseline!==P.CENTER||(h=r-(e=u.textSize()*this._textLeading)/2,d=r+e/2);if(c===P.WORD){for(var p=[],m=0;ma.HALF_PI&&e<=3*a.HALF_PI?Math.atan(r/o*Math.tan(e))+a.PI:Math.atan(r/o*Math.tan(e))+a.TWO_PI,t=t<=a.HALF_PI?Math.atan(r/o*Math.tan(t)):t>a.HALF_PI&&t<=3*a.HALF_PI?Math.atan(r/o*Math.tan(t))+a.PI:Math.atan(r/o*Math.tan(t))+a.TWO_PI),tp||Math.abs(this.accelerationY-this.pAccelerationY)>p||Math.abs(this.accelerationZ-this.pAccelerationZ)>p)&&s.deviceMoved(),"function"==typeof s.deviceTurned&&(t=this.rotationX+180,e=this.pRotationX+180,r=l+180,0>>16,e[1+r]=(65280&t[o])>>>8,e[2+r]=255&t[o],e[3+r]=(4278190080&t[o])>>>24},_toImageData:function(e){return e instanceof ImageData?e:e.getContext("2d").getImageData(0,0,e.width,e.height)},_createImageData:function(e,t){return V._tmpCanvas=document.createElement("canvas"),V._tmpCtx=V._tmpCanvas.getContext("2d"),this._tmpCtx.createImageData(e,t)},apply:function(e,t,r){var o=e.getContext("2d"),n=o.getImageData(0,0,e.width,e.height),t=t(n,r);t instanceof ImageData?o.putImageData(t,0,0,0,0,e.width,e.height):o.putImageData(n,0,0,0,0,e.width,e.height)},threshold:function(e,t){for(var r=V._toPixels(e),o=(void 0===t&&(t=.5),Math.floor(255*t)),n=0;n>8)/o,r[n+1]=255*(i*t>>8)/o,r[n+2]=255*(a*t>>8)/o}},dilate:function(e){for(var t,r,o,n,s,i,a,l,u,c=V._toPixels(e),d=0,h=c.length?c.length/4:0,f=new Int32Array(h);d>16&255)+151*(n>>8&255)+28*(255&n))<(a=77*(u>>16&255)+151*(u>>8&255)+28*(255&u))&&(o=u,n=a),n<(a=77*((u=V._getARGB(c,l))>>16&255)+151*(u>>8&255)+28*(255&u))&&(o=u,n=a),n<(l=77*(s>>16&255)+151*(s>>8&255)+28*(255&s))&&(o=s,n=l),n<(u=77*(i>>16&255)+151*(i>>8&255)+28*(255&i))&&(o=i,n=u),f[d++]=o;V._setPixels(c,f)},erode:function(e){for(var t,r,o,n,s,i,a,l,u,c=V._toPixels(e),d=0,h=c.length?c.length/4:0,f=new Int32Array(h);d>16&255)+151*(u>>8&255)+28*(255&u))<(n=77*(n>>16&255)+151*(n>>8&255)+28*(255&n))&&(o=u,n=a),(a=77*((u=V._getARGB(c,l))>>16&255)+151*(u>>8&255)+28*(255&u))>16&255)+151*(s>>8&255)+28*(255&s))>16&255)+151*(i>>8&255)+28*(255&i))>>24],r+=j[(16711680&I)>>16],o+=j[(65280&I)>>8],n+=j[255&I],t+=B[b],i++}T[a=k+g]=s/t,M[a]=r/t,E[a]=o/t,F[a]=n/t}k+=h}for(u=(l=-U)*h,v=k=0;v"+p.length.toString()+" out of "+c.toString()),e.next=48,new Promise(function(e){return setTimeout(e,0)});e.next=50;break;case 48:e.next=39;break;case 50:i||m.html("Frames processed, generating color palette..."),this.loop(),this.pixelDensity(f),v=(0,P.GIFEncoder)(),b=function(e){for(var t=new Uint8Array(e.length*e[0].length),r=0;r"+S.toString()+" out of "+c.toString()),e.next=68,new Promise(function(e){return setTimeout(e,0)});case 68:S++,e.next=60;break;case 71:v.finish(),k=v.bytesView(),k=new Blob([k],{type:"image/gif"}),p=[],this._recording=!1,this.loop(),i||(m.html("Done. Downloading your gif!🌸"),0=t&&(t=Math.floor(r.timeDisplayed/t),r.timeDisplayed=0,r.lastChangeTime=e,r.displayIndex+=t,r.loopCount=Math.floor(r.displayIndex/r.numFrames),null!==r.loopLimit&&r.loopCount>=r.loopLimit?r.playing=!1:(e=r.displayIndex%r.numFrames,this.drawingContext.putImageData(r.frames[e].image,0,0),r.displayIndex=e,this.setModified(!0))))}},{key:"_setProperty",value:function(e,t){this[e]=t,this.setModified(!0)}},{key:"loadPixels",value:function(){s.default.Renderer2D.prototype.loadPixels.call(this),this.setModified(!0)}},{key:"updatePixels",value:function(e,t,r,o){s.default.Renderer2D.prototype.updatePixels.call(this,e,t,r,o),this.setModified(!0)}},{key:"get",value:function(e,t,r,o){return s.default._validateParameters("p5.Image.get",arguments),s.default.Renderer2D.prototype.get.apply(this,arguments)}},{key:"_getPixel",value:function(){for(var e=arguments.length,t=new Array(e),r=0;r/g,">").replace(/"/g,""").replace(/'/g,"'")}function i(e,t){t&&!0!==t&&"true"!==t||(t="");var r="";return(e=e||"untitled")&&e.includes(".")&&(r=e.split(".").pop()),t&&r!==t&&(r=t,e="".concat(e,".").concat(r)),[e,r]}e("../core/friendly_errors/validate_params"),e("../core/friendly_errors/file_errors"),e("../core/friendly_errors/fes_core"),v.default.prototype.loadJSON=function(){for(var e=arguments.length,t=new Array(e),r=0;r"),n.print("");if(n.print(' '),n.print(""),n.print(""),n.print(" "),"0"!==s[0]){n.print(" ");for(var c=0;c".concat(d)),n.print(" ")}n.print(" ")}for(var h=0;h");for(var f=0;f".concat(p)),n.print(" ")}n.print(" ")}n.print("
        "),n.print(""),n.print("")}n.close(),n.clear()},v.default.prototype.writeFile=function(e,t,r){var o="application/octet-stream",e=(v.default.prototype._isSafari()&&(o="text/plain"),new Blob(e,{type:o}));v.default.prototype.downloadFile(e,t,r)},v.default.prototype.downloadFile=function(e,t,r){var o,t=i(t,r),r=t[0];e instanceof Blob?n.default.saveAs(e,r):((o=document.createElement("a")).href=e,o.download=r,o.onclick=function(e){document.body.removeChild(e.target),e.stopPropagation()},o.style.display="none",document.body.appendChild(o),v.default.prototype._isSafari()&&(e=(e='Hello, Safari user! To download this file...\n1. Go to File --\x3e Save As.\n2. Choose "Page Source" as the Format.\n')+'3. Name it with this extension: ."'.concat(t[1],'"'),alert(e)),o.click())},v.default.prototype._checkFileExtension=i,v.default.prototype._isSafari=function(){return 0>>0},getSeed:function(){return t},rand:function(){return(r=(1664525*r+1013904223)%o)/o}};n.setSeed(e),j=new Array(4096);for(var s=0;s<4096;s++)j[s]=n.rand()},e.default);r.default=e},{"../core/main":275}],308:[function(e,t,r){"use strict";function o(e){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function i(e){return(i="function"==typeof Symbol&&"symbol"===o(Symbol.iterator)?function(e){return o(e)}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":o(e)})(e)}e("core-js/modules/es.symbol"),e("core-js/modules/es.symbol.description"),e("core-js/modules/es.symbol.iterator"),e("core-js/modules/es.array.concat"),e("core-js/modules/es.array.every"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.slice"),e("core-js/modules/es.array.some"),e("core-js/modules/es.math.sign"),e("core-js/modules/es.number.constructor"),e("core-js/modules/es.number.is-finite"),e("core-js/modules/es.object.get-own-property-descriptor"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.string.iterator"),e("core-js/modules/es.string.sub"),e("core-js/modules/es.weak-map"),e("core-js/modules/web.dom-collections.iterator"),e("core-js/modules/es.array.concat"),e("core-js/modules/es.array.every"),e("core-js/modules/es.array.slice"),e("core-js/modules/es.array.some"),e("core-js/modules/es.math.sign"),e("core-js/modules/es.number.constructor"),e("core-js/modules/es.number.is-finite"),e("core-js/modules/es.string.sub"),Object.defineProperty(r,"__esModule",{value:!0}),r.default=void 0;var a=(n=e("../core/main"))&&n.__esModule?n:{default:n},s=function(e){if(e&&e.__esModule)return e;if(null===e||"object"!==i(e)&&"function"!=typeof e)return{default:e};var t=l();if(t&&t.has(e))return t.get(e);var r,o={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(r in e){var s;Object.prototype.hasOwnProperty.call(e,r)&&((s=n?Object.getOwnPropertyDescriptor(e,r):null)&&(s.get||s.set)?Object.defineProperty(o,r,s):o[r]=e[r])}o.default=e,t&&t.set(e,o);return o}(e("../core/constants"));function l(){var e;return"function"!=typeof WeakMap?null:(e=new WeakMap,l=function(){return e},e)}function u(e,t){for(var r=0;r>>0},n.default.prototype.randomSeed=function(e){this._lcgSetSeed(s,e),this._gaussian_previous=!1},n.default.prototype.random=function(e,t){var r,o;return n.default._validateParameters("random",arguments),r=null!=this[s]?this._lcg(s):Math.random(),void 0===e?r:void 0===t?e instanceof Array?e[Math.floor(r*e.length)]:r*e:(tf&&(b=d,v=a,s=l,d=x+f*(i&&x=t?r.substring(r.length-t,r.length):r}},o.default.prototype.unhex=function(e){return e instanceof Array?e.map(o.default.prototype.unhex):parseInt("0x".concat(e),16)};e=o.default;r.default=e},{"../core/main":275,"core-js/modules/es.array.map":164,"core-js/modules/es.number.constructor":173,"core-js/modules/es.object.to-string":182,"core-js/modules/es.regexp.to-string":188,"core-js/modules/es.string.repeat":195}],316:[function(e,t,r){"use strict";e("core-js/modules/es.symbol"),e("core-js/modules/es.symbol.description"),e("core-js/modules/es.symbol.iterator"),e("core-js/modules/es.array.filter"),e("core-js/modules/es.array.index-of"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.join"),e("core-js/modules/es.array.map"),e("core-js/modules/es.array.slice"),e("core-js/modules/es.number.to-fixed"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.regexp.constructor"),e("core-js/modules/es.regexp.exec"),e("core-js/modules/es.regexp.to-string"),e("core-js/modules/es.string.iterator"),e("core-js/modules/es.string.match"),e("core-js/modules/es.string.pad-start"),e("core-js/modules/es.string.replace"),e("core-js/modules/es.string.split"),e("core-js/modules/es.string.trim"),e("core-js/modules/web.dom-collections.iterator"),e("core-js/modules/es.array.filter"),e("core-js/modules/es.array.index-of"),e("core-js/modules/es.array.join"),e("core-js/modules/es.array.map"),e("core-js/modules/es.array.slice"),e("core-js/modules/es.number.to-fixed"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.regexp.constructor"),e("core-js/modules/es.regexp.exec"),e("core-js/modules/es.regexp.to-string"),e("core-js/modules/es.string.match"),e("core-js/modules/es.string.pad-start"),e("core-js/modules/es.string.replace"),e("core-js/modules/es.string.split"),e("core-js/modules/es.string.trim"),Object.defineProperty(r,"__esModule",{value:!0}),r.default=void 0;var s=(u=e("../core/main"))&&u.__esModule?u:{default:u};function i(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e)){var r=[],o=!0,n=!1,s=void 0;try{for(var i,a=e[Symbol.iterator]();!(o=(i=a.next()).done)&&(r.push(i.value),!t||r.length!==t);o=!0);}catch(e){n=!0,s=e}finally{try{o||null==a.return||a.return()}finally{if(n)throw s}}return r}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function o(e,t,r){var o=i(e.toString().split("."),2),n=o[0],o=o[1];return void 0===r?(n=n.padStart(t,"0"),o?n+"."+o:n):(n=(e=i(e.toFixed(r).toString().split("."),2))[0],o=e[1],n=n.padStart(t,"0"),void 0===o?n:n+"."+o)}function n(e,t){var r=(e=e.toString()).indexOf("."),o=-1!==r?e.substring(r):"",e=(e=-1!==r?e.substring(0,r):e).toString().replace(/\B(?=(\d{3})+(?!\d))/g,",");if(0===t)o="";else if(void 0!==t)if(t>o.length)for(var n=t-(o+=-1===r?".":"").length+1,s=0;s=_.TWO_PI?"".concat(c="ellipse","|"):"".concat(c="arc","|").concat(s,"|").concat(i,"|").concat(a,"|")).concat(l,"|"),c=(this.geometryInHash(u)||((t=new S.default.Geometry(l,1,function(){if(s.toFixed(10)!==i.toFixed(10)){a!==_.PIE&&void 0!==a||(this.vertices.push(new S.default.Vector(.5,.5,0)),this.uvs.push([.5,.5]));for(var e=0;e<=l;e++){var t=(i-s)*(e/l)+s,r=.5+Math.cos(t)/2,t=.5+Math.sin(t)/2;this.vertices.push(new S.default.Vector(r,t,0)),this.uvs.push([r,t]),e>5&31)/31,(p>>10&31)/31):(r=i,o=a,l)),new x.default.Vector(y,g,v)),j=1;j<=3;j++){var _=m+12*j,_=new x.default.Vector(u.getFloat32(_,!0),u.getFloat32(4+_,!0),u.getFloat32(8+_,!0));e.vertices.push(_),e.vertexNormals.push(b),d&&s.push(r,o,n)}e.faces.push([3*f,3*f+1,3*f+2]),e.uvs.push([0,0],[0,0],[0,0])}}(e,t);else{t=new DataView(t);if(!("TextDecoder"in window))return console.warn("Sorry, ASCII STL loading only works in browsers that support TextDecoder (https://caniuse.com/#feat=textencoder)");t=new TextDecoder("utf-8").decode(t).split("\n");!function(e,t){for(var r,o,n="",s=[],i=0;ithis.cameraFar&&(i=this.cameraFar),Math.acos(Math.max(-1,Math.min(1,_.default.Vector.dot(o,n))))+t),t=e;(r<=0||r>=Math.PI)&&(this.upX*=-1,this.upY*=-1,this.upZ*=-1),n.mult(Math.cos(r)),a.mult(Math.cos(t)*Math.sin(r)),s.mult(Math.sin(t)*Math.sin(r)),o.set(n).add(a).add(s),this.eyeX=i*o.x+this.centerX,this.eyeY=i*o.y+this.centerY,this.eyeZ=i*o.z+this.centerZ,this.camera(this.eyeX,this.eyeY,this.eyeZ,this.centerX,this.centerY,this.centerZ,this.upX,this.upY,this.upZ)}},{key:"_orbitFree",value:function(e,t,r){var o=this.eyeX-this.centerX,n=this.eyeY-this.centerY,s=this.eyeZ-this.centerZ,i=Math.hypot(o,n,s),o=new _.default.Vector(o,n,s).normalize(),n=new _.default.Vector(this.upX,this.upY,this.upZ),s=new _.default.Vector.cross(n,o).normalize(),a=new _.default.Vector.cross(o,s),l=Math.atan2(t,e),l=(a.mult(Math.sin(l)),s.mult(Math.cos(l)).add(a),Math.sqrt(e*e+t*t)),a=new _.default.Vector.cross(o,s),e=((i=(i*=Math.pow(10,r))this.cameraFar&&(i=this.cameraFar),Math.cos(l)),t=Math.sin(l),r=n.dot(o),l=n.dot(s),u=r*e+l*t,r=-r*t+l*e,l=n.dot(a);n.x=u*o.x+r*s.x+l*a.x,n.y=u*o.y+r*s.y+l*a.y,n.z=u*o.z+r*s.z+l*a.z,s.mult(-t),o.mult(e).add(s).mult(i),this.camera(o.x+this.centerX,o.y+this.centerY,o.z+this.centerZ,this.centerX,this.centerY,this.centerZ,n.x,n.y,n.z)}},{key:"_isActive",value:function(){return this===this._renderer._curCamera}}])&&n(e.prototype,r),o&&n(e,o),t}(),_.default.prototype.setCamera=function(e){this._renderer._curCamera=e,this._renderer.uPMatrix.set(e.projMatrix.mat4[0],e.projMatrix.mat4[1],e.projMatrix.mat4[2],e.projMatrix.mat4[3],e.projMatrix.mat4[4],e.projMatrix.mat4[5],e.projMatrix.mat4[6],e.projMatrix.mat4[7],e.projMatrix.mat4[8],e.projMatrix.mat4[9],e.projMatrix.mat4[10],e.projMatrix.mat4[11],e.projMatrix.mat4[12],e.projMatrix.mat4[13],e.projMatrix.mat4[14],e.projMatrix.mat4[15])};e=_.default.Camera;r.default=e},{"../core/main":275,"core-js/modules/es.array.slice":165,"core-js/modules/es.math.hypot":170,"core-js/modules/es.string.sub":200}],325:[function(e,t,r){"use strict";e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.slice"),e("core-js/modules/es.math.log2"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.typed-array.float32-array"),e("core-js/modules/es.typed-array.copy-within"),e("core-js/modules/es.typed-array.every"),e("core-js/modules/es.typed-array.fill"),e("core-js/modules/es.typed-array.filter"),e("core-js/modules/es.typed-array.find"),e("core-js/modules/es.typed-array.find-index"),e("core-js/modules/es.typed-array.for-each"),e("core-js/modules/es.typed-array.includes"),e("core-js/modules/es.typed-array.index-of"),e("core-js/modules/es.typed-array.iterator"),e("core-js/modules/es.typed-array.join"),e("core-js/modules/es.typed-array.last-index-of"),e("core-js/modules/es.typed-array.map"),e("core-js/modules/es.typed-array.reduce"),e("core-js/modules/es.typed-array.reduce-right"),e("core-js/modules/es.typed-array.reverse"),e("core-js/modules/es.typed-array.set"),e("core-js/modules/es.typed-array.slice"),e("core-js/modules/es.typed-array.some"),e("core-js/modules/es.typed-array.sort"),e("core-js/modules/es.typed-array.subarray"),e("core-js/modules/es.typed-array.to-locale-string"),e("core-js/modules/es.typed-array.to-string"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.slice"),e("core-js/modules/es.math.log2"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.typed-array.float32-array"),e("core-js/modules/es.typed-array.copy-within"),e("core-js/modules/es.typed-array.every"),e("core-js/modules/es.typed-array.fill"),e("core-js/modules/es.typed-array.filter"),e("core-js/modules/es.typed-array.find"),e("core-js/modules/es.typed-array.find-index"),e("core-js/modules/es.typed-array.for-each"),e("core-js/modules/es.typed-array.includes"),e("core-js/modules/es.typed-array.index-of"),e("core-js/modules/es.typed-array.iterator"),e("core-js/modules/es.typed-array.join"),e("core-js/modules/es.typed-array.last-index-of"),e("core-js/modules/es.typed-array.map"),e("core-js/modules/es.typed-array.reduce"),e("core-js/modules/es.typed-array.reduce-right"),e("core-js/modules/es.typed-array.reverse"),e("core-js/modules/es.typed-array.set"),e("core-js/modules/es.typed-array.slice"),e("core-js/modules/es.typed-array.some"),e("core-js/modules/es.typed-array.sort"),e("core-js/modules/es.typed-array.subarray"),e("core-js/modules/es.typed-array.to-locale-string"),e("core-js/modules/es.typed-array.to-string"),Object.defineProperty(r,"__esModule",{value:!0}),r.default=void 0;e=(e=e("../core/main"))&&e.__esModule?e:{default:e};function n(e,t){for(var r=0;r=this.width||t>=this.height)&&(console.warn("The x and y values passed to p5.Framebuffer.get are outside of its range and will be clamped."),e=this.target.constrain(e,0,this.width-1),t=this.target.constrain(t,0,this.height-1)),(0,p.readPixelWebGL)(this.gl,this.framebuffer,e*this.density,t*this.density,n.format,n.type);e=this.target.constrain(e,0,this.width-1),t=this.target.constrain(t,0,this.height-1),r=this.target.constrain(r,1,this.width-e),o=this.target.constrain(o,1,this.height-t);for(var s=(0,p.readPixelsWebGL)(void 0,this.gl,this.framebuffer,e*this.density,t*this.density,r*this.density,o*this.density,n.format,n.type),i=new Uint8ClampedArray(r*o*this.density*this.density*4),a=(i.fill(255),n.type===this.gl.RGB?3:4),l=0;lthis.vertices.length-1-this.detailX;o--)e.add(this.vertexNormals[o]);e=m.default.Vector.div(e,this.detailX);for(var n=this.vertices.length-1;n>this.vertices.length-1-this.detailX;n--)this.vertexNormals[n]=e;return this}},{key:"_makeTriangleEdges",value:function(){for(var e=this.edges.length=0;e 65535 triangles. Your web browser does not support the WebGL Extension OES_element_index_uint.");r.drawElements(r.TRIANGLES,t.vertexCount,t.indexBufferType,0)}else r.drawArrays(e||r.TRIANGLES,0,t.vertexCount)},a.default.RendererGL.prototype._drawPoints=function(e,t){var r=this.GL,o=this._getImmediatePointShader();this._setPointUniforms(o),this._bindBuffer(t,r.ARRAY_BUFFER,this._vToNArray(e),Float32Array,r.STATIC_DRAW),o.enableAttrib(o.attributes.aPosition,3),this._applyColorBlend(this.curStrokeColor),r.drawArrays(r.Points,0,e.length),o.unbindShader()};var s=a.default.RendererGL;r.default=s},{"../core/constants":264,"../core/main":275,"./p5.RenderBuffer":329,"./p5.RendererGL":332,"core-js/modules/es.array.fill":154,"core-js/modules/es.array.iterator":161,"core-js/modules/es.array.some":166,"core-js/modules/es.object.get-own-property-descriptor":178,"core-js/modules/es.object.keys":181,"core-js/modules/es.object.to-string":182,"core-js/modules/es.string.iterator":192,"core-js/modules/es.symbol":204,"core-js/modules/es.symbol.description":202,"core-js/modules/es.symbol.iterator":203,"core-js/modules/es.typed-array.copy-within":205,"core-js/modules/es.typed-array.every":206,"core-js/modules/es.typed-array.fill":207,"core-js/modules/es.typed-array.filter":208,"core-js/modules/es.typed-array.find":210,"core-js/modules/es.typed-array.find-index":209,"core-js/modules/es.typed-array.float32-array":211,"core-js/modules/es.typed-array.for-each":213,"core-js/modules/es.typed-array.includes":214,"core-js/modules/es.typed-array.index-of":215,"core-js/modules/es.typed-array.iterator":218,"core-js/modules/es.typed-array.join":219,"core-js/modules/es.typed-array.last-index-of":220,"core-js/modules/es.typed-array.map":221,"core-js/modules/es.typed-array.reduce":223,"core-js/modules/es.typed-array.reduce-right":222,"core-js/modules/es.typed-array.reverse":224,"core-js/modules/es.typed-array.set":225,"core-js/modules/es.typed-array.slice":226,"core-js/modules/es.typed-array.some":227,"core-js/modules/es.typed-array.sort":228,"core-js/modules/es.typed-array.subarray":229,"core-js/modules/es.typed-array.to-locale-string":230,"core-js/modules/es.typed-array.to-string":231,"core-js/modules/es.typed-array.uint16-array":232,"core-js/modules/es.typed-array.uint32-array":233,"core-js/modules/es.weak-map":236,"core-js/modules/web.dom-collections.iterator":238}],332:[function(e,t,r){"use strict";function o(e){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function i(e){return(i="function"==typeof Symbol&&"symbol"===o(Symbol.iterator)?function(e){return o(e)}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":o(e)})(e)}e("core-js/modules/es.symbol"),e("core-js/modules/es.symbol.description"),e("core-js/modules/es.symbol.iterator"),e("core-js/modules/es.array.concat"),e("core-js/modules/es.array.copy-within"),e("core-js/modules/es.array.every"),e("core-js/modules/es.array.fill"),e("core-js/modules/es.array.from"),e("core-js/modules/es.array.includes"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.slice"),e("core-js/modules/es.array.some"),e("core-js/modules/es.map"),e("core-js/modules/es.object.assign"),e("core-js/modules/es.object.get-own-property-descriptor"),e("core-js/modules/es.object.get-prototype-of"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.reflect.construct"),e("core-js/modules/es.reflect.get"),e("core-js/modules/es.regexp.to-string"),e("core-js/modules/es.set"),e("core-js/modules/es.string.includes"),e("core-js/modules/es.string.iterator"),e("core-js/modules/es.typed-array.float32-array"),e("core-js/modules/es.typed-array.float64-array"),e("core-js/modules/es.typed-array.int16-array"),e("core-js/modules/es.typed-array.uint8-array"),e("core-js/modules/es.typed-array.uint16-array"),e("core-js/modules/es.typed-array.uint32-array"),e("core-js/modules/es.typed-array.copy-within"),e("core-js/modules/es.typed-array.every"),e("core-js/modules/es.typed-array.fill"),e("core-js/modules/es.typed-array.filter"),e("core-js/modules/es.typed-array.find"),e("core-js/modules/es.typed-array.find-index"),e("core-js/modules/es.typed-array.for-each"),e("core-js/modules/es.typed-array.includes"),e("core-js/modules/es.typed-array.index-of"),e("core-js/modules/es.typed-array.iterator"),e("core-js/modules/es.typed-array.join"),e("core-js/modules/es.typed-array.last-index-of"),e("core-js/modules/es.typed-array.map"),e("core-js/modules/es.typed-array.reduce"),e("core-js/modules/es.typed-array.reduce-right"),e("core-js/modules/es.typed-array.reverse"),e("core-js/modules/es.typed-array.set"),e("core-js/modules/es.typed-array.slice"),e("core-js/modules/es.typed-array.some"),e("core-js/modules/es.typed-array.sort"),e("core-js/modules/es.typed-array.subarray"),e("core-js/modules/es.typed-array.to-locale-string"),e("core-js/modules/es.typed-array.to-string"),e("core-js/modules/es.weak-map"),e("core-js/modules/web.dom-collections.iterator"),e("core-js/modules/es.symbol"),e("core-js/modules/es.symbol.description"),e("core-js/modules/es.symbol.iterator"),e("core-js/modules/es.array.concat"),e("core-js/modules/es.array.copy-within"),e("core-js/modules/es.array.every"),e("core-js/modules/es.array.fill"),e("core-js/modules/es.array.from"),e("core-js/modules/es.array.includes"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.slice"),e("core-js/modules/es.array.some"),e("core-js/modules/es.map"),e("core-js/modules/es.object.assign"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.set"),e("core-js/modules/es.string.includes"),e("core-js/modules/es.string.iterator"),e("core-js/modules/es.typed-array.float32-array"),e("core-js/modules/es.typed-array.float64-array"),e("core-js/modules/es.typed-array.int16-array"),e("core-js/modules/es.typed-array.uint8-array"),e("core-js/modules/es.typed-array.uint16-array"),e("core-js/modules/es.typed-array.uint32-array"),e("core-js/modules/es.typed-array.copy-within"),e("core-js/modules/es.typed-array.every"),e("core-js/modules/es.typed-array.fill"),e("core-js/modules/es.typed-array.filter"),e("core-js/modules/es.typed-array.find"),e("core-js/modules/es.typed-array.find-index"),e("core-js/modules/es.typed-array.for-each"),e("core-js/modules/es.typed-array.includes"),e("core-js/modules/es.typed-array.index-of"),e("core-js/modules/es.typed-array.iterator"),e("core-js/modules/es.typed-array.join"),e("core-js/modules/es.typed-array.last-index-of"),e("core-js/modules/es.typed-array.map"),e("core-js/modules/es.typed-array.reduce"),e("core-js/modules/es.typed-array.reduce-right"),e("core-js/modules/es.typed-array.reverse"),e("core-js/modules/es.typed-array.set"),e("core-js/modules/es.typed-array.slice"),e("core-js/modules/es.typed-array.some"),e("core-js/modules/es.typed-array.sort"),e("core-js/modules/es.typed-array.subarray"),e("core-js/modules/es.typed-array.to-locale-string"),e("core-js/modules/es.typed-array.to-string"),e("core-js/modules/web.dom-collections.iterator"),Object.defineProperty(r,"__esModule",{value:!0}),r.readPixelsWebGL=k,r.readPixelWebGL=C,r.default=void 0;var g=n(e("../core/main")),l=function(e){if(e&&e.__esModule)return e;if(null===e||"object"!==i(e)&&"function"!=typeof e)return{default:e};var t=d();if(t&&t.has(e))return t.get(e);var r,o={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(r in e){var s;Object.prototype.hasOwnProperty.call(e,r)&&((s=n?Object.getOwnPropertyDescriptor(e,r):null)&&(s.get||s.set)?Object.defineProperty(o,r,s):o[r]=e[r])}o.default=e,t&&t.set(e,o);return o}(e("../core/constants")),a=n(e("./GeometryBuilder")),u=n(e("libtess")),c=(e("./p5.Shader"),e("./p5.Camera"),e("../core/p5.Renderer"),e("./p5.Matrix"),e("./p5.Framebuffer"),e("path"),e("./p5.Texture"));function d(){var e;return"function"!=typeof WeakMap?null:(e=new WeakMap,d=function(){return e},e)}function n(e){return e&&e.__esModule?e:{default:e}}function h(e){return function(e){if(Array.isArray(e)){for(var t=0,r=new Array(e.length);t vTexCoord.y;\n bool y1 = p1.y > vTexCoord.y;\n bool y2 = p2.y > vTexCoord.y;\n\n // could web be under the curve (after t1)?\n if (y1 ? !y2 : y0) {\n // add the coverage for t1\n coverage.x += saturate(C1.x + 0.5);\n // calculate the anti-aliasing for t1\n weight.x = min(weight.x, abs(C1.x));\n }\n\n // are we outside the curve (after t2)?\n if (y1 ? !y0 : y2) {\n // subtract the coverage for t2\n coverage.x -= saturate(C2.x + 0.5);\n // calculate the anti-aliasing for t2\n weight.x = min(weight.x, abs(C2.x));\n }\n}\n\n// this is essentially the same as coverageX, but with the axes swapped\nvoid coverageY(vec2 p0, vec2 p1, vec2 p2) {\n\n vec2 C1, C2;\n calulateCrossings(p0, p1, p2, C1, C2);\n\n bool x0 = p0.x > vTexCoord.x;\n bool x1 = p1.x > vTexCoord.x;\n bool x2 = p2.x > vTexCoord.x;\n\n if (x1 ? !x2 : x0) {\n coverage.y -= saturate(C1.y + 0.5);\n weight.y = min(weight.y, abs(C1.y));\n }\n\n if (x1 ? !x0 : x2) {\n coverage.y += saturate(C2.y + 0.5);\n weight.y = min(weight.y, abs(C2.y));\n }\n}\n\nvoid main() {\n\n // calculate the pixel scale based on screen-coordinates\n pixelScale = hardness / fwidth(vTexCoord);\n\n // which grid cell is this pixel in?\n ivec2 gridCoord = ifloor(vTexCoord * vec2(uGridSize));\n\n // intersect curves in this row\n {\n // the index into the row info bitmap\n int rowIndex = gridCoord.y + uGridOffset.y;\n // fetch the info texel\n vec4 rowInfo = getTexel(uSamplerRows, rowIndex, uGridImageSize);\n // unpack the rowInfo\n int rowStrokeIndex = getInt16(rowInfo.xy);\n int rowStrokeCount = getInt16(rowInfo.zw);\n\n for (int iRowStroke = INT(0); iRowStroke < N; iRowStroke++) {\n if (iRowStroke >= rowStrokeCount)\n break;\n\n // each stroke is made up of 3 points: the start and control point\n // and the start of the next curve.\n // fetch the indices of this pair of strokes:\n vec4 strokeIndices = getTexel(uSamplerRowStrokes, rowStrokeIndex++, uCellsImageSize);\n\n // unpack the stroke index\n int strokePos = getInt16(strokeIndices.xy);\n\n // fetch the two strokes\n vec4 stroke0 = getTexel(uSamplerStrokes, strokePos + INT(0), uStrokeImageSize);\n vec4 stroke1 = getTexel(uSamplerStrokes, strokePos + INT(1), uStrokeImageSize);\n\n // calculate the coverage\n coverageX(stroke0.xy, stroke0.zw, stroke1.xy);\n }\n }\n\n // intersect curves in this column\n {\n int colIndex = gridCoord.x + uGridOffset.x;\n vec4 colInfo = getTexel(uSamplerCols, colIndex, uGridImageSize);\n int colStrokeIndex = getInt16(colInfo.xy);\n int colStrokeCount = getInt16(colInfo.zw);\n \n for (int iColStroke = INT(0); iColStroke < N; iColStroke++) {\n if (iColStroke >= colStrokeCount)\n break;\n\n vec4 strokeIndices = getTexel(uSamplerColStrokes, colStrokeIndex++, uCellsImageSize);\n\n int strokePos = getInt16(strokeIndices.xy);\n vec4 stroke0 = getTexel(uSamplerStrokes, strokePos + INT(0), uStrokeImageSize);\n vec4 stroke1 = getTexel(uSamplerStrokes, strokePos + INT(1), uStrokeImageSize);\n coverageY(stroke0.xy, stroke0.zw, stroke1.xy);\n }\n }\n\n weight = saturate(1.0 - weight * 2.0);\n float distance = max(weight.x + weight.y, minDistance); // manhattan approx.\n float antialias = abs(dot(coverage, weight) / distance);\n float cover = min(abs(coverage.x), abs(coverage.y));\n OUT_COLOR = vec4(uMaterialColor.rgb, 1.) * uMaterialColor.a;\n OUT_COLOR *= saturate(max(antialias, cover));\n}\n",lineVert:T+"/*\n Part of the Processing project - http://processing.org\n Copyright (c) 2012-15 The Processing Foundation\n Copyright (c) 2004-12 Ben Fry and Casey Reas\n Copyright (c) 2001-04 Massachusetts Institute of Technology\n This library is free software; you can redistribute it and/or\n modify it under the terms of the GNU Lesser General Public\n License as published by the Free Software Foundation, version 2.1.\n This library is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n Lesser General Public License for more details.\n You should have received a copy of the GNU Lesser General\n Public License along with this library; if not, write to the\n Free Software Foundation, Inc., 59 Temple Place, Suite 330,\n Boston, MA 02111-1307 USA\n*/\n\n#define PROCESSING_LINE_SHADER\n\nprecision mediump int;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform float uStrokeWeight;\n\nuniform bool uUseLineColor;\nuniform vec4 uMaterialColor;\n\nuniform vec4 uViewport;\nuniform int uPerspective;\nuniform int uStrokeJoin;\n\nIN vec4 aPosition;\nIN vec3 aTangentIn;\nIN vec3 aTangentOut;\nIN float aSide;\nIN vec4 aVertexColor;\n\nOUT vec4 vColor;\nOUT vec2 vTangent;\nOUT vec2 vCenter;\nOUT vec2 vPosition;\nOUT float vMaxDist;\nOUT float vCap;\nOUT float vJoin;\n\nvec2 lineIntersection(vec2 aPoint, vec2 aDir, vec2 bPoint, vec2 bDir) {\n // Rotate and translate so a starts at the origin and goes out to the right\n bPoint -= aPoint;\n vec2 rotatedBFrom = vec2(\n bPoint.x*aDir.x + bPoint.y*aDir.y,\n bPoint.y*aDir.x - bPoint.x*aDir.y\n );\n vec2 bTo = bPoint + bDir;\n vec2 rotatedBTo = vec2(\n bTo.x*aDir.x + bTo.y*aDir.y,\n bTo.y*aDir.x - bTo.x*aDir.y\n );\n float intersectionDistance =\n rotatedBTo.x + (rotatedBFrom.x - rotatedBTo.x) * rotatedBTo.y /\n (rotatedBTo.y - rotatedBFrom.y);\n return aPoint + aDir * intersectionDistance;\n}\n\nvoid main() {\n // Caps have one of either the in or out tangent set to 0\n vCap = (aTangentIn == vec3(0.)) != (aTangentOut == (vec3(0.)))\n ? 1. : 0.;\n\n // Joins have two unique, defined tangents\n vJoin = (\n aTangentIn != vec3(0.) &&\n aTangentOut != vec3(0.) &&\n aTangentIn != aTangentOut\n ) ? 1. : 0.;\n\n vec4 posp = uModelViewMatrix * aPosition;\n vec4 posqIn = uModelViewMatrix * (aPosition + vec4(aTangentIn, 0));\n vec4 posqOut = uModelViewMatrix * (aPosition + vec4(aTangentOut, 0));\n\n float facingCamera = pow(\n // The word space tangent's z value is 0 if it's facing the camera\n abs(normalize(posqIn-posp).z),\n\n // Using pow() here to ramp `facingCamera` up from 0 to 1 really quickly\n // so most lines get scaled and don't get clipped\n 0.25\n );\n\n // using a scale <1 moves the lines towards the camera\n // in order to prevent popping effects due to half of\n // the line disappearing behind the geometry faces.\n float scale = mix(1., 0.995, facingCamera);\n\n // Moving vertices slightly toward the camera\n // to avoid depth-fighting with the fill triangles.\n // Discussed here:\n // http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=252848 \n posp.xyz = posp.xyz * scale;\n posqIn.xyz = posqIn.xyz * scale;\n posqOut.xyz = posqOut.xyz * scale;\n\n vec4 p = uProjectionMatrix * posp;\n vec4 qIn = uProjectionMatrix * posqIn;\n vec4 qOut = uProjectionMatrix * posqOut;\n vCenter = p.xy;\n\n // formula to convert from clip space (range -1..1) to screen space (range 0..[width or height])\n // screen_p = (p.xy/p.w + <1,1>) * 0.5 * uViewport.zw\n\n // prevent division by W by transforming the tangent formula (div by 0 causes\n // the line to disappear, see https://github.com/processing/processing/issues/5183)\n // t = screen_q - screen_p\n //\n // tangent is normalized and we don't care which aDirection it points to (+-)\n // t = +- normalize( screen_q - screen_p )\n // t = +- normalize( (q.xy/q.w+<1,1>)*0.5*uViewport.zw - (p.xy/p.w+<1,1>)*0.5*uViewport.zw )\n //\n // extract common factor, <1,1> - <1,1> cancels out\n // t = +- normalize( (q.xy/q.w - p.xy/p.w) * 0.5 * uViewport.zw )\n //\n // convert to common divisor\n // t = +- normalize( ((q.xy*p.w - p.xy*q.w) / (p.w*q.w)) * 0.5 * uViewport.zw )\n //\n // remove the common scalar divisor/factor, not needed due to normalize and +-\n // (keep uViewport - can't remove because it has different components for x and y\n // and corrects for aspect ratio, see https://github.com/processing/processing/issues/5181)\n // t = +- normalize( (q.xy*p.w - p.xy*q.w) * uViewport.zw )\n\n vec2 tangentIn = normalize((qIn.xy*p.w - p.xy*qIn.w) * uViewport.zw);\n vec2 tangentOut = normalize((qOut.xy*p.w - p.xy*qOut.w) * uViewport.zw);\n\n vec2 curPerspScale;\n if(uPerspective == 1) {\n // Perspective ---\n // convert from world to clip by multiplying with projection scaling factor\n // to get the right thickness (see https://github.com/processing/processing/issues/5182)\n\n // The y value of the projection matrix may be flipped if rendering to a Framebuffer.\n // Multiplying again by its sign here negates the flip to get just the scale.\n curPerspScale = (uProjectionMatrix * vec4(1, sign(uProjectionMatrix[1][1]), 0, 0)).xy;\n } else {\n // No Perspective ---\n // multiply by W (to cancel out division by W later in the pipeline) and\n // convert from screen to clip (derived from clip to screen above)\n curPerspScale = p.w / (0.5 * uViewport.zw);\n }\n\n vec2 offset;\n if (vJoin == 1.) {\n vTangent = normalize(tangentIn + tangentOut);\n vec2 normalIn = vec2(-tangentIn.y, tangentIn.x);\n vec2 normalOut = vec2(-tangentOut.y, tangentOut.x);\n float side = sign(aSide);\n float sideEnum = abs(aSide);\n\n // We generate vertices for joins on either side of the centerline, but\n // the \"elbow\" side is the only one needing a join. By not setting the\n // offset for the other side, all its vertices will end up in the same\n // spot and not render, effectively discarding it.\n if (sign(dot(tangentOut, vec2(-tangentIn.y, tangentIn.x))) != side) {\n // Side enums:\n // 1: the side going into the join\n // 2: the middle of the join\n // 3: the side going out of the join\n if (sideEnum == 2.) {\n // Calculate the position + tangent on either side of the join, and\n // find where the lines intersect to find the elbow of the join\n vec2 c = (posp.xy/posp.w + vec2(1.,1.)) * 0.5 * uViewport.zw;\n vec2 intersection = lineIntersection(\n c + (side * normalIn * uStrokeWeight / 2.),\n tangentIn,\n c + (side * normalOut * uStrokeWeight / 2.),\n tangentOut\n );\n offset = (intersection - c);\n\n // When lines are thick and the angle of the join approaches 180, the\n // elbow might be really far from the center. We'll apply a limit to\n // the magnitude to avoid lines going across the whole screen when this\n // happens.\n float mag = length(offset);\n float maxMag = 3. * uStrokeWeight;\n if (mag > maxMag) {\n offset *= maxMag / mag;\n }\n } else if (sideEnum == 1.) {\n offset = side * normalIn * uStrokeWeight / 2.;\n } else if (sideEnum == 3.) {\n offset = side * normalOut * uStrokeWeight / 2.;\n }\n }\n if (uStrokeJoin == STROKE_JOIN_BEVEL) {\n vec2 avgNormal = vec2(-vTangent.y, vTangent.x);\n vMaxDist = abs(dot(avgNormal, normalIn * uStrokeWeight / 2.));\n } else {\n vMaxDist = uStrokeWeight / 2.;\n }\n } else {\n vec2 tangent = aTangentIn == vec3(0.) ? tangentOut : tangentIn;\n vTangent = tangent;\n vec2 normal = vec2(-tangent.y, tangent.x);\n\n float normalOffset = sign(aSide);\n // Caps will have side values of -2 or 2 on the edge of the cap that\n // extends out from the line\n float tangentOffset = abs(aSide) - 1.;\n offset = (normal * normalOffset + tangent * tangentOffset) *\n uStrokeWeight * 0.5;\n vMaxDist = uStrokeWeight / 2.;\n }\n vPosition = vCenter + offset;\n\n gl_Position.xy = p.xy + offset.xy * curPerspScale;\n gl_Position.zw = p.zw;\n \n vColor = (uUseLineColor ? aVertexColor : uMaterialColor);\n}\n",lineFrag:T+"precision mediump int;\n\nuniform vec4 uMaterialColor;\nuniform int uStrokeCap;\nuniform int uStrokeJoin;\nuniform float uStrokeWeight;\n\nIN vec4 vColor;\nIN vec2 vTangent;\nIN vec2 vCenter;\nIN vec2 vPosition;\nIN float vMaxDist;\nIN float vCap;\nIN float vJoin;\n\nfloat distSquared(vec2 a, vec2 b) {\n vec2 aToB = b - a;\n return dot(aToB, aToB);\n}\n\nvoid main() {\n if (vCap > 0.) {\n if (\n uStrokeCap == STROKE_CAP_ROUND &&\n distSquared(vPosition, vCenter) > uStrokeWeight * uStrokeWeight * 0.25\n ) {\n discard;\n } else if (\n uStrokeCap == STROKE_CAP_SQUARE &&\n dot(vPosition - vCenter, vTangent) > 0.\n ) {\n discard;\n }\n // Use full area for PROJECT\n } else if (vJoin > 0.) {\n if (\n uStrokeJoin == STROKE_JOIN_ROUND &&\n distSquared(vPosition, vCenter) > uStrokeWeight * uStrokeWeight * 0.25\n ) {\n discard;\n } else if (uStrokeJoin == STROKE_JOIN_BEVEL) {\n vec2 normal = vec2(-vTangent.y, vTangent.x);\n if (abs(dot(vPosition - vCenter, normal)) > vMaxDist) {\n discard;\n }\n }\n // Use full area for MITER\n }\n OUT_COLOR = vec4(vColor.rgb, 1.) * vColor.a;\n}\n",pointVert:"IN vec3 aPosition;\nuniform float uPointSize;\nOUT float vStrokeWeight;\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nvoid main() {\n\tvec4 positionVec4 = vec4(aPosition, 1.0);\n\tgl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n\tgl_PointSize = uPointSize;\n\tvStrokeWeight = uPointSize;\n}\n",pointFrag:"precision mediump int;\nuniform vec4 uMaterialColor;\nIN float vStrokeWeight;\n\nvoid main(){\n float mask = 0.0;\n\n // make a circular mask using the gl_PointCoord (goes from 0 - 1 on a point)\n // might be able to get a nicer edge on big strokeweights with smoothstep but slightly less performant\n\n mask = step(0.98, length(gl_PointCoord * 2.0 - 1.0));\n\n // if strokeWeight is 1 or less lets just draw a square\n // this prevents weird artifacting from carving circles when our points are really small\n // if strokeWeight is larger than 1, we just use it as is\n\n mask = mix(0.0, mask, clamp(floor(vStrokeWeight - 0.5),0.0,1.0));\n\n // throw away the borders of the mask\n // otherwise we get weird alpha blending issues\n\n if(mask > 0.98){\n discard;\n }\n\n OUT_COLOR = vec4(uMaterialColor.rgb, 1.) * uMaterialColor.a;\n}\n",imageLightVert:"precision highp float;\nattribute vec3 aPosition;\nattribute vec3 aNormal;\nattribute vec2 aTexCoord;\n\nvarying vec3 localPos;\nvarying vec3 vWorldNormal;\nvarying vec3 vWorldPosition;\nvarying vec2 vTexCoord;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform mat3 uNormalMatrix;\n\nvoid main() {\n // Multiply the position by the matrix.\n vec4 viewModelPosition = uModelViewMatrix * vec4(aPosition, 1.0);\n gl_Position = uProjectionMatrix * viewModelPosition; \n \n // orient the normals and pass to the fragment shader\n vWorldNormal = uNormalMatrix * aNormal;\n \n // send the view position to the fragment shader\n vWorldPosition = (uModelViewMatrix * vec4(aPosition, 1.0)).xyz;\n \n localPos = vWorldPosition;\n vTexCoord = aTexCoord;\n}\n\n\n/*\nin the vertex shader we'll compute the world position and world oriented normal of the vertices and pass those to the fragment shader as varyings.\n*/\n",imageLightDiffusedFrag:"precision highp float;\nvarying vec3 localPos;\n\n// the HDR cubemap converted (can be from an equirectangular environment map.)\nuniform sampler2D environmentMap;\nvarying vec2 vTexCoord;\n\nconst float PI = 3.14159265359;\n\nvec2 nTOE( vec3 v ){\n // x = r sin(phi) cos(theta) \n // y = r cos(phi) \n // z = r sin(phi) sin(theta)\n float phi = acos( v.y );\n // if phi is 0, then there are no x, z components\n float theta = 0.0;\n // else \n theta = acos(v.x / sin(phi));\n float sinTheta = v.z / sin(phi);\n if (sinTheta < 0.0) {\n // Turn it into -theta, but in the 0-2PI range\n theta = 2.0 * PI - theta;\n }\n theta = theta / (2.0 * 3.14159);\n phi = phi / 3.14159 ;\n \n vec2 angles = vec2( phi, theta );\n return angles;\n}\n\nvoid main()\n{ \t \n\t// the sample direction equals the hemisphere's orientation\n float phi = vTexCoord.x * 2.0 * PI;\n float theta = vTexCoord.y * PI;\n float x = sin(theta) * cos(phi);\n float y = sin(theta) * sin(phi);\n float z = cos(theta);\n vec3 normal = vec3( x, y, z);\n\n\t// Discretely sampling the hemisphere given the integral's\n // spherical coordinates translates to the following fragment code:\n\tvec3 irradiance = vec3(0.0); \n\tvec3 up\t= vec3(0.0, 1.0, 0.0);\n\tvec3 right = normalize(cross(up, normal));\n\tup = normalize(cross(normal, right));\n\n\t// We specify a fixed sampleDelta delta value to traverse\n // the hemisphere; decreasing or increasing the sample delta\n // will increase or decrease the accuracy respectively.\n\tconst float sampleDelta = 0.025;\n\tfloat nrSamples = 0.0;\n \n\tfor(float phi = 0.0; phi < 2.0 * PI; phi += sampleDelta)\n\t{\n for(float theta = 0.0; theta < ( 0.5 ) * PI; theta += sampleDelta)\n {\n // spherical to cartesian (in tangent space) // tangent space to world // add each sample result to irradiance\n float x = sin(theta) * cos(phi);\n float y = sin(theta) * sin(phi);\n float z = cos(theta);\n vec3 tangentSample = vec3( x, y, z);\n \n vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * normal;\n irradiance += (texture2D(environmentMap, nTOE(sampleVec)).xyz) * cos(theta) * sin(theta);\n nrSamples++;\n }\n\t}\n\t// divide by the total number of samples taken, giving us the average sampled irradiance.\n\tirradiance = PI * irradiance * (1.0 / float(nrSamples )) ;\n \n \n\tgl_FragColor = vec4(irradiance, 1.0);\n}",imageLightSpecularFrag:"precision highp float;\r\nvarying vec3 localPos;\r\nvarying vec2 vTexCoord;\r\n\r\n// our texture\r\nuniform sampler2D environmentMap;\r\nuniform float roughness;\r\n\r\nconst float PI = 3.14159265359;\r\n\r\nfloat VanDerCorput(int bits);\r\nvec2 HammersleyNoBitOps(int i, int N);\r\nvec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness);\r\n\r\n\r\nvec2 nTOE( vec3 v ){\r\n // x = r sin(phi) cos(theta) \r\n // y = r cos(phi) \r\n // z = r sin(phi) sin(theta)\r\n float phi = acos( v.y );\r\n // if phi is 0, then there are no x, z components\r\n float theta = 0.0;\r\n // else \r\n theta = acos(v.x / sin(phi));\r\n float sinTheta = v.z / sin(phi);\r\n if (sinTheta < 0.0) {\r\n // Turn it into -theta, but in the 0-2PI range\r\n theta = 2.0 * PI - theta;\r\n }\r\n theta = theta / (2.0 * 3.14159);\r\n phi = phi / 3.14159 ;\r\n \r\n vec2 angles = vec2( phi, theta );\r\n return angles;\r\n}\r\n\r\n\r\nvoid main(){\r\n const int SAMPLE_COUNT = 1024; // 4096\r\n float totalWeight = 0.0;\r\n vec3 prefilteredColor = vec3(0.0);\r\n float phi = vTexCoord.x * 2.0 * PI;\r\n float theta = vTexCoord.y * PI;\r\n float x = sin(theta) * cos(phi);\r\n float y = sin(theta) * sin(phi);\r\n float z = cos(theta);\r\n vec3 N = vec3(x,y,z);\r\n vec3 V = N;\r\n for (int i = 0; i < SAMPLE_COUNT; ++i)\r\n {\r\n vec2 Xi = HammersleyNoBitOps(i, SAMPLE_COUNT);\r\n vec3 H = ImportanceSampleGGX(Xi, N, roughness);\r\n vec3 L = normalize(2.0 * dot(V, H) * H - V);\r\n\r\n float NdotL = max(dot(N, L), 0.0);\r\n if (NdotL > 0.0)\r\n {\r\n prefilteredColor += texture2D(environmentMap, nTOE(L)).xyz * NdotL;\r\n totalWeight += NdotL;\r\n }\r\n }\r\n prefilteredColor = prefilteredColor / totalWeight;\r\n\r\n gl_FragColor = vec4(prefilteredColor, 1.0);\r\n}\r\n\r\nvec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness){\r\n float a = roughness * roughness;\r\n\r\n float phi = 2.0 * PI * Xi.x;\r\n float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y));\r\n float sinTheta = sqrt(1.0 - cosTheta * cosTheta);\r\n // from spherical coordinates to cartesian coordinates\r\n vec3 H;\r\n H.x = cos(phi) * sinTheta;\r\n H.y = sin(phi) * sinTheta;\r\n H.z = cosTheta;\r\n\r\n // from tangent-space vector to world-space sample vector\r\n vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);\r\n vec3 tangent = normalize(cross(up, N));\r\n vec3 bitangent = cross(N, tangent);\r\n\r\n vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;\r\n return normalize(sampleVec);\r\n}\r\n\r\n\r\nfloat VanDerCorput(int n, int base)\r\n{\r\n float invBase = 1.0 / float(base);\r\n float denom = 1.0;\r\n float result = 0.0;\r\n\r\n for (int i = 0; i < 32; ++i)\r\n {\r\n\tif (n > 0)\r\n\t{\r\n \tdenom = mod(float(n), 2.0);\r\n \tresult += denom * invBase;\r\n \tinvBase = invBase / 2.0;\r\n \tn = int(float(n) / 2.0);\r\n\t}\r\n }\r\n\r\n return result;\r\n}\r\n\r\nvec2 HammersleyNoBitOps(int i, int N)\r\n{\r\n return vec2(float(i) / float(N), VanDerCorput(i, 2));\r\n}\r\n"};for(x in M)M[x]="#ifdef WEBGL2\n\n#define IN in\n#define OUT out\n\n#ifdef FRAGMENT_SHADER\nout vec4 outColor;\n#define OUT_COLOR outColor\n#endif\n#define TEXTURE texture\n\n#else\n\n#ifdef FRAGMENT_SHADER\n#define IN varying\n#else\n#define IN attribute\n#endif\n#define OUT varying\n#define TEXTURE texture2D\n\n#ifdef FRAGMENT_SHADER\n#define OUT_COLOR gl_FragColor\n#endif\n\n#endif\n"+M[x];j(e={},l.GRAY,"precision highp float;\n\nvarying vec2 vTexCoord;\n\nuniform sampler2D tex0;\n\nfloat luma(vec3 color) {\n // weighted grayscale with luminance values\n return dot(color, vec3(0.2126, 0.7152, 0.0722));\n}\n\nvoid main() {\n vec4 tex = texture2D(tex0, vTexCoord);\n float gray = luma(tex.rgb);\n gl_FragColor = vec4(gray, gray, gray, tex.a);\n}\n"),j(e,l.ERODE,"// Reduces the bright areas in an image\n\nprecision highp float;\n\nvarying vec2 vTexCoord;\n\nuniform sampler2D tex0;\nuniform vec2 texelSize;\n\nfloat luma(vec3 color) {\n // weighted grayscale with luminance values\n // weights 77, 151, 28 taken from src/image/filters.js\n return dot(color, vec3(0.300781, 0.589844, 0.109375));\n}\n\nvoid main() {\n vec4 color = texture2D(tex0, vTexCoord);\n float lum = luma(color.rgb);\n\n // set current color as the darkest neighbor color\n\n vec4 neighbors[4];\n neighbors[0] = texture2D(tex0, vTexCoord + vec2( texelSize.x, 0.0));\n neighbors[1] = texture2D(tex0, vTexCoord + vec2(-texelSize.x, 0.0));\n neighbors[2] = texture2D(tex0, vTexCoord + vec2(0.0, texelSize.y));\n neighbors[3] = texture2D(tex0, vTexCoord + vec2(0.0, -texelSize.y));\n\n for (int i = 0; i < 4; i++) {\n vec4 neighborColor = neighbors[i];\n float neighborLum = luma(neighborColor.rgb);\n\n if (neighborLum < lum) {\n color = neighborColor;\n lum = neighborLum;\n }\n }\n\n gl_FragColor = color;\n}\n"),j(e,l.DILATE,"// Increase the bright areas in an image\n\nprecision highp float;\n\nvarying vec2 vTexCoord;\n\nuniform sampler2D tex0;\nuniform vec2 texelSize;\n\nfloat luma(vec3 color) {\n // weighted grayscale with luminance values\n // weights 77, 151, 28 taken from src/image/filters.js\n return dot(color, vec3(0.300781, 0.589844, 0.109375));\n}\n\nvoid main() {\n vec4 color = texture2D(tex0, vTexCoord);\n float lum = luma(color.rgb);\n\n // set current color as the brightest neighbor color\n\n vec4 neighbors[4];\n neighbors[0] = texture2D(tex0, vTexCoord + vec2( texelSize.x, 0.0));\n neighbors[1] = texture2D(tex0, vTexCoord + vec2(-texelSize.x, 0.0));\n neighbors[2] = texture2D(tex0, vTexCoord + vec2(0.0, texelSize.y));\n neighbors[3] = texture2D(tex0, vTexCoord + vec2(0.0, -texelSize.y));\n\n for (int i = 0; i < 4; i++) {\n vec4 neighborColor = neighbors[i];\n float neighborLum = luma(neighborColor.rgb);\n\n if (neighborLum > lum) {\n color = neighborColor;\n lum = neighborLum;\n }\n }\n\n gl_FragColor = color;\n}\n"),j(e,l.BLUR,"precision highp float;\n\n// Two-pass blur filter, unweighted kernel.\n// See also a similar blur at Adam Ferriss' repo of shader examples:\n// https://github.com/aferriss/p5jsShaderExamples/blob/gh-pages/4_image-effects/4-9_single-pass-blur/effect.frag\n\n\nuniform sampler2D tex0;\nvarying vec2 vTexCoord;\nuniform vec2 direction;\nuniform vec2 canvasSize;\nuniform float radius;\n\nfloat random(vec2 p) {\n vec3 p3 = fract(vec3(p.xyx) * .1031);\n p3 += dot(p3, p3.yzx + 33.33);\n return fract((p3.x + p3.y) * p3.z);\n}\n\n// This isn't a real Gaussian weight, it's a quadratic weight. It's what the\n// CPU mode's blur uses though, so we also use it here to match.\nfloat quadWeight(float x, float e) {\n return pow(e-abs(x), 2.);\n}\n\nvoid main(){\n vec2 uv = vTexCoord;\n\n // A reasonable maximum number of samples\n const float maxSamples = 64.0;\n\n float numSamples = floor(7. * radius);\n if (fract(numSamples / 2.) == 0.) {\n numSamples++;\n }\n vec4 avg = vec4(0.0);\n float total = 0.0;\n\n // Calculate the spacing to avoid skewing if numSamples > maxSamples\n float spacing = 1.0;\n if (numSamples > maxSamples) {\n spacing = numSamples / maxSamples;\n numSamples = maxSamples;\n }\n\n float randomOffset = (spacing - 1.0) * mix(-0.5, 0.5, random(gl_FragCoord.xy));\n for (float i = 0.0; i < maxSamples; i++) {\n if (i >= numSamples) break;\n\n float sample = i * spacing - (numSamples - 1.0) * 0.5 * spacing + randomOffset;\n vec2 sampleCoord = uv + vec2(sample, sample) / canvasSize * direction;\n float weight = quadWeight(sample, (numSamples - 1.0) * 0.5 * spacing);\n\n avg += weight * texture2D(tex0, sampleCoord);\n total += weight;\n }\n\n avg /= total;\n gl_FragColor = avg;\n}\n"),j(e,l.POSTERIZE,"// Limit color space for a stylized cartoon / poster effect\n\nprecision highp float;\n\nvarying vec2 vTexCoord;\n\nuniform sampler2D tex0;\nuniform float filterParameter;\n\nvec3 quantize(vec3 color, float n) {\n // restrict values to N options/bins\n // and floor each channel to nearest value\n //\n // eg. when N = 5, values = 0.0, 0.25, 0.50, 0.75, 1.0\n // then quantize (0.1, 0.7, 0.9) -> (0.0, 0.5, 1.0)\n\n color = color * n;\n color = floor(color);\n color = color / (n - 1.0);\n return color;\n}\n\nvoid main() {\n vec4 color = texture2D(tex0, vTexCoord);\n\n vec3 restrictedColor = quantize(color.rgb / color.a, filterParameter);\n\n gl_FragColor = vec4(restrictedColor.rgb * color.a, color.a);\n}\n"),j(e,l.OPAQUE,"// Set alpha channel to entirely opaque\n\nprecision highp float;\n\nvarying vec2 vTexCoord;\n\nuniform sampler2D tex0;\n\nvoid main() {\n vec4 color = texture2D(tex0, vTexCoord);\n gl_FragColor = vec4(color.rgb / color.a, 1.0);\n}\n"),j(e,l.INVERT,"// Set each pixel to inverse value\n// Note that original INVERT does not change the opacity, so this follows suit\n\nprecision highp float;\n\nvarying vec2 vTexCoord;\n\nuniform sampler2D tex0;\n\nvoid main() {\nvec4 color = texture2D(tex0, vTexCoord);\nvec3 origColor = color.rgb / color.a;\nvec3 invertedColor = vec3(1.0) - origColor;\ngl_FragColor = vec4(invertedColor * color.a, color.a);\n}\n"),j(e,l.THRESHOLD,"// Convert pixels to either white or black, \n// depending on if their luma is above or below filterParameter\n\nprecision highp float;\n\nvarying vec2 vTexCoord;\n\nuniform sampler2D tex0;\nuniform float filterParameter;\n\nfloat luma(vec3 color) {\n // weighted grayscale with luminance values\n return dot(color, vec3(0.2126, 0.7152, 0.0722));\n}\n\nvoid main() {\n vec4 color = texture2D(tex0, vTexCoord);\n float gray = luma(color.rgb / color.a);\n // floor() used to match src/image/filters.js\n float threshold = floor(filterParameter * 255.0) / 255.0;\n float blackOrWhite = step(threshold, gray);\n gl_FragColor = vec4(vec3(blackOrWhite) * color.a, color.a);\n}\n");var E=e;function k(e,t,r,o,n,s,i,a,l,u){var c=t.getParameter(t.FRAMEBUFFER_BINDING),r=(t.bindFramebuffer(t.FRAMEBUFFER,r),a===t.RGBA?4:3),d=s*i*r,h=l===t.UNSIGNED_BYTE?Uint8Array:Float32Array;if(e instanceof h&&e.length===d||(e=new h(d)),t.readPixels(o,u?u-n-i:n,s,i,a,l,e),t.bindFramebuffer(t.FRAMEBUFFER,c),u)for(var f=Math.floor(i/2),p=new h(s*r),m=0;m>7,127&d,c>>7,127&c);for(var h=0;h>7,127&f,0,0)}}return{cellImageInfo:a,dimOffset:t,dimImageInfo:n}}}}]),t}();B.default.RendererGL.prototype._renderText=function(e,t,r,o,n){if(this._textFont&&"string"!=typeof this._textFont){if(!(n<=o)&&this._doFill){if(this._isOpenType()){e.push();var n=this._doStroke,s=this.drawMode,i=(this._doStroke=!1,this.drawMode=M.TEXTURE,this._textFont.font),a=(a=this._textFont._fontInfo)||(this._textFont._fontInfo=new E(i)),r=this._textFont._handleAlignment(this,t,r,o),o=this._textSize/i.unitsPerEm,l=(this.translate(r.x,r.y,0),this.scale(o,o,1),this.GL),r=!this._defaultFontShader,u=this._getFontShader(),c=(u.init(),u.bindShader(),r&&(u.setUniform("uGridImageSize",[64,64]),u.setUniform("uCellsImageSize",[64,64]),u.setUniform("uStrokeImageSize",[64,64]),u.setUniform("uGridSize",[9,9])),this._applyColorBlend(this.curFillColor),this.retainedMode.geometry.glyph),d=(c||((o=this._textGeom=new B.default.Geometry(1,1,function(){for(var e=0;e<=1;e++)for(var t=0;t<=1;t++)this.vertices.push(new B.default.Vector(t,e,0)),this.uvs.push(t,e)})).computeFaces().computeNormals(),c=this.createBuffers("glyph",o)),!0),r=!1,o=void 0;try{for(var h,f=this.retainedMode.buffers.text[Symbol.iterator]();!(d=(h=f.next()).done);d=!0)h.value._prepareBuffer(c,u)}catch(e){r=!0,o=e}finally{try{d||null==f.return||f.return()}finally{if(r)throw o}}this._bindBuffer(c.indexBuffer,l.ELEMENT_ARRAY_BUFFER),u.setUniform("uMaterialColor",this.curFillColor),l.pixelStorei(l.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1);try{var p=0,m=null,y=i.stringToGlyphs(t),g=!0,v=!1,b=void 0;try{for(var j,_=y[Symbol.iterator]();!(g=(j=_.next()).done);g=!0){var x,w,S=j.value,T=(m&&(p+=i.getKerningValue(m,S)),a.getGlyphInfo(S));T.uGlyphRect&&(x=T.rowInfo,w=T.colInfo,u.setUniform("uSamplerStrokes",T.strokeImageInfo.imageData),u.setUniform("uSamplerRowStrokes",x.cellImageInfo.imageData),u.setUniform("uSamplerRows",x.dimImageInfo.imageData),u.setUniform("uSamplerColStrokes",w.cellImageInfo.imageData),u.setUniform("uSamplerCols",w.dimImageInfo.imageData),u.setUniform("uGridOffset",T.uGridOffset),u.setUniform("uGlyphRect",T.uGlyphRect),u.setUniform("uGlyphOffset",p),u.bindTextures(),l.drawElements(l.TRIANGLES,6,this.GL.UNSIGNED_SHORT,0)),p+=S.advanceWidth,m=S}}catch(e){v=!0,b=e}finally{try{g||null==_.return||_.return()}finally{if(v)throw b}}}finally{u.unbindShader(),this._doStroke=n,this.drawMode=s,l.pixelStorei(l.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!0),e.pop()}}else console.log("WEBGL: only Opentype (.otf) and Truetype (.ttf) fonts are supported");return e}}else console.log("WEBGL: you must load and set a font before drawing text. See `loadFont` and `textFont` for more details.")}},{"../core/constants":264,"../core/main":275,"./p5.RendererGL.Retained":331,"./p5.Shader":333,"core-js/modules/es.array.iterator":161,"core-js/modules/es.object.get-own-property-descriptor":178,"core-js/modules/es.object.to-string":182,"core-js/modules/es.regexp.exec":187,"core-js/modules/es.string.iterator":192,"core-js/modules/es.string.split":198,"core-js/modules/es.string.sub":200,"core-js/modules/es.symbol":204,"core-js/modules/es.symbol.description":202,"core-js/modules/es.symbol.iterator":203,"core-js/modules/es.weak-map":236,"core-js/modules/web.dom-collections.iterator":238}]},{},[259])(259)}); \ No newline at end of file +/*! p5.js v1.10.0 July 31, 2024 */ +!function(e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).p5=e()}(function(){var s,t,r;return function o(n,s,i){function a(t,e){if(!s[t]){if(!n[t]){var r="function"==typeof require&&require;if(!e&&r)return r(t,!0);if(l)return l(t,!0);throw(e=new Error("Cannot find module '"+t+"'")).code="MODULE_NOT_FOUND",e}r=s[t]={exports:{}},n[t][0].call(r.exports,function(e){return a(n[t][1][e]||e)},r,r.exports,o,n,s,i)}return s[t].exports}for(var l="function"==typeof require&&require,e=0;e>16&255,s[i++]=t>>8&255,s[i++]=255&t;2===o&&(t=l[e.charCodeAt(r)]<<2|l[e.charCodeAt(r+1)]>>4,s[i++]=255&t);1===o&&(t=l[e.charCodeAt(r)]<<10|l[e.charCodeAt(r+1)]<<4|l[e.charCodeAt(r+2)]>>2,s[i++]=t>>8&255,s[i++]=255&t);return s},r.fromByteArray=function(e){for(var t,r=e.length,o=r%3,n=[],s=0,i=r-o;s>18&63]+a[e>>12&63]+a[e>>6&63]+a[63&e]}(o));return n.join("")}(e,s,i>2]+a[t<<4&63]+"==")):2==o&&(t=(e[r-2]<<8)+e[r-1],n.push(a[t>>10]+a[t>>4&63]+a[t<<2&63]+"="));return n.join("")};for(var a=[],l=[],u="undefined"!=typeof Uint8Array?Uint8Array:Array,o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",n=0,s=o.length;n>>1;case"base64":return M(e).length;default:if(n)return o?-1:E(e).length;t=(""+t).toLowerCase(),n=!0}}function r(e,t,r){var o,n=!1;if((t=void 0===t||t<0?0:t)>this.length)return"";if((r=void 0===r||r>this.length?this.length:r)<=0)return"";if((r>>>=0)<=(t>>>=0))return"";for(e=e||"utf8";;)switch(e){case"hex":var s=this,i=t,a=r,l=s.length;(!a||a<0||l=e.length){if(n)return-1;r=e.length-1}else if(r<0){if(!n)return-1;r=0}if("string"==typeof t&&(t=d.from(t,o)),d.isBuffer(t))return 0===t.length?-1:p(e,t,r,o,n);if("number"==typeof t)return t&=255,"function"==typeof Uint8Array.prototype.indexOf?(n?Uint8Array.prototype.indexOf:Uint8Array.prototype.lastIndexOf).call(e,t,r):p(e,[t],r,o,n);throw new TypeError("val must be string, number or Buffer")}function p(e,t,r,o,n){var s=1,i=e.length,a=t.length;if(void 0!==o&&("ucs2"===(o=String(o).toLowerCase())||"ucs-2"===o||"utf16le"===o||"utf-16le"===o)){if(e.length<2||t.length<2)return-1;i/=s=2,a/=2,r/=2}function l(e,t){return 1===s?e[t]:e.readUInt16BE(t*s)}if(n)for(var u=-1,c=r;c>8,o=o%256,n.push(o),n.push(r);return n}(t,e.length-r),e,r,o)}function T(e,t,r){r=Math.min(e.length,r);for(var o=[],n=t;n>>10&1023|55296),c=56320|1023&c),o.push(c),n+=d}var h=o,f=h.length;if(f<=v)return String.fromCharCode.apply(String,h);for(var p="",m=0;mt&&(e+=" ... "),""},e&&(d.prototype[e]=d.prototype.inspect),d.prototype.compare=function(e,t,r,o,n){if(O(e,Uint8Array)&&(e=d.from(e,e.offset,e.byteLength)),!d.isBuffer(e))throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. Received type '+typeof e);if(void 0===r&&(r=e?e.length:0),void 0===o&&(o=0),void 0===n&&(n=this.length),(t=void 0===t?0:t)<0||r>e.length||o<0||n>this.length)throw new RangeError("out of range index");if(n<=o&&r<=t)return 0;if(n<=o)return-1;if(r<=t)return 1;if(this===e)return 0;for(var s=(n>>>=0)-(o>>>=0),i=(r>>>=0)-(t>>>=0),a=Math.min(s,i),l=this.slice(o,n),u=e.slice(t,r),c=0;c>>=0,isFinite(r)?(r>>>=0,void 0===o&&(o="utf8")):(o=r,r=void 0)}var n=this.length-t;if((void 0===r||nthis.length)throw new RangeError("Attempt to write outside buffer bounds");o=o||"utf8";for(var s,i,a,l=!1;;)switch(o){case"hex":var u=this,c=e,d=t,h=r,f=(d=Number(d)||0,u.length-d);(!h||f<(h=Number(h)))&&(h=f),(f=c.length)/2e.length)throw new RangeError("Index out of range")}function j(e,t,r,o){if(r+o>e.length)throw new RangeError("Index out of range");if(r<0)throw new RangeError("Index out of range")}function _(e,t,r,o,n){return t=+t,r>>>=0,n||j(e,0,r,4),s.write(e,t,r,o,23,4),r+4}function x(e,t,r,o,n){return t=+t,r>>>=0,n||j(e,0,r,8),s.write(e,t,r,o,52,8),r+8}d.prototype.slice=function(e,t){var r=this.length,r=((e=~~e)<0?(e+=r)<0&&(e=0):r>>=0,t>>>=0,r||m(e,t,this.length);for(var o=this[e],n=1,s=0;++s>>=0,t>>>=0,r||m(e,t,this.length);for(var o=this[e+--t],n=1;0>>=0,t||m(e,1,this.length),this[e]},d.prototype.readUInt16LE=function(e,t){return e>>>=0,t||m(e,2,this.length),this[e]|this[e+1]<<8},d.prototype.readUInt16BE=function(e,t){return e>>>=0,t||m(e,2,this.length),this[e]<<8|this[e+1]},d.prototype.readUInt32LE=function(e,t){return e>>>=0,t||m(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},d.prototype.readUInt32BE=function(e,t){return e>>>=0,t||m(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},d.prototype.readIntLE=function(e,t,r){e>>>=0,t>>>=0,r||m(e,t,this.length);for(var o=this[e],n=1,s=0;++s>>=0,t>>>=0,r||m(e,t,this.length);for(var o=t,n=1,s=this[e+--o];0>>=0,t||m(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},d.prototype.readInt16LE=function(e,t){e>>>=0,t||m(e,2,this.length);t=this[e]|this[e+1]<<8;return 32768&t?4294901760|t:t},d.prototype.readInt16BE=function(e,t){e>>>=0,t||m(e,2,this.length);t=this[e+1]|this[e]<<8;return 32768&t?4294901760|t:t},d.prototype.readInt32LE=function(e,t){return e>>>=0,t||m(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},d.prototype.readInt32BE=function(e,t){return e>>>=0,t||m(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},d.prototype.readFloatLE=function(e,t){return e>>>=0,t||m(e,4,this.length),s.read(this,e,!0,23,4)},d.prototype.readFloatBE=function(e,t){return e>>>=0,t||m(e,4,this.length),s.read(this,e,!1,23,4)},d.prototype.readDoubleLE=function(e,t){return e>>>=0,t||m(e,8,this.length),s.read(this,e,!0,52,8)},d.prototype.readDoubleBE=function(e,t){return e>>>=0,t||m(e,8,this.length),s.read(this,e,!1,52,8)},d.prototype.writeUIntLE=function(e,t,r,o){e=+e,t>>>=0,r>>>=0,o||b(this,e,t,r,Math.pow(2,8*r)-1,0);var n=1,s=0;for(this[t]=255&e;++s>>=0,r>>>=0,o||b(this,e,t,r,Math.pow(2,8*r)-1,0);var n=r-1,s=1;for(this[t+n]=255&e;0<=--n&&(s*=256);)this[t+n]=e/s&255;return t+r},d.prototype.writeUInt8=function(e,t,r){return e=+e,t>>>=0,r||b(this,e,t,1,255,0),this[t]=255&e,t+1},d.prototype.writeUInt16LE=function(e,t,r){return e=+e,t>>>=0,r||b(this,e,t,2,65535,0),this[t]=255&e,this[t+1]=e>>>8,t+2},d.prototype.writeUInt16BE=function(e,t,r){return e=+e,t>>>=0,r||b(this,e,t,2,65535,0),this[t]=e>>>8,this[t+1]=255&e,t+2},d.prototype.writeUInt32LE=function(e,t,r){return e=+e,t>>>=0,r||b(this,e,t,4,4294967295,0),this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e,t+4},d.prototype.writeUInt32BE=function(e,t,r){return e=+e,t>>>=0,r||b(this,e,t,4,4294967295,0),this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e,t+4},d.prototype.writeIntLE=function(e,t,r,o){e=+e,t>>>=0,o||b(this,e,t,r,(o=Math.pow(2,8*r-1))-1,-o);var n=0,s=1,i=0;for(this[t]=255&e;++n>0)-i&255;return t+r},d.prototype.writeIntBE=function(e,t,r,o){e=+e,t>>>=0,o||b(this,e,t,r,(o=Math.pow(2,8*r-1))-1,-o);var n=r-1,s=1,i=0;for(this[t+n]=255&e;0<=--n&&(s*=256);)e<0&&0===i&&0!==this[t+n+1]&&(i=1),this[t+n]=(e/s>>0)-i&255;return t+r},d.prototype.writeInt8=function(e,t,r){return e=+e,t>>>=0,r||b(this,e,t,1,127,-128),this[t]=255&(e=e<0?255+e+1:e),t+1},d.prototype.writeInt16LE=function(e,t,r){return e=+e,t>>>=0,r||b(this,e,t,2,32767,-32768),this[t]=255&e,this[t+1]=e>>>8,t+2},d.prototype.writeInt16BE=function(e,t,r){return e=+e,t>>>=0,r||b(this,e,t,2,32767,-32768),this[t]=e>>>8,this[t+1]=255&e,t+2},d.prototype.writeInt32LE=function(e,t,r){return e=+e,t>>>=0,r||b(this,e,t,4,2147483647,-2147483648),this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24,t+4},d.prototype.writeInt32BE=function(e,t,r){return e=+e,t>>>=0,r||b(this,e,t,4,2147483647,-2147483648),this[t]=(e=e<0?4294967295+e+1:e)>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e,t+4},d.prototype.writeFloatLE=function(e,t,r){return _(this,e,t,!0,r)},d.prototype.writeFloatBE=function(e,t,r){return _(this,e,t,!1,r)},d.prototype.writeDoubleLE=function(e,t,r){return x(this,e,t,!0,r)},d.prototype.writeDoubleBE=function(e,t,r){return x(this,e,t,!1,r)},d.prototype.copy=function(e,t,r,o){if(!d.isBuffer(e))throw new TypeError("argument should be a Buffer");if(r=r||0,o||0===o||(o=this.length),t>=e.length&&(t=e.length),(o=0=this.length)throw new RangeError("Index out of range");if(o<0)throw new RangeError("sourceEnd out of bounds");o>this.length&&(o=this.length);var n=(o=e.length-t>>=0,r=void 0===r?this.length:r>>>0,"number"==typeof(e=e||0))for(s=t;s>6|192,63&r|128)}else if(r<65536){if((t-=3)<0)break;s.push(r>>12|224,r>>6&63|128,63&r|128)}else{if(!(r<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;s.push(r>>18|240,r>>12&63|128,r>>6&63|128,63&r|128)}}return s}function M(e){return S.toByteArray(function(e){if((e=(e=e.split("=")[0]).trim().replace(w,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function k(e,t,r,o){for(var n=0;n=t.length||n>=e.length);++n)t[n+r]=e[n];return n}function O(e,t){return e instanceof t||null!=e&&null!=e.constructor&&null!=e.constructor.name&&e.constructor.name===t.name}function C(e){return e!=e}var A=function(){for(var e="0123456789abcdef",t=new Array(256),r=0;r<16;++r)for(var o=16*r,n=0;n<16;++n)t[o+n]=e[r]+e[n];return t}()}.call(this,P("buffer").Buffer)},{"base64-js":1,buffer:4,ieee754:254}],5:[function(e,t,r){t.exports=function(e){if("function"!=typeof e)throw TypeError(String(e)+" is not a function");return e}},{}],6:[function(e,t,r){var o=e("../internals/is-object");t.exports=function(e){if(o(e)||null===e)return e;throw TypeError("Can't set "+String(e)+" as a prototype")}},{"../internals/is-object":75}],7:[function(e,t,r){var o=e("../internals/well-known-symbol"),n=e("../internals/object-create"),e=e("../internals/object-define-property"),s=o("unscopables"),i=Array.prototype;null==i[s]&&e.f(i,s,{configurable:!0,value:n(null)}),t.exports=function(e){i[s][e]=!0}},{"../internals/object-create":91,"../internals/object-define-property":93,"../internals/well-known-symbol":150}],8:[function(e,t,r){"use strict";var o=e("../internals/string-multibyte").charAt;t.exports=function(e,t,r){return t+(r?o(e,t).length:1)}},{"../internals/string-multibyte":125}],9:[function(e,t,r){t.exports=function(e,t,r){if(e instanceof t)return e;throw TypeError("Incorrect "+(r?r+" ":"")+"invocation")}},{}],10:[function(e,t,r){var o=e("../internals/is-object");t.exports=function(e){if(o(e))return e;throw TypeError(String(e)+" is not an object")}},{"../internals/is-object":75}],11:[function(e,t,r){t.exports="undefined"!=typeof ArrayBuffer&&"undefined"!=typeof DataView},{}],12:[function(e,t,r){"use strict";function o(e){return l(e)&&u(E,c(e))}var n,s=e("../internals/array-buffer-native"),i=e("../internals/descriptors"),a=e("../internals/global"),l=e("../internals/is-object"),u=e("../internals/has"),c=e("../internals/classof"),d=e("../internals/create-non-enumerable-property"),h=e("../internals/redefine"),f=e("../internals/object-define-property").f,p=e("../internals/object-get-prototype-of"),m=e("../internals/object-set-prototype-of"),y=e("../internals/well-known-symbol"),e=e("../internals/uid"),g=a.Int8Array,v=g&&g.prototype,b=a.Uint8ClampedArray,b=b&&b.prototype,j=g&&p(g),_=v&&p(v),x=Object.prototype,w=x.isPrototypeOf,y=y("toStringTag"),S=e("TYPED_ARRAY_TAG"),T=s&&!!m&&"Opera"!==c(a.opera),e=!1,E={Int8Array:1,Uint8Array:1,Uint8ClampedArray:1,Int16Array:2,Uint16Array:2,Int32Array:4,Uint32Array:4,Float32Array:4,Float64Array:8};for(n in E)a[n]||(T=!1);if((!T||"function"!=typeof j||j===Function.prototype)&&(j=function(){throw TypeError("Incorrect invocation")},T))for(n in E)a[n]&&m(a[n],j);if((!T||!_||_===x)&&(_=j.prototype,T))for(n in E)a[n]&&m(a[n].prototype,_);if(T&&p(b)!==_&&m(b,_),i&&!u(_,y))for(n in e=!0,f(_,y,{get:function(){return l(this)?this[S]:void 0}}),E)a[n]&&d(a[n],S,n);t.exports={NATIVE_ARRAY_BUFFER_VIEWS:T,TYPED_ARRAY_TAG:e&&S,aTypedArray:function(e){if(o(e))return e;throw TypeError("Target is not a typed array")},aTypedArrayConstructor:function(e){if(m){if(w.call(j,e))return e}else for(var t in E)if(u(E,n)){t=a[t];if(t&&(e===t||w.call(t,e)))return e}throw TypeError("Target is not a typed array constructor")},exportTypedArrayMethod:function(e,t,r){if(i){if(r)for(var o in E){o=a[o];o&&u(o.prototype,e)&&delete o.prototype[e]}_[e]&&!r||h(_,e,!r&&T&&v[e]||t)}},exportTypedArrayStaticMethod:function(e,t,r){var o,n;if(i){if(m){if(r)for(o in E)(n=a[o])&&u(n,e)&&delete n[e];if(j[e]&&!r)return;try{return h(j,e,!r&&T&&g[e]||t)}catch(e){}}for(o in E)!(n=a[o])||n[e]&&!r||h(n,e,t)}},isView:function(e){e=c(e);return"DataView"===e||u(E,e)},isTypedArray:o,TypedArray:j,TypedArrayPrototype:_}},{"../internals/array-buffer-native":11,"../internals/classof":29,"../internals/create-non-enumerable-property":38,"../internals/descriptors":43,"../internals/global":60,"../internals/has":61,"../internals/is-object":75,"../internals/object-define-property":93,"../internals/object-get-prototype-of":98,"../internals/object-set-prototype-of":102,"../internals/redefine":110,"../internals/uid":147,"../internals/well-known-symbol":150}],13:[function(e,t,D){"use strict";function r(e){return[255&e]}function o(e){return[255&e,e>>8&255]}function n(e){return[255&e,e>>8&255,e>>16&255,e>>24&255]}function s(e){return e[3]<<24|e[2]<<16|e[1]<<8|e[0]}function i(e){return C(e,23,4)}function F(e){return C(e,52,8)}function a(e,t){H(e[w],t,{get:function(){return b(this)[t]}})}function l(e,t,r,o){if(r=m(r),e=b(e),r+t>e.byteLength)throw O(S);var n=b(e.buffer).bytes,r=r+e.byteOffset,e=n.slice(r,r+t);return o?e:e.reverse()}function u(e,t,r,o,n,s){if(r=m(r),e=b(e),r+t>e.byteLength)throw O(S);for(var i=b(e.buffer).bytes,a=r+e.byteOffset,l=o(+n),u=0;uR;)(P=L[R++])in E||N(E,P,T[P]);c.constructor=E}g&&V(e)!==k&&g(e,k);var y=new M(new E(2)),I=e.setInt8;y.setInt8(0,2147483648),y.setInt8(1,2147483649),!y.getInt8(0)&&y.getInt8(1)||h(e,{setInt8:function(e,t){I.call(this,e,t<<24>>24)},setUint8:function(e,t){I.call(this,e,t<<24>>24)}},{unsafe:!0})}else E=function(e){p(this,E,_);e=m(e);j(this,{bytes:W.call(new Array(e),0),byteLength:e}),d||(this.byteLength=e)},M=function(e,t,r){p(this,M,x),p(e,E,x);var o=b(e).byteLength,t=B(t);if(t<0||o>24},getUint8:function(e){return l(this,1,e)[0]},getInt16:function(e){e=l(this,2,e,1>16},getUint16:function(e){e=l(this,2,e,1>>0},getFloat32:function(e){return A(l(this,4,e,1"+e+""}},{"../internals/require-object-coercible":115}],37:[function(e,t,r){"use strict";function o(){return this}var n=e("../internals/iterators-core").IteratorPrototype,s=e("../internals/object-create"),i=e("../internals/create-property-descriptor"),a=e("../internals/set-to-string-tag"),l=e("../internals/iterators");t.exports=function(e,t,r){t+=" Iterator";return e.prototype=s(n,{next:i(1,r)}),a(e,t,!1,!0),l[t]=o,e}},{"../internals/create-property-descriptor":39,"../internals/iterators":80,"../internals/iterators-core":79,"../internals/object-create":91,"../internals/set-to-string-tag":119}],38:[function(e,t,r){var o=e("../internals/descriptors"),n=e("../internals/object-define-property"),s=e("../internals/create-property-descriptor");t.exports=o?function(e,t,r){return n.f(e,t,s(1,r))}:function(e,t,r){return e[t]=r,e}},{"../internals/create-property-descriptor":39,"../internals/descriptors":43,"../internals/object-define-property":93}],39:[function(e,t,r){t.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},{}],40:[function(e,t,r){"use strict";var o=e("../internals/to-primitive"),n=e("../internals/object-define-property"),s=e("../internals/create-property-descriptor");t.exports=function(e,t,r){t=o(t);t in e?n.f(e,t,s(0,r)):e[t]=r}},{"../internals/create-property-descriptor":39,"../internals/object-define-property":93,"../internals/to-primitive":142}],41:[function(e,t,r){"use strict";function m(){return this}var y=e("../internals/export"),g=e("../internals/create-iterator-constructor"),v=e("../internals/object-get-prototype-of"),b=e("../internals/object-set-prototype-of"),j=e("../internals/set-to-string-tag"),_=e("../internals/create-non-enumerable-property"),x=e("../internals/redefine"),o=e("../internals/well-known-symbol"),w=e("../internals/is-pure"),S=e("../internals/iterators"),e=e("../internals/iterators-core"),T=e.IteratorPrototype,E=e.BUGGY_SAFARI_ITERATORS,M=o("iterator"),k="values",O="entries";t.exports=function(e,t,r,o,n,s,i){g(r,t,o);function a(e){if(e===n&&f)return f;if(!E&&e in d)return d[e];switch(e){case"keys":case k:case O:return function(){return new r(this,e)}}return function(){return new r(this)}}var l,u,o=t+" Iterator",c=!1,d=e.prototype,h=d[M]||d["@@iterator"]||n&&d[n],f=!E&&h||a(n),p="Array"==t&&d.entries||h;if(p&&(p=v(p.call(new e)),T!==Object.prototype&&p.next&&(w||v(p)===T||(b?b(p,T):"function"!=typeof p[M]&&_(p,M,m)),j(p,o,!0,!0),w&&(S[o]=m))),n==k&&h&&h.name!==k&&(c=!0,f=function(){return h.call(this)}),w&&!i||d[M]===f||_(d,M,f),S[t]=f,n)if(l={values:a(k),keys:s?f:a("keys"),entries:a(O)},i)for(u in l)!E&&!c&&u in d||x(d,u,l[u]);else y({target:t,proto:!0,forced:E||c},l);return l}},{"../internals/create-iterator-constructor":37,"../internals/create-non-enumerable-property":38,"../internals/export":50,"../internals/is-pure":76,"../internals/iterators":80,"../internals/iterators-core":79,"../internals/object-get-prototype-of":98,"../internals/object-set-prototype-of":102,"../internals/redefine":110,"../internals/set-to-string-tag":119,"../internals/well-known-symbol":150}],42:[function(e,t,r){var o=e("../internals/path"),n=e("../internals/has"),s=e("../internals/well-known-symbol-wrapped"),i=e("../internals/object-define-property").f;t.exports=function(e){var t=o.Symbol||(o.Symbol={});n(t,e)||i(t,e,{value:s.f(e)})}},{"../internals/has":61,"../internals/object-define-property":93,"../internals/path":106,"../internals/well-known-symbol-wrapped":149}],43:[function(e,t,r){e=e("../internals/fails");t.exports=!e(function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]})},{"../internals/fails":51}],44:[function(e,t,r){var o=e("../internals/global"),e=e("../internals/is-object"),n=o.document,s=e(n)&&e(n.createElement);t.exports=function(e){return s?n.createElement(e):{}}},{"../internals/global":60,"../internals/is-object":75}],45:[function(e,t,r){t.exports={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0}},{}],46:[function(e,t,r){e=e("../internals/engine-user-agent");t.exports=/(iphone|ipod|ipad).*applewebkit/i.test(e)},{"../internals/engine-user-agent":47}],47:[function(e,t,r){e=e("../internals/get-built-in");t.exports=e("navigator","userAgent")||""},{"../internals/get-built-in":57}],48:[function(e,t,r){var o,n,s=e("../internals/global"),e=e("../internals/engine-user-agent"),s=s.process,s=s&&s.versions,s=s&&s.v8;s?n=(o=s.split("."))[0]+o[1]:e&&(!(o=e.match(/Edge\/(\d+)/))||74<=o[1])&&(o=e.match(/Chrome\/(\d+)/))&&(n=o[1]),t.exports=n&&+n},{"../internals/engine-user-agent":47,"../internals/global":60}],49:[function(e,t,r){t.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},{}],50:[function(e,t,r){var u=e("../internals/global"),c=e("../internals/object-get-own-property-descriptor").f,d=e("../internals/create-non-enumerable-property"),h=e("../internals/redefine"),f=e("../internals/set-global"),p=e("../internals/copy-constructor-properties"),m=e("../internals/is-forced");t.exports=function(e,t){var r,o,n,s=e.target,i=e.global,a=e.stat,l=i?u:a?u[s]||f(s,{}):(u[s]||{}).prototype;if(l)for(r in t){if(o=t[r],n=e.noTargetGet?(n=c(l,r))&&n.value:l[r],!m(i?r:s+(a?".":"#")+r,e.forced)&&void 0!==n){if(typeof o==typeof n)continue;p(o,n)}(e.sham||n&&n.sham)&&d(o,"sham",!0),h(l,r,o,e)}}},{"../internals/copy-constructor-properties":33,"../internals/create-non-enumerable-property":38,"../internals/global":60,"../internals/is-forced":74,"../internals/object-get-own-property-descriptor":94,"../internals/redefine":110,"../internals/set-global":117}],51:[function(e,t,r){t.exports=function(e){try{return!!e()}catch(e){return!0}}},{}],52:[function(e,t,r){"use strict";e("../modules/es.regexp.exec");var u=e("../internals/redefine"),c=e("../internals/fails"),d=e("../internals/well-known-symbol"),h=e("../internals/regexp-exec"),f=e("../internals/create-non-enumerable-property"),p=d("species"),m=!c(function(){var e=/./;return e.exec=function(){var e=[];return e.groups={a:"7"},e},"7"!=="".replace(e,"$")}),y="$0"==="a".replace(/./,"$0"),e=d("replace"),g=!!/./[e]&&""===/./[e]("a","$0"),v=!c(function(){var e=/(?:)/,t=e.exec,e=(e.exec=function(){return t.apply(this,arguments)},"ab".split(e));return 2!==e.length||"a"!==e[0]||"b"!==e[1]});t.exports=function(r,e,t,o){var s,n,i=d(r),a=!c(function(){var e={};return e[i]=function(){return 7},7!=""[r](e)}),l=a&&!c(function(){var e=!1,t=/a/;return"split"===r&&((t={constructor:{}}).constructor[p]=function(){return t},t.flags="",t[i]=/./[i]),t.exec=function(){return e=!0,null},t[i](""),!e});a&&l&&("replace"!==r||m&&y&&!g)&&("split"!==r||v)||(s=/./[i],t=(l=t(i,""[r],function(e,t,r,o,n){return t.exec===h?a&&!n?{done:!0,value:s.call(t,r,o)}:{done:!0,value:e.call(r,t,o)}:{done:!1}},{REPLACE_KEEPS_$0:y,REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE:g}))[0],n=l[1],u(String.prototype,r,t),u(RegExp.prototype,i,2==e?function(e,t){return n.call(e,this,t)}:function(e){return n.call(e,this)})),o&&f(RegExp.prototype[i],"sham",!0)}},{"../internals/create-non-enumerable-property":38,"../internals/fails":51,"../internals/redefine":110,"../internals/regexp-exec":112,"../internals/well-known-symbol":150,"../modules/es.regexp.exec":195}],53:[function(e,t,r){"use strict";function h(e,t,r,o,n,s,i,a){for(var l,u=n,c=0,d=!!i&&m(i,a,3);c>1,u=23===t?f(2,-24)-f(2,-77):0,c=e<0||0===e&&1/e<0?1:0,d=0;for((e=h(e))!=e||e===1/0?(n=e!=e?1:0,o=r):(o=p(m(e)/y),e*(s=f(2,-o))<1&&(o--,s*=2),2<=(e+=1<=o+l?u/s:u*f(2,1-l))*s&&(o++,s/=2),r<=o+l?(n=0,o=r):1<=o+l?(n=(e*s-1)*f(2,t),o+=l):(n=e*f(2,l-1)*f(2,t),o=0));8<=t;i[d++]=255&n,n/=256,t-=8);for(o=o<>1,a=n-7,l=o-1,n=e[l--],u=127&n;for(n>>=7;0>=-a,a+=t;0"+e+""},m=function(){try{n=document.domain&&new ActiveXObject("htmlfile")}catch(e){}m=n?((e=n).write(p("")),e.close(),t=e.parentWindow.Object,e=null,t):(e=c("iframe"),t="java"+h+":",e.style.display="none",u.appendChild(e),e.src=String(t),(t=e.contentWindow.document).open(),t.write(p("document.F=Object")),t.close(),t.F);for(var e,t,r=a.length;r--;)delete m[d][a[r]];return m()};l[f]=!0,t.exports=Object.create||function(e,t){var r;return null!==e?(o[d]=s(e),r=new o,o[d]=null,r[f]=e):r=m(),void 0===t?r:i(r,t)}},{"../internals/an-object":10,"../internals/document-create-element":44,"../internals/enum-bug-keys":49,"../internals/hidden-keys":62,"../internals/html":64,"../internals/object-define-properties":92,"../internals/shared-key":120}],92:[function(e,t,r){var o=e("../internals/descriptors"),i=e("../internals/object-define-property"),a=e("../internals/an-object"),l=e("../internals/object-keys");t.exports=o?Object.defineProperties:function(e,t){a(e);for(var r,o=l(t),n=o.length,s=0;sn;)!i(o,r=t[n++])||~l(s,r)||s.push(r);return s}},{"../internals/array-includes":18,"../internals/has":61,"../internals/hidden-keys":62,"../internals/to-indexed-object":136}],100:[function(e,t,r){var o=e("../internals/object-keys-internal"),n=e("../internals/enum-bug-keys");t.exports=Object.keys||function(e){return o(e,n)}},{"../internals/enum-bug-keys":49,"../internals/object-keys-internal":99}],101:[function(e,t,r){"use strict";var o={}.propertyIsEnumerable,n=Object.getOwnPropertyDescriptor,s=n&&!o.call({1:2},1);r.f=s?function(e){e=n(this,e);return!!e&&e.enumerable}:o},{}],102:[function(e,t,r){var n=e("../internals/an-object"),s=e("../internals/a-possible-prototype");t.exports=Object.setPrototypeOf||("__proto__"in{}?function(){var r,o=!1,e={};try{(r=Object.getOwnPropertyDescriptor(Object.prototype,"__proto__").set).call(e,[]),o=e instanceof Array}catch(e){}return function(e,t){return n(e),s(t),o?r.call(e,t):e.__proto__=t,e}}():void 0)},{"../internals/a-possible-prototype":6,"../internals/an-object":10}],103:[function(e,t,r){function o(a){return function(e){for(var t,r=c(e),o=u(r),n=o.length,s=0,i=[];st&&(o=o.slice(0,t)),n?e+o:o+e)}}var s=e("../internals/to-length"),i=e("../internals/string-repeat"),a=e("../internals/require-object-coercible"),l=Math.ceil;t.exports={start:o(!1),end:o(!0)}},{"../internals/require-object-coercible":115,"../internals/string-repeat":129,"../internals/to-length":138}],128:[function(e,t,r){"use strict";function g(e){return e+22+75*(e<26)}function s(e){var t,r=[],o=(e=function(e){for(var t=[],r=0,o=e.length;rT((v-s)/d))throw RangeError(w);for(s+=(u-n)*d,n=u,c=0;cv)throw RangeError(w);if(t==n){for(var h=s,f=b;;f+=b){var p=f<=i?1:i+j<=f?j:f-i;if(h>1,e+=T(e/t);S*j>>1>>=1)&&(t+=t))1&o&&(r+=t);return r}},{"../internals/require-object-coercible":115,"../internals/to-integer":137}],130:[function(e,t,r){var o=e("../internals/fails"),n=e("../internals/whitespaces");t.exports=function(e){return o(function(){return!!n[e]()||"​…᠎"!="​…᠎"[e]()||n[e].name!==e})}},{"../internals/fails":51,"../internals/whitespaces":151}],131:[function(e,t,r){function o(t){return function(e){e=String(n(e));return 1&t&&(e=e.replace(s,"")),e=2&t?e.replace(i,""):e}}var n=e("../internals/require-object-coercible"),e="["+e("../internals/whitespaces")+"]",s=RegExp("^"+e+e+"*"),i=RegExp(e+e+"*$");t.exports={start:o(1),end:o(2),trim:o(3)}},{"../internals/require-object-coercible":115,"../internals/whitespaces":151}],132:[function(e,t,r){function o(e){return function(){x(e)}}function n(e){x(e.data)}function s(e){a.postMessage(e+"",f.protocol+"//"+f.host)}var i,a=e("../internals/global"),l=e("../internals/fails"),u=e("../internals/classof-raw"),c=e("../internals/function-bind-context"),d=e("../internals/html"),h=e("../internals/document-create-element"),e=e("../internals/engine-is-ios"),f=a.location,p=a.setImmediate,m=a.clearImmediate,y=a.process,g=a.MessageChannel,v=a.Dispatch,b=0,j={},_="onreadystatechange",x=function(e){var t;j.hasOwnProperty(e)&&(t=j[e],delete j[e],t())};p&&m||(p=function(e){for(var t=[],r=1;r=t.length?{value:e.target=void 0,done:!0}:"keys"==r?{value:o,done:!1}:"values"==r?{value:t[o],done:!1}:{value:[o,t[o]],done:!1}},"values"),s.Arguments=s.Array,n("keys"),n("values"),n("entries")},{"../internals/add-to-unscopables":7,"../internals/define-iterator":41,"../internals/internal-state":71,"../internals/iterators":80,"../internals/to-indexed-object":136}],166:[function(e,t,r){"use strict";var o=e("../internals/export"),n=e("../internals/indexed-object"),s=e("../internals/to-indexed-object"),e=e("../internals/array-method-is-strict"),i=[].join,n=n!=Object,e=e("join",",");o({target:"Array",proto:!0,forced:n||!e},{join:function(e){return i.call(s(this),void 0===e?",":e)}})},{"../internals/array-method-is-strict":22,"../internals/export":50,"../internals/indexed-object":67,"../internals/to-indexed-object":136}],167:[function(e,t,r){var o=e("../internals/export"),e=e("../internals/array-last-index-of");o({target:"Array",proto:!0,forced:e!==[].lastIndexOf},{lastIndexOf:e})},{"../internals/array-last-index-of":20,"../internals/export":50}],168:[function(e,t,r){"use strict";var o=e("../internals/export"),n=e("../internals/array-iteration").map,s=e("../internals/array-method-has-species-support"),e=e("../internals/array-method-uses-to-length"),s=s("map"),e=e("map");o({target:"Array",proto:!0,forced:!s||!e},{map:function(e){return n(this,e,1T;T++)l(b,x=S[T])&&!l(w,x)&&y(w,x,m(b,x));(w.prototype=j).constructor=w,a(s,v,w)}},{"../internals/classof-raw":28,"../internals/descriptors":43,"../internals/fails":51,"../internals/global":60,"../internals/has":61,"../internals/inherit-if-required":68,"../internals/is-forced":74,"../internals/object-create":91,"../internals/object-define-property":93,"../internals/object-get-own-property-descriptor":94,"../internals/object-get-own-property-names":96,"../internals/redefine":110,"../internals/string-trim":131,"../internals/to-primitive":142}],180:[function(e,t,r){e("../internals/export")({target:"Number",stat:!0},{EPSILON:Math.pow(2,-52)})},{"../internals/export":50}],181:[function(e,t,r){e("../internals/export")({target:"Number",stat:!0},{isFinite:e("../internals/number-is-finite")})},{"../internals/export":50,"../internals/number-is-finite":89}],182:[function(e,t,r){"use strict";function c(e,t,r){return 0===t?r:t%2==1?c(e,t-1,r*e):c(e*e,t/2,r)}var o=e("../internals/export"),d=e("../internals/to-integer"),h=e("../internals/this-number-value"),f=e("../internals/string-repeat"),e=e("../internals/fails"),n=1..toFixed,p=Math.floor;o({target:"Number",proto:!0,forced:n&&("0.000"!==8e-5.toFixed(3)||"1"!==.9.toFixed(0)||"1.25"!==1.255.toFixed(2)||"1000000000000000128"!==0xde0b6b3a7640080.toFixed(0))||!e(function(){n.call({})})},{toFixed:function(e){function t(e,t){for(var r=-1,o=t;++r<6;)o+=e*a[r],a[r]=o%1e7,o=p(o/1e7)}function r(e){for(var t=6,r=0;0<=--t;)r+=a[t],a[t]=p(r/e),r=r%e*1e7}function o(){for(var e,t=6,r="";0<=--t;)""===r&&0!==t&&0===a[t]||(e=String(a[t]),r=""===r?e:r+f.call("0",7-e.length)+e);return r}var n,s,i=h(this),e=d(e),a=[0,0,0,0,0,0],l="",u="0";if(e<0||20n;){var s,i,a,l=y[n++],u=t?l.ok:l.fail,c=l.resolve,d=l.reject,h=l.domain;try{u?(t||(p.rejection===oe&&function(e,t){v.call(g,function(){if(k)T.emit("rejectionHandled",e);else se(te,e,t.value)})}(f,p),p.rejection=A),!0===u?s=e:(h&&h.enter(),s=u(e),h&&(h.exit(),a=!0)),s===l.promise?d(w("Promise-chain cycle")):(i=ne(s))?i.call(s,c,d):c(s)):d(e)}catch(e){h&&!a&&h.exit(),d(e)}}p.reactions=[],p.notified=!1,m&&!p.rejection&&(r=f,o=p,v.call(g,function(){var e=o.value,t=ie(o);if(t&&(t=b(function(){k?T.emit("unhandledRejection",e,r):se(O,r,e)}),o.rejection=k||ie(o)?oe:A,t.error))throw t.value}))}))},se=function(e,t,r){var o;ee?((o=S.createEvent("Event")).promise=t,o.reason=r,o.initEvent(e,!1,!0),g.dispatchEvent(o)):o={promise:t,reason:r},(t=g["on"+e])?t(o):e===O&&Y("Unhandled promise rejection",r)},ie=function(e){return e.rejection!==A&&!e.parent},L=function(t,r,o,n){return function(e){t(r,o,e,n)}},R=function(e,t,r,o){t.done||(t.done=!0,(t=o?o:t).value=r,t.state=re,P(e,t,!0))},I=function(r,o,e,t){if(!o.done){o.done=!0,t&&(o=t);try{if(r===e)throw w("Promise can't be resolved itself");var n=ne(e);n?u(function(){var t={done:!1};try{n.call(e,L(I,r,t,o),L(R,r,t,o))}catch(e){R(r,t,e,o)}}):(o.value=e,o.state=C,P(r,o,!1))}catch(e){R(r,{done:!1},e,o)}}};e&&(x=function(e){z(this,x,j),c(e),r.call(this);var t=_(this);try{e(L(I,this,t),L(R,this,t))}catch(e){R(this,t,e)}},(r=function(e){K(this,{type:j,done:!1,notified:!1,parent:!1,reactions:[],rejection:!1,state:0,value:void 0})}).prototype=N(x.prototype,{then:function(e,t){var r=J(this),o=M(X(this,x));return o.ok="function"!=typeof e||e,o.fail="function"==typeof t&&t,o.domain=k?T.domain:void 0,r.parent=!0,r.reactions.push(o),0!=r.state&&P(this,r,!1),o.promise},catch:function(e){return this.then(void 0,e)}}),t=function(){var e=new r,t=_(e);this.promise=e,this.resolve=L(I,e,t),this.reject=L(R,e,t)},f.f=M=function(e){return e===x||e===o?new t:$(e)},i||"function"!=typeof l||(n=l.prototype.then,U(l.prototype,"then",function(e,t){var r=this;return new x(function(e,t){n.call(r,e,t)}).then(e,t)},{unsafe:!0}),"function"==typeof E&&s({global:!0,enumerable:!0,forced:!0},{fetch:function(e){return h(x,E.apply(g,arguments))}}))),s({global:!0,wrap:!0,forced:e},{Promise:x}),B(x,j,!1,!0),G(j),o=a(j),s({target:j,stat:!0,forced:e},{reject:function(e){var t=M(this);return t.reject.call(void 0,e),t.promise}}),s({target:j,stat:!0,forced:i||e},{resolve:function(e){return h(i&&this===o?x:this,e)}}),s({target:j,stat:!0,forced:m},{all:function(e){var a=this,t=M(a),l=t.resolve,u=t.reject,r=b(function(){var o=c(a.resolve),n=[],s=0,i=1;d(e,function(e){var t=s++,r=!1;n.push(void 0),i++,o.call(a,e).then(function(e){r||(r=!0,n[t]=e,--i||l(n))},u)}),--i||l(n)});return r.error&&u(r.value),t.promise},race:function(e){var r=this,o=M(r),n=o.reject,t=b(function(){var t=c(r.resolve);d(e,function(e){t.call(r,e).then(o.resolve,n)})});return t.error&&n(t.value),o.promise}})},{"../internals/a-function":5,"../internals/an-instance":9,"../internals/check-correctness-of-iteration":27,"../internals/classof-raw":28,"../internals/engine-v8-version":48,"../internals/export":50,"../internals/get-built-in":57,"../internals/global":60,"../internals/host-report-errors":63,"../internals/inspect-source":69,"../internals/internal-state":71,"../internals/is-forced":74,"../internals/is-object":75,"../internals/is-pure":76,"../internals/iterate":78,"../internals/microtask":82,"../internals/native-promise-constructor":83,"../internals/new-promise-capability":87,"../internals/perform":107,"../internals/promise-resolve":108,"../internals/redefine":110,"../internals/redefine-all":109,"../internals/set-species":118,"../internals/set-to-string-tag":119,"../internals/species-constructor":123,"../internals/task":132,"../internals/well-known-symbol":150}],192:[function(e,t,r){var o=e("../internals/export"),n=e("../internals/get-built-in"),s=e("../internals/a-function"),i=e("../internals/an-object"),a=e("../internals/is-object"),l=e("../internals/object-create"),u=e("../internals/function-bind"),e=e("../internals/fails"),c=n("Reflect","construct"),d=e(function(){function e(){}return!(c(function(){},[],e)instanceof e)}),h=!e(function(){c(function(){})}),n=d||h;o({target:"Reflect",stat:!0,forced:n,sham:n},{construct:function(e,t){s(e),i(t);var r=arguments.length<3?e:s(arguments[2]);if(h&&!d)return c(e,t,r);if(e==r){switch(t.length){case 0:return new e;case 1:return new e(t[0]);case 2:return new e(t[0],t[1]);case 3:return new e(t[0],t[1],t[2]);case 4:return new e(t[0],t[1],t[2],t[3])}var o=[null];return o.push.apply(o,t),new(u.apply(e,o))}o=r.prototype,r=l(a(o)?o:Object.prototype),o=Function.apply.call(e,r,t);return a(o)?o:r}})},{"../internals/a-function":5,"../internals/an-object":10,"../internals/export":50,"../internals/fails":51,"../internals/function-bind":56,"../internals/get-built-in":57,"../internals/is-object":75,"../internals/object-create":91}],193:[function(e,t,r){var o=e("../internals/export"),s=e("../internals/is-object"),i=e("../internals/an-object"),a=e("../internals/has"),l=e("../internals/object-get-own-property-descriptor"),u=e("../internals/object-get-prototype-of");o({target:"Reflect",stat:!0},{get:function e(t,r){var o,n=arguments.length<3?t:arguments[2];return i(t)===n?t[r]:(o=l.f(t,r))?a(o,"value")?o.value:void 0===o.get?void 0:o.get.call(n):s(o=u(t))?e(o,r,n):void 0}})},{"../internals/an-object":10,"../internals/export":50,"../internals/has":61,"../internals/is-object":75,"../internals/object-get-own-property-descriptor":94,"../internals/object-get-prototype-of":98}],194:[function(e,t,r){var o=e("../internals/descriptors"),n=e("../internals/global"),s=e("../internals/is-forced"),i=e("../internals/inherit-if-required"),a=e("../internals/object-define-property").f,l=e("../internals/object-get-own-property-names").f,u=e("../internals/is-regexp"),c=e("../internals/regexp-flags"),d=e("../internals/regexp-sticky-helpers"),h=e("../internals/redefine"),f=e("../internals/fails"),p=e("../internals/internal-state").set,m=e("../internals/set-species"),y=e("../internals/well-known-symbol")("match"),g=n.RegExp,v=g.prototype,b=/a/g,j=/a/g,_=new g(b)!==b,x=d.UNSUPPORTED_Y;if(o&&s("RegExp",!_||x||f(function(){return j[y]=!1,g(b)!=b||g(j)==j||"/a/i"!=g(b,"i")}))){for(var w=function(e,t){var r,o=this instanceof w,n=u(e),s=void 0===t;if(!o&&n&&e.constructor===w&&s)return e;_?n&&!s&&(e=e.source):e instanceof w&&(s&&(t=c.call(e)),e=e.source),x&&(r=!!t&&-1T;)!function(t){t in w||a(w,t,{configurable:!0,get:function(){return g[t]},set:function(e){g[t]=e}})}(S[T++]);(v.constructor=w).prototype=v,h(n,"RegExp",w)}m("RegExp")},{"../internals/descriptors":43,"../internals/fails":51,"../internals/global":60,"../internals/inherit-if-required":68,"../internals/internal-state":71,"../internals/is-forced":74,"../internals/is-regexp":77,"../internals/object-define-property":93,"../internals/object-get-own-property-names":96,"../internals/redefine":110,"../internals/regexp-flags":113,"../internals/regexp-sticky-helpers":114,"../internals/set-species":118,"../internals/well-known-symbol":150}],195:[function(e,t,r){"use strict";var o=e("../internals/export"),e=e("../internals/regexp-exec");o({target:"RegExp",proto:!0,forced:/./.exec!==e},{exec:e})},{"../internals/export":50,"../internals/regexp-exec":112}],196:[function(e,t,r){"use strict";var o=e("../internals/redefine"),n=e("../internals/an-object"),s=e("../internals/fails"),i=e("../internals/regexp-flags"),e="toString",a=RegExp.prototype,l=a[e],s=s(function(){return"/a/b"!=l.call({source:"a",flags:"b"})}),u=l.name!=e;(s||u)&&o(RegExp.prototype,e,function(){var e=n(this),t=String(e.source),r=e.flags;return"/"+t+"/"+String(void 0===r&&e instanceof RegExp&&!("flags"in a)?i.call(e):r)},{unsafe:!0})},{"../internals/an-object":10,"../internals/fails":51,"../internals/redefine":110,"../internals/regexp-flags":113}],197:[function(e,t,r){"use strict";var o=e("../internals/collection"),e=e("../internals/collection-strong");t.exports=o("Set",function(e){return function(){return e(this,arguments.length?arguments[0]:void 0)}},e)},{"../internals/collection":32,"../internals/collection-strong":30}],198:[function(e,t,r){"use strict";var o=e("../internals/export"),n=e("../internals/object-get-own-property-descriptor").f,s=e("../internals/to-length"),i=e("../internals/not-a-regexp"),a=e("../internals/require-object-coercible"),l=e("../internals/correct-is-regexp-logic"),e=e("../internals/is-pure"),u="".endsWith,c=Math.min,l=l("endsWith");o({target:"String",proto:!0,forced:!!(e||l||(!(o=n(String.prototype,"endsWith"))||o.writable))&&!l},{endsWith:function(e){var t=String(a(this)),r=(i(e),1=t.length?{value:void 0,done:!0}:(t=o(t,r),e.index+=t.length,{value:t,done:!1})})},{"../internals/define-iterator":41,"../internals/internal-state":71,"../internals/string-multibyte":125}],201:[function(e,t,r){"use strict";var o=e("../internals/fix-regexp-well-known-symbol-logic"),c=e("../internals/an-object"),d=e("../internals/to-length"),n=e("../internals/require-object-coercible"),h=e("../internals/advance-string-index"),f=e("../internals/regexp-exec-abstract");o("match",1,function(o,l,u){return[function(e){var t=n(this),r=null==e?void 0:e[o];return void 0!==r?r.call(e,t):new RegExp(e)[o](String(t))},function(e){var t=u(l,e,this);if(t.done)return t.value;var r=c(e),o=String(this);if(!r.global)return f(r,o);for(var n=r.unicode,s=[],i=r.lastIndex=0;null!==(a=f(r,o));){var a=String(a[0]);""===(s[i]=a)&&(r.lastIndex=h(o,d(r.lastIndex),n)),i++}return 0===i?null:s}]})},{"../internals/advance-string-index":8,"../internals/an-object":10,"../internals/fix-regexp-well-known-symbol-logic":52,"../internals/regexp-exec-abstract":111,"../internals/require-object-coercible":115,"../internals/to-length":138}],202:[function(e,t,r){"use strict";var o=e("../internals/export"),n=e("../internals/string-pad").start;o({target:"String",proto:!0,forced:e("../internals/string-pad-webkit-bug")},{padStart:function(e){return n(this,e,1]*>)/g,I=/\$([$&'`]|\d\d?)/g;o("replace",2,function(n,j,_,e){var x=e.REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE,w=e.REPLACE_KEEPS_$0,S=x?"$":"$0";return[function(e,t){var r=s(this),o=null==e?void 0:e[n];return void 0!==o?o.call(e,r,t):j.call(String(r),e,t)},function(e,t){if(!x&&w||"string"==typeof t&&-1===t.indexOf(S)){var r=_(j,e,this,t);if(r.done)return r.value}for(var o,n=T(e),s=String(this),i="function"==typeof t,a=(i||(t=String(t)),n.global),l=(a&&(o=n.unicode,n.lastIndex=0),[]);null!==(f=C(n,s))&&(l.push(f),a);)""===String(f[0])&&(n.lastIndex=O(s,M(n.lastIndex),o));for(var u,c="",d=0,h=0;h>>0;if(0==o)return[];if(void 0===e)return[r];if(!c(e))return p.call(r,e,o);for(var n,s,i,a=[],t=(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.unicode?"u":"")+(e.sticky?"y":""),l=0,u=new RegExp(e.source,t+"g");(n=h.call(u,r))&&!(l<(s=u.lastIndex)&&(a.push(r.slice(l,n.index)),1=o));)u.lastIndex===n.index&&u.lastIndex++;return l===r.length?!i&&u.test("")||a.push(""):a.push(r.slice(l)),a.length>o?a.slice(0,o):a}:"0".split(void 0,0).length?function(e,t){return void 0===e&&0===t?[]:p.call(this,e,t)}:p;return[function(e,t){var r=d(this),o=null==e?void 0:e[n];return void 0!==o?o.call(e,r,t):y.call(String(r),e,t)},function(e,t){var r=m(y,e,this,t,y!==p);if(r.done)return r.value;var r=g(e),o=String(this),e=v(r,RegExp),n=r.unicode,s=(r.ignoreCase?"i":"")+(r.multiline?"m":"")+(r.unicode?"u":"")+(S?"y":"g"),i=new e(S?r:"^(?:"+r.source+")",s),a=void 0===t?w:t>>>0;if(0==a)return[];if(0===o.length)return null===_(i,o)?[o]:[];for(var l=0,u=0,c=[];ue.key){o.splice(t,0,e);break}t===s&&o.push(e)}r.updateURL()},forEach:function(e){for(var t,r=A(this).entries,o=v(e,16)return;a=0;while(h()){l=null;if(a>0)if(h()=="."&&a<4)n++;else return;if(!x.test(h()))return;while(x.test(h())){u=parseInt(h(),10);if(l===null)l=u;else if(l==0)return;else l=l*10+u;if(l>255)return;n++}t[r]=t[r]*256+l;a++;if(a==2||a==4)r++}if(a!=4)return;break}else if(h()==":"){n++;if(!h())return}else if(h())return;t[r++]=s}if(o!==null){c=r-o;r=7;while(r!=0&&c>0){d=t[r];t[r--]=t[o+c-1];t[o+--c]=d}}else if(r!=8)return;return t}(t.slice(1,-1)))?void(e.host=r):_;if(k(e))return t=z(t),ne.test(t)||null===(r=function(e){var t=e.split("."),r,o,n,s,i,a,l;if(t.length&&t[t.length-1]=="")t.pop();if((r=t.length)>4)return e;for(o=[],n=0;n1&&s.charAt(0)=="0"){i=ee.test(s)?16:8;s=s.slice(i==8?1:2)}if(s==="")a=0;else{if(!(i==10?re:i==8?te:oe).test(s))return e;a=parseInt(s,i)}o.push(a)}for(n=0;n=Z(256,5-r))return null}else if(a>255)return null}for(l=o.pop(),n=0;n":1,"`":1}),ce=d({},ue,{"#":1,"?":1,"{":1,"}":1}),T=d({},ce,{"/":1,":":1,";":1,"=":1,"@":1,"[":1,"\\":1,"]":1,"^":1,"|":1}),E=function(e,t){var r=V(e,0);return 32h,applyPalette:()=>function(e,t,r="rgb565"){if(!e||!e.buffer)throw new Error("quantize() expected RGBA Uint8Array data");if(!(e instanceof Uint8Array||e instanceof Uint8ClampedArray))throw new Error("quantize() expected RGBA Uint8Array data");if(256>24&255,c=l>>16&255,d=l>>8&255,l=255&l,h=A(l,d,c,u),h=h in a?a[h]:a[h]=function(t,r,o,n,s){let i=0,a=1e100;for(let e=0;ea||(l=u[0],(c+=v(l-t))>a||(l=u[1],(c+=v(l-r))>a||(l=u[2],(c+=v(l-o))>a||(a=c,i=e))))}return i}(l,d,c,u,t);i[e]=h}else{const g="rgb444"===r?P:C;for(let e=0;e>16&255,m=f>>8&255,f=255&f,y=g(f,m,p),y=y in a?a[y]:a[y]=function(t,r,o,n){let s=0,i=1e100;for(let e=0;ei||(a=l[1],(u+=v(a-r))>i||(a=l[2],(u+=v(a-o))>i||(i=u,s=e)))}return s}(f,m,p,t);i[e]=y}}return i},default:()=>f,nearestColor:()=>function(e,t,r=u){return e[l(e,t,r)]},nearestColorIndex:()=>l,nearestColorIndexWithDistance:()=>d,prequantize:()=>function(e,{roundRGB:r=5,roundAlpha:o=10,oneBitAlpha:n=null}={}){const s=new Uint32Array(e.buffer);for(let t=0;t>24&255;var a,l=i>>16&255,u=i>>8&255,i=255&i;e=c(e,o),n&&(a="number"==typeof n?n:127,e=e<=a?0:255),i=c(i,r),u=c(u,r),l=c(l,r),s[t]=e<<24|l<<16|u<<8|i<<0}},quantize:()=>function(e,t,r={}){var{format:o="rgb565",clearAlpha:n=!0,clearAlphaColor:s=0,clearAlphaThreshold:i=0,oneBitAlpha:a=!1}=r;if(!e||!e.buffer)throw new Error("quantize() expected RGBA Uint8Array data");if(!(e instanceof Uint8Array||e instanceof Uint8ClampedArray))throw new Error("quantize() expected RGBA Uint8Array data");e=new Uint32Array(e.buffer);let l=!1!==r.useSqrt;const u="rgba4444"===o,c=function(r,e){const t="rgb444"===e?4096:65536,o=new Array(t),n=r.length;if("rgba4444"===e)for(let t=0;t>24&255,a=s>>16&255,l=s>>8&255,s=255&s,u=A(s,l,a,i);let e=u in o?o[u]:o[u]=D();e.rc+=s,e.gc+=l,e.bc+=a,e.ac+=i,e.cnt++}else if("rgb444"===e)for(let t=0;t>16&255,h=c>>8&255,c=255&c,f=P(c,h,d);let e=f in o?o[f]:o[f]=D();e.rc+=c,e.gc+=h,e.bc+=d,e.cnt++}else for(let t=0;t>16&255,y=p>>8&255,p=255&p,g=C(p,y,m);let e=g in o?o[g]:o[g]=D();e.rc+=p,e.gc+=y,e.bc+=m,e.cnt++}return o}(e,o),d=c.length,h=d-1,f=new Uint32Array(d+1);for(var p=0,m=0;m>1,!(c[y=f[v]].err<=b));g=v)f[g]=y;f[g]=m}var j,_=p-t;for(m=0;m<_;){for(;;){var x=f[1];if((j=c[x]).tm>=j.mtm&&c[j.nn].mtm<=j.tm)break;j.mtm==h?x=f[1]=f[f[0]--]:(I(c,x,!1),j.tm=m);b=c[x].err;for(g=1;(v=g+g)<=f[0]&&(vc[f[v+1]].err&&v++,!(b<=c[y=f[v]].err));g=v)f[g]=y;f[g]=x}var w=c[j.nn],S=j.cnt,T=w.cnt,E=1/(S+T);u&&(j.ac=E*(S*j.ac+T*w.ac)),j.rc=E*(S*j.rc+T*w.rc),j.gc=E*(S*j.gc+T*w.gc),j.bc=E*(S*j.bc+T*w.bc),j.cnt+=w.cnt,j.mtm=++m,c[w.bk].fw=w.fw,c[w.fw].bk=w.bk,w.mtm=h}let M=[];for(m=0;;0){let e=L(Math.round(c[m].rc),0,255),t=L(Math.round(c[m].gc),0,255),r=L(Math.round(c[m].bc),0,255),o=255;u&&(o=L(Math.round(c[m].ac),0,255),a&&(k="number"==typeof a?a:127,o=o<=k?0:255),n&&o<=i&&(e=t=r=s,o=0));var k=u?[e,t,r,o]:[e,t,r];if(function(t,r){for(let e=0;efunction(r,o,e=5){if(r.length&&o.length){var n=r.map(e=>e.slice(0,3)),s=e*e,i=r[0].length;for(let t=0;ti?e.slice(0,3):e.slice();var a=d(n,e.slice(0,3),u),l=a[0],a=a[1];0>>0),0!=t&&(e=Math.max(e,256));const r=s;s=new Uint8Array(e),0>=8,c-=8;if((v>m||f)&&(f?(p=h,m=(1<>=8,c-=8;0>3}function A(e,t,r,o){return e>>4|240&t|(240&r)<<4|(240&o)<<8}function P(e,t,r){return e>>4<<8|240&t|r>>4}function L(e,t,r){return e>8&255)}function O(e,t){for(var r=0;r>1,c=-7,d=r?n-1:0,h=r?-1:1,n=e[t+d];for(d+=h,s=n&(1<<-c)-1,n>>=-c,c+=a;0>=-c,c+=o;0>1,d=23===n?Math.pow(2,-24)-Math.pow(2,-77):0,h=o?0:s-1,f=o?1:-1,s=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(a=isNaN(t)?1:0,i=u):(i=Math.floor(Math.log(t)/Math.LN2),t*(o=Math.pow(2,-i))<1&&(i--,o*=2),2<=(t+=1<=i+c?d/o:d*Math.pow(2,1-c))*o&&(i++,o/=2),u<=i+c?(a=0,i=u):1<=i+c?(a=(t*o-1)*Math.pow(2,n),i+=c):(a=t*Math.pow(2,c-1)*Math.pow(2,n),i=0));8<=n;e[r+h]=255&a,h+=f,a/=256,n-=8);for(i=i<Math.abs(e[0])&&(t=1),t=Math.abs(e[2])>Math.abs(e[t])?2:t}function M(e,t){e.f+=t.f,e.b.f+=t.b.f}function h(e,t,r){return e=e.a,t=t.a,r=r.a,t.b.a===e?r.b.a===e?g(t.a,r.a)?b(r.b.a,t.a,r.a)<=0:0<=b(t.b.a,r.a,t.a):b(r.b.a,e,r.a)<=0:r.b.a===e?0<=b(t.b.a,e,t.a):(t=v(t.b.a,e,t.a),(e=v(r.b.a,e,r.a))<=t)}function k(e){e.a.i=null;var t=e.e;t.a.c=t.c,t.c.a=t.a,e.e=null}function O(e,t){m(e.a),e.c=!1,(e.a=t).i=e}function C(e){for(var t=e.a.a;(e=G(e)).a.a===t;);return e.c&&(O(e,t=S(B(e).a.b,e.a.e)),e=G(e)),e}function q(e,t,r){var o=new N;return o.a=r,o.e=p(e.f,t.e,o),r.i=o}function X(e,t){switch(e.s){case 100130:return 0!=(1&t);case 100131:return 0!==t;case 100132:return 0>1]],a[i[u]])?U:ue)(r,u),a[s]=null,l[s]=r.b,r.b=s}else for(r.c[-(s+1)]=null;0Math.max(i.a,l.a))){if(g(s,i)){if(0r.f&&(r.f*=2,r.c=ae(r.c,r.f+1)),0===r.b?n=o:(n=r.b,r.b=r.c[r.b]),r.e[n]=t,r.c[n]=o,r.d[o]=n,r.h&&ue(r,o),n):(r=e.a++,e.c[r]=t,-(r+1))}function se(e){if(0===e.a)return le(e.b);var t=e.c[e.d[e.a-1]];if(0!==e.b.a&&g(F(e.b),t))return le(e.b);for(;--e.a,0e.a||g(o[i],o[l])){n[r[s]=i]=s;break}n[r[s]=l]=s,s=a}}function ue(e,t){for(var r=e.d,o=e.e,n=e.c,s=t,i=r[s];;){var a=s>>1,l=r[a];if(0==a||g(o[l],o[i])){n[r[s]=i]=s;break}n[r[s]=l]=s,s=a}}function N(){this.e=this.a=null,this.f=0,this.c=this.b=this.h=this.d=!1}function B(e){return e.e.c.b}function G(e){return e.e.a.b}(t=r.prototype).x=function(){I(this,0)},t.B=function(e,t){switch(e){case 100142:return;case 100140:switch(t){case 100130:case 100131:case 100132:case 100133:case 100134:return void(this.s=t)}break;case 100141:return void(this.m=!!t);default:return void l(this,100900)}l(this,100901)},t.y=function(e){switch(e){case 100142:return 0;case 100140:return this.s;case 100141:return this.m;default:l(this,100900)}return!1},t.A=function(e,t,r){this.j[0]=e,this.j[1]=t,this.j[2]=r},t.z=function(e,t){var r=t||null;switch(e){case 100100:case 100106:this.h=r;break;case 100104:case 100110:this.l=r;break;case 100101:case 100107:this.k=r;break;case 100102:case 100108:this.i=r;break;case 100103:case 100109:this.p=r;break;case 100105:case 100111:this.o=r;break;case 100112:this.r=r;break;default:l(this,100900)}},t.C=function(e,t){var r=!1,o=[0,0,0];I(this,2);for(var n=0;n<3;++n){var s=e[n];s<-1e150&&(s=-1e150,r=!0),1e150o[u]&&(o[u]=c,n[u]=r)}if(o[1]-a[1]>o[r=0]-a[0]&&(r=1),a[r=o[2]-a[2]>o[r]-a[r]?2:r]>=o[r])i[0]=0,i[1]=0,i[2]=1;else{for(a=l[r],n=n[r],l=[o=0,0,0],a=[a.g[0]-n.g[0],a.g[1]-n.g[1],a.g[2]-n.g[2]],u=[0,0,0],r=s.e;r!==s;r=r.e)u[0]=r.g[0]-n.g[0],u[1]=r.g[1]-n.g[1],u[2]=r.g[2]-n.g[2],l[0]=a[1]*u[2]-a[2]*u[1],l[1]=a[2]*u[0]-a[0]*u[2],l[2]=a[0]*u[1]-a[1]*u[0],o<(c=l[0]*l[0]+l[1]*l[1]+l[2]*l[2])&&(o=c,i[0]=l[0],i[1]=l[1],i[2]=l[2]);o<=0&&(i[0]=i[1]=i[2]=0,i[W(a)]=1)}s=!0}for(l=W(i),r=this.b.c,o=(l+1)%3,n=(l+2)%3,l=0>=1;)++n;if(i=1<>8&255,g[v++]=255&t,g[v++]=t>>8&255,g[v++]=(null!==b?128:0)|n,g[v++]=s,g[v++]=0,null!==b)for(var a=0,l=b.length;a>16&255,g[v++]=u>>8&255,g[v++]=255&u}if(null!==o){if(o<0||65535>8&255,g[v++]=0}var _=!1;this.addFrame=function(e,t,r,o,n,s){if(!0===_&&(--v,_=!1),s=void 0===s?{}:s,e<0||t<0||65535>=1;)++u;var l=1<>8&255,g[v++]=f,g[v++]=0),g[v++]=44,g[v++]=255&e,g[v++]=e>>8&255,g[v++]=255&t,g[v++]=t>>8&255,g[v++]=255&r,g[v++]=r>>8&255,g[v++]=255&o,g[v++]=o>>8&255,g[v++]=!0===i?128|u-1:0,!0===i)for(var p=0,m=a.length;p>16&255,g[v++]=y>>8&255,g[v++]=255&y}return v=function(t,r,e,o){t[r++]=e;var n=r++,s=1<>=8,c-=8,r===n+256&&(t[n]=255,n=r++)}function f(e){d|=e<>=8,c-=8,r===n+256&&(t[n]=255,n=r++);4096===l?(f(s),l=1+a,u=e+1,m={}):(1<>=l,c-=l,y==s)a=1+i,u=(1<<(l=n+1))-1,m=null;else{if(y==i)break;for(var g=y>8,++v;var j=b;if(o>=8;null!==m&&a<4096&&(p[a++]=m<<8|j,u+1<=a&&l<12&&(++l,u=u<<1|1)),m=y}}h!==o&&console.log("Warning, gif stream shorter than expected.")}try{r.GifWriter=o,r.GifReader=function(b){var e=0;if(71!==b[e++]||73!==b[e++]||70!==b[e++]||56!==b[e++]||56!=(b[e++]+1&253)||97!==b[e++])throw new Error("Invalid GIF 87a/89a header.");var j=b[e++]|b[e++]<<8,t=b[e++]|b[e++]<<8,r=b[e++],o=1<<1+(7&r),n=(b[e++],b[e++],null),s=null,i=(r>>7&&(n=e,e+=3*(s=o)),!0),a=[],l=0,u=null,c=0,d=null;for(this.width=j,this.height=t;i&&e>2&7,e++;break;case 254:for(;;){if(!(0<=(f=b[e++])))throw Error("Invalid block size");if(0===f)break;e+=f}break;default:throw new Error("Unknown graphic control label: 0x"+b[e-1].toString(16))}break;case 44:var f,p=b[e++]|b[e++]<<8,m=b[e++]|b[e++]<<8,y=b[e++]|b[e++]<<8,g=b[e++]|b[e++]<<8,v=b[e++],_=v>>6&1,x=1<<1+(7&v),w=n,S=s,T=!1,v=(v>>7&&(T=!0,w=e,e+=3*(S=x)),e);for(e++;;){if(!(0<=(f=b[e++])))throw Error("Invalid block size");if(0===f)break;e+=f}a.push({x:p,y:m,width:y,height:g,has_local_palette:T,palette_offset:w,palette_size:S,data_offset:v,data_length:e-v,transparent_index:u,interlaced:!!_,delay:l,disposal:c});break;case 59:i=!1;break;default:throw new Error("Unknown gif block: 0x"+b[e-1].toString(16))}this.numFrames=function(){return a.length},this.loopCount=function(){return d},this.frameInfo=function(e){if(e<0||e>=a.length)throw new Error("Frame index out of range.");return a[e]},this.decodeAndBlitFrameBGRA=function(e,t){for(var e=this.frameInfo(e),r=e.width*e.height,o=new Uint8Array(r),n=(E(b,e.data_offset,o,r),e.palette_offset),s=e.transparent_index,i=(null===s&&(s=256),e.width),a=j-i,l=i,u=4*(e.y*j+e.x),c=4*((e.y+e.height)*j+e.x),d=u,h=4*a,f=(!0===e.interlaced&&(h+=4*j*7),8),p=0,m=o.length;p>=1)),v===s?d+=4:(y=b[n+3*v],g=b[n+3*v+1],v=b[n+3*v+2],t[d++]=v,t[d++]=g,t[d++]=y,t[d++]=255),--l}},this.decodeAndBlitFrameRGBA=function(e,t){for(var e=this.frameInfo(e),r=e.width*e.height,o=new Uint8Array(r),n=(E(b,e.data_offset,o,r),e.palette_offset),s=e.transparent_index,i=(null===s&&(s=256),e.width),a=j-i,l=i,u=4*(e.y*j+e.x),c=4*((e.y+e.height)*j+e.x),d=u,h=4*a,f=(!0===e.interlaced&&(h+=4*j*7),8),p=0,m=o.length;p>=1)),v===s?d+=4:(y=b[n+3*v],g=b[n+3*v+1],v=b[n+3*v+2],t[d++]=y,t[d++]=g,t[d++]=v,t[d++]=255),--l}}}}catch(e){}},{}],257:[function(Pr,r,o){!function(Ar){var e,t;e=this,t=function(j){"use strict";function D(e){if(null==this)throw TypeError();var t,r=String(this),o=r.length,e=e?Number(e):0;if(!((e=e!=e?0:e)<0||o<=e))return 55296<=(t=r.charCodeAt(e))&&t<=56319&&e+1>>16-t;return e.tag>>>=t,e.bitcount-=t,o+r}function $(e,t){for(;e.bitcount<24;)e.tag|=e.source[e.sourceIndex++]<>>=1,r+=t.table[++n],0<=(o-=t.table[n]););return e.tag=s,e.bitcount-=n,t.trans[r+o]}function ee(e,t,r){for(;;){var o=$(e,t);if(256===o)return U;if(o<256)e.dest[e.destLen++]=o;else for(var n,s=b(e,H[o-=257],W[o]),o=$(e,r),i=n=e.destLen-b(e,q[o],X[o]);i>>=1,o=n,b(s,2,0)){case 0:r=function(e){for(var t,r;8this.x2&&(this.x2=e)),"number"==typeof t&&((isNaN(this.y1)||isNaN(this.y2))&&(this.y1=t,this.y2=t),tthis.y2&&(this.y2=t))},a.prototype.addX=function(e){this.addPoint(e,null)},a.prototype.addY=function(e){this.addPoint(null,e)},a.prototype.addBezier=function(e,t,r,o,n,s,i,a){var l=[e,t],u=[r,o],c=[n,s],d=[i,a];this.addPoint(e,t),this.addPoint(i,a);for(var h=0;h<=1;h++){var f,p=6*l[h]-12*u[h]+6*c[h],m=-3*l[h]+9*u[h]-9*c[h]+3*d[h],y=3*u[h]-3*l[h];0==m?0==p||0<(f=-y/p)&&f<1&&(0===h&&this.addX(g(l[h],u[h],c[h],d[h],f)),1===h&&this.addY(g(l[h],u[h],c[h],d[h],f))):(f=Math.pow(p,2)-4*y*m)<0||(0<(y=(-p+Math.sqrt(f))/(2*m))&&y<1&&(0===h&&this.addX(g(l[h],u[h],c[h],d[h],y)),1===h&&this.addY(g(l[h],u[h],c[h],d[h],y))),0<(y=(-p-Math.sqrt(f))/(2*m))&&y<1&&(0===h&&this.addX(g(l[h],u[h],c[h],d[h],y)),1===h&&this.addY(g(l[h],u[h],c[h],d[h],y))))}},a.prototype.addQuad=function(e,t,r,o,n,s){r=e+2/3*(r-e),o=t+2/3*(o-t);this.addBezier(e,t,r,o,r+1/3*(n-e),o+1/3*(s-t),n,s)},h.prototype.moveTo=function(e,t){this.commands.push({type:"M",x:e,y:t})},h.prototype.lineTo=function(e,t){this.commands.push({type:"L",x:e,y:t})},h.prototype.curveTo=h.prototype.bezierCurveTo=function(e,t,r,o,n,s){this.commands.push({type:"C",x1:e,y1:t,x2:r,y2:o,x:n,y:s})},h.prototype.quadTo=h.prototype.quadraticCurveTo=function(e,t,r,o){this.commands.push({type:"Q",x1:e,y1:t,x:r,y:o})},h.prototype.close=h.prototype.closePath=function(){this.commands.push({type:"Z"})},h.prototype.extend=function(e){var t;if(e.commands)e=e.commands;else if(e instanceof a)return t=e,this.moveTo(t.x1,t.y1),this.lineTo(t.x2,t.y1),this.lineTo(t.x2,t.y2),this.lineTo(t.x1,t.y2),void this.close();Array.prototype.push.apply(this.commands,e)},h.prototype.getBoundingBox=function(){for(var e=new a,t=0,r=0,o=0,n=0,s=0;s>8&255,255&e]},l.USHORT=r(2),w.SHORT=function(e){return[(e=32768<=e?-(65536-e):e)>>8&255,255&e]},l.SHORT=r(2),w.UINT24=function(e){return[e>>16&255,e>>8&255,255&e]},l.UINT24=r(3),w.ULONG=function(e){return[e>>24&255,e>>16&255,e>>8&255,255&e]},l.ULONG=r(4),w.LONG=function(e){return[(e=2147483648<=e?-(4294967296-e):e)>>24&255,e>>16&255,e>>8&255,255&e]},l.LONG=r(4),w.FIXED=w.ULONG,l.FIXED=l.ULONG,w.FWORD=w.SHORT,l.FWORD=l.SHORT,w.UFWORD=w.USHORT,l.UFWORD=l.USHORT,w.LONGDATETIME=function(e){return[0,0,0,0,e>>24&255,e>>16&255,e>>8&255,255&e]},l.LONGDATETIME=r(8),w.TAG=function(e){return L.argument(4===e.length,"Tag should be exactly 4 ASCII characters."),[e.charCodeAt(0),e.charCodeAt(1),e.charCodeAt(2),e.charCodeAt(3)]},l.TAG=r(4),w.Card8=w.BYTE,l.Card8=l.BYTE,w.Card16=w.USHORT,l.Card16=l.USHORT,w.OffSize=w.BYTE,l.OffSize=l.BYTE,w.SID=w.USHORT,l.SID=l.USHORT,w.NUMBER=function(e){return-107<=e&&e<=107?[e+139]:108<=e&&e<=1131?[247+((e-=108)>>8),255&e]:-1131<=e&&e<=-108?[251+((e=-e-108)>>8),255&e]:-32768<=e&&e<=32767?w.NUMBER16(e):w.NUMBER32(e)},l.NUMBER=function(e){return w.NUMBER(e).length},w.NUMBER16=function(e){return[28,e>>8&255,255&e]},l.NUMBER16=r(3),w.NUMBER32=function(e){return[29,e>>24&255,e>>16&255,e>>8&255,255&e]},l.NUMBER32=r(5),w.REAL=function(e){for(var t=e.toString(),r=/\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/.exec(t),o=(r&&(r=parseFloat("1e"+((r[2]?+r[2]:0)+r[1].length)),t=(Math.round(e*r)/r).toString()),""),n=0,s=t.length;n>8&255,t[t.length]=255&o}return t},l.UTF16=function(e){return 2*e.length};var se,ie={"x-mac-croatian":"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®Š™´¨≠ŽØ∞±≤≥∆µ∂∑∏š∫ªºΩžø¿¡¬√ƒ≈Ć«Č… ÀÃÕŒœĐ—“”‘’÷◊©⁄€‹›Æ»–·‚„‰ÂćÁčÈÍÎÏÌÓÔđÒÚÛÙıˆ˜¯πË˚¸Êæˇ","x-mac-cyrillic":"АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ†°Ґ£§•¶І®©™Ђђ≠Ѓѓ∞±≤≥іµґЈЄєЇїЉљЊњјЅ¬√ƒ≈∆«»… ЋћЌќѕ–—“”‘’÷„ЎўЏџ№Ёёяабвгдежзийклмнопрстуфхцчшщъыьэю","x-mac-gaelic":"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØḂ±≤≥ḃĊċḊḋḞḟĠġṀæøṁṖṗɼƒſṠ«»… ÀÃÕŒœ–—“”‘’ṡẛÿŸṪ€‹›Ŷŷṫ·Ỳỳ⁊ÂÊÁËÈÍÎÏÌÓÔ♣ÒÚÛÙıÝýŴŵẄẅẀẁẂẃ","x-mac-greek":"Ĺ²É³ÖÜ΅àâä΄¨çéèê룙î‰ôö¦€ùûü†ΓΔΘΛΞΠß®©ΣΪ§≠°·Α±≤≥¥ΒΕΖΗΙΚΜΦΫΨΩάΝ¬ΟΡ≈Τ«»… ΥΧΆΈœ–―“”‘’÷ΉΊΌΎέήίόΏύαβψδεφγηιξκλμνοπώρστθωςχυζϊϋΐΰ­","x-mac-icelandic":"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûüÝ°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€ÐðÞþý·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ","x-mac-inuit":"ᐃᐄᐅᐆᐊᐋᐱᐲᐳᐴᐸᐹᑉᑎᑏᑐᑑᑕᑖᑦᑭᑮᑯᑰᑲᑳᒃᒋᒌᒍᒎᒐᒑ°ᒡᒥᒦ•¶ᒧ®©™ᒨᒪᒫᒻᓂᓃᓄᓅᓇᓈᓐᓯᓰᓱᓲᓴᓵᔅᓕᓖᓗᓘᓚᓛᓪᔨᔩᔪᔫᔭ… ᔮᔾᕕᕖᕗ–—“”‘’ᕘᕙᕚᕝᕆᕇᕈᕉᕋᕌᕐᕿᖀᖁᖂᖃᖄᖅᖏᖐᖑᖒᖓᖔᖕᙱᙲᙳᙴᙵᙶᖖᖠᖡᖢᖣᖤᖥᖦᕼŁł","x-mac-ce":"ÄĀāÉĄÖÜáąČäčĆć鏟ĎíďĒēĖóėôöõúĚěü†°Ę£§•¶ß®©™ę¨≠ģĮįĪ≤≥īĶ∂∑łĻļĽľĹĺŅņѬ√ńŇ∆«»… ňŐÕőŌ–—“”‘’÷◊ōŔŕŘ‹›řŖŗŠ‚„šŚśÁŤťÍŽžŪÓÔūŮÚůŰűŲųÝýķŻŁżĢˇ",macintosh:"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€‹›fifl‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ","x-mac-romanian":"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ĂȘ∞±≤≥¥µ∂∑∏π∫ªºΩăș¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€‹›Țț‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ","x-mac-turkish":"ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸĞğİıŞş‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙˆ˜¯˘˙˚¸˝˛ˇ"},ae=(m.MACSTRING=function(e,t,r,o){var n=ie[o];if(void 0!==n){for(var s="",i=0;i>8&255,l+256&255)}return s})(e,t,r);return r},w.INDEX=function(e){for(var t=1,r=[t],o=[],n=0;n>8,t[c+1]=255&d,t=t.concat(o[u])}return t},l.TABLE=function(e){for(var t=0,r=e.fields.length,o=0;o>1,a.skip("uShort",3),y.glyphIndexMap={};for(var j,_=new R.Parser(g,v+b+14),x=new R.Parser(g,v+b+16+2*j),w=new R.Parser(g,v+b+16+4*j),S=new R.Parser(g,v+b+16+6*j),T=v+b+16+8*j,E=0;E>4,s=15&s;if(15==i)break;if(o+=n[i],15==s)break;o+=n[s]}return parseFloat(o)}if(32<=t&&t<=246)return t-139;if(247<=t&&t<=250)return 256*(t-247)+e.parseByte()+108;if(251<=t&&t<=254)return 256*-(t-251)-e.parseByte()-108;throw new Error("Invalid b0 "+t)}function Ie(e,t,r){var o=new R.Parser(e,t=void 0!==t?t:0),n=[],s=[];for(r=void 0!==r?r:e.length;o.relativeOffset>1,E.length=0,k=!0}return function e(t){for(var r,o,n,s,i,a,l,u,c,d,h,f,p=0;pMath.abs(f-A)?C=h+E.shift():A=f+E.shift(),T.curveTo(v,b,j,_,l,u),T.curveTo(c,d,h,f,C,A);break;default:console.log("Glyph "+g.index+": unknown operator 1200"+m),E.length=0}break;case 14:0>3;break;case 21:2>16),p+=2;break;case 29:i=E.pop()+y.gsubrsBias,(a=y.gsubrs[i])&&e(a);break;case 30:for(;0=r.begin&&e=c.length&&(s=o.parseChar(),r.names.push(o.parseString(s)));break;case 2.5:r.numberOfGlyphs=o.parseUShort(),r.offset=new Array(r.numberOfGlyphs);for(var a=0;at.value.tag?1:-1}),t.fields=t.fields.concat(o),t.fields=t.fields.concat(n),t}function xt(e,t,r){for(var o=0;o 123 are reserved for internal usage");f|=1<>>1,s=e[n].tag;if(s===t)return n;s>>1,s=e[n];if(s===t)return n;s>>1,i=(n=e[s]).start;if(i===t)return n;i(n=e[r-1]).end?0:n}function Mt(e,t){this.font=e,this.tableName=t}function kt(e){Mt.call(this,e,"gpos")}function i(e){Mt.call(this,e,"gsub")}function Ot(e,t,r){for(var o=e.subtables,n=0;nt.points.length-1||o.matchedPoints[1]>n.points.length-1)throw Error("Matched points out of range in "+t.name);var i=t.points[o.matchedPoints[0]],a=n.points[o.matchedPoints[1]],o={xScale:o.xScale,scale01:o.scale01,scale10:o.scale10,yScale:o.yScale,dx:0,dy:0},a=Lt([a],o)[0];o.dx=i.x-a.x,o.dy=i.y-a.y,s=Lt(n.points,o)}t.points=t.points.concat(s)}}return Rt(t.points)}(kt.prototype=Mt.prototype={searchTag:St,binSearch:Tt,getTable:function(e){var t=this.font.tables[this.tableName];return t=!t&&e?this.font.tables[this.tableName]=this.createDefaultTable():t},getScriptNames:function(){var e=this.getTable();return e?e.scripts.map(function(e){return e.tag}):[]},getDefaultScriptName:function(){var e=this.getTable();if(e){for(var t=!1,r=0;r=i[t-1].tag,"Features must be added in alphabetical order."),i.push(n={tag:r,feature:{params:0,lookupListIndexes:[]}}),s.push(t),n.feature}},getLookupTables:function(e,t,r,o,n){var e=this.getFeatureTable(e,t,r,n),s=[];if(e){for(var i,a=e.lookupListIndexes,l=this.font.tables[this.tableName].lookups,u=0;u",s),t.stack.push(Math.round(64*s))}function hr(e,t){var r=t.stack,o=r.pop(),n=t.fv,s=t.pv,i=t.ppem,a=t.deltaBase+16*(e-1),l=t.deltaShift,u=t.z0;j.DEBUG&&console.log(t.step,"DELTAP["+e+"]",o,r);for(var c=0;c>4)===i&&(0<=(h=(15&h)-8)&&h++,j.DEBUG&&console.log(t.step,"DELTAPFIX",d,"by",h*l),d=u[d],n.setRelative(d,d,h*l,s))}}function fr(e,t){var r=t.stack,o=r.pop();j.DEBUG&&console.log(t.step,"ROUND[]"),r.push(64*t.round(o/64))}function pr(e,t){var r=t.stack,o=r.pop(),n=t.ppem,s=t.deltaBase+16*(e-1),i=t.deltaShift;j.DEBUG&&console.log(t.step,"DELTAC["+e+"]",o,r);for(var a=0;a>4)===n&&(0<=(u=(15&u)-8)&&u++,u=u*i,j.DEBUG&&console.log(t.step,"DELTACFIX",l,"by",u),t.cvt[l]+=u)}}function mr(e,t){var r,o=t.stack,n=o.pop(),o=o.pop(),s=t.z2[n],i=t.z1[o];j.DEBUG&&console.log(t.step,"SDPVTL["+e+"]",n,o),n=e?(r=s.y-i.y,i.x-s.x):(r=i.x-s.x,i.y-s.y),t.dpv=qt(r,n)}function k(e,t){var r=t.stack,o=t.prog,n=t.ip;j.DEBUG&&console.log(t.step,"PUSHB["+e+"]");for(var s=0;s":"_")+(o?"R":"_")+(0===n?"Gr":1===n?"Bl":2===n?"Wh":"")+"]",e?u+"("+s.cvt[u]+","+a+")":"",l,"(d =",i,"->",y*m,")"),s.rp1=s.rp0,s.rp2=l,t&&(s.rp0=l)}Ft.prototype.exec=function(e,t){if("number"!=typeof t)throw new Error("Point size is not a number!");if(!(2",o),a.interpolate(d,s,i,l),a.touch(d)}e.loop=1},lr.bind(void 0,0),lr.bind(void 0,1),function(e){for(var t=e.stack,r=e.rp0,o=e.z0[r],n=e.loop,s=e.fv,i=e.pv,a=e.z1;n--;){var l=t.pop(),u=a[l];j.DEBUG&&console.log(e.step,(1'.concat(n,"").concat(t,""),this.dummyDOM||(this.dummyDOM=document.getElementById(o).parentNode),this.descriptions?this.descriptions.fallbackElements||(this.descriptions.fallbackElements={}):this.descriptions={fallbackElements:{}},this.descriptions.fallbackElements[e]?this.descriptions.fallbackElements[e].innerHTML!==n&&(this.descriptions.fallbackElements[e].innerHTML=n):this._describeElementHTML("fallback",e,n),r===this.LABEL&&(this.descriptions.labelElements||(this.descriptions.labelElements={}),this.descriptions.labelElements[e]?this.descriptions.labelElements[e].innerHTML!==n&&(this.descriptions.labelElements[e].innerHTML=n):this._describeElementHTML("label",e,n)))},s.default.prototype._describeHTML=function(e,t){var r,o=this.canvas.id;"fallback"===e?(this.dummyDOM.querySelector("#".concat(o+i))?this.dummyDOM.querySelector("#"+o+l).insertAdjacentHTML("beforebegin",'

        ')):(r='

        '),this.dummyDOM.querySelector("#".concat(o,"accessibleOutput"))?this.dummyDOM.querySelector("#".concat(o,"accessibleOutput")).insertAdjacentHTML("beforebegin",r):this.dummyDOM.querySelector("#".concat(o)).innerHTML=r),this.descriptions.fallback=this.dummyDOM.querySelector("#".concat(o).concat(a)),this.descriptions.fallback.innerHTML=t):"label"===e&&(this.dummyDOM.querySelector("#".concat(o+u))?this.dummyDOM.querySelector("#".concat(o+d))&&this.dummyDOM.querySelector("#".concat(o+d)).insertAdjacentHTML("beforebegin",'

        ')):(r='

        '),this.dummyDOM.querySelector("#".concat(o,"accessibleOutputLabel"))?this.dummyDOM.querySelector("#".concat(o,"accessibleOutputLabel")).insertAdjacentHTML("beforebegin",r):this.dummyDOM.querySelector("#"+o).insertAdjacentHTML("afterend",r)),this.descriptions.label=this.dummyDOM.querySelector("#"+o+c),this.descriptions.label.innerHTML=t)},s.default.prototype._describeElementHTML=function(e,t,r){var o,n=this.canvas.id;"fallback"===e?(this.dummyDOM.querySelector("#".concat(n+i))?this.dummyDOM.querySelector("#"+n+l)||this.dummyDOM.querySelector("#"+n+a).insertAdjacentHTML("afterend",'
        Canvas elements and their descriptions
        ')):(o='
        Canvas elements and their descriptions
        '),this.dummyDOM.querySelector("#".concat(n,"accessibleOutput"))?this.dummyDOM.querySelector("#".concat(n,"accessibleOutput")).insertAdjacentHTML("beforebegin",o):this.dummyDOM.querySelector("#"+n).innerHTML=o),(o=document.createElement("tr")).id=n+"_fte_"+t,this.dummyDOM.querySelector("#"+n+l).appendChild(o),this.descriptions.fallbackElements[t]=this.dummyDOM.querySelector("#".concat(n).concat("_fte_").concat(t)),this.descriptions.fallbackElements[t].innerHTML=r):"label"===e&&(this.dummyDOM.querySelector("#".concat(n+u))?this.dummyDOM.querySelector("#".concat(n+d))||this.dummyDOM.querySelector("#"+n+c).insertAdjacentHTML("afterend",'
        ')):(o='
        '),this.dummyDOM.querySelector("#".concat(n,"accessibleOutputLabel"))?this.dummyDOM.querySelector("#".concat(n,"accessibleOutputLabel")).insertAdjacentHTML("beforebegin",o):this.dummyDOM.querySelector("#"+n).insertAdjacentHTML("afterend",o)),(e=document.createElement("tr")).id=n+"_lte_"+t,this.dummyDOM.querySelector("#"+n+d).appendChild(e),this.descriptions.labelElements[t]=this.dummyDOM.querySelector("#".concat(n).concat("_lte_").concat(t)),this.descriptions.labelElements[t].innerHTML=r)};e=s.default;r.default=e},{"../core/main":283,"core-js/modules/es.array.concat":153,"core-js/modules/es.regexp.exec":195,"core-js/modules/es.string.ends-with":198,"core-js/modules/es.string.replace":204}],264:[function(e,t,r){"use strict";e("core-js/modules/es.array.concat"),e("core-js/modules/es.array.from"),e("core-js/modules/es.array.map"),e("core-js/modules/es.string.iterator"),e("core-js/modules/es.array.concat"),e("core-js/modules/es.array.from"),e("core-js/modules/es.array.map"),e("core-js/modules/es.string.iterator"),Object.defineProperty(r,"__esModule",{value:!0}),r.default=void 0;e=(e=e("../core/main"))&&e.__esModule?e:{default:e};e.default.prototype._updateGridOutput=function(e){var t,r,o,n;this.dummyDOM.querySelector("#".concat(e,"_summary"))&&(t=this._accessibleOutputs[e],o=function(e,t,r,o){t="".concat(t," canvas, ").concat(r," by ").concat(o," pixels, contains ").concat(e[0]);t=(1===e[0]?"".concat(t," shape: "):"".concat(t," shapes: ")).concat(e[1]);return t}((r=function(e,t){var r,o="",n="",s=0;for(r in t){var i,a=0;for(i in t[r]){var l='
      • ').concat(t[r][i].color," ").concat(r,",");"line"===r?l+=" location = ".concat(t[r][i].pos,", length = ").concat(t[r][i].length," pixels"):(l+=" location = ".concat(t[r][i].pos),"point"!==r&&(l+=", area = ".concat(t[r][i].area," %")),l+="
      • "),o+=l,a++,s++}n=1').concat(t[r][a].color," ").concat(r,"
        "):'').concat(t[r][a].color," ").concat(r," midpoint"),t[r][a].loc.locY";s=s+c+""}return s}(e,this.ingredients.shapes),o!==t.summary.innerHTML&&(t.summary.innerHTML=o),n!==t.map.innerHTML&&(t.map.innerHTML=n),r.details!==t.shapeDetails.innerHTML&&(t.shapeDetails.innerHTML=r.details),this._accessibleOutputs[e]=t)};e=e.default;r.default=e},{"../core/main":283,"core-js/modules/es.array.concat":153,"core-js/modules/es.array.from":162,"core-js/modules/es.array.map":168,"core-js/modules/es.string.iterator":200}],265:[function(e,t,r){"use strict";e("core-js/modules/es.symbol"),e("core-js/modules/es.symbol.description"),e("core-js/modules/es.symbol.iterator"),e("core-js/modules/es.array.concat"),e("core-js/modules/es.array.fill"),e("core-js/modules/es.array.from"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.map"),e("core-js/modules/es.number.to-fixed"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.regexp.to-string"),e("core-js/modules/es.string.iterator"),e("core-js/modules/web.dom-collections.iterator"),e("core-js/modules/es.array.concat"),e("core-js/modules/es.array.fill"),e("core-js/modules/es.array.map"),e("core-js/modules/es.number.to-fixed"),Object.defineProperty(r,"__esModule",{value:!0}),r.default=void 0;var o=(e=e("../core/main"))&&e.__esModule?e:{default:e};function l(e){return function(e){if(Array.isArray(e)){for(var t=0,r=new Array(e.length);t
        ')):this.dummyDOM.querySelector("#".concat(s)).innerHTML='
        '))):"Label"===t&&(r=s+e+(i=t),this.dummyDOM.querySelector("#".concat(o=s+"accessibleOutput"+t))||(this.dummyDOM.querySelector("#".concat(s,"_Label"))?this.dummyDOM.querySelector("#".concat(s,"_Label")):this.dummyDOM.querySelector("#".concat(s))).insertAdjacentHTML("afterend",'
        '))),this._accessibleOutputs[r]={},"textOutput"===e?(i="#".concat(s,"gridOutput").concat(i),n='
        Text Output

          '),this.dummyDOM.querySelector(i)?this.dummyDOM.querySelector(i).insertAdjacentHTML("beforebegin",n):this.dummyDOM.querySelector("#".concat(o)).innerHTML=n,this._accessibleOutputs[r].list=this.dummyDOM.querySelector("#".concat(r,"_list"))):"gridOutput"===e&&(i="#".concat(s,"textOutput").concat(i),n='
          Grid Output

            '),this.dummyDOM.querySelector(i)?this.dummyDOM.querySelector(i).insertAdjacentHTML("afterend",n):this.dummyDOM.querySelector("#".concat(o)).innerHTML=n,this._accessibleOutputs[r].map=this.dummyDOM.querySelector("#".concat(r,"_map"))),this._accessibleOutputs[r].shapeDetails=this.dummyDOM.querySelector("#".concat(r,"_shapeDetails")),this._accessibleOutputs[r].summary=this.dummyDOM.querySelector("#".concat(r,"_summary"))},o.default.prototype._updateAccsOutput=function(){var e=this.canvas.id;JSON.stringify(this.ingredients.shapes)===this.ingredients.pShapes&&this.ingredients.colors.background===this.ingredients.pBackground||(this.ingredients.pShapes=JSON.stringify(this.ingredients.shapes),this._accessibleOutputs.text&&this._updateTextOutput(e+"textOutput"),this._accessibleOutputs.grid&&this._updateGridOutput(e+"gridOutput"),this._accessibleOutputs.textLabel&&this._updateTextOutput(e+"textOutputLabel"),this._accessibleOutputs.gridLabel&&this._updateGridOutput(e+"gridOutputLabel"))},o.default.prototype._accsBackground=function(e){this.ingredients.pShapes=JSON.stringify(this.ingredients.shapes),this.ingredients.pBackground=this.ingredients.colors.background,this.ingredients.shapes={},this.ingredients.colors.backgroundRGBA!==e&&(this.ingredients.colors.backgroundRGBA=e,this.ingredients.colors.background=this._rgbColorName(e))},o.default.prototype._accsCanvasColors=function(e,t){"fill"===e?this.ingredients.colors.fillRGBA!==t&&(this.ingredients.colors.fillRGBA=t,this.ingredients.colors.fill=this._rgbColorName(t)):"stroke"===e&&this.ingredients.colors.strokeRGBA!==t&&(this.ingredients.colors.strokeRGBA=t,this.ingredients.colors.stroke=this._rgbColorName(t))},o.default.prototype._accsOutput=function(e,t){"ellipse"===e&&t[2]===t[3]?e="circle":"rectangle"===e&&t[2]===t[3]&&(e="square");var r,o,n={},s=!0,i=function(e,t){var r;e="rectangle"===e||"ellipse"===e||"arc"===e||"circle"===e||"square"===e?(r=Math.round(t[0]+t[2]/2),Math.round(t[1]+t[3]/2)):"triangle"===e?(r=(t[0]+t[2]+t[4])/3,(t[1]+t[3]+t[5])/3):"quadrilateral"===e?(r=(t[0]+t[2]+t[4]+t[6])/4,(t[1]+t[3]+t[5]+t[7])/4):"line"===e?(r=(t[0]+t[2])/2,(t[1]+t[3])/2):(r=t[0],t[1]);return[r,e]}(e,t);if("line"===e?(n.color=this.ingredients.colors.stroke,n.length=Math.round(this.dist(t[0],t[1],t[2],t[3])),r=this._getPos(t[0],[1]),o=this._getPos(t[2],[3]),n.loc=u(i,this.width,this.height),n.pos=r===o?"at ".concat(r):"from ".concat(r," to ").concat(o)):("point"===e?n.color=this.ingredients.colors.stroke:(n.color=this.ingredients.colors.fill,n.area=this._getArea(e,t)),n.pos=this._getPos.apply(this,l(i)),n.loc=u(i,this.width,this.height)),this.ingredients.shapes[e]){if(this.ingredients.shapes[e]!==[n]){for(var a in this.ingredients.shapes[e])JSON.stringify(this.ingredients.shapes[e][a])===JSON.stringify(n)&&(s=!1);!0===s&&this.ingredients.shapes[e].push(n)}}else this.ingredients.shapes[e]=[n]},o.default.prototype._getPos=function(e,t){var e=new DOMPointReadOnly(e,t),t=this._renderer.isP3D?new DOMMatrix(this._renderer.uMVMatrix.mat4):this.drawingContext.getTransform(),e=e.matrixTransform(t),t=e.x,e=e.y,r=this.width*this._pixelDensity,o=this.height*this._pixelDensity;return t<.4*r?e<.4*o?"top left":.6*oMath.PI?n+=o:n-=o)):"ellipse"===e||"circle"===e?n=3.14*t[2]/2*t[3]/2:"line"===e||"point"===e?n=0:"quadrilateral"===e?n=Math.abs((t[6]+t[0])*(t[7]-t[1])+(t[0]+t[2])*(t[1]-t[3])+(t[2]+t[4])*(t[3]-t[5])+(t[4]+t[6])*(t[5]-t[7]))/2:"rectangle"===e||"square"===e?n=t[2]*t[3]:"triangle"===e&&(n=Math.abs(t[0]*(t[3]-t[5])+t[2]*(t[5]-t[1])+t[4]*(t[1]-t[3]))/2),this.width*this._pixelDensity),i=this.height*this._pixelDensity,a=[new DOMPoint(0,0),new DOMPoint(s,0),new DOMPoint(s,i),new DOMPoint(0,i)],l=(this._renderer.isP3D?new DOMMatrix(this._renderer.uMVMatrix.mat4):this.drawingContext.getTransform()).inverse(),u=a.map(function(e){return e.matrixTransform(l)}),c=Math.abs((u[3].x+u[0].x)*(u[3].y-u[0].y)+(u[0].x+u[1].x)*(u[0].y-u[1].y)+(u[1].x+u[2].x)*(u[1].y-u[2].y)+(u[2].x+u[3].x)*(u[2].y-u[3].y))/2;return Math.round(100*n/c)};e=o.default;r.default=e},{"../core/main":283,"core-js/modules/es.array.concat":153,"core-js/modules/es.array.fill":156,"core-js/modules/es.array.from":162,"core-js/modules/es.array.iterator":165,"core-js/modules/es.array.map":168,"core-js/modules/es.number.to-fixed":182,"core-js/modules/es.object.to-string":190,"core-js/modules/es.regexp.to-string":196,"core-js/modules/es.string.iterator":200,"core-js/modules/es.symbol":212,"core-js/modules/es.symbol.description":210,"core-js/modules/es.symbol.iterator":211,"core-js/modules/web.dom-collections.iterator":246}],266:[function(e,t,r){"use strict";e("core-js/modules/es.array.concat"),e("core-js/modules/es.array.concat"),Object.defineProperty(r,"__esModule",{value:!0}),r.default=void 0;e=(e=e("../core/main"))&&e.__esModule?e:{default:e};e.default.prototype._updateTextOutput=function(e){var t,r,o,n;this.dummyDOM.querySelector("#".concat(e,"_summary"))&&(t=this._accessibleOutputs[e],o=function(e,t,r,o){r="Your output is a, ".concat(r," by ").concat(o," pixels, ").concat(t," canvas containing the following");r=1===e?"".concat(r," shape:"):"".concat(r," ").concat(e," shapes:");return r}((r=function(e,t){var r,o="",n=0;for(r in t)for(var s in t[r]){var i='
          • ').concat(t[r][s].color," ").concat(r,"");"line"===r?i+=", ".concat(t[r][s].pos,", ").concat(t[r][s].length," pixels long.
          • "):(i+=", at ".concat(t[r][s].pos),"point"!==r&&(i+=", covering ".concat(t[r][s].area,"% of the canvas")),i+="."),o+=i,n++}return{numShapes:n,listShapes:o}}(e,this.ingredients.shapes)).numShapes,this.ingredients.colors.background,this.width,this.height),n=function(e,t){var r,o="",n=0;for(r in t)for(var s in t[r]){var i='').concat(t[r][s].color," ").concat(r,"");"line"===r?i+="location = ".concat(t[r][s].pos,"length = ").concat(t[r][s].length," pixels"):(i+="location = ".concat(t[r][s].pos,""),"point"!==r&&(i+=" area = ".concat(t[r][s].area,"%")),i+=""),o+=i,n++}return o}(e,this.ingredients.shapes),o!==t.summary.innerHTML&&(t.summary.innerHTML=o),r.listShapes!==t.list.innerHTML&&(t.list.innerHTML=r.listShapes),n!==t.shapeDetails.innerHTML&&(t.shapeDetails.innerHTML=n),this._accessibleOutputs[e]=t)};e=e.default;r.default=e},{"../core/main":283,"core-js/modules/es.array.concat":153}],267:[function(e,t,r){"use strict";var o=(o=e("./core/main"))&&o.__esModule?o:{default:o};e("./core/constants"),e("./core/environment"),e("./core/friendly_errors/stacktrace"),e("./core/friendly_errors/validate_params"),e("./core/friendly_errors/file_errors"),e("./core/friendly_errors/fes_core"),e("./core/friendly_errors/sketch_reader"),e("./core/helpers"),e("./core/legacy"),e("./core/preload"),e("./core/p5.Element"),e("./core/p5.Graphics"),e("./core/p5.Renderer"),e("./core/p5.Renderer2D"),e("./core/rendering"),e("./core/shim"),e("./core/structure"),e("./core/transform"),e("./core/shape/2d_primitives"),e("./core/shape/attributes"),e("./core/shape/curves"),e("./core/shape/vertex"),e("./accessibility/outputs"),e("./accessibility/textOutput"),e("./accessibility/gridOutput"),e("./accessibility/color_namer"),e("./color/color_conversion"),e("./color/creating_reading"),e("./color/p5.Color"),e("./color/setting"),e("./data/p5.TypedDict"),e("./data/local_storage.js"),e("./dom/dom"),e("./accessibility/describe"),e("./events/acceleration"),e("./events/keyboard"),e("./events/mouse"),e("./events/touch"),e("./image/filters"),e("./image/image"),e("./image/loading_displaying"),e("./image/p5.Image"),e("./image/pixels"),e("./io/files"),e("./io/p5.Table"),e("./io/p5.TableRow"),e("./io/p5.XML"),e("./math/calculation"),e("./math/math"),e("./math/noise"),e("./math/p5.Vector"),e("./math/random"),e("./math/trigonometry"),e("./typography/attributes"),e("./typography/loading_displaying"),e("./typography/p5.Font"),e("./utilities/array_functions"),e("./utilities/conversion"),e("./utilities/string_functions"),e("./utilities/time_date"),e("./webgl/3d_primitives"),e("./webgl/interaction"),e("./webgl/light"),e("./webgl/loading"),e("./webgl/material"),e("./webgl/p5.Camera"),e("./webgl/p5.DataArray"),e("./webgl/p5.Geometry"),e("./webgl/p5.Matrix"),e("./webgl/p5.Quat"),e("./webgl/p5.RendererGL.Immediate"),e("./webgl/p5.RendererGL"),e("./webgl/p5.RendererGL.Retained"),e("./webgl/p5.Framebuffer"),e("./webgl/p5.Shader"),e("./webgl/p5.RenderBuffer"),e("./webgl/p5.Texture"),e("./webgl/text"),e("./core/init"),t.exports=o.default},{"./accessibility/color_namer":262,"./accessibility/describe":263,"./accessibility/gridOutput":264,"./accessibility/outputs":265,"./accessibility/textOutput":266,"./color/color_conversion":268,"./color/creating_reading":269,"./color/p5.Color":270,"./color/setting":271,"./core/constants":272,"./core/environment":273,"./core/friendly_errors/fes_core":274,"./core/friendly_errors/file_errors":275,"./core/friendly_errors/sketch_reader":276,"./core/friendly_errors/stacktrace":277,"./core/friendly_errors/validate_params":278,"./core/helpers":279,"./core/init":280,"./core/legacy":282,"./core/main":283,"./core/p5.Element":284,"./core/p5.Graphics":285,"./core/p5.Renderer":286,"./core/p5.Renderer2D":287,"./core/preload":288,"./core/rendering":289,"./core/shape/2d_primitives":290,"./core/shape/attributes":291,"./core/shape/curves":292,"./core/shape/vertex":293,"./core/shim":294,"./core/structure":295,"./core/transform":296,"./data/local_storage.js":297,"./data/p5.TypedDict":298,"./dom/dom":299,"./events/acceleration":300,"./events/keyboard":301,"./events/mouse":302,"./events/touch":303,"./image/filters":304,"./image/image":305,"./image/loading_displaying":306,"./image/p5.Image":307,"./image/pixels":308,"./io/files":309,"./io/p5.Table":310,"./io/p5.TableRow":311,"./io/p5.XML":312,"./math/calculation":313,"./math/math":314,"./math/noise":315,"./math/p5.Vector":316,"./math/random":317,"./math/trigonometry":318,"./typography/attributes":319,"./typography/loading_displaying":320,"./typography/p5.Font":321,"./utilities/array_functions":322,"./utilities/conversion":323,"./utilities/string_functions":324,"./utilities/time_date":325,"./webgl/3d_primitives":326,"./webgl/interaction":328,"./webgl/light":329,"./webgl/loading":330,"./webgl/material":331,"./webgl/p5.Camera":332,"./webgl/p5.DataArray":333,"./webgl/p5.Framebuffer":334,"./webgl/p5.Geometry":335,"./webgl/p5.Matrix":336,"./webgl/p5.Quat":337,"./webgl/p5.RenderBuffer":338,"./webgl/p5.RendererGL":341,"./webgl/p5.RendererGL.Immediate":339,"./webgl/p5.RendererGL.Retained":340,"./webgl/p5.Shader":342,"./webgl/p5.Texture":343,"./webgl/text":344}],268:[function(e,t,r){"use strict";Object.defineProperty(r,"__esModule",{value:!0}),r.default=void 0;e=(e=e("../core/main"))&&e.__esModule?e:{default:e};e.default.ColorConversion={_hsbaToHSLA:function(e){var t=e[0],r=e[1],o=e[2],n=(2-r)*o/2;return 0!=n&&(1==n?r=0:n<.5?r/=2-r:r=r*o/(2-2*n)),[t,r,n,e[3]]},_hsbaToRGBA:function(e){var t,r,o,n,s,i=6*e[0],a=e[1],l=e[2];return 0===a?[l,l,l,e[3]]:(r=l*(1-a),o=l*(1-a*(i-(t=Math.floor(i)))),a=l*(1-a*(1+t-i)),i=1===t?(n=o,s=l,r):2===t?(n=r,s=l,a):3===t?(n=r,s=o,l):4===t?(n=a,s=r,l):5===t?(n=l,s=r,o):(n=l,s=a,r),[n,s,i,e[3]])},_hslaToHSBA:function(e){var t=e[0],r=e[1],o=e[2],n=o<.5?(1+r)*o:o+r-o*r;return[t,r=2*(n-o)/n,n,e[3]]},_hslaToRGBA:function(e){var t,r=6*e[0],o=e[1],n=e[2];return 0===o?[n,n,n,e[3]]:[(t=function(e,t,r){return e<0?e+=6:6<=e&&(e-=6),e<1?t+(r-t)*e:e<3?r:e<4?t+(r-t)*(4-e):t})(2+r,o=2*n-(n=n<.5?(1+o)*n:n+o-n*o),n),t(r,o,n),t(r-2,o,n),e[3]]},_rgbaToHSBA:function(e){var t,r,o=e[0],n=e[1],s=e[2],i=Math.max(o,n,s),a=i-Math.min(o,n,s);return 0==a?r=t=0:(r=a/i,o===i?t=(n-s)/a:n===i?t=2+(s-o)/a:s===i&&(t=4+(o-n)/a),t<0?t+=6:6<=t&&(t-=6)),[t/6,r,i,e[3]]},_rgbaToHSLA:function(e){var t,r,o=e[0],n=e[1],s=e[2],i=Math.max(o,n,s),a=Math.min(o,n,s),l=i+a,a=i-a;return 0==a?r=t=0:(r=l<1?a/l:a/(2-l),o===i?t=(n-s)/a:n===i?t=2+(s-o)/a:s===i&&(t=4+(o-n)/a),t<0?t+=6:6<=t&&(t-=6)),[t/6,r,l/2,e[3]]}};e=e.default.ColorConversion;r.default=e},{"../core/main":283}],269:[function(e,t,r){"use strict";function o(e){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function i(e){return(i="function"==typeof Symbol&&"symbol"===o(Symbol.iterator)?function(e){return o(e)}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":o(e)})(e)}e("core-js/modules/es.symbol"),e("core-js/modules/es.symbol.description"),e("core-js/modules/es.symbol.iterator"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.map"),e("core-js/modules/es.object.get-own-property-descriptor"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.string.iterator"),e("core-js/modules/es.weak-map"),e("core-js/modules/web.dom-collections.iterator"),e("core-js/modules/es.array.map"),Object.defineProperty(r,"__esModule",{value:!0}),r.default=void 0;var l=(n=e("../core/main"))&&n.__esModule?n:{default:n},u=function(e){if(e&&e.__esModule)return e;if(null===e||"object"!==i(e)&&"function"!=typeof e)return{default:e};var t=a();if(t&&t.has(e))return t.get(e);var r,o={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(r in e){var s;Object.prototype.hasOwnProperty.call(e,r)&&((s=n?Object.getOwnPropertyDescriptor(e,r):null)&&(s.get||s.set)?Object.defineProperty(o,r,s):o[r]=e[r])}o.default=e,t&&t.set(e,o);return o}(e("../core/constants"));function a(){var e;return"function"!=typeof WeakMap?null:(e=new WeakMap,a=function(){return e},e)}e("./p5.Color"),e("../core/friendly_errors/validate_params"),e("../core/friendly_errors/file_errors"),e("../core/friendly_errors/fes_core"),l.default.prototype.alpha=function(e){return l.default._validateParameters("alpha",arguments),this.color(e)._getAlpha()},l.default.prototype.blue=function(e){return l.default._validateParameters("blue",arguments),this.color(e)._getBlue()},l.default.prototype.brightness=function(e){return l.default._validateParameters("brightness",arguments),this.color(e)._getBrightness()},l.default.prototype.color=function(){for(var e,t=arguments.length,r=new Array(t),o=0;os[0]?s[0]+=1:n[0]+=1),1<=(o=this.lerp(n[0],s[0],r))&&--o),e=this.lerp(n[1],s[1],r),t=this.lerp(n[2],s[2],r),n=this.lerp(n[3],s[3],r),o*=a[i][0],e*=a[i][1],t*=a[i][2],n*=a[i][3],this.color(o,e,t,n)},l.default.prototype.lightness=function(e){return l.default._validateParameters("lightness",arguments),this.color(e)._getLightness()},l.default.prototype.red=function(e){return l.default._validateParameters("red",arguments),this.color(e)._getRed()},l.default.prototype.saturation=function(e){return l.default._validateParameters("saturation",arguments),this.color(e)._getSaturation()};var n=l.default;r.default=n},{"../core/constants":272,"../core/friendly_errors/fes_core":274,"../core/friendly_errors/file_errors":275,"../core/friendly_errors/validate_params":278,"../core/main":283,"./p5.Color":270,"core-js/modules/es.array.iterator":165,"core-js/modules/es.array.map":168,"core-js/modules/es.object.get-own-property-descriptor":186,"core-js/modules/es.object.to-string":190,"core-js/modules/es.string.iterator":200,"core-js/modules/es.symbol":212,"core-js/modules/es.symbol.description":210,"core-js/modules/es.symbol.iterator":211,"core-js/modules/es.weak-map":244,"core-js/modules/web.dom-collections.iterator":246}],270:[function(e,t,r){"use strict";function o(e){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function i(e){return(i="function"==typeof Symbol&&"symbol"===o(Symbol.iterator)?function(e){return o(e)}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":o(e)})(e)}e("core-js/modules/es.symbol"),e("core-js/modules/es.symbol.description"),e("core-js/modules/es.symbol.iterator"),e("core-js/modules/es.array.includes"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.join"),e("core-js/modules/es.array.map"),e("core-js/modules/es.array.slice"),e("core-js/modules/es.object.get-own-property-descriptor"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.regexp.constructor"),e("core-js/modules/es.regexp.exec"),e("core-js/modules/es.regexp.to-string"),e("core-js/modules/es.string.includes"),e("core-js/modules/es.string.iterator"),e("core-js/modules/es.string.trim"),e("core-js/modules/es.weak-map"),e("core-js/modules/web.dom-collections.iterator"),e("core-js/modules/es.array.includes"),e("core-js/modules/es.array.join"),e("core-js/modules/es.array.map"),e("core-js/modules/es.array.slice"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.regexp.constructor"),e("core-js/modules/es.regexp.exec"),e("core-js/modules/es.regexp.to-string"),e("core-js/modules/es.string.includes"),e("core-js/modules/es.string.trim"),Object.defineProperty(r,"__esModule",{value:!0}),r.default=void 0;var n=s(e("../core/main")),d=function(e){if(e&&e.__esModule)return e;if(null===e||"object"!==i(e)&&"function"!=typeof e)return{default:e};var t=a();if(t&&t.has(e))return t.get(e);var r,o={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(r in e){var s;Object.prototype.hasOwnProperty.call(e,r)&&((s=n?Object.getOwnPropertyDescriptor(e,r):null)&&(s.get||s.set)?Object.defineProperty(o,r,s):o[r]=e[r])}o.default=e,t&&t.set(e,o);return o}(e("../core/constants")),h=s(e("./color_conversion"));function a(){var e;return"function"!=typeof WeakMap?null:(e=new WeakMap,a=function(){return e},e)}function s(e){return e&&e.__esModule?e:{default:e}}function l(e,t){for(var r=0;r"].indexOf(r[0])?void 0:r[0],lineNumber:r[1],columnNumber:r[2],source:e}},this)},parseFFOrSafari:function(e){return e.stack.split("\n").filter(function(e){return!e.match(o)},this).map(function(e){var t,r;return-1===(e=-1 eval")?e.replace(/ line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g,":$1"):e).indexOf("@")&&-1===e.indexOf(":")?{functionName:e}:{functionName:(r=e.match(t=/((.*".+"[^@]*)?[^@]*)(?:@)/))&&r[1]?r[1]:void 0,fileName:(r=this.extractLocation(e.replace(t,"")))[0],lineNumber:r[1],columnNumber:r[2],source:e}},this)},parseOpera:function(e){return!e.stacktrace||-1e.stacktrace.split("\n").length?this.parseOpera9(e):e.stack?this.parseOpera11(e):this.parseOpera10(e)},parseOpera9:function(e){for(var t=/Line (\d+).*script (?:in )?(\S+)/i,r=e.message.split("\n"),o=[],n=2,s=r.length;n/,"$2").replace(/\([^)]*\)/g,"")||void 0,args:void 0===(t=r.match(/\(([^)]*)\)/)?r.replace(/^[^(]+\(([^)]*)\)$/,"$1"):t)||"[arguments not available]"===t?void 0:t.split(","),fileName:o[0],lineNumber:o[1],columnNumber:o[2],source:e}},this)}}}e.default._getErrorStackParser=function(){return new o};e=e.default;r.default=e},{"../main":283,"core-js/modules/es.array.filter":157,"core-js/modules/es.array.index-of":164,"core-js/modules/es.array.join":166,"core-js/modules/es.array.map":168,"core-js/modules/es.array.slice":169,"core-js/modules/es.regexp.exec":195,"core-js/modules/es.string.match":201,"core-js/modules/es.string.replace":204,"core-js/modules/es.string.split":206}],278:[function(e,t,r){"use strict";function o(e){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}e("core-js/modules/es.symbol"),e("core-js/modules/es.symbol.description"),e("core-js/modules/es.symbol.iterator"),e("core-js/modules/es.array.concat"),e("core-js/modules/es.array.for-each"),e("core-js/modules/es.array.includes"),e("core-js/modules/es.array.index-of"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.join"),e("core-js/modules/es.array.last-index-of"),e("core-js/modules/es.array.map"),e("core-js/modules/es.array.slice"),e("core-js/modules/es.function.name"),e("core-js/modules/es.map"),e("core-js/modules/es.number.constructor"),e("core-js/modules/es.object.get-own-property-descriptor"),e("core-js/modules/es.object.get-prototype-of"),e("core-js/modules/es.object.keys"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.reflect.construct"),e("core-js/modules/es.regexp.exec"),e("core-js/modules/es.regexp.to-string"),e("core-js/modules/es.set"),e("core-js/modules/es.string.includes"),e("core-js/modules/es.string.iterator"),e("core-js/modules/es.string.split"),e("core-js/modules/es.weak-map"),e("core-js/modules/web.dom-collections.for-each"),e("core-js/modules/web.dom-collections.iterator"),e("core-js/modules/es.symbol"),e("core-js/modules/es.symbol.description"),e("core-js/modules/es.symbol.iterator"),e("core-js/modules/es.array.concat"),e("core-js/modules/es.array.for-each"),e("core-js/modules/es.array.includes"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.join"),e("core-js/modules/es.array.last-index-of"),e("core-js/modules/es.array.map"),e("core-js/modules/es.array.slice"),e("core-js/modules/es.function.name"),e("core-js/modules/es.number.constructor"),e("core-js/modules/es.object.keys"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.regexp.exec"),e("core-js/modules/es.regexp.to-string"),e("core-js/modules/es.set"),e("core-js/modules/es.string.includes"),e("core-js/modules/es.string.iterator"),e("core-js/modules/es.string.split"),e("core-js/modules/web.dom-collections.for-each"),e("core-js/modules/web.dom-collections.iterator"),Object.defineProperty(r,"__esModule",{value:!0}),r.default=void 0;var n=(n=e("../main"))&&n.__esModule?n:{default:n};(function(e){if(e&&e.__esModule)return;if(null===e||"object"!==a(e)&&"function"!=typeof e)return;var t=i();if(t&&t.has(e))return t.get(e);var r,o={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(r in e){var s;Object.prototype.hasOwnProperty.call(e,r)&&((s=n?Object.getOwnPropertyDescriptor(e,r):null)&&(s.get||s.set)?Object.defineProperty(o,r,s):o[r]=e[r])}o.default=e,t&&t.set(e,o)})(e("../constants")),e("../internationalization");function i(){var e;return"function"!=typeof WeakMap?null:(e=new WeakMap,i=function(){return e},e)}function a(e){return(a="function"==typeof Symbol&&"symbol"===o(Symbol.iterator)?function(e){return o(e)}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":o(e)})(e)}n.default._validateParameters=n.default._clearValidateParamsCache=function(){};e=n.default;r.default=e},{"../../../docs/parameterData.json":void 0,"../constants":272,"../internationalization":281,"../main":283,"core-js/modules/es.array.concat":153,"core-js/modules/es.array.for-each":161,"core-js/modules/es.array.includes":163,"core-js/modules/es.array.index-of":164,"core-js/modules/es.array.iterator":165,"core-js/modules/es.array.join":166,"core-js/modules/es.array.last-index-of":167,"core-js/modules/es.array.map":168,"core-js/modules/es.array.slice":169,"core-js/modules/es.function.name":174,"core-js/modules/es.map":175,"core-js/modules/es.number.constructor":179,"core-js/modules/es.object.get-own-property-descriptor":186,"core-js/modules/es.object.get-prototype-of":188,"core-js/modules/es.object.keys":189,"core-js/modules/es.object.to-string":190,"core-js/modules/es.reflect.construct":192,"core-js/modules/es.regexp.exec":195,"core-js/modules/es.regexp.to-string":196,"core-js/modules/es.set":197,"core-js/modules/es.string.includes":199,"core-js/modules/es.string.iterator":200,"core-js/modules/es.string.split":206,"core-js/modules/es.symbol":212,"core-js/modules/es.symbol.description":210,"core-js/modules/es.symbol.iterator":211,"core-js/modules/es.weak-map":244,"core-js/modules/web.dom-collections.for-each":245,"core-js/modules/web.dom-collections.iterator":246}],279:[function(e,t,r){"use strict";function o(e){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function i(e){return(i="function"==typeof Symbol&&"symbol"===o(Symbol.iterator)?function(e){return o(e)}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":o(e)})(e)}e("core-js/modules/es.symbol"),e("core-js/modules/es.symbol.description"),e("core-js/modules/es.symbol.iterator"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.object.get-own-property-descriptor"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.string.iterator"),e("core-js/modules/es.weak-map"),e("core-js/modules/web.dom-collections.iterator"),Object.defineProperty(r,"__esModule",{value:!0}),r.default=void 0;var s=function(e){if(e&&e.__esModule)return e;if(null===e||"object"!==i(e)&&"function"!=typeof e)return{default:e};var t=a();if(t&&t.has(e))return t.get(e);var r,o={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(r in e){var s;Object.prototype.hasOwnProperty.call(e,r)&&((s=n?Object.getOwnPropertyDescriptor(e,r):null)&&(s.get||s.set)?Object.defineProperty(o,r,s):o[r]=e[r])}o.default=e,t&&t.set(e,o);return o}(e("./constants"));function a(){var e;return"function"!=typeof WeakMap?null:(e=new WeakMap,a=function(){return e},e)}r.default={modeAdjust:function(e,t,r,o,n){return n===s.CORNER?{x:e,y:t,w:r,h:o}:n===s.CORNERS?{x:e,y:t,w:r-e,h:o-t}:n===s.RADIUS?{x:e-r,y:t-o,w:2*r,h:2*o}:n===s.CENTER?{x:e-.5*r,y:t-.5*o,w:r,h:o}:void 0}}},{"./constants":272,"core-js/modules/es.array.iterator":165,"core-js/modules/es.object.get-own-property-descriptor":186,"core-js/modules/es.object.to-string":190,"core-js/modules/es.string.iterator":200,"core-js/modules/es.symbol":212,"core-js/modules/es.symbol.description":210,"core-js/modules/es.symbol.iterator":211,"core-js/modules/es.weak-map":244,"core-js/modules/web.dom-collections.iterator":246}],280:[function(e,t,r){"use strict";e("core-js/modules/es.array.iterator"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.promise"),e("core-js/modules/es.string.iterator"),e("core-js/modules/web.dom-collections.iterator"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.promise"),e("core-js/modules/es.string.iterator"),e("core-js/modules/web.dom-collections.iterator");var o=(n=e("../core/main"))&&n.__esModule?n:{default:n};e("./internationalization");var n=Promise.resolve();Promise.all([new Promise(function(e,t){"complete"===document.readyState?e():window.addEventListener("load",e,!1)}),n]).then(function(){void 0!==window._setupDone?console.warn("p5.js seems to have been imported multiple times. Please remove the duplicate import"):window.mocha||(window.setup&&"function"==typeof window.setup||window.draw&&"function"==typeof window.draw)&&!o.default.instance&&new o.default})},{"../core/main":283,"./internationalization":281,"core-js/modules/es.array.iterator":165,"core-js/modules/es.object.to-string":190,"core-js/modules/es.promise":191,"core-js/modules/es.string.iterator":200,"core-js/modules/web.dom-collections.iterator":246}],281:[function(e,t,r){"use strict";e("core-js/modules/es.array.includes"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.join"),e("core-js/modules/es.array.slice"),e("core-js/modules/es.object.keys"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.promise"),e("core-js/modules/es.regexp.exec"),e("core-js/modules/es.string.includes"),e("core-js/modules/es.string.iterator"),e("core-js/modules/es.string.split"),e("core-js/modules/web.dom-collections.iterator"),e("core-js/modules/es.array.includes"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.join"),e("core-js/modules/es.array.slice"),e("core-js/modules/es.object.keys"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.promise"),e("core-js/modules/es.regexp.exec"),e("core-js/modules/es.string.includes"),e("core-js/modules/es.string.iterator"),e("core-js/modules/es.string.split"),e("core-js/modules/web.dom-collections.iterator"),Object.defineProperty(r,"__esModule",{value:!0}),r.setTranslatorLanguage=r.currentTranslatorLanguage=r.availableTranslatorLanguages=r.initialize=r.translator=void 0;var n,s,o=a(e("i18next")),i=a(e("i18next-browser-languagedetector"));function a(e){return e&&e.__esModule?e:{default:e}}function l(e,t){for(var r=0;r=i.width||t>=i.height?[0,0,0,0]:this._getPixel(e,t);n=new a.default.Image(r*s,o*s);return n.pixelDensity(s),n.canvas.getContext("2d").drawImage(i,e,t,r*s,o*s,0,0,r*s,o*s),n}},{key:"textLeading",value:function(e){return"number"==typeof e?(this._setProperty("_leadingSet",!0),this._setProperty("_textLeading",e),this._pInst):this._textLeading}},{key:"textStyle",value:function(e){return e?(e!==A.NORMAL&&e!==A.ITALIC&&e!==A.BOLD&&e!==A.BOLDITALIC||this._setProperty("_textStyle",e),this._applyTextProperties()):this._textStyle}},{key:"textAscent",value:function(){return null===this._textAscent&&this._updateTextMetrics(),this._textAscent}},{key:"textDescent",value:function(){return null===this._textDescent&&this._updateTextMetrics(),this._textDescent}},{key:"textAlign",value:function(e,t){return void 0!==e?(this._setProperty("_textAlign",e),void 0!==t&&this._setProperty("_textBaseline",t),this._applyTextProperties()):{horizontal:this._textAlign,vertical:this._textBaseline}}},{key:"textWrap",value:function(e){return this._setProperty("_textWrap",e),this._textWrap}},{key:"text",value:function(e,t,r,o,n){var s,i,a,l,u=this._pInst,c=this._textWrap,d=Number.MAX_VALUE,h=r;if((this._doFill||this._doStroke)&&void 0!==e){if(s=(e=(e="string"!=typeof e?e.toString():e).replace(/(\t)/g," ")).split("\n"),void 0!==o){switch(this._rectMode===A.CENTER&&(t-=o/2),this._textAlign){case A.CENTER:t+=o/2;break;case A.RIGHT:t+=o}if(void 0!==n){this._rectMode===A.CENTER&&(r-=n/2,h-=n/2);var e=r,f=u.textAscent();switch(this._textBaseline){case A.BOTTOM:l=r+n,r=Math.max(l,r),h+=f;break;case A.CENTER:l=r+n/2,r=Math.max(l,r),h+=f/2}d=r+n-f,this._textBaseline===A.CENTER&&(d=e+n-f/2)}else this._textBaseline!==A.BOTTOM&&this._textBaseline!==A.CENTER||(h=r-(e=u.textSize()*this._textLeading)/2,d=r+e/2);if(c===A.WORD){for(var p=[],m=0;ma.HALF_PI&&e<=3*a.HALF_PI?Math.atan(r/o*Math.tan(e))+a.PI:Math.atan(r/o*Math.tan(e))+a.TWO_PI,t=t<=a.HALF_PI?Math.atan(r/o*Math.tan(t)):t>a.HALF_PI&&t<=3*a.HALF_PI?Math.atan(r/o*Math.tan(t))+a.PI:Math.atan(r/o*Math.tan(t))+a.TWO_PI),th||Math.abs(this.accelerationY-this.pAccelerationY)>h||Math.abs(this.accelerationZ-this.pAccelerationZ)>h)&&s.deviceMoved(),"function"==typeof s.deviceTurned&&(t=this._toDegrees(this.rotationX)+180,r=this._toDegrees(this.pRotationX)+180,e=i+180,0>>16,e[1+r]=(65280&t[o])>>>8,e[2+r]=255&t[o],e[3+r]=(4278190080&t[o])>>>24},_toImageData:function(e){return e instanceof ImageData?e:e.getContext("2d").getImageData(0,0,e.width,e.height)},_createImageData:function(e,t){return V._tmpCanvas=document.createElement("canvas"),V._tmpCtx=V._tmpCanvas.getContext("2d"),this._tmpCtx.createImageData(e,t)},apply:function(e,t,r){var o=e.getContext("2d"),n=o.getImageData(0,0,e.width,e.height),t=t(n,r);t instanceof ImageData?o.putImageData(t,0,0,0,0,e.width,e.height):o.putImageData(n,0,0,0,0,e.width,e.height)},threshold:function(e){for(var t=1>8)/o,r[n+1]=255*(i*t>>8)/o,r[n+2]=255*(a*t>>8)/o}},dilate:function(e){for(var t,r,o,n,s,i,a,l,u,c=V._toPixels(e),d=0,h=c.length?c.length/4:0,f=new Int32Array(h);d>16&255)+151*(n>>8&255)+28*(255&n))<(a=77*(u>>16&255)+151*(u>>8&255)+28*(255&u))&&(o=u,n=a),n<(a=77*((u=V._getARGB(c,l))>>16&255)+151*(u>>8&255)+28*(255&u))&&(o=u,n=a),n<(l=77*(s>>16&255)+151*(s>>8&255)+28*(255&s))&&(o=s,n=l),n<(u=77*(i>>16&255)+151*(i>>8&255)+28*(255&i))&&(o=i,n=u),f[d++]=o;V._setPixels(c,f)},erode:function(e){for(var t,r,o,n,s,i,a,l,u,c=V._toPixels(e),d=0,h=c.length?c.length/4:0,f=new Int32Array(h);d>16&255)+151*(u>>8&255)+28*(255&u))<(n=77*(n>>16&255)+151*(n>>8&255)+28*(255&n))&&(o=u,n=a),(a=77*((u=V._getARGB(c,l))>>16&255)+151*(u>>8&255)+28*(255&u))>16&255)+151*(s>>8&255)+28*(255&s))>16&255)+151*(i>>8&255)+28*(255&i))>>24],r+=j[(16711680&I)>>16],o+=j[(65280&I)>>8],n+=j[255&I],t+=B[b],i++}T[a=k+g]=s/t,E[a]=r/t,M[a]=o/t,F[a]=n/t}k+=h}for(u=(l=-U)*h,v=k=0;v"+p.length.toString()+" out of "+c.toString()),e.next=48,new Promise(function(e){return setTimeout(e,0)});e.next=50;break;case 48:e.next=39;break;case 50:i||m.html("Frames processed, generating color palette..."),this.loop(),this.pixelDensity(f),v=(0,A.GIFEncoder)(),b=function(e){for(var t=new Uint8Array(e.length*e[0].length),r=0;r"+S.toString()+" out of "+c.toString()),e.next=68,new Promise(function(e){return setTimeout(e,0)});case 68:S++,e.next=60;break;case 71:v.finish(),k=v.bytesView(),k=new Blob([k],{type:"image/gif"}),p=[],this._recording=!1,this.loop(),i||(m.html("Done. Downloading your gif!🌸"),0=t&&(t=Math.floor(r.timeDisplayed/t),r.timeDisplayed=0,r.lastChangeTime=e,r.displayIndex+=t,r.loopCount=Math.floor(r.displayIndex/r.numFrames),null!==r.loopLimit&&r.loopCount>=r.loopLimit?r.playing=!1:(e=r.displayIndex%r.numFrames,this.drawingContext.putImageData(r.frames[e].image,0,0),r.displayIndex=e,this.setModified(!0))))}},{key:"_setProperty",value:function(e,t){this[e]=t,this.setModified(!0)}},{key:"loadPixels",value:function(){i.default.Renderer2D.prototype.loadPixels.call(this),this.setModified(!0)}},{key:"updatePixels",value:function(e,t,r,o){i.default.Renderer2D.prototype.updatePixels.call(this,e,t,r,o),this.setModified(!0)}},{key:"get",value:function(e,t,r,o){return i.default._validateParameters("p5.Image.get",arguments),i.default.Renderer2D.prototype.get.apply(this,arguments)}},{key:"_getPixel",value:function(){for(var e=arguments.length,t=new Array(e),r=0;r/g,">").replace(/"/g,""").replace(/'/g,"'")}function i(e,t){t&&!0!==t&&"true"!==t||(t="");var r="";return(e=e||"untitled")&&e.includes(".")&&(r=e.split(".").pop()),t&&r!==t&&(r=t,e="".concat(e,".").concat(r)),[e,r]}e("../core/friendly_errors/validate_params"),e("../core/friendly_errors/file_errors"),e("../core/friendly_errors/fes_core"),v.default.prototype.loadJSON=function(){for(var e=arguments.length,t=new Array(e),r=0;r"),n.print("");if(n.print(' '),n.print(""),n.print(""),n.print(" "),"0"!==s[0]){n.print(" ");for(var c=0;c".concat(d)),n.print(" ")}n.print(" ")}for(var h=0;h");for(var f=0;f".concat(p)),n.print(" ")}n.print(" ")}n.print("
            "),n.print(""),n.print("")}n.close(),n.clear()},v.default.prototype.writeFile=function(e,t,r){var o="application/octet-stream",e=(v.default.prototype._isSafari()&&(o="text/plain"),new Blob(e,{type:o}));v.default.prototype.downloadFile(e,t,r)},v.default.prototype.downloadFile=function(e,t,r){var o,t=i(t,r),r=t[0];e instanceof Blob?n.default.saveAs(e,r):((o=document.createElement("a")).href=e,o.download=r,o.onclick=function(e){document.body.removeChild(e.target),e.stopPropagation()},o.style.display="none",document.body.appendChild(o),v.default.prototype._isSafari()&&(e=(e='Hello, Safari user! To download this file...\n1. Go to File --\x3e Save As.\n2. Choose "Page Source" as the Format.\n')+'3. Name it with this extension: ."'.concat(t[1],'"'),alert(e)),o.click())},v.default.prototype._checkFileExtension=i,v.default.prototype._isSafari=function(){return window.HTMLElement.toString().includes("Constructor")};e=v.default;r.default=e},{"../core/friendly_errors/fes_core":274,"../core/friendly_errors/file_errors":275,"../core/friendly_errors/validate_params":278,"../core/main":283,"core-js/modules/es.array.concat":153,"core-js/modules/es.array.includes":163,"core-js/modules/es.array.iterator":165,"core-js/modules/es.array.last-index-of":167,"core-js/modules/es.array.map":168,"core-js/modules/es.array.slice":169,"core-js/modules/es.array.splice":171,"core-js/modules/es.function.name":174,"core-js/modules/es.object.from-entries":185,"core-js/modules/es.object.to-string":190,"core-js/modules/es.promise":191,"core-js/modules/es.regexp.exec":195,"core-js/modules/es.regexp.to-string":196,"core-js/modules/es.string.includes":199,"core-js/modules/es.string.iterator":200,"core-js/modules/es.string.replace":204,"core-js/modules/es.string.split":206,"core-js/modules/es.symbol":212,"core-js/modules/es.symbol.description":210,"core-js/modules/es.symbol.iterator":211,"core-js/modules/es.typed-array.copy-within":213,"core-js/modules/es.typed-array.every":214,"core-js/modules/es.typed-array.fill":215,"core-js/modules/es.typed-array.filter":216,"core-js/modules/es.typed-array.find":218,"core-js/modules/es.typed-array.find-index":217,"core-js/modules/es.typed-array.for-each":221,"core-js/modules/es.typed-array.includes":222,"core-js/modules/es.typed-array.index-of":223,"core-js/modules/es.typed-array.iterator":226,"core-js/modules/es.typed-array.join":227,"core-js/modules/es.typed-array.last-index-of":228,"core-js/modules/es.typed-array.map":229,"core-js/modules/es.typed-array.reduce":231,"core-js/modules/es.typed-array.reduce-right":230,"core-js/modules/es.typed-array.reverse":232,"core-js/modules/es.typed-array.set":233,"core-js/modules/es.typed-array.slice":234,"core-js/modules/es.typed-array.some":235,"core-js/modules/es.typed-array.sort":236,"core-js/modules/es.typed-array.subarray":237,"core-js/modules/es.typed-array.to-locale-string":238,"core-js/modules/es.typed-array.to-string":239,"core-js/modules/es.typed-array.uint8-array":242,"core-js/modules/web.dom-collections.iterator":246,"core-js/modules/web.url":248,"es6-promise/auto":249,"fetch-jsonp":251,"file-saver":252,"whatwg-fetch":261}],310:[function(e,t,r){"use strict";e("core-js/modules/es.array.concat"),e("core-js/modules/es.array.index-of"),e("core-js/modules/es.array.join"),e("core-js/modules/es.array.splice"),e("core-js/modules/es.regexp.constructor"),e("core-js/modules/es.regexp.exec"),e("core-js/modules/es.regexp.to-string"),e("core-js/modules/es.string.match"),e("core-js/modules/es.string.replace"),e("core-js/modules/es.array.concat"),e("core-js/modules/es.array.index-of"),e("core-js/modules/es.array.join"),e("core-js/modules/es.array.splice"),e("core-js/modules/es.regexp.constructor"),e("core-js/modules/es.regexp.exec"),e("core-js/modules/es.regexp.to-string"),e("core-js/modules/es.string.match"),e("core-js/modules/es.string.replace"),Object.defineProperty(r,"__esModule",{value:!0}),r.default=void 0;var n=(e=e("../core/main"))&&e.__esModule?e:{default:e};function s(e,t){for(var r=0;r>>0},getSeed:function(){return t},rand:function(){return(r=(1664525*r+1013904223)%o)/o}};n.setSeed(e),j=new Array(4096);for(var s=0;s<4096;s++)j[s]=n.rand()},e.default);r.default=e},{"../core/main":283}],316:[function(e,t,r){"use strict";function o(e){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function i(e){return(i="function"==typeof Symbol&&"symbol"===o(Symbol.iterator)?function(e){return o(e)}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":o(e)})(e)}e("core-js/modules/es.symbol"),e("core-js/modules/es.symbol.description"),e("core-js/modules/es.symbol.iterator"),e("core-js/modules/es.array.concat"),e("core-js/modules/es.array.every"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.some"),e("core-js/modules/es.math.sign"),e("core-js/modules/es.number.constructor"),e("core-js/modules/es.number.epsilon"),e("core-js/modules/es.number.is-finite"),e("core-js/modules/es.object.get-own-property-descriptor"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.string.iterator"),e("core-js/modules/es.string.sub"),e("core-js/modules/es.weak-map"),e("core-js/modules/web.dom-collections.iterator"),e("core-js/modules/es.array.concat"),e("core-js/modules/es.array.every"),e("core-js/modules/es.array.some"),e("core-js/modules/es.math.sign"),e("core-js/modules/es.number.constructor"),e("core-js/modules/es.number.epsilon"),e("core-js/modules/es.number.is-finite"),e("core-js/modules/es.string.sub"),Object.defineProperty(r,"__esModule",{value:!0}),r.default=void 0;var u=(n=e("../core/main"))&&n.__esModule?n:{default:n},s=function(e){if(e&&e.__esModule)return e;if(null===e||"object"!==i(e)&&"function"!=typeof e)return{default:e};var t=a();if(t&&t.has(e))return t.get(e);var r,o={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(r in e){var s;Object.prototype.hasOwnProperty.call(e,r)&&((s=n?Object.getOwnPropertyDescriptor(e,r):null)&&(s.get||s.set)?Object.defineProperty(o,r,s):o[r]=e[r])}o.default=e,t&&t.set(e,o);return o}(e("../core/constants"));function a(){var e;return"function"!=typeof WeakMap?null:(e=new WeakMap,a=function(){return e},e)}function l(e,t){for(var r=0;r>>0},n.default.prototype.randomSeed=function(e){this._lcgSetSeed(s,e),this._gaussian_previous=!1},n.default.prototype.random=function(e,t){var r,o;return n.default._validateParameters("random",arguments),r=null!=this[s]?this._lcg(s):Math.random(),void 0===e?r:void 0===t?Array.isArray(e)?e[Math.floor(r*e.length)]:r*e:(tf&&(b=d,v=a,s=l,d=x+f*(i&&x=t?r.substring(r.length-t,r.length):r}},o.default.prototype.unhex=function(e){return e instanceof Array?e.map(o.default.prototype.unhex):parseInt("0x".concat(e),16)};e=o.default;r.default=e},{"../core/main":283,"core-js/modules/es.array.map":168,"core-js/modules/es.number.constructor":179,"core-js/modules/es.object.to-string":190,"core-js/modules/es.regexp.to-string":196,"core-js/modules/es.string.repeat":203}],324:[function(e,t,r){"use strict";e("core-js/modules/es.symbol"),e("core-js/modules/es.symbol.description"),e("core-js/modules/es.symbol.iterator"),e("core-js/modules/es.array.filter"),e("core-js/modules/es.array.index-of"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.join"),e("core-js/modules/es.array.map"),e("core-js/modules/es.array.slice"),e("core-js/modules/es.number.to-fixed"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.regexp.constructor"),e("core-js/modules/es.regexp.exec"),e("core-js/modules/es.regexp.to-string"),e("core-js/modules/es.string.iterator"),e("core-js/modules/es.string.match"),e("core-js/modules/es.string.pad-start"),e("core-js/modules/es.string.replace"),e("core-js/modules/es.string.split"),e("core-js/modules/es.string.trim"),e("core-js/modules/web.dom-collections.iterator"),e("core-js/modules/es.array.filter"),e("core-js/modules/es.array.index-of"),e("core-js/modules/es.array.join"),e("core-js/modules/es.array.map"),e("core-js/modules/es.array.slice"),e("core-js/modules/es.number.to-fixed"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.regexp.constructor"),e("core-js/modules/es.regexp.exec"),e("core-js/modules/es.regexp.to-string"),e("core-js/modules/es.string.match"),e("core-js/modules/es.string.pad-start"),e("core-js/modules/es.string.replace"),e("core-js/modules/es.string.split"),e("core-js/modules/es.string.trim"),Object.defineProperty(r,"__esModule",{value:!0}),r.default=void 0;var s=(u=e("../core/main"))&&u.__esModule?u:{default:u};function i(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e)){var r=[],o=!0,n=!1,s=void 0;try{for(var i,a=e[Symbol.iterator]();!(o=(i=a.next()).done)&&(r.push(i.value),!t||r.length!==t);o=!0);}catch(e){n=!0,s=e}finally{try{o||null==a.return||a.return()}finally{if(n)throw s}}return r}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function o(e,t,r){var o=i(e.toString().split("."),2),n=o[0],o=o[1];return void 0===r?(n=n.padStart(t,"0"),o?n+"."+o:n):(n=(e=i(e.toFixed(r).toString().split("."),2))[0],o=e[1],n=n.padStart(t,"0"),void 0===o?n:n+"."+o)}function n(e,t){var r=(e=e.toString()).indexOf("."),o=-1!==r?e.substring(r):"",e=(e=-1!==r?e.substring(0,r):e).toString().replace(/\B(?=(\d{3})+(?!\d))/g,",");if(0===t)o="";else if(void 0!==t)if(t>o.length)for(var n=t-(o+=-1===r?".":"").length+1,s=0;s=_.TWO_PI?"".concat(c="ellipse","|"):"".concat(c="arc","|").concat(s,"|").concat(i,"|").concat(a,"|")).concat(l,"|"),c=(this.geometryInHash(u)||((e=new S.default.Geometry(l,1,function(){if(s.toFixed(10)!==i.toFixed(10)){a!==_.PIE&&void 0!==a||(this.vertices.push(new S.default.Vector(.5,.5,0)),this.uvs.push([.5,.5]));for(var e=0;e<=l;e++){var t=(i-s)*(e/l)+s,r=.5+Math.cos(t)/2,t=.5+Math.sin(t)/2;this.vertices.push(new S.default.Vector(r,t,0)),this.uvs.push([r,t]),e>5&31)/31,(p>>10&31)/31):(r=i,o=a,l)),new x.default.Vector(y,g,v)),j=1;j<=3;j++){var _=m+12*j,_=new x.default.Vector(u.getFloat32(_,!0),u.getFloat32(4+_,!0),u.getFloat32(8+_,!0));e.vertices.push(_),e.vertexNormals.push(b),d&&s.push(r,o,n)}e.faces.push([3*f,3*f+1,3*f+2]),e.uvs.push([0,0],[0,0],[0,0])}}(e,t);else{t=new DataView(t);if(!("TextDecoder"in window))return console.warn("Sorry, ASCII STL loading only works in browsers that support TextDecoder (https://caniuse.com/#feat=textencoder)");t=new TextDecoder("utf-8").decode(t).split("\n");!function(e,t){for(var r,o,n="",s=[],i=0;ithis.cameraFar&&(i=this.cameraFar),Math.acos(Math.max(-1,Math.min(1,_.default.Vector.dot(o,n))))+t),t=e;(r<=0||r>=Math.PI)&&(this.upX*=-1,this.upY*=-1,this.upZ*=-1),n.mult(Math.cos(r)),a.mult(Math.cos(t)*Math.sin(r)),s.mult(Math.sin(t)*Math.sin(r)),o.set(n).add(a).add(s),this.eyeX=i*o.x+this.centerX,this.eyeY=i*o.y+this.centerY,this.eyeZ=i*o.z+this.centerZ,this.camera(this.eyeX,this.eyeY,this.eyeZ,this.centerX,this.centerY,this.centerZ,this.upX,this.upY,this.upZ)}},{key:"_orbitFree",value:function(e,t,r){var o=this.eyeX-this.centerX,n=this.eyeY-this.centerY,s=this.eyeZ-this.centerZ,i=Math.hypot(o,n,s),o=new _.default.Vector(o,n,s).normalize(),n=new _.default.Vector(this.upX,this.upY,this.upZ),s=_.default.Vector.cross(n,o).normalize(),a=_.default.Vector.cross(o,s),l=Math.atan2(t,e),l=(a.mult(Math.sin(l)),s.mult(Math.cos(l)).add(a),Math.sqrt(e*e+t*t)),a=_.default.Vector.cross(o,s),e=((i=(i*=Math.pow(10,r))this.cameraFar&&(i=this.cameraFar),Math.cos(l)),t=Math.sin(l),r=n.dot(o),l=n.dot(s),u=r*e+l*t,r=-r*t+l*e,l=n.dot(a);n.x=u*o.x+r*s.x+l*a.x,n.y=u*o.y+r*s.y+l*a.y,n.z=u*o.z+r*s.z+l*a.z,s.mult(-t),o.mult(e).add(s).mult(i),this.camera(o.x+this.centerX,o.y+this.centerY,o.z+this.centerZ,this.centerX,this.centerY,this.centerZ,n.x,n.y,n.z)}},{key:"_isActive",value:function(){return this===this._renderer._curCamera}}])&&n(e.prototype,r),o&&n(e,o),t}(),_.default.prototype.setCamera=function(e){this._renderer._curCamera=e,this._renderer.uPMatrix.set(e.projMatrix),this._renderer.uViewMatrix.set(e.cameraMatrix)};e=_.default.Camera;r.default=e},{"../core/main":283,"core-js/modules/es.array.slice":169,"core-js/modules/es.math.hypot":176,"core-js/modules/es.string.sub":208}],333:[function(e,t,r){"use strict";e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.slice"),e("core-js/modules/es.math.log2"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.typed-array.float32-array"),e("core-js/modules/es.typed-array.copy-within"),e("core-js/modules/es.typed-array.every"),e("core-js/modules/es.typed-array.fill"),e("core-js/modules/es.typed-array.filter"),e("core-js/modules/es.typed-array.find"),e("core-js/modules/es.typed-array.find-index"),e("core-js/modules/es.typed-array.for-each"),e("core-js/modules/es.typed-array.includes"),e("core-js/modules/es.typed-array.index-of"),e("core-js/modules/es.typed-array.iterator"),e("core-js/modules/es.typed-array.join"),e("core-js/modules/es.typed-array.last-index-of"),e("core-js/modules/es.typed-array.map"),e("core-js/modules/es.typed-array.reduce"),e("core-js/modules/es.typed-array.reduce-right"),e("core-js/modules/es.typed-array.reverse"),e("core-js/modules/es.typed-array.set"),e("core-js/modules/es.typed-array.slice"),e("core-js/modules/es.typed-array.some"),e("core-js/modules/es.typed-array.sort"),e("core-js/modules/es.typed-array.subarray"),e("core-js/modules/es.typed-array.to-locale-string"),e("core-js/modules/es.typed-array.to-string"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.slice"),e("core-js/modules/es.math.log2"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.typed-array.float32-array"),e("core-js/modules/es.typed-array.copy-within"),e("core-js/modules/es.typed-array.every"),e("core-js/modules/es.typed-array.fill"),e("core-js/modules/es.typed-array.filter"),e("core-js/modules/es.typed-array.find"),e("core-js/modules/es.typed-array.find-index"),e("core-js/modules/es.typed-array.for-each"),e("core-js/modules/es.typed-array.includes"),e("core-js/modules/es.typed-array.index-of"),e("core-js/modules/es.typed-array.iterator"),e("core-js/modules/es.typed-array.join"),e("core-js/modules/es.typed-array.last-index-of"),e("core-js/modules/es.typed-array.map"),e("core-js/modules/es.typed-array.reduce"),e("core-js/modules/es.typed-array.reduce-right"),e("core-js/modules/es.typed-array.reverse"),e("core-js/modules/es.typed-array.set"),e("core-js/modules/es.typed-array.slice"),e("core-js/modules/es.typed-array.some"),e("core-js/modules/es.typed-array.sort"),e("core-js/modules/es.typed-array.subarray"),e("core-js/modules/es.typed-array.to-locale-string"),e("core-js/modules/es.typed-array.to-string"),Object.defineProperty(r,"__esModule",{value:!0}),r.default=void 0;e=(e=e("../core/main"))&&e.__esModule?e:{default:e};function n(e,t){for(var r=0;r=this.width||t>=this.height)&&(console.warn("The x and y values passed to p5.Framebuffer.get are outside of its range and will be clamped."),e=this.target.constrain(e,0,this.width-1),t=this.target.constrain(t,0,this.height-1)),(0,p.readPixelWebGL)(this.gl,this.framebuffer,e*this.density,t*this.density,n.format,n.type);e=this.target.constrain(e,0,this.width-1),t=this.target.constrain(t,0,this.height-1),r=this.target.constrain(r,1,this.width-e),o=this.target.constrain(o,1,this.height-t);for(var s=(0,p.readPixelsWebGL)(void 0,this.gl,this.framebuffer,e*this.density,t*this.density,r*this.density,o*this.density,n.format,n.type),i=new Uint8ClampedArray(r*o*this.density*this.density*4),a=(i.fill(255),n.type===this.gl.RGB?3:4),l=0;lthis.vertices.length-1-this.detailX;o--)e.add(this.vertexNormals[o]);e=F.default.Vector.div(e,this.detailX);for(var n=this.vertices.length-1;n>this.vertices.length-1-this.detailX;n--)this.vertexNormals[n]=e;return this}},{key:"_makeTriangleEdges",value:function(){for(var e=this.edges.length=0;e 65535 triangles. Your web browser does not support the WebGL Extension OES_element_index_uint.");r.drawElements(r.TRIANGLES,t.vertexCount,t.indexBufferType,0)}else r.drawArrays(e||r.TRIANGLES,0,t.vertexCount)},a.default.RendererGL.prototype._drawPoints=function(e,t){var r=this.GL,o=this._getImmediatePointShader();this._setPointUniforms(o),this._bindBuffer(t,r.ARRAY_BUFFER,this._vToNArray(e),Float32Array,r.STATIC_DRAW),o.enableAttrib(o.attributes.aPosition,3),this._applyColorBlend(this.curStrokeColor),r.drawArrays(r.Points,0,e.length),o.unbindShader()};var s=a.default.RendererGL;r.default=s},{"../core/constants":272,"../core/main":283,"./p5.RenderBuffer":338,"./p5.RendererGL":341,"core-js/modules/es.array.fill":156,"core-js/modules/es.array.iterator":165,"core-js/modules/es.array.some":170,"core-js/modules/es.object.get-own-property-descriptor":186,"core-js/modules/es.object.keys":189,"core-js/modules/es.object.to-string":190,"core-js/modules/es.string.iterator":200,"core-js/modules/es.symbol":212,"core-js/modules/es.symbol.description":210,"core-js/modules/es.symbol.iterator":211,"core-js/modules/es.typed-array.copy-within":213,"core-js/modules/es.typed-array.every":214,"core-js/modules/es.typed-array.fill":215,"core-js/modules/es.typed-array.filter":216,"core-js/modules/es.typed-array.find":218,"core-js/modules/es.typed-array.find-index":217,"core-js/modules/es.typed-array.float32-array":219,"core-js/modules/es.typed-array.for-each":221,"core-js/modules/es.typed-array.includes":222,"core-js/modules/es.typed-array.index-of":223,"core-js/modules/es.typed-array.iterator":226,"core-js/modules/es.typed-array.join":227,"core-js/modules/es.typed-array.last-index-of":228,"core-js/modules/es.typed-array.map":229,"core-js/modules/es.typed-array.reduce":231,"core-js/modules/es.typed-array.reduce-right":230,"core-js/modules/es.typed-array.reverse":232,"core-js/modules/es.typed-array.set":233,"core-js/modules/es.typed-array.slice":234,"core-js/modules/es.typed-array.some":235,"core-js/modules/es.typed-array.sort":236,"core-js/modules/es.typed-array.subarray":237,"core-js/modules/es.typed-array.to-locale-string":238,"core-js/modules/es.typed-array.to-string":239,"core-js/modules/es.typed-array.uint16-array":240,"core-js/modules/es.typed-array.uint32-array":241,"core-js/modules/es.weak-map":244,"core-js/modules/web.dom-collections.iterator":246}],341:[function(e,t,r){"use strict";function o(e){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function i(e){return(i="function"==typeof Symbol&&"symbol"===o(Symbol.iterator)?function(e){return o(e)}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":o(e)})(e)}e("core-js/modules/es.symbol"),e("core-js/modules/es.symbol.description"),e("core-js/modules/es.symbol.iterator"),e("core-js/modules/es.array.concat"),e("core-js/modules/es.array.copy-within"),e("core-js/modules/es.array.every"),e("core-js/modules/es.array.fill"),e("core-js/modules/es.array.flat"),e("core-js/modules/es.array.flat-map"),e("core-js/modules/es.array.from"),e("core-js/modules/es.array.includes"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.map"),e("core-js/modules/es.array.slice"),e("core-js/modules/es.array.some"),e("core-js/modules/es.array.unscopables.flat"),e("core-js/modules/es.array.unscopables.flat-map"),e("core-js/modules/es.map"),e("core-js/modules/es.object.assign"),e("core-js/modules/es.object.get-own-property-descriptor"),e("core-js/modules/es.object.get-prototype-of"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.reflect.construct"),e("core-js/modules/es.reflect.get"),e("core-js/modules/es.regexp.to-string"),e("core-js/modules/es.set"),e("core-js/modules/es.string.includes"),e("core-js/modules/es.string.iterator"),e("core-js/modules/es.typed-array.float32-array"),e("core-js/modules/es.typed-array.float64-array"),e("core-js/modules/es.typed-array.int16-array"),e("core-js/modules/es.typed-array.uint8-array"),e("core-js/modules/es.typed-array.uint16-array"),e("core-js/modules/es.typed-array.uint32-array"),e("core-js/modules/es.typed-array.copy-within"),e("core-js/modules/es.typed-array.every"),e("core-js/modules/es.typed-array.fill"),e("core-js/modules/es.typed-array.filter"),e("core-js/modules/es.typed-array.find"),e("core-js/modules/es.typed-array.find-index"),e("core-js/modules/es.typed-array.for-each"),e("core-js/modules/es.typed-array.includes"),e("core-js/modules/es.typed-array.index-of"),e("core-js/modules/es.typed-array.iterator"),e("core-js/modules/es.typed-array.join"),e("core-js/modules/es.typed-array.last-index-of"),e("core-js/modules/es.typed-array.map"),e("core-js/modules/es.typed-array.reduce"),e("core-js/modules/es.typed-array.reduce-right"),e("core-js/modules/es.typed-array.reverse"),e("core-js/modules/es.typed-array.set"),e("core-js/modules/es.typed-array.slice"),e("core-js/modules/es.typed-array.some"),e("core-js/modules/es.typed-array.sort"),e("core-js/modules/es.typed-array.subarray"),e("core-js/modules/es.typed-array.to-locale-string"),e("core-js/modules/es.typed-array.to-string"),e("core-js/modules/es.weak-map"),e("core-js/modules/web.dom-collections.iterator"),e("core-js/modules/es.symbol"),e("core-js/modules/es.symbol.description"),e("core-js/modules/es.symbol.iterator"),e("core-js/modules/es.array.concat"),e("core-js/modules/es.array.copy-within"),e("core-js/modules/es.array.every"),e("core-js/modules/es.array.fill"),e("core-js/modules/es.array.flat"),e("core-js/modules/es.array.flat-map"),e("core-js/modules/es.array.from"),e("core-js/modules/es.array.includes"),e("core-js/modules/es.array.iterator"),e("core-js/modules/es.array.map"),e("core-js/modules/es.array.slice"),e("core-js/modules/es.array.some"),e("core-js/modules/es.array.unscopables.flat"),e("core-js/modules/es.array.unscopables.flat-map"),e("core-js/modules/es.map"),e("core-js/modules/es.object.assign"),e("core-js/modules/es.object.to-string"),e("core-js/modules/es.set"),e("core-js/modules/es.string.includes"),e("core-js/modules/es.string.iterator"),e("core-js/modules/es.typed-array.float32-array"),e("core-js/modules/es.typed-array.float64-array"),e("core-js/modules/es.typed-array.int16-array"),e("core-js/modules/es.typed-array.uint8-array"),e("core-js/modules/es.typed-array.uint16-array"),e("core-js/modules/es.typed-array.uint32-array"),e("core-js/modules/es.typed-array.copy-within"),e("core-js/modules/es.typed-array.every"),e("core-js/modules/es.typed-array.fill"),e("core-js/modules/es.typed-array.filter"),e("core-js/modules/es.typed-array.find"),e("core-js/modules/es.typed-array.find-index"),e("core-js/modules/es.typed-array.for-each"),e("core-js/modules/es.typed-array.includes"),e("core-js/modules/es.typed-array.index-of"),e("core-js/modules/es.typed-array.iterator"),e("core-js/modules/es.typed-array.join"),e("core-js/modules/es.typed-array.last-index-of"),e("core-js/modules/es.typed-array.map"),e("core-js/modules/es.typed-array.reduce"),e("core-js/modules/es.typed-array.reduce-right"),e("core-js/modules/es.typed-array.reverse"),e("core-js/modules/es.typed-array.set"),e("core-js/modules/es.typed-array.slice"),e("core-js/modules/es.typed-array.some"),e("core-js/modules/es.typed-array.sort"),e("core-js/modules/es.typed-array.subarray"),e("core-js/modules/es.typed-array.to-locale-string"),e("core-js/modules/es.typed-array.to-string"),e("core-js/modules/web.dom-collections.iterator"),Object.defineProperty(r,"__esModule",{value:!0}),r.readPixelsWebGL=O,r.readPixelWebGL=C,r.default=void 0;var g=n(e("../core/main")),l=function(e){if(e&&e.__esModule)return e;if(null===e||"object"!==i(e)&&"function"!=typeof e)return{default:e};var t=d();if(t&&t.has(e))return t.get(e);var r,o={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(r in e){var s;Object.prototype.hasOwnProperty.call(e,r)&&((s=n?Object.getOwnPropertyDescriptor(e,r):null)&&(s.get||s.set)?Object.defineProperty(o,r,s):o[r]=e[r])}o.default=e,t&&t.set(e,o);return o}(e("../core/constants")),a=n(e("./GeometryBuilder")),u=n(e("libtess")),c=(e("./p5.Shader"),e("./p5.Camera"),e("../core/p5.Renderer"),e("./p5.Matrix"),e("./p5.Framebuffer"),e("path"),e("./p5.Texture"));function d(){var e;return"function"!=typeof WeakMap?null:(e=new WeakMap,d=function(){return e},e)}function n(e){return e&&e.__esModule?e:{default:e}}function h(e){return function(e){if(Array.isArray(e)){for(var t=0,r=new Array(e.length);t vTexCoord.y;\n bool y1 = p1.y > vTexCoord.y;\n bool y2 = p2.y > vTexCoord.y;\n\n // could web be under the curve (after t1)?\n if (y1 ? !y2 : y0) {\n // add the coverage for t1\n coverage.x += saturate(C1.x + 0.5);\n // calculate the anti-aliasing for t1\n weight.x = min(weight.x, abs(C1.x));\n }\n\n // are we outside the curve (after t2)?\n if (y1 ? !y0 : y2) {\n // subtract the coverage for t2\n coverage.x -= saturate(C2.x + 0.5);\n // calculate the anti-aliasing for t2\n weight.x = min(weight.x, abs(C2.x));\n }\n}\n\n// this is essentially the same as coverageX, but with the axes swapped\nvoid coverageY(vec2 p0, vec2 p1, vec2 p2) {\n\n vec2 C1, C2;\n calulateCrossings(p0, p1, p2, C1, C2);\n\n bool x0 = p0.x > vTexCoord.x;\n bool x1 = p1.x > vTexCoord.x;\n bool x2 = p2.x > vTexCoord.x;\n\n if (x1 ? !x2 : x0) {\n coverage.y -= saturate(C1.y + 0.5);\n weight.y = min(weight.y, abs(C1.y));\n }\n\n if (x1 ? !x0 : x2) {\n coverage.y += saturate(C2.y + 0.5);\n weight.y = min(weight.y, abs(C2.y));\n }\n}\n\nvoid main() {\n\n // calculate the pixel scale based on screen-coordinates\n pixelScale = hardness / fwidth(vTexCoord);\n\n // which grid cell is this pixel in?\n ivec2 gridCoord = ifloor(vTexCoord * vec2(uGridSize));\n\n // intersect curves in this row\n {\n // the index into the row info bitmap\n int rowIndex = gridCoord.y + uGridOffset.y;\n // fetch the info texel\n vec4 rowInfo = getTexel(uSamplerRows, rowIndex, uGridImageSize);\n // unpack the rowInfo\n int rowStrokeIndex = getInt16(rowInfo.xy);\n int rowStrokeCount = getInt16(rowInfo.zw);\n\n for (int iRowStroke = INT(0); iRowStroke < N; iRowStroke++) {\n if (iRowStroke >= rowStrokeCount)\n break;\n\n // each stroke is made up of 3 points: the start and control point\n // and the start of the next curve.\n // fetch the indices of this pair of strokes:\n vec4 strokeIndices = getTexel(uSamplerRowStrokes, rowStrokeIndex++, uCellsImageSize);\n\n // unpack the stroke index\n int strokePos = getInt16(strokeIndices.xy);\n\n // fetch the two strokes\n vec4 stroke0 = getTexel(uSamplerStrokes, strokePos + INT(0), uStrokeImageSize);\n vec4 stroke1 = getTexel(uSamplerStrokes, strokePos + INT(1), uStrokeImageSize);\n\n // calculate the coverage\n coverageX(stroke0.xy, stroke0.zw, stroke1.xy);\n }\n }\n\n // intersect curves in this column\n {\n int colIndex = gridCoord.x + uGridOffset.x;\n vec4 colInfo = getTexel(uSamplerCols, colIndex, uGridImageSize);\n int colStrokeIndex = getInt16(colInfo.xy);\n int colStrokeCount = getInt16(colInfo.zw);\n \n for (int iColStroke = INT(0); iColStroke < N; iColStroke++) {\n if (iColStroke >= colStrokeCount)\n break;\n\n vec4 strokeIndices = getTexel(uSamplerColStrokes, colStrokeIndex++, uCellsImageSize);\n\n int strokePos = getInt16(strokeIndices.xy);\n vec4 stroke0 = getTexel(uSamplerStrokes, strokePos + INT(0), uStrokeImageSize);\n vec4 stroke1 = getTexel(uSamplerStrokes, strokePos + INT(1), uStrokeImageSize);\n coverageY(stroke0.xy, stroke0.zw, stroke1.xy);\n }\n }\n\n weight = saturate(1.0 - weight * 2.0);\n float distance = max(weight.x + weight.y, minDistance); // manhattan approx.\n float antialias = abs(dot(coverage, weight) / distance);\n float cover = min(abs(coverage.x), abs(coverage.y));\n OUT_COLOR = vec4(uMaterialColor.rgb, 1.) * uMaterialColor.a;\n OUT_COLOR *= saturate(max(antialias, cover));\n}\n",lineVert:T+"/*\n Part of the Processing project - http://processing.org\n Copyright (c) 2012-15 The Processing Foundation\n Copyright (c) 2004-12 Ben Fry and Casey Reas\n Copyright (c) 2001-04 Massachusetts Institute of Technology\n This library is free software; you can redistribute it and/or\n modify it under the terms of the GNU Lesser General Public\n License as published by the Free Software Foundation, version 2.1.\n This library is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n Lesser General Public License for more details.\n You should have received a copy of the GNU Lesser General\n Public License along with this library; if not, write to the\n Free Software Foundation, Inc., 59 Temple Place, Suite 330,\n Boston, MA 02111-1307 USA\n*/\n\n#define PROCESSING_LINE_SHADER\n\nprecision mediump int;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform float uStrokeWeight;\n\nuniform bool uUseLineColor;\nuniform vec4 uMaterialColor;\n\nuniform vec4 uViewport;\nuniform int uPerspective;\nuniform int uStrokeJoin;\n\nIN vec4 aPosition;\nIN vec3 aTangentIn;\nIN vec3 aTangentOut;\nIN float aSide;\nIN vec4 aVertexColor;\n\nOUT vec4 vColor;\nOUT vec2 vTangent;\nOUT vec2 vCenter;\nOUT vec2 vPosition;\nOUT float vMaxDist;\nOUT float vCap;\nOUT float vJoin;\n\nvec2 lineIntersection(vec2 aPoint, vec2 aDir, vec2 bPoint, vec2 bDir) {\n // Rotate and translate so a starts at the origin and goes out to the right\n bPoint -= aPoint;\n vec2 rotatedBFrom = vec2(\n bPoint.x*aDir.x + bPoint.y*aDir.y,\n bPoint.y*aDir.x - bPoint.x*aDir.y\n );\n vec2 bTo = bPoint + bDir;\n vec2 rotatedBTo = vec2(\n bTo.x*aDir.x + bTo.y*aDir.y,\n bTo.y*aDir.x - bTo.x*aDir.y\n );\n float intersectionDistance =\n rotatedBTo.x + (rotatedBFrom.x - rotatedBTo.x) * rotatedBTo.y /\n (rotatedBTo.y - rotatedBFrom.y);\n return aPoint + aDir * intersectionDistance;\n}\n\nvoid main() {\n // Caps have one of either the in or out tangent set to 0\n vCap = (aTangentIn == vec3(0.)) != (aTangentOut == (vec3(0.)))\n ? 1. : 0.;\n\n // Joins have two unique, defined tangents\n vJoin = (\n aTangentIn != vec3(0.) &&\n aTangentOut != vec3(0.) &&\n aTangentIn != aTangentOut\n ) ? 1. : 0.;\n\n vec4 posp = uModelViewMatrix * aPosition;\n vec4 posqIn = uModelViewMatrix * (aPosition + vec4(aTangentIn, 0));\n vec4 posqOut = uModelViewMatrix * (aPosition + vec4(aTangentOut, 0));\n\n float facingCamera = pow(\n // The word space tangent's z value is 0 if it's facing the camera\n abs(normalize(posqIn-posp).z),\n\n // Using pow() here to ramp `facingCamera` up from 0 to 1 really quickly\n // so most lines get scaled and don't get clipped\n 0.25\n );\n\n // Moving vertices slightly toward the camera\n // to avoid depth-fighting with the fill triangles.\n // This prevents popping effects due to half of\n // the line disappearing behind the geometry faces.\n \n float zOffset = mix(-0.00045, -1., facingCamera);\n posp.z -= zOffset;\n posqIn.z -= zOffset;\n posqOut.z -= zOffset;\n \n vec4 p = uProjectionMatrix * posp;\n vec4 qIn = uProjectionMatrix * posqIn;\n vec4 qOut = uProjectionMatrix * posqOut;\n vCenter = p.xy;\n\n // formula to convert from clip space (range -1..1) to screen space (range 0..[width or height])\n // screen_p = (p.xy/p.w + <1,1>) * 0.5 * uViewport.zw\n\n // prevent division by W by transforming the tangent formula (div by 0 causes\n // the line to disappear, see https://github.com/processing/processing/issues/5183)\n // t = screen_q - screen_p\n //\n // tangent is normalized and we don't care which aDirection it points to (+-)\n // t = +- normalize( screen_q - screen_p )\n // t = +- normalize( (q.xy/q.w+<1,1>)*0.5*uViewport.zw - (p.xy/p.w+<1,1>)*0.5*uViewport.zw )\n //\n // extract common factor, <1,1> - <1,1> cancels out\n // t = +- normalize( (q.xy/q.w - p.xy/p.w) * 0.5 * uViewport.zw )\n //\n // convert to common divisor\n // t = +- normalize( ((q.xy*p.w - p.xy*q.w) / (p.w*q.w)) * 0.5 * uViewport.zw )\n //\n // remove the common scalar divisor/factor, not needed due to normalize and +-\n // (keep uViewport - can't remove because it has different components for x and y\n // and corrects for aspect ratio, see https://github.com/processing/processing/issues/5181)\n // t = +- normalize( (q.xy*p.w - p.xy*q.w) * uViewport.zw )\n\n vec2 tangentIn = normalize((qIn.xy*p.w - p.xy*qIn.w) * uViewport.zw);\n vec2 tangentOut = normalize((qOut.xy*p.w - p.xy*qOut.w) * uViewport.zw);\n\n vec2 curPerspScale;\n if(uPerspective == 1) {\n // Perspective ---\n // convert from world to clip by multiplying with projection scaling factor\n // to get the right thickness (see https://github.com/processing/processing/issues/5182)\n\n // The y value of the projection matrix may be flipped if rendering to a Framebuffer.\n // Multiplying again by its sign here negates the flip to get just the scale.\n curPerspScale = (uProjectionMatrix * vec4(1, sign(uProjectionMatrix[1][1]), 0, 0)).xy;\n } else {\n // No Perspective ---\n // multiply by W (to cancel out division by W later in the pipeline) and\n // convert from screen to clip (derived from clip to screen above)\n curPerspScale = p.w / (0.5 * uViewport.zw);\n }\n\n vec2 offset;\n if (vJoin == 1.) {\n vTangent = normalize(tangentIn + tangentOut);\n vec2 normalIn = vec2(-tangentIn.y, tangentIn.x);\n vec2 normalOut = vec2(-tangentOut.y, tangentOut.x);\n float side = sign(aSide);\n float sideEnum = abs(aSide);\n\n // We generate vertices for joins on either side of the centerline, but\n // the \"elbow\" side is the only one needing a join. By not setting the\n // offset for the other side, all its vertices will end up in the same\n // spot and not render, effectively discarding it.\n if (sign(dot(tangentOut, vec2(-tangentIn.y, tangentIn.x))) != side) {\n // Side enums:\n // 1: the side going into the join\n // 2: the middle of the join\n // 3: the side going out of the join\n if (sideEnum == 2.) {\n // Calculate the position + tangent on either side of the join, and\n // find where the lines intersect to find the elbow of the join\n vec2 c = (posp.xy/posp.w + vec2(1.,1.)) * 0.5 * uViewport.zw;\n vec2 intersection = lineIntersection(\n c + (side * normalIn * uStrokeWeight / 2.),\n tangentIn,\n c + (side * normalOut * uStrokeWeight / 2.),\n tangentOut\n );\n offset = (intersection - c);\n\n // When lines are thick and the angle of the join approaches 180, the\n // elbow might be really far from the center. We'll apply a limit to\n // the magnitude to avoid lines going across the whole screen when this\n // happens.\n float mag = length(offset);\n float maxMag = 3. * uStrokeWeight;\n if (mag > maxMag) {\n offset *= maxMag / mag;\n }\n } else if (sideEnum == 1.) {\n offset = side * normalIn * uStrokeWeight / 2.;\n } else if (sideEnum == 3.) {\n offset = side * normalOut * uStrokeWeight / 2.;\n }\n }\n if (uStrokeJoin == STROKE_JOIN_BEVEL) {\n vec2 avgNormal = vec2(-vTangent.y, vTangent.x);\n vMaxDist = abs(dot(avgNormal, normalIn * uStrokeWeight / 2.));\n } else {\n vMaxDist = uStrokeWeight / 2.;\n }\n } else {\n vec2 tangent = aTangentIn == vec3(0.) ? tangentOut : tangentIn;\n vTangent = tangent;\n vec2 normal = vec2(-tangent.y, tangent.x);\n\n float normalOffset = sign(aSide);\n // Caps will have side values of -2 or 2 on the edge of the cap that\n // extends out from the line\n float tangentOffset = abs(aSide) - 1.;\n offset = (normal * normalOffset + tangent * tangentOffset) *\n uStrokeWeight * 0.5;\n vMaxDist = uStrokeWeight / 2.;\n }\n vPosition = vCenter + offset;\n\n gl_Position.xy = p.xy + offset.xy * curPerspScale;\n gl_Position.zw = p.zw;\n \n vColor = (uUseLineColor ? aVertexColor : uMaterialColor);\n}\n",lineFrag:T+"precision mediump int;\n\nuniform vec4 uMaterialColor;\nuniform int uStrokeCap;\nuniform int uStrokeJoin;\nuniform float uStrokeWeight;\n\nIN vec4 vColor;\nIN vec2 vTangent;\nIN vec2 vCenter;\nIN vec2 vPosition;\nIN float vMaxDist;\nIN float vCap;\nIN float vJoin;\n\nfloat distSquared(vec2 a, vec2 b) {\n vec2 aToB = b - a;\n return dot(aToB, aToB);\n}\n\nvoid main() {\n if (vCap > 0.) {\n if (\n uStrokeCap == STROKE_CAP_ROUND &&\n distSquared(vPosition, vCenter) > uStrokeWeight * uStrokeWeight * 0.25\n ) {\n discard;\n } else if (\n uStrokeCap == STROKE_CAP_SQUARE &&\n dot(vPosition - vCenter, vTangent) > 0.\n ) {\n discard;\n }\n // Use full area for PROJECT\n } else if (vJoin > 0.) {\n if (\n uStrokeJoin == STROKE_JOIN_ROUND &&\n distSquared(vPosition, vCenter) > uStrokeWeight * uStrokeWeight * 0.25\n ) {\n discard;\n } else if (uStrokeJoin == STROKE_JOIN_BEVEL) {\n vec2 normal = vec2(-vTangent.y, vTangent.x);\n if (abs(dot(vPosition - vCenter, normal)) > vMaxDist) {\n discard;\n }\n }\n // Use full area for MITER\n }\n OUT_COLOR = vec4(vColor.rgb, 1.) * vColor.a;\n}\n",pointVert:"IN vec3 aPosition;\nuniform float uPointSize;\nOUT float vStrokeWeight;\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nvoid main() {\n\tvec4 positionVec4 = vec4(aPosition, 1.0);\n\tgl_Position = uProjectionMatrix * uModelViewMatrix * positionVec4;\n\tgl_PointSize = uPointSize;\n\tvStrokeWeight = uPointSize;\n}\n",pointFrag:"precision mediump int;\nuniform vec4 uMaterialColor;\nIN float vStrokeWeight;\n\nvoid main(){\n float mask = 0.0;\n\n // make a circular mask using the gl_PointCoord (goes from 0 - 1 on a point)\n // might be able to get a nicer edge on big strokeweights with smoothstep but slightly less performant\n\n mask = step(0.98, length(gl_PointCoord * 2.0 - 1.0));\n\n // if strokeWeight is 1 or less lets just draw a square\n // this prevents weird artifacting from carving circles when our points are really small\n // if strokeWeight is larger than 1, we just use it as is\n\n mask = mix(0.0, mask, clamp(floor(vStrokeWeight - 0.5),0.0,1.0));\n\n // throw away the borders of the mask\n // otherwise we get weird alpha blending issues\n\n if(mask > 0.98){\n discard;\n }\n\n OUT_COLOR = vec4(uMaterialColor.rgb, 1.) * uMaterialColor.a;\n}\n",imageLightVert:"precision highp float;\nattribute vec3 aPosition;\nattribute vec3 aNormal;\nattribute vec2 aTexCoord;\n\nvarying vec3 localPos;\nvarying vec3 vWorldNormal;\nvarying vec3 vWorldPosition;\nvarying vec2 vTexCoord;\n\nuniform mat4 uModelViewMatrix;\nuniform mat4 uProjectionMatrix;\nuniform mat3 uNormalMatrix;\n\nvoid main() {\n // Multiply the position by the matrix.\n vec4 viewModelPosition = uModelViewMatrix * vec4(aPosition, 1.0);\n gl_Position = uProjectionMatrix * viewModelPosition; \n \n // orient the normals and pass to the fragment shader\n vWorldNormal = uNormalMatrix * aNormal;\n \n // send the view position to the fragment shader\n vWorldPosition = (uModelViewMatrix * vec4(aPosition, 1.0)).xyz;\n \n localPos = vWorldPosition;\n vTexCoord = aTexCoord;\n}\n\n\n/*\nin the vertex shader we'll compute the world position and world oriented normal of the vertices and pass those to the fragment shader as varyings.\n*/\n",imageLightDiffusedFrag:"precision highp float;\nvarying vec3 localPos;\n\n// the HDR cubemap converted (can be from an equirectangular environment map.)\nuniform sampler2D environmentMap;\nvarying vec2 vTexCoord;\n\nconst float PI = 3.14159265359;\n\nvec2 nTOE( vec3 v ){\n // x = r sin(phi) cos(theta) \n // y = r cos(phi) \n // z = r sin(phi) sin(theta)\n float phi = acos( v.y );\n // if phi is 0, then there are no x, z components\n float theta = 0.0;\n // else \n theta = acos(v.x / sin(phi));\n float sinTheta = v.z / sin(phi);\n if (sinTheta < 0.0) {\n // Turn it into -theta, but in the 0-2PI range\n theta = 2.0 * PI - theta;\n }\n theta = theta / (2.0 * 3.14159);\n phi = phi / 3.14159 ;\n \n vec2 angles = vec2( phi, theta );\n return angles;\n}\n\nfloat random(vec2 p) {\n vec3 p3 = fract(vec3(p.xyx) * .1031);\n p3 += dot(p3, p3.yzx + 33.33);\n return fract((p3.x + p3.y) * p3.z);\n}\n\nvoid main()\n{ \t \n\t// the sample direction equals the hemisphere's orientation\n float phi = vTexCoord.x * 2.0 * PI;\n float theta = vTexCoord.y * PI;\n float x = sin(theta) * cos(phi);\n float y = sin(theta) * sin(phi);\n float z = cos(theta);\n vec3 normal = vec3( x, y, z);\n\n\t// Discretely sampling the hemisphere given the integral's\n // spherical coordinates translates to the following fragment code:\n\tvec3 irradiance = vec3(0.0); \n\tvec3 up\t= vec3(0.0, 1.0, 0.0);\n\tvec3 right = normalize(cross(up, normal));\n\tup = normalize(cross(normal, right));\n\n\t// We specify a fixed sampleDelta delta value to traverse\n // the hemisphere; decreasing or increasing the sample delta\n // will increase or decrease the accuracy respectively.\n\tconst float sampleDelta = 0.100;\n\tfloat nrSamples = 0.0;\n float randomOffset = random(gl_FragCoord.xy) * sampleDelta;\n\tfor(float rawPhi = 0.0; rawPhi < 2.0 * PI; rawPhi += sampleDelta)\n\t{\n float phi = rawPhi + randomOffset;\n for(float rawTheta = 0.0; rawTheta < ( 0.5 ) * PI; rawTheta += sampleDelta)\n {\n float theta = rawTheta + randomOffset;\n // spherical to cartesian (in tangent space) // tangent space to world // add each sample result to irradiance\n float x = sin(theta) * cos(phi);\n float y = sin(theta) * sin(phi);\n float z = cos(theta);\n vec3 tangentSample = vec3( x, y, z);\n \n vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * normal;\n irradiance += (texture2D(environmentMap, nTOE(sampleVec)).xyz) * cos(theta) * sin(theta);\n nrSamples++;\n }\n\t}\n\t// divide by the total number of samples taken, giving us the average sampled irradiance.\n\tirradiance = PI * irradiance * (1.0 / float(nrSamples )) ;\n \n \n\tgl_FragColor = vec4(irradiance, 1.0);\n}",imageLightSpecularFrag:"precision highp float;\r\nvarying vec3 localPos;\r\nvarying vec2 vTexCoord;\r\n\r\n// our texture\r\nuniform sampler2D environmentMap;\r\nuniform float roughness;\r\n\r\nconst float PI = 3.14159265359;\r\n\r\nfloat VanDerCorput(int bits);\r\nvec2 HammersleyNoBitOps(int i, int N);\r\nvec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness);\r\n\r\n\r\nvec2 nTOE( vec3 v ){\r\n // x = r sin(phi) cos(theta) \r\n // y = r cos(phi) \r\n // z = r sin(phi) sin(theta)\r\n float phi = acos( v.y );\r\n // if phi is 0, then there are no x, z components\r\n float theta = 0.0;\r\n // else \r\n theta = acos(v.x / sin(phi));\r\n float sinTheta = v.z / sin(phi);\r\n if (sinTheta < 0.0) {\r\n // Turn it into -theta, but in the 0-2PI range\r\n theta = 2.0 * PI - theta;\r\n }\r\n theta = theta / (2.0 * 3.14159);\r\n phi = phi / 3.14159 ;\r\n \r\n vec2 angles = vec2( phi, theta );\r\n return angles;\r\n}\r\n\r\n\r\nvoid main(){\r\n const int SAMPLE_COUNT = 400; // 4096\r\n int lowRoughnessLimit = int(pow(2.0,(roughness+0.1)*20.0));\r\n float totalWeight = 0.0;\r\n vec3 prefilteredColor = vec3(0.0);\r\n float phi = vTexCoord.x * 2.0 * PI;\r\n float theta = vTexCoord.y * PI;\r\n float x = sin(theta) * cos(phi);\r\n float y = sin(theta) * sin(phi);\r\n float z = cos(theta);\r\n vec3 N = vec3(x,y,z);\r\n vec3 V = N;\r\n for (int i = 0; i < SAMPLE_COUNT; ++i)\r\n {\r\n // break at smaller sample numbers for low roughness levels\r\n if(i == lowRoughnessLimit)\r\n {\r\n break;\r\n }\r\n vec2 Xi = HammersleyNoBitOps(i, SAMPLE_COUNT);\r\n vec3 H = ImportanceSampleGGX(Xi, N, roughness);\r\n vec3 L = normalize(2.0 * dot(V, H) * H - V);\r\n\r\n float NdotL = max(dot(N, L), 0.0);\r\n if (NdotL > 0.0)\r\n {\r\n prefilteredColor += texture2D(environmentMap, nTOE(L)).xyz * NdotL;\r\n totalWeight += NdotL;\r\n }\r\n }\r\n prefilteredColor = prefilteredColor / totalWeight;\r\n\r\n gl_FragColor = vec4(prefilteredColor, 1.0);\r\n}\r\n\r\nvec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness){\r\n float a = roughness * roughness;\r\n\r\n float phi = 2.0 * PI * Xi.x;\r\n float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y));\r\n float sinTheta = sqrt(1.0 - cosTheta * cosTheta);\r\n // from spherical coordinates to cartesian coordinates\r\n vec3 H;\r\n H.x = cos(phi) * sinTheta;\r\n H.y = sin(phi) * sinTheta;\r\n H.z = cosTheta;\r\n\r\n // from tangent-space vector to world-space sample vector\r\n vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);\r\n vec3 tangent = normalize(cross(up, N));\r\n vec3 bitangent = cross(N, tangent);\r\n\r\n vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z;\r\n return normalize(sampleVec);\r\n}\r\n\r\n\r\nfloat VanDerCorput(int n, int base)\r\n{\r\n#ifdef WEBGL2\r\n\r\n uint bits = uint(n);\r\n bits = (bits << 16u) | (bits >> 16u);\r\n bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);\r\n bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);\r\n bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);\r\n bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);\r\n return float(bits) * 2.3283064365386963e-10; // / 0x100000000\r\n\r\n#else\r\n\r\n float invBase = 1.0 / float(base);\r\n float denom = 1.0;\r\n float result = 0.0;\r\n\r\n\r\n for (int i = 0; i < 32; ++i)\r\n {\r\n if (n > 0)\r\n {\r\n denom = mod(float(n), 2.0);\r\n result += denom * invBase;\r\n invBase = invBase / 2.0;\r\n n = int(float(n) / 2.0);\r\n }\r\n }\r\n\r\n\r\n return result;\r\n\r\n#endif\r\n}\r\n\r\nvec2 HammersleyNoBitOps(int i, int N)\r\n{\r\n return vec2(float(i) / float(N), VanDerCorput(i, 2));\r\n}\r\n"},M=E.sphereMappingFrag;for(x in E)E[x]="#ifdef WEBGL2\n\n#define IN in\n#define OUT out\n\n#ifdef FRAGMENT_SHADER\nout vec4 outColor;\n#define OUT_COLOR outColor\n#endif\n#define TEXTURE texture\n\n#else\n\n#ifdef FRAGMENT_SHADER\n#define IN varying\n#else\n#define IN attribute\n#endif\n#define OUT varying\n#define TEXTURE texture2D\n\n#ifdef FRAGMENT_SHADER\n#define OUT_COLOR gl_FragColor\n#endif\n\n#endif\n"+E[x];j(e={},l.GRAY,"precision highp float;\n\nvarying vec2 vTexCoord;\n\nuniform sampler2D tex0;\n\nfloat luma(vec3 color) {\n // weighted grayscale with luminance values\n return dot(color, vec3(0.2126, 0.7152, 0.0722));\n}\n\nvoid main() {\n vec4 tex = texture2D(tex0, vTexCoord);\n float gray = luma(tex.rgb);\n gl_FragColor = vec4(gray, gray, gray, tex.a);\n}\n"),j(e,l.ERODE,"// Reduces the bright areas in an image\n\nprecision highp float;\n\nvarying vec2 vTexCoord;\n\nuniform sampler2D tex0;\nuniform vec2 texelSize;\n\nfloat luma(vec3 color) {\n // weighted grayscale with luminance values\n // weights 77, 151, 28 taken from src/image/filters.js\n return dot(color, vec3(0.300781, 0.589844, 0.109375));\n}\n\nvoid main() {\n vec4 color = texture2D(tex0, vTexCoord);\n float lum = luma(color.rgb);\n\n // set current color as the darkest neighbor color\n\n vec4 neighbors[4];\n neighbors[0] = texture2D(tex0, vTexCoord + vec2( texelSize.x, 0.0));\n neighbors[1] = texture2D(tex0, vTexCoord + vec2(-texelSize.x, 0.0));\n neighbors[2] = texture2D(tex0, vTexCoord + vec2(0.0, texelSize.y));\n neighbors[3] = texture2D(tex0, vTexCoord + vec2(0.0, -texelSize.y));\n\n for (int i = 0; i < 4; i++) {\n vec4 neighborColor = neighbors[i];\n float neighborLum = luma(neighborColor.rgb);\n\n if (neighborLum < lum) {\n color = neighborColor;\n lum = neighborLum;\n }\n }\n\n gl_FragColor = color;\n}\n"),j(e,l.DILATE,"// Increase the bright areas in an image\n\nprecision highp float;\n\nvarying vec2 vTexCoord;\n\nuniform sampler2D tex0;\nuniform vec2 texelSize;\n\nfloat luma(vec3 color) {\n // weighted grayscale with luminance values\n // weights 77, 151, 28 taken from src/image/filters.js\n return dot(color, vec3(0.300781, 0.589844, 0.109375));\n}\n\nvoid main() {\n vec4 color = texture2D(tex0, vTexCoord);\n float lum = luma(color.rgb);\n\n // set current color as the brightest neighbor color\n\n vec4 neighbors[4];\n neighbors[0] = texture2D(tex0, vTexCoord + vec2( texelSize.x, 0.0));\n neighbors[1] = texture2D(tex0, vTexCoord + vec2(-texelSize.x, 0.0));\n neighbors[2] = texture2D(tex0, vTexCoord + vec2(0.0, texelSize.y));\n neighbors[3] = texture2D(tex0, vTexCoord + vec2(0.0, -texelSize.y));\n\n for (int i = 0; i < 4; i++) {\n vec4 neighborColor = neighbors[i];\n float neighborLum = luma(neighborColor.rgb);\n\n if (neighborLum > lum) {\n color = neighborColor;\n lum = neighborLum;\n }\n }\n\n gl_FragColor = color;\n}\n"),j(e,l.BLUR,"precision highp float;\n\n// Two-pass blur filter, unweighted kernel.\n// See also a similar blur at Adam Ferriss' repo of shader examples:\n// https://github.com/aferriss/p5jsShaderExamples/blob/gh-pages/4_image-effects/4-9_single-pass-blur/effect.frag\n\n\nuniform sampler2D tex0;\nvarying vec2 vTexCoord;\nuniform vec2 direction;\nuniform vec2 canvasSize;\nuniform float radius;\n\nfloat random(vec2 p) {\n vec3 p3 = fract(vec3(p.xyx) * .1031);\n p3 += dot(p3, p3.yzx + 33.33);\n return fract((p3.x + p3.y) * p3.z);\n}\n\n// This isn't a real Gaussian weight, it's a quadratic weight. It's what the\n// CPU mode's blur uses though, so we also use it here to match.\nfloat quadWeight(float x, float e) {\n return pow(e-abs(x), 2.);\n}\n\nvoid main(){\n vec2 uv = vTexCoord;\n\n // A reasonable maximum number of samples\n const float maxSamples = 64.0;\n\n float numSamples = floor(7. * radius);\n if (fract(numSamples / 2.) == 0.) {\n numSamples++;\n }\n vec4 avg = vec4(0.0);\n float total = 0.0;\n\n // Calculate the spacing to avoid skewing if numSamples > maxSamples\n float spacing = 1.0;\n if (numSamples > maxSamples) {\n spacing = numSamples / maxSamples;\n numSamples = maxSamples;\n }\n\n float randomOffset = (spacing - 1.0) * mix(-0.5, 0.5, random(gl_FragCoord.xy));\n for (float i = 0.0; i < maxSamples; i++) {\n if (i >= numSamples) break;\n\n float sample = i * spacing - (numSamples - 1.0) * 0.5 * spacing + randomOffset;\n vec2 sampleCoord = uv + vec2(sample, sample) / canvasSize * direction;\n float weight = quadWeight(sample, (numSamples - 1.0) * 0.5 * spacing);\n\n avg += weight * texture2D(tex0, sampleCoord);\n total += weight;\n }\n\n avg /= total;\n gl_FragColor = avg;\n}\n"),j(e,l.POSTERIZE,"// Limit color space for a stylized cartoon / poster effect\n\nprecision highp float;\n\nvarying vec2 vTexCoord;\n\nuniform sampler2D tex0;\nuniform float filterParameter;\n\nvec3 quantize(vec3 color, float n) {\n // restrict values to N options/bins\n // and floor each channel to nearest value\n //\n // eg. when N = 5, values = 0.0, 0.25, 0.50, 0.75, 1.0\n // then quantize (0.1, 0.7, 0.9) -> (0.0, 0.5, 1.0)\n\n color = color * n;\n color = floor(color);\n color = color / (n - 1.0);\n return color;\n}\n\nvoid main() {\n vec4 color = texture2D(tex0, vTexCoord);\n\n vec3 restrictedColor = quantize(color.rgb / color.a, filterParameter);\n\n gl_FragColor = vec4(restrictedColor.rgb * color.a, color.a);\n}\n"),j(e,l.OPAQUE,"// Set alpha channel to entirely opaque\n\nprecision highp float;\n\nvarying vec2 vTexCoord;\n\nuniform sampler2D tex0;\n\nvoid main() {\n vec4 color = texture2D(tex0, vTexCoord);\n gl_FragColor = vec4(color.rgb / color.a, 1.0);\n}\n"),j(e,l.INVERT,"// Set each pixel to inverse value\n// Note that original INVERT does not change the opacity, so this follows suit\n\nprecision highp float;\n\nvarying vec2 vTexCoord;\n\nuniform sampler2D tex0;\n\nvoid main() {\nvec4 color = texture2D(tex0, vTexCoord);\nvec3 origColor = color.rgb / color.a;\nvec3 invertedColor = vec3(1.0) - origColor;\ngl_FragColor = vec4(invertedColor * color.a, color.a);\n}\n"),j(e,l.THRESHOLD,"// Convert pixels to either white or black, \n// depending on if their luma is above or below filterParameter\n\nprecision highp float;\n\nvarying vec2 vTexCoord;\n\nuniform sampler2D tex0;\nuniform float filterParameter;\n\nfloat luma(vec3 color) {\n // weighted grayscale with luminance values\n return dot(color, vec3(0.2126, 0.7152, 0.0722));\n}\n\nvoid main() {\n vec4 color = texture2D(tex0, vTexCoord);\n float gray = luma(color.rgb / color.a);\n // floor() used to match src/image/filters.js\n float threshold = floor(filterParameter * 255.0) / 255.0;\n float blackOrWhite = step(threshold, gray);\n gl_FragColor = vec4(vec3(blackOrWhite) * color.a, color.a);\n}\n");var k=e;function O(e,t,r,o,n,s,i,a,l,u){var c=t.getParameter(t.FRAMEBUFFER_BINDING),r=(t.bindFramebuffer(t.FRAMEBUFFER,r),a===t.RGBA?4:3),d=s*i*r,h=l===t.UNSIGNED_BYTE?Uint8Array:Float32Array;if(e instanceof h&&e.length===d||(e=new h(d)),t.readPixels(o,u?u-n-i:n,s,i,a,l,e),t.bindFramebuffer(t.FRAMEBUFFER,c),u)for(var f=Math.floor(i/2),p=new h(s*r),m=0;m>7,127&d,c>>7,127&c);for(var h=0;h>7,127&f,0,0)}}return{cellImageInfo:a,dimOffset:t,dimImageInfo:n}}}}]),t}();B.default.RendererGL.prototype._renderText=function(e,t,r,o,n){if(this._textFont&&"string"!=typeof this._textFont){if(!(n<=o)&&this._doFill){if(this._isOpenType()){e.push();var n=this._doStroke,s=this.drawMode,i=(this._doStroke=!1,this.drawMode=E.TEXTURE,this._textFont.font),a=(a=this._textFont._fontInfo)||(this._textFont._fontInfo=new M(i)),r=this._textFont._handleAlignment(this,t,r,o),o=this._textSize/i.unitsPerEm,l=(this.translate(r.x,r.y,0),this.scale(o,o,1),this.GL),r=!this._defaultFontShader,u=this._getFontShader(),c=(u.init(),u.bindShader(),r&&(u.setUniform("uGridImageSize",[64,64]),u.setUniform("uCellsImageSize",[64,64]),u.setUniform("uStrokeImageSize",[64,64]),u.setUniform("uGridSize",[9,9])),this._applyColorBlend(this.curFillColor),this.retainedMode.geometry.glyph),d=(c||((o=this._textGeom=new B.default.Geometry(1,1,function(){for(var e=0;e<=1;e++)for(var t=0;t<=1;t++)this.vertices.push(new B.default.Vector(t,e,0)),this.uvs.push(t,e)})).computeFaces().computeNormals(),c=this.createBuffers("glyph",o)),!0),r=!1,o=void 0;try{for(var h,f=this.retainedMode.buffers.text[Symbol.iterator]();!(d=(h=f.next()).done);d=!0)h.value._prepareBuffer(c,u)}catch(e){r=!0,o=e}finally{try{d||null==f.return||f.return()}finally{if(r)throw o}}this._bindBuffer(c.indexBuffer,l.ELEMENT_ARRAY_BUFFER),u.setUniform("uMaterialColor",this.curFillColor),l.pixelStorei(l.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1);try{var p=0,m=null,y=i.stringToGlyphs(t),g=!0,v=!1,b=void 0;try{for(var j,_=y[Symbol.iterator]();!(g=(j=_.next()).done);g=!0){var x,w,S=j.value,T=(m&&(p+=i.getKerningValue(m,S)),a.getGlyphInfo(S));T.uGlyphRect&&(x=T.rowInfo,w=T.colInfo,u.setUniform("uSamplerStrokes",T.strokeImageInfo.imageData),u.setUniform("uSamplerRowStrokes",x.cellImageInfo.imageData),u.setUniform("uSamplerRows",x.dimImageInfo.imageData),u.setUniform("uSamplerColStrokes",w.cellImageInfo.imageData),u.setUniform("uSamplerCols",w.dimImageInfo.imageData),u.setUniform("uGridOffset",T.uGridOffset),u.setUniform("uGlyphRect",T.uGlyphRect),u.setUniform("uGlyphOffset",p),u.bindTextures(),l.drawElements(l.TRIANGLES,6,this.GL.UNSIGNED_SHORT,0)),p+=S.advanceWidth,m=S}}catch(e){v=!0,b=e}finally{try{g||null==_.return||_.return()}finally{if(v)throw b}}}finally{u.unbindShader(),this._doStroke=n,this.drawMode=s,l.pixelStorei(l.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!0),e.pop()}}else console.log("WEBGL: only Opentype (.otf) and Truetype (.ttf) fonts are supported");return e}}else console.log("WEBGL: you must load and set a font before drawing text. See `loadFont` and `textFont` for more details.")}},{"../core/constants":272,"../core/main":283,"./p5.RendererGL.Retained":340,"./p5.Shader":342,"core-js/modules/es.array.iterator":165,"core-js/modules/es.object.get-own-property-descriptor":186,"core-js/modules/es.object.to-string":190,"core-js/modules/es.regexp.exec":195,"core-js/modules/es.string.iterator":200,"core-js/modules/es.string.split":206,"core-js/modules/es.string.sub":208,"core-js/modules/es.symbol":212,"core-js/modules/es.symbol.description":210,"core-js/modules/es.symbol.iterator":211,"core-js/modules/es.weak-map":244,"core-js/modules/web.dom-collections.iterator":246}]},{},[267])(267)}); \ No newline at end of file diff --git a/src/lib/iframe-source.ts b/src/lib/iframe-source.ts index c56e75e..ae46657 100644 --- a/src/lib/iframe-source.ts +++ b/src/lib/iframe-source.ts @@ -4,7 +4,7 @@ export function iframeSource(code: string, baseUrl: string) { - +