diff --git a/.all-contributorsrc b/.all-contributorsrc index 68bff60a05..b0f4165cfb 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -6395,6 +6395,24 @@ "contributions": [ "doc" ] + }, + { + "login": "zs-5", + "name": "ℤ", + "avatar_url": "https://avatars.githubusercontent.com/u/177980470?v=4", + "profile": "https://github.com/zs-5", + "contributions": [ + "doc" + ] + }, + { + "login": "Dhanush111", + "name": "dhanush", + "avatar_url": "https://avatars.githubusercontent.com/u/51503598?v=4", + "profile": "https://github.com/Dhanush111", + "contributions": [ + "doc" + ] } ], "repoType": "github", diff --git a/README.md b/README.md index 942b5cb6c1..0f0827f282 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![npm version](https://badge.fury.io/js/p5.svg)](https://www.npmjs.com/package/p5) -[![All Contributors](https://img.shields.io/github/all-contributors/processing/p5.js?color=ee8449&style=flat-square)](#contributors) +[![All Contributors](https://img.shields.io/github/all-contributors/processing/p5.js?color=ee8449)](#contributors) [![Total Downloads](https://img.shields.io/npm/dt/p5)](https://www.npmjs.com/package/p5) # [p5.js](https://p5js.org) @@ -1072,6 +1072,8 @@ We recognize all types of contributions. This project follows the [all-contribut ashish singh
ashish singh

💻 blackboxlogic
blackboxlogic

📖 + ℤ

📖 + dhanush
dhanush

📖 diff --git a/package-lock.json b/package-lock.json index 25859a143b..7cd922865b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "p5", - "version": "1.11.1", + "version": "1.11.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "p5", - "version": "1.11.1", + "version": "1.11.2", "license": "LGPL-2.1", "devDependencies": { "@babel/core": "^7.7.7", diff --git a/package.json b/package.json index 9d10fceece..44d91bdb0f 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "node --require @babel/register ./utils/sample-linter.js" ] }, - "version": "1.11.1", + "version": "1.11.2", "devDependencies": { "@babel/core": "^7.7.7", "@babel/preset-env": "^7.10.2", diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index 1cf953eeeb..563e891958 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -28,7 +28,7 @@ const labelTableElId = '_lte_'; //Label Table Element * visible to screen readers. This is the default mode. * * Read - * Writing accessible canvas descriptions + * Writing accessible canvas descriptions * to learn more about making sketches accessible. * * @method describe @@ -179,7 +179,7 @@ p5.prototype.describe = function(text, display) { * mode. * * Read - * Writing accessible canvas descriptions + * Writing accessible canvas descriptions * to learn more about making sketches accessible. * * @method describeElement diff --git a/src/accessibility/outputs.js b/src/accessibility/outputs.js index 6fe0a37b4a..4cdb308c27 100644 --- a/src/accessibility/outputs.js +++ b/src/accessibility/outputs.js @@ -34,7 +34,7 @@ import p5 from '../core/main'; * mode. * * Read - * Writing accessible canvas descriptions + * Writing accessible canvas descriptions * to learn more about making sketches accessible. * * @method textOutput @@ -169,7 +169,7 @@ p5.prototype.textOutput = function(display) { * mode. * * Read - * Writing accessible canvas descriptions + * Writing accessible canvas descriptions * to learn more about making sketches accessible. * * @method gridOutput diff --git a/src/color/setting.js b/src/color/setting.js index a8ee4b3235..ae8ee0aa90 100644 --- a/src/color/setting.js +++ b/src/color/setting.js @@ -1000,7 +1000,7 @@ p5.prototype.colorMode = function(mode, max1, max2, max3, maxA) { * @param {Number} v1 red value if color mode is RGB or hue value if color mode is HSB. * @param {Number} v2 green value if color mode is RGB or saturation value if color mode is HSB. * @param {Number} v3 blue value if color mode is RGB or brightness value if color mode is HSB. - * @param {Number} [alpha] + * @param {Number} [alpha] optional alpha value, controls transparency (0 - transparent, 255 - opaque). * @chainable * @example *
diff --git a/src/core/helpers.js b/src/core/helpers.js index 5caa9e2b91..0bc0ddbe3d 100644 --- a/src/core/helpers.js +++ b/src/core/helpers.js @@ -15,35 +15,56 @@ function modeAdjust(a, b, c, d, mode) { if (mode === constants.CORNER) { - // CORNER mode already corresponds to a bounding box (top-left corner, width, height) - bbox = { x: a, y: b, w: c, h: d }; + // CORNER mode already corresponds to a bounding box (top-left corner, width, height). + // For negative widhts or heights, the absolute value is used. + bbox = { + x: a, + y: b, + w: Math.abs(c), + h: Math.abs(d) + }; } else if (mode === constants.CORNERS) { // CORNERS mode uses two opposite corners, in any configuration. // Make sure to get the top left corner by using the minimum of the x and y coordniates. - bbox = { x: Math.min(a, c), y: Math.min(b, d), w: c - a, h: d - b }; + bbox = { + x: Math.min(a, c), + y: Math.min(b, d), + w: Math.abs(c - a), + h: Math.abs(d - b) + }; } else if (mode === constants.RADIUS) { // RADIUS mode uses the center point and half the width and height. // c (half width) and d (half height) could be negative, so use the absolute value // in calculating the top left corner (x, y). - bbox = { x: a - Math.abs(c), y: b - Math.abs(d), w: 2 * c, h: 2 * d }; + c = Math.abs(c); + d = Math.abs(d); + bbox = { + x: a - c, + y: b - d, + w: 2 * c, + h: 2 * d + }; } else if (mode === constants.CENTER) { // CENTER mode uses the center point, width and height. // c (width) and d (height) could be negative, so use the absolute value - // in calculating the top-left corner (x,y). - bbox = { x: a - Math.abs(c * 0.5), y: b - Math.abs(d * 0.5), w: c, h: d }; + // in calculating the top-left corner (x, y). + c = Math.abs(c); + d = Math.abs(d); + bbox = { + x: a - (c * 0.5), + y: b - (d * 0.5), + w: c, + h: d + }; } - // p5 supports negative width and heights for rectangles, ellipses and arcs - bbox.w = Math.abs(bbox.w); - bbox.h = Math.abs(bbox.h); - return bbox; } diff --git a/src/core/shape/2d_primitives.js b/src/core/shape/2d_primitives.js index 92a5f527b2..f916339514 100644 --- a/src/core/shape/2d_primitives.js +++ b/src/core/shape/2d_primitives.js @@ -1339,6 +1339,15 @@ p5.prototype._renderRect = function() { this._renderer._rectMode ); + // For the default rectMode (CORNER), restore a possible negative width/height + // removed by modeAdjust(). This results in flipped/mirrored rendering, + // which is especially noticable when using WEGBL rendering and texture(). + // Note that this behavior only applies to rect(), NOT to ellipse() and arc(). + if (this._renderer._rectMode === constants.CORNER) { + vals.w = arguments[2]; + vals.h = arguments[3]; + } + const args = [vals.x, vals.y, vals.w, vals.h]; // append the additional arguments (either cornder radii, or // segment details) to the argument list diff --git a/src/dom/dom.js b/src/dom/dom.js index d35a53bc74..2f04be1ef2 100644 --- a/src/dom/dom.js +++ b/src/dom/dom.js @@ -1442,18 +1442,18 @@ p5.prototype.createSelect = function(...args) { * * The parameter is optional. If a string is passed, as in * `let myRadio = createSelect('food')`, then each radio option will - * have `"food"` as its `name` parameter: `<input name="food"></input>`. + * have `"food"` as its `name` parameter: `<input name="food">`. * If an existing `<div></div>` or `<span></span>` * element is passed, as in `let myRadio = createSelect(container)`, it will * become the radio button's parent element. * * Radio buttons extend the p5.Element class with a few * helpful methods for managing options: - * - `myRadio.option(value, [label])` adds an option to the menu. The first paremeter, `value`, is a string that sets the option's value and label. The second parameter, `label`, is optional. If provided, it sets the label displayed for the `value`. If an option with `value` already exists, its label is changed and its value is returned. + * - `myRadio.option(value, [label])` adds an option to the menu. The first parameter, `value`, is a string that sets the option's value and label. The second parameter, `label`, is optional. If provided, it sets the label displayed for the `value`. If an option with `value` already exists, its label is changed and its value is returned. * - `myRadio.value()` returns the currently-selected option's value. * - `myRadio.selected()` returns the currently-selected option. * - `myRadio.selected(value)` selects the given option and returns it as an `HTMLInputElement`. - * - `myRadio.disable(shouldDisable)` enables the entire radio button if `true` is passed and disables it if `false` is passed. + * - `myRadio.disable(shouldDisable)` Disables the radio button if `true` is passed, and enables it if `false` is passed. * * @method createRadio * @param {Object} [containerElement] container HTML Element, either a `<div></div>` @@ -1463,6 +1463,18 @@ p5.prototype.createSelect = function(...args) { * @example *
* + * let style = document.createElement('style'); + * style.innerHTML = ` + * .p5-radio label { + * display: flex; + * align-items: center; + * } + * .p5-radio input { + * margin-right: 5px; + * } + * `; + * document.head.appendChild(style); + * * let myRadio; * * function setup() { @@ -1472,6 +1484,7 @@ p5.prototype.createSelect = function(...args) { * // in the top-left corner. * myRadio = createRadio(); * myRadio.position(0, 0); + * myRadio.class('p5-radio'); * myRadio.size(60); * * // Add a few color options. @@ -1538,6 +1551,7 @@ p5.prototype.createSelect = function(...args) { * // in the top-left corner. * myRadio = createRadio(); * myRadio.position(0, 0); + * myRadio.class('p5-radio'); * myRadio.size(50); * * // Add a few color options. diff --git a/src/webgl/p5.Framebuffer.js b/src/webgl/p5.Framebuffer.js index 7a16d04a23..ac32c872ed 100644 --- a/src/webgl/p5.Framebuffer.js +++ b/src/webgl/p5.Framebuffer.js @@ -1752,7 +1752,7 @@ class Framebuffer { */ /** - * An object that stores the framebuffer's dpeth data. + * An object that stores the framebuffer's depth data. * * Each framebuffer uses a * WebGLTexture diff --git a/src/webgl/p5.RendererGL.js b/src/webgl/p5.RendererGL.js index f1e52b174e..908a056714 100644 --- a/src/webgl/p5.RendererGL.js +++ b/src/webgl/p5.RendererGL.js @@ -1667,6 +1667,8 @@ p5.RendererGL = class RendererGL extends p5.Renderer { // So that the activeImageLight gets reset in push/pop properties.activeImageLight = this.activeImageLight; + properties.textureMode = this.textureMode; + return style; } pop(...args) { diff --git a/test/unit/visual/cases/shape_modes.js b/test/unit/visual/cases/shape_modes.js index d17565b320..8fa4c0f951 100644 --- a/test/unit/visual/cases/shape_modes.js +++ b/test/unit/visual/cases/shape_modes.js @@ -17,6 +17,12 @@ function shapeCorners(p5, shape, mode, x1, y1, x2, y2) { // Don't use abs(), so we get negative values as well let w = x2 - x1; // w let h = y2 - y1; // h + // With mode CORNER, rects with negative widths/heights result in mirrored/flipped rendering + // In this case, adjust position so the rect is in line with the other cases + if (shape === 'rect') { + if (w < 0) { x += (-w); } // Move right + if (h < 0) { y += (-h); } // Move down + } x1 = x; y1 = y; x2 = w; y2 = h; } else if (mode === p5.CENTER) { // Find center @@ -56,14 +62,15 @@ function shapeCorners(p5, shape, mode, x1, y1, x2, y2) { } -/* - Comprehensive test for rendering ellipse(), arc(), and rect() - with the different ellipseMode() / rectMode() values: CORNERS, CORNER, CENTER, RADIUS. - Each of the 3 shapes is tested with each of the 4 possible modes, resulting in 12 test. - Each test renders the shape in 16 different coordinate configurations, - testing combinations of positive and negative coordinate values. -*/ visualSuite('Shape Modes', function(...args) { + /* + Comprehensive test for rendering ellipse(), arc(), and rect() + with the different ellipseMode() / rectMode() values: CORNERS, CORNER, CENTER, RADIUS. + Each of the 3 shapes is tested with each of the 4 possible modes, resulting in 12 tests. + Each test renders the shape in 16 different coordinate configurations, + testing combinations of positive and negative coordinate values. + */ + // Shapes to test const SHAPES = [ 'ellipse', 'arc', 'rect' ]; @@ -113,6 +120,60 @@ visualSuite('Shape Modes', function(...args) { }); // End of: visualTest } // End of: MODES loop - }); // End of: Inner visualSuite + }); // End of: visualSuite } // End of: SHAPES loop -}); // End of: Outer visualSuite + + + /* + An extra test suite specific to shape mode CORNER and negative dimensions. + For rect, negative widths/heights result in flipped rendering (horizontally/vertically) + For ellipse and arc, using negative widths/heights has no effect (the absolute value is used) + */ + visualSuite('Negative dimensions', function() { + // Negative widths/height result in flipped rects. + visualTest('rect', function(p5, screenshot) { + p5.createCanvas(50, 50); + p5.translate(p5.width/2, p5.height/2); + p5.rectMode(p5.CORNER); + p5.rect(0, 0, 20, 10); + p5.fill('red'); + p5.rect(0, 0, -20, 10); + p5.fill('green'); + p5.rect(0, 0, 20, -10); + p5.fill('blue'); + p5.rect(0, 0, -20, -10); + screenshot(); + }); + // Since negative widths/heights are used with their absolute value, + // ellipses are drawn on top of each other, blue one last + visualTest('ellipse', function(p5, screenshot) { + p5.createCanvas(50, 50); + p5.translate(p5.width/2, p5.height/2); + p5.ellipseMode(p5.CORNER); + p5.ellipse(0, 0, 20, 10); + p5.fill('red'); + p5.ellipse(0, 0, -20, 10); + p5.fill('green'); + p5.ellipse(0, 0, 20, -10); + p5.fill('blue'); + p5.ellipse(0, 0, -20, -10); + screenshot(); + }); + // Since negative widths/heights are used with their absolute value, + // arcs are drawn on top of each other, blue one last. + visualTest('arc', function(p5, screenshot) { + p5.createCanvas(50, 50); + p5.translate(p5.width/2, p5.height/2); + p5.ellipseMode(p5.CORNER); + p5.arc(0, 0, 20, 10, 0, p5.PI + p5.HALF_PI); + p5.fill('red'); + p5.arc(0, 0, -20, 10, 0, p5.PI + p5.HALF_PI); + p5.fill('green'); + p5.arc(0, 0, 20, -10, 0, p5.PI + p5.HALF_PI); + p5.fill('blue'); + p5.arc(0, 0, -20, -10, 0, p5.PI + p5.HALF_PI); + screenshot(); + }); + }); + +}); diff --git a/test/unit/visual/screenshots/Shape Modes/Negative dimensions/arc/000.png b/test/unit/visual/screenshots/Shape Modes/Negative dimensions/arc/000.png new file mode 100644 index 0000000000..b0732e0093 Binary files /dev/null and b/test/unit/visual/screenshots/Shape Modes/Negative dimensions/arc/000.png differ diff --git a/test/unit/visual/screenshots/Shape Modes/Negative dimensions/arc/metadata.json b/test/unit/visual/screenshots/Shape Modes/Negative dimensions/arc/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/Shape Modes/Negative dimensions/arc/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/Shape Modes/Negative dimensions/ellipse/000.png b/test/unit/visual/screenshots/Shape Modes/Negative dimensions/ellipse/000.png new file mode 100644 index 0000000000..9351dc2adf Binary files /dev/null and b/test/unit/visual/screenshots/Shape Modes/Negative dimensions/ellipse/000.png differ diff --git a/test/unit/visual/screenshots/Shape Modes/Negative dimensions/ellipse/metadata.json b/test/unit/visual/screenshots/Shape Modes/Negative dimensions/ellipse/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/Shape Modes/Negative dimensions/ellipse/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/Shape Modes/Negative dimensions/rect/000.png b/test/unit/visual/screenshots/Shape Modes/Negative dimensions/rect/000.png new file mode 100644 index 0000000000..59aab0876f Binary files /dev/null and b/test/unit/visual/screenshots/Shape Modes/Negative dimensions/rect/000.png differ diff --git a/test/unit/visual/screenshots/Shape Modes/Negative dimensions/rect/metadata.json b/test/unit/visual/screenshots/Shape Modes/Negative dimensions/rect/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/Shape Modes/Negative dimensions/rect/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/Shape Modes/Shape rect/Mode CORNER/000.png b/test/unit/visual/screenshots/Shape Modes/Shape rect/Mode CORNER/000.png index 5c096e42bb..9e6ecdcd59 100644 Binary files a/test/unit/visual/screenshots/Shape Modes/Shape rect/Mode CORNER/000.png and b/test/unit/visual/screenshots/Shape Modes/Shape rect/Mode CORNER/000.png differ