diff --git a/docs/parameterData.json b/docs/parameterData.json
index 6cf76f3c4a..41da80e4ab 100644
--- a/docs/parameterData.json
+++ b/docs/parameterData.json
@@ -305,6 +305,7 @@
},
"ellipseMode": {
"overloads": [
+ [],
[
"CENTER|RADIUS|CORNER|CORNERS"
]
@@ -808,6 +809,7 @@
},
"rectMode": {
"overloads": [
+ [],
[
"CENTER|RADIUS|CORNER|CORNERS"
]
@@ -878,7 +880,8 @@
"ARROW|CROSS|HAND|MOVE|TEXT|WAIT|String",
"Number?",
"Number?"
- ]
+ ],
+ []
]
},
"createElement": {
@@ -1086,7 +1089,8 @@
"overloads": [
[
"ROUND|SQUARE|PROJECT"
- ]
+ ],
+ []
]
},
"lerp": {
@@ -1292,7 +1296,8 @@
"overloads": [
[
"MITER|BEVEL|ROUND"
- ]
+ ],
+ []
]
},
"noCursor": {
@@ -1391,7 +1396,8 @@
"overloads": [
[
"Number"
- ]
+ ],
+ []
]
},
"degrees": {
@@ -2268,6 +2274,7 @@
},
"colorMode": {
"overloads": [
+ [],
[
"RGB|HSB|HSL|RGBHDR|HWB|LAB|LCH|OKLAB|OKLCH",
"Number?"
@@ -2492,6 +2499,7 @@
},
"tint": {
"overloads": [
+ [],
[
"Number",
"Number",
@@ -2631,6 +2639,7 @@
},
"fill": {
"overloads": [
+ [],
[
"Number",
"Number",
@@ -2680,7 +2689,8 @@
[
"LEFT|CENTER|RIGHT?",
"TOP|BOTTOM|CENTER|BASELINE?"
- ]
+ ],
+ []
]
},
"textAscent": {
@@ -2701,7 +2711,8 @@
"overloads": [
[
"Number?"
- ]
+ ],
+ []
]
},
"textFont": {
@@ -2709,7 +2720,8 @@
[
"p5.Font|String|Object?",
"Number?"
- ]
+ ],
+ []
]
},
"textSize": {
@@ -2854,6 +2866,7 @@
},
"imageMode": {
"overloads": [
+ [],
[
"CORNER|CORNERS|CENTER"
]
@@ -2983,6 +2996,7 @@
},
"stroke": {
"overloads": [
+ [],
[
"Number",
"Number",
@@ -3227,6 +3241,7 @@
},
"blendMode": {
"overloads": [
+ [],
[
"BLEND|DARKEST|LIGHTEST|DIFFERENCE|MULTIPLY|EXCLUSION|SCREEN|REPLACE|OVERLAY|HARD_LIGHT|SOFT_LIGHT|DODGE|BURN|ADD|REMOVE|SUBTRACT"
]
@@ -3298,7 +3313,8 @@
"overloads": [
[
"Object"
- ]
+ ],
+ []
]
},
"linePerspective": {
@@ -3387,7 +3403,8 @@
"overloads": [
[
"IMAGE|NORMAL"
- ]
+ ],
+ []
]
},
"setCamera": {
@@ -3409,7 +3426,8 @@
[
"CLAMP|REPEAT|MIRROR",
"CLAMP|REPEAT|MIRROR?"
- ]
+ ],
+ []
]
},
"normalMaterial": {
diff --git a/src/color/p5.Color.js b/src/color/p5.Color.js
index cd7561b939..1c89b21f9a 100644
--- a/src/color/p5.Color.js
+++ b/src/color/p5.Color.js
@@ -724,7 +724,7 @@ class Color {
if(!Array.isArray(v)){
return [0, v];
}else{
- return v
+ return v;
}
});
diff --git a/src/color/setting.js b/src/color/setting.js
index 6a066b986e..cae961600b 100644
--- a/src/color/setting.js
+++ b/src/color/setting.js
@@ -580,8 +580,7 @@ function setting(p5, fn){
* @chainable
*/
fn.background = function(...args) {
- this._renderer.background(...args);
- return this;
+ return this._renderer.background(...args);
};
/**
@@ -1096,6 +1095,8 @@ function setting(p5, fn){
* or `HSLA` colors, depending on the current colorMode(). The last parameter
* sets the alpha (transparency) value.
*
+ * Calling `fill()` without an argument returns the current fill as a p5.Color object.
+ *
* @method fill
* @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.
@@ -1284,9 +1285,12 @@ function setting(p5, fn){
* @param {p5.Color} color the fill color.
* @chainable
*/
+ /**
+ * @method fill
+ * @return {p5.Color} the current fill color.
+ */
fn.fill = function(...args) {
- this._renderer.fill(...args);
- return this;
+ return this._renderer.fill(...args);
};
/**
@@ -1415,6 +1419,8 @@ function setting(p5, fn){
* or HSLA colors, depending on the current `colorMode()`. The last parameter
* sets the alpha (transparency) value.
*
+ * Calling `stroke()` without an argument returns the current stroke as a p5.Color object.
+ *
* @method stroke
* @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.
@@ -1601,9 +1607,12 @@ function setting(p5, fn){
* @param {p5.Color} color the stroke color.
* @chainable
*/
+ /**
+ * @method stroke
+ * @return {p5.Color} the current stroke color.
+ */
fn.stroke = function(...args) {
- this._renderer.stroke(...args);
- return this;
+ return this._renderer.stroke(...args);
};
/**
@@ -1768,6 +1777,8 @@ function setting(p5, fn){
* EXCLUSION, SCREEN, REPLACE, OVERLAY, HARD_LIGHT,
* SOFT_LIGHT, DODGE, BURN, ADD, REMOVE or SUBTRACT
*
+ * Calling `blendMode()` without an argument returns the current blendMode.
+ *
* @example
* function setup() {
* createCanvas(100, 100);
@@ -2136,6 +2147,10 @@ function setting(p5, fn){
* describe('A yellow line and a turquoise line form an X on a gray background. The area where they overlap is green.');
* }
*/
+ /**
+ * @method blendMode
+ * @return {(BLEND|DARKEST|LIGHTEST|DIFFERENCE|MULTIPLY|EXCLUSION|SCREEN|REPLACE|OVERLAY|HARD_LIGHT|SOFT_LIGHT|DODGE|BURN|ADD|REMOVE|SUBTRACT)} the current blend mode.
+ */
fn.blendMode = function (mode) {
// p5._validateParameters('blendMode', arguments);
if (mode === constants.NORMAL) {
@@ -2145,7 +2160,7 @@ function setting(p5, fn){
);
mode = constants.BLEND;
}
- this._renderer.blendMode(mode);
+ return this._renderer.blendMode(mode);
};
}
diff --git a/src/core/environment.js b/src/core/environment.js
index 350d1d1e54..6fffe81973 100644
--- a/src/core/environment.js
+++ b/src/core/environment.js
@@ -215,6 +215,8 @@ function environment(p5, fn, lifecycles){
* cursor, `x` and `y` set the location pointed to within the image. They are
* both 0 by default, so the cursor points to the image's top-left corner. `x`
* and `y` must be less than the image's width and height, respectively.
+ *
+ * Calling `cursor()` without an argument returns the current cursor type as a string.
*
* @method cursor
* @param {(ARROW|CROSS|HAND|MOVE|TEXT|WAIT|String)} type Built-in: either ARROW, CROSS, HAND, MOVE, TEXT, or WAIT.
@@ -281,9 +283,17 @@ function environment(p5, fn, lifecycles){
* }
* }
*/
+ /**
+ * @method cursor
+ * @return {(ARROW|CROSS|HAND|MOVE|TEXT|WAIT|String)} the current cursor type
+ */
fn.cursor = function(type, x, y) {
let cursor = 'auto';
const canvas = this._curElement.elt;
+ if (typeof type === 'undefined') {
+ let curstr = canvas.style.cursor;
+ return curstr.length ? curstr : 'default';
+ }
if (standardCursors.includes(type)) {
// Standard css cursor
cursor = type;
diff --git a/src/core/p5.Renderer.js b/src/core/p5.Renderer.js
index c0fe4a6c02..f9caac7793 100644
--- a/src/core/p5.Renderer.js
+++ b/src/core/p5.Renderer.js
@@ -45,6 +45,11 @@ class Renderer {
rectMode: constants.CORNER,
ellipseMode: constants.CENTER,
strokeWeight: 1,
+ bezierOrder: 3,
+ splineProperties: new ClonableObject({
+ ends: constants.INCLUDE,
+ tightness: 0
+ }),
textFont: { family: 'sans-serif' },
textLeading: 15,
@@ -52,15 +57,8 @@ class Renderer {
textSize: 12,
textAlign: constants.LEFT,
textBaseline: constants.BASELINE,
- bezierOrder: 3,
- splineProperties: new ClonableObject({
- ends: constants.INCLUDE,
- tightness: 0
- }),
textWrap: constants.WORD,
-
- // added v2.0
- fontStyle: constants.NORMAL, // v1: textStyle
+ fontStyle: constants.NORMAL, // v1: was textStyle
fontStretch: constants.NORMAL,
fontWeight: constants.NORMAL,
lineHeight: constants.NORMAL,
@@ -330,9 +328,12 @@ class Renderer {
}
fill(...args) {
- this.states.setValue('fillSet', true);
- this.states.setValue('fillColor', this._pInst.color(...args));
- this.updateShapeVertexProperties();
+ if (args.length > 0) {
+ this.states.setValue('fillSet', true);
+ this.states.setValue('fillColor', this._pInst.color(...args));
+ this.updateShapeVertexProperties();
+ }
+ return this.states.fillColor;
}
noFill() {
@@ -340,14 +341,16 @@ class Renderer {
}
strokeWeight(w) {
- if (w === undefined) {
+ if (typeof w === 'undefined') {
return this.states.strokeWeight;
- } else {
- this.states.setValue('strokeWeight', w);
}
+ this.states.setValue('strokeWeight', w);
}
stroke(...args) {
+ if (args.length === 0) {
+ return this.states.strokeColor;
+ }
this.states.setValue('strokeSet', true);
this.states.setValue('strokeColor', this._pInst.color(...args));
this.updateShapeVertexProperties();
diff --git a/src/core/p5.Renderer2D.js b/src/core/p5.Renderer2D.js
index fbe5747449..a98f60f339 100644
--- a/src/core/p5.Renderer2D.js
+++ b/src/core/p5.Renderer2D.js
@@ -166,18 +166,18 @@ class Renderer2D extends Renderer {
//////////////////////////////////////////////
background(...args) {
+ if (args.length === 0) {
+ return this;// setter with no args does nothing
+ }
this.push();
this.resetMatrix();
-
if (args[0] instanceof Image) {
+ const img = args[0];
if (args[1] >= 0) {
// set transparency of background
- const img = args[0];
this.drawingContext.globalAlpha = args[1] / 255;
- this._pInst.image(img, 0, 0, this.width, this.height);
- } else {
- this._pInst.image(args[0], 0, 0, this.width, this.height);
}
+ this._pInst.image(img, 0, 0, this.width, this.height);
} else {
// create background rect
const color = this._pInst.color(...args);
@@ -202,6 +202,8 @@ class Renderer2D extends Renderer {
}
}
this.pop();
+
+ return this;
}
clear() {
@@ -214,6 +216,9 @@ class Renderer2D extends Renderer {
fill(...args) {
super.fill(...args);
const color = this.states.fillColor;
+ if (args.length === 0) {
+ return color; // getter
+ }
this._setFill(color.toString());
// Add accessible outputs if the method exists; on success,
@@ -226,6 +231,9 @@ class Renderer2D extends Renderer {
stroke(...args) {
super.stroke(...args);
const color = this.states.strokeColor;
+ if (args.length === 0) {
+ return color; // getter
+ }
this._setStroke(color.toString());
// Add accessible outputs if the method exists; on success,
@@ -484,6 +492,9 @@ class Renderer2D extends Renderer {
//////////////////////////////////////////////
blendMode(mode) {
+ if (typeof mode === 'undefined') { // getter
+ return this._cachedBlendMode;
+ }
if (mode === constants.SUBTRACT) {
console.warn('blendMode(SUBTRACT) only works in WEBGL mode.');
} else if (
@@ -1004,6 +1015,9 @@ class Renderer2D extends Renderer {
//////////////////////////////////////////////
strokeCap(cap) {
+ if (typeof cap === 'undefined') { // getter
+ return this.drawingContext.lineCap;
+ }
if (
cap === constants.ROUND ||
cap === constants.SQUARE ||
@@ -1015,6 +1029,9 @@ class Renderer2D extends Renderer {
}
strokeJoin(join) {
+ if (typeof join === 'undefined') { // getter
+ return this.drawingContext.lineJoin;
+ }
if (
join === constants.ROUND ||
join === constants.BEVEL ||
@@ -1027,7 +1044,10 @@ class Renderer2D extends Renderer {
strokeWeight(w) {
super.strokeWeight(w);
- if (typeof w === 'undefined' || w === 0) {
+ if (typeof w === 'undefined') {
+ return this.states.strokeWeight;
+ }
+ if (w === 0) {
// hack because lineWidth 0 doesn't work
this.drawingContext.lineWidth = 0.0001;
} else {
@@ -1090,16 +1110,22 @@ class Renderer2D extends Renderer {
rotate(rad) {
this.drawingContext.rotate(rad);
+ return this;
}
scale(x, y) {
+ // support passing objects with x,y properties (including p5.Vector)
+ if (typeof x === 'object' && 'x' in x && 'y' in x) {
+ y = x.y;
+ x = x.x;
+ }
this.drawingContext.scale(x, y);
return this;
}
translate(x, y) {
- // support passing a vector as the 1st parameter
- if (x instanceof p5.Vector) {
+ // support passing objects with x,y properties (including p5.Vector)
+ if (typeof x === 'object' && 'x' in x && 'y' in x) {
y = x.y;
x = x.x;
}
diff --git a/src/core/p5.Renderer3D.js b/src/core/p5.Renderer3D.js
index 4241a56157..b98cb19178 100644
--- a/src/core/p5.Renderer3D.js
+++ b/src/core/p5.Renderer3D.js
@@ -132,7 +132,7 @@ export class Renderer3D extends Renderer {
this.states._useShininess = 1;
this.states._useMetalness = 0;
- this.states.tint = [255, 255, 255, 255];
+ this.states.tint = new Color([1, 1, 1, 1]);
this.states.constantAttenuation = 1;
this.states.linearAttenuation = 0;
@@ -721,10 +721,10 @@ export class Renderer3D extends Renderer {
this.states.setValue("enableLighting", false);
//reset tint value for new frame
- this.states.setValue("tint", [255, 255, 255, 255]);
+ this.states.setValue("tint", new Color([1,1,1,1]));
//Clear depth every frame
- this._resetBuffersBeforeDraw()
+ this._resetBuffersBeforeDraw();
}
background(...args) {
@@ -1486,7 +1486,7 @@ export class Renderer3D extends Renderer {
// works differently and is global p5 state. If the p5 state has
// been cleared, we also need to clear the value in uSampler to match.
fillShader.setUniform("uSampler", this.states._tex || empty);
- fillShader.setUniform("uTint", this.states.tint);
+ fillShader.setUniform("uTint", this.states.tint._getRGBA([255, 255, 255, 255]));
fillShader.setUniform("uHasSetAmbient", this.states._hasSetAmbient);
fillShader.setUniform("uAmbientMatColor", this.states.curAmbientColor);
diff --git a/src/core/transform.js b/src/core/transform.js
index e8a6a32da3..0b8eb95a5b 100644
--- a/src/core/transform.js
+++ b/src/core/transform.js
@@ -420,8 +420,7 @@ function transform(p5, fn){
*/
fn.rotate = function(angle, axis) {
// p5._validateParameters('rotate', arguments);
- this._renderer.rotate(this._toRadians(angle), axis);
- return this;
+ return this._renderer.rotate(this._toRadians(angle), axis);
};
/**
@@ -543,8 +542,7 @@ function transform(p5, fn){
fn.rotateX = function(angle) {
this._assert3d('rotateX');
// p5._validateParameters('rotateX', arguments);
- this._renderer.rotateX(this._toRadians(angle));
- return this;
+ return this._renderer.rotateX(this._toRadians(angle));
};
/**
@@ -666,8 +664,7 @@ function transform(p5, fn){
fn.rotateY = function(angle) {
this._assert3d('rotateY');
// p5._validateParameters('rotateY', arguments);
- this._renderer.rotateY(this._toRadians(angle));
- return this;
+ return this._renderer.rotateY(this._toRadians(angle));
};
/**
@@ -789,8 +786,7 @@ function transform(p5, fn){
fn.rotateZ = function(angle) {
this._assert3d('rotateZ');
// p5._validateParameters('rotateZ', arguments);
- this._renderer.rotateZ(this._toRadians(angle));
- return this;
+ return this._renderer.rotateZ(this._toRadians(angle));
};
/**
@@ -966,9 +962,7 @@ function transform(p5, fn){
z = 1;
}
- this._renderer.scale(x, y, z);
-
- return this;
+ return this._renderer.scale(x, y, z);
};
/**
@@ -1274,11 +1268,10 @@ function transform(p5, fn){
fn.translate = function(x, y, z) {
// p5._validateParameters('translate', arguments);
if (this._renderer.isP3D) {
- this._renderer.translate(x, y, z);
+ return this._renderer.translate(x, y, z);
} else {
- this._renderer.translate(x, y);
+ return this._renderer.translate(x, y);
}
- return this;
};
/**
diff --git a/src/image/loading_displaying.js b/src/image/loading_displaying.js
index 3b9ed18fd6..28149c4412 100644
--- a/src/image/loading_displaying.js
+++ b/src/image/loading_displaying.js
@@ -1138,6 +1138,9 @@ function loadingDisplaying(p5, fn){
* sets the alpha value. For example, `tint(255, 0, 0, 100)` will give images
* a red tint and make them transparent.
*
+ * Calling `tint()` without an argument returns the current tint as a
+ * p5.Color object.
+ *
* @method tint
* @param {Number} v1 red or hue value.
* @param {Number} v2 green or saturation value.
@@ -1242,10 +1245,18 @@ function loadingDisplaying(p5, fn){
* @method tint
* @param {p5.Color} color the tint color
*/
+ /**
+ * @method tint
+ * @return {p5.Color} the current tint color
+ */
fn.tint = function(...args) {
- // p5._validateParameters('tint', args);
- const c = this.color(...args);
- this._renderer.states.setValue('tint', c._getRGBA([255, 255, 255, 255]));
+ if (args.length === 0) {
+ return this._renderer.states.tint; // getter
+ }
+ else {
+ this._renderer.states.setValue('tint', this.color(...args));
+ return this;
+ }
};
/**
@@ -1279,6 +1290,7 @@ function loadingDisplaying(p5, fn){
*/
fn.noTint = function() {
this._renderer.states.setValue('tint', null);
+ return this;
};
/**
@@ -1310,6 +1322,8 @@ function loadingDisplaying(p5, fn){
* image() as the x- and y-coordinates of the image's
* center. The next parameters are its width and height.
*
+ * Calling `imageMode()` without an argument returns the current image mode, either `CORNER`, `CORNERS`, or `CENTER`.
+ *
* @method imageMode
* @param {(CORNER|CORNERS|CENTER)} mode either CORNER, CORNERS, or CENTER.
*
@@ -1373,8 +1387,15 @@ function loadingDisplaying(p5, fn){
* describe('A square image of a brick wall is drawn on a gray square.');
* }
*/
+ /**
+ * @method imageMode
+ * @return {(CORNER|CORNERS|CENTER)} the current image mode
+ */
fn.imageMode = function(m) {
// p5._validateParameters('imageMode', arguments);
+ if (typeof m === 'undefined') { // getter
+ return this._renderer.states.imageMode;
+ }
if (
m === constants.CORNER ||
m === constants.CORNERS ||
diff --git a/src/math/trigonometry.js b/src/math/trigonometry.js
index 979adb1c16..d2c5491b7d 100644
--- a/src/math/trigonometry.js
+++ b/src/math/trigonometry.js
@@ -774,7 +774,8 @@ function trigonometry(p5, fn){
* @returns {Number}
*/
fn._toRadians = function(angle) {
- if (this._angleMode === DEGREES) {
+ // returns undefined if no argument
+ if (typeof angle !== 'undefined' && this._angleMode === DEGREES) {
return angle * constants.DEG_TO_RAD;
}
return angle;
diff --git a/src/shape/attributes.js b/src/shape/attributes.js
index f6bcf02576..812159267f 100644
--- a/src/shape/attributes.js
+++ b/src/shape/attributes.js
@@ -35,6 +35,8 @@ function attributes(p5, fn){
* the constants `CENTER`, `RADIUS`, `CORNER`, and `CORNERS` are defined this
* way. JavaScript is a case-sensitive language.
*
+ * Calling `ellipseMode()` without an argument returns the current ellipseMode, either `CENTER`, `RADIUS`, `CORNER`, or `CORNERS`.
+ *
* @method ellipseMode
* @param {(CENTER|RADIUS|CORNER|CORNERS)} mode either CENTER, RADIUS, CORNER, or CORNERS
* @chainable
@@ -77,8 +79,15 @@ function attributes(p5, fn){
* describe('A white circle with a gray circle at its top-left corner. Both circles have black outlines.');
* }
*/
+ /**
+ * @method ellipseMode
+ * @return {(CENTER|RADIUS|CORNER|CORNERS)} the current ellipseMode.
+ */
fn.ellipseMode = function(m) {
// p5._validateParameters('ellipseMode', arguments);
+ if (typeof m === 'undefined') { // getter
+ return this._renderer?.states.ellipseMode;
+ }
if (
m === constants.CORNER ||
m === constants.CORNERS ||
@@ -186,6 +195,8 @@ function attributes(p5, fn){
* constants `CENTER`, `RADIUS`, `CORNER`, and `CORNERS` are defined this way.
* JavaScript is a case-sensitive language.
*
+ * Calling `rectMode()` without an argument returns the current rectMode, either `CORNER`, `CORNERS`, `CENTER`, or `RADIUS`.
+ *
* @method rectMode
* @param {(CENTER|RADIUS|CORNER|CORNERS)} mode either CORNER, CORNERS, CENTER, or RADIUS
* @chainable
@@ -254,8 +265,15 @@ function attributes(p5, fn){
* describe('A small gray square drawn at the center of a white square.');
* }
*/
+ /**
+ * @method rectMode
+ * @return {(CENTER|RADIUS|CORNER|CORNERS)} the current rectMode.
+ */
fn.rectMode = function(m) {
// p5._validateParameters('rectMode', arguments);
+ if (typeof m === 'undefined') { // getter
+ return this._renderer?.states.rectMode;
+ }
if (
m === constants.CORNER ||
m === constants.CORNERS ||
@@ -380,6 +398,9 @@ function attributes(p5, fn){
*/
fn.strokeCap = function(cap) {
// p5._validateParameters('strokeCap', arguments);
+ if (typeof cap === 'undefined') { // getter
+ return this._renderer.strokeCap();
+ }
if (
cap === constants.ROUND ||
cap === constants.SQUARE ||
@@ -401,6 +422,8 @@ function attributes(p5, fn){
* the constants `MITER`, `BEVEL`, and `ROUND` are defined this way.
* JavaScript is a case-sensitive language.
*
+ * Calling `strokeJoin()` without an argument returns the current stroke join style, either `MITER`, `BEVEL`, or `ROUND`.
+ *
* @method strokeJoin
* @param {(MITER|BEVEL|ROUND)} join either MITER, BEVEL, or ROUND
* @chainable
@@ -467,8 +490,15 @@ function attributes(p5, fn){
* describe('A right-facing arrowhead shape with a rounded tip in center of canvas.');
* }
*/
+ /**
+ * @method strokeJoin
+ * @return {(MITER|BEVEL|ROUND)} the current stroke join style.
+ */
fn.strokeJoin = function(join) {
// p5._validateParameters('strokeJoin', arguments);
+ if (typeof join === 'undefined') { // getter
+ return this._renderer.strokeJoin();
+ }
if (
join === constants.ROUND ||
join === constants.BEVEL ||
@@ -485,6 +515,8 @@ function attributes(p5, fn){
*
* Note: `strokeWeight()` is affected by transformations, especially calls to
* scale().
+ *
+ * Calling `strokeWeight()` without an argument returns the current stroke weight as a number.
*
* @method strokeWeight
* @param {Number} weight the weight of the stroke (in pixels).
@@ -527,10 +559,13 @@ function attributes(p5, fn){
* describe('Two horizontal black lines. The top line is thin and the bottom is five times thicker than the top.');
* }
*/
+ /**
+ * @method strokeWeight
+ * @return {Number} the current stroke weight.
+ */
fn.strokeWeight = function(w) {
// p5._validateParameters('strokeWeight', arguments);
- this._renderer.strokeWeight(w);
- return this;
+ return this._renderer.strokeWeight(w);
};
}
diff --git a/src/shape/custom_shapes.js b/src/shape/custom_shapes.js
index 3a09200f75..f287a4823e 100644
--- a/src/shape/custom_shapes.js
+++ b/src/shape/custom_shapes.js
@@ -1611,6 +1611,8 @@ function customShapes(p5, fn) {
* Note: `bezierVertex()` won’t work when an argument is passed to
* beginShape().
*
+ * Calling `bezierOrder()` without an argument returns the current Bézier order.
+ *
* @method bezierOrder
* @param {Number} order The new order to set. Can be either 2 or 3, by default 3
*
diff --git a/src/type/textCore.js b/src/type/textCore.js
index 345267fa4c..909609ef0c 100644
--- a/src/type/textCore.js
+++ b/src/type/textCore.js
@@ -1459,22 +1459,37 @@ function textCore(p5, fn) {
Renderer.prototype.textAlign = function (h, v) {
- // the setter
- if (typeof h !== 'undefined') {
+ if (arguments.length === 0) { // the getter
+ return {
+ horizontal: this.states.textAlign,
+ vertical: this.states.textBaseline
+ };
+ }
+
+ // allow an object with horizontal and vertical properties
+ if (typeof h === 'object' && h !== null) {
+ if (h.hasOwnProperty('vertical')) {
+ v = h.vertical;
+ }
+ if (h.hasOwnProperty('horizontal')) {
+ h = h.horizontal;
+ }
+ }
+
+ // horizontal value as separate argument
+ if (typeof h === 'string' || h instanceof String) {
this.states.setValue('textAlign', h);
- if (typeof v !== 'undefined') {
- if (v === fn.CENTER) {
- v = textCoreConstants._CTX_MIDDLE;
- }
- this.states.setValue('textBaseline', v);
+ }
+
+ // vertical value as separate argument
+ if (typeof v === 'string' || v instanceof String) {
+ if (v === fn.CENTER) {
+ v = textCoreConstants._CTX_MIDDLE;
}
- return this._applyTextProperties();
+ this.states.setValue('textBaseline', v);
}
- // the getter
- return {
- horizontal: this.states.textAlign,
- vertical: this.states.textBaseline
- };
+
+ return this._applyTextProperties();
};
Renderer.prototype._currentTextFont = function () {
diff --git a/src/webgl/material.js b/src/webgl/material.js
index 2e1bc0c7e1..3d0378e26e 100644
--- a/src/webgl/material.js
+++ b/src/webgl/material.js
@@ -2652,6 +2652,8 @@ function material(p5, fn) {
*
* Note: `textureMode()` can only be used in WebGL mode.
*
+ * Calling `textureMode()` with no arguments returns the current texture mode.
+ *
* @method textureMode
* @param {(IMAGE|NORMAL)} mode either IMAGE or NORMAL.
*
@@ -2714,7 +2716,14 @@ function material(p5, fn) {
* endShape();
* }
*/
+ /**
+ * @method textureMode
+ * @return {(IMAGE|NORMAL)} The current texture mode, either IMAGE or NORMAL.
+ */
fn.textureMode = function (mode) {
+ if (typeof mode === 'undefined') { // getter
+ return this._renderer.states.textureMode;
+ }
if (mode !== constants.IMAGE && mode !== constants.NORMAL) {
console.warn(
`You tried to set ${mode} textureMode only supports IMAGE & NORMAL `,
@@ -2822,6 +2831,9 @@ function material(p5, fn) {
*
* Note: `textureWrap()` can only be used in WebGL mode.
*
+ * Calling `textureWrap()` with no arguments returns an object with the current
+ * mode for x and y directions, as in `{ wrapX: CLAMP, wrapY: REPEAT }`.
+ *
* @method textureWrap
* @param {(CLAMP|REPEAT|MIRROR)} wrapX either CLAMP, REPEAT, or MIRROR
* @param {(CLAMP|REPEAT|MIRROR)} [wrapY=wrapX] either CLAMP, REPEAT, or MIRROR
@@ -2977,13 +2989,31 @@ function material(p5, fn) {
* endShape();
* }
*/
+ /**
+ * @method textureWrap
+ * @return {{x: (CLAMP|REPEAT|MIRROR), y: (CLAMP|REPEAT|MIRROR)}} The current texture wrapping for x and y.
+ */
fn.textureWrap = function (wrapX, wrapY = wrapX) {
- this._renderer.states.setValue("textureWrapX", wrapX);
- this._renderer.states.setValue("textureWrapY", wrapY);
+ if (typeof wrapX === 'undefined') { // getter
+ return {
+ x: this._renderer.states.textureWrapX,
+ y: this._renderer.states.textureWrapY
+ };
+ }
+ // accept what is returned from the getter
+ if (wrapX.hasOwnProperty('x') && wrapX.hasOwnProperty('y')) {
+ wrapX = wrapX.x;
+ wrapY = wrapX.y;
+ }
+ this._renderer.states.setValue('textureWrapX', wrapX);
+ this._renderer.states.setValue('textureWrapY', wrapY);
- for (const texture of this._renderer.textures.values()) {
- texture.setWrapMode(wrapX, wrapY);
+ if (this._renderer.textures) {
+ for (const texture of this._renderer.textures.values()) {
+ texture.setWrapMode(wrapX, wrapY);
+ }
}
+ return this;
};
/**
diff --git a/test/unit/core/properties.js b/test/unit/core/properties.js
new file mode 100644
index 0000000000..e7def6900e
--- /dev/null
+++ b/test/unit/core/properties.js
@@ -0,0 +1,68 @@
+import p5 from '../../../src/app.js';
+
+suite('Set/get properties', function() {
+
+ let p = new p5(function (sketch) {
+ sketch.setup = function () { };
+ sketch.draw = function () { };
+ });
+
+ let getters = {
+ fill: new p5.Color([100, 200, 50]),
+ stroke: new p5.Color([200, 100, 50, 100]),
+ tint: new p5.Color([100, 140, 50]),
+
+ rectMode: p.CENTER,
+ colorMode: p.HSB,
+ blendMode: p.BLEND,
+ imageMode: p.CORNER,
+ ellipseMode: p.CORNER,
+ angleMode: p.DEGREES,
+
+ strokeWeight: 6,
+ strokeCap: p.ROUND,
+ strokeJoin: p.MITER,
+ cursor: p.HAND,
+ pixelDensity: 1,
+
+ bezierOrder: 2,
+ splineProperties: { ends: p.EXCLUDE, tightness: -5 },
+
+ textureMode: p.IMAGE, // 3D only
+ textureWrap: { x: p.REPEAT, y: p.MIRROR }, // 3D only
+
+ textAlign: { horizontal: p.CENTER, vertical: p.CENTER },
+ textLeading: 18,
+ textFont: 'arial',
+ textSize: 1,
+ textStyle: 1,
+ textWrap: p.WORD,
+ textDirection: 1,
+ textWeight: 1
+
+ // see #8278
+ // rotate: p.PI,
+ // translate: { x: 1, y: 2 },
+ // scale: { x: 1, y: 2 },
+ // background: new p5.Color([100, 100, 50])
+ };
+
+ Object.keys(getters).forEach(prop => {
+ let arg = getters[prop];
+ test(`${prop}()`, function() {
+
+ // setter
+ if (typeof arg === 'object' && !(arg instanceof p5.Color)) {
+ p[prop](...Object.values(arg)); // set with object
+ }
+ else if (Array.isArray(arg)) {
+ p[prop](...arg); // set with array
+ }
+ else {
+ p[prop](arg); // set with primitive or p5.Color
+ }
+ // getter
+ assert.strictEqual(p[prop]().toString(), arg.toString(), `${arg.toString()}`);
+ });
+ });
+});
diff --git a/test/unit/webgl/p5.RendererGL.js b/test/unit/webgl/p5.RendererGL.js
index b42562051f..4d3eaaf7aa 100644
--- a/test/unit/webgl/p5.RendererGL.js
+++ b/test/unit/webgl/p5.RendererGL.js
@@ -1492,31 +1492,52 @@ suite('p5.RendererGL', function() {
suite('tint() in WEBGL mode', function() {
test('default tint value is set and not null', function() {
myp5.createCanvas(100, 100, myp5.WEBGL);
- assert.deepEqual(myp5._renderer.states.tint, [255, 255, 255, 255]);
+ assert.deepEqual(myp5._renderer.states.tint
+ ._getRGBA([255, 255, 255, 255]), [255, 255, 255, 255]);
});
+
+
test('tint value is modified correctly when tint() is called', function() {
+
+ function assertColorEq(tint, colArray) {
+ assert.deepEqual(tint._getRGBA([255, 255, 255, 255]), colArray);
+ }
+
myp5.createCanvas(100, 100, myp5.WEBGL);
+
myp5.tint(0, 153, 204, 126);
- assert.deepEqual(myp5._renderer.states.tint, [0, 153, 204, 126]);
+ assertColorEq(myp5._renderer.states.tint, [0, 153, 204, 126]);
+
myp5.tint(100, 120, 140);
- assert.deepEqual(myp5._renderer.states.tint, [100, 120, 140, 255]);
+ assertColorEq(myp5._renderer.states.tint, [100, 120, 140, 255]);
+
myp5.tint('violet');
- assert.deepEqual(myp5._renderer.states.tint, [238, 130, 238, 255]);
+ // Note that in WEBGL mode, we don't convert color strings to arrays until the shader,
+ // so the tint state is still the string 'violet' at this point, not the array [238, 130, 238, 255].
+ //assertDeepEqualColor(myp5._renderer.states.tint, [238, 130, 238, 255]);
+ assert.equal(myp5._renderer.states.tint, 'violet');
+
myp5.tint(100);
- assert.deepEqual(myp5._renderer.states.tint, [100, 100, 100, 255]);
+ assertColorEq(myp5._renderer.states.tint, [100, 100, 100, 255]);
+
myp5.tint(100, 126);
- assert.deepEqual(myp5._renderer.states.tint, [100, 100, 100, 126]);
+ assertColorEq(myp5._renderer.states.tint, [100, 100, 100, 126]);
+
myp5.tint([100, 126, 0, 200]);
- assert.deepEqual(myp5._renderer.states.tint, [100, 126, 0, 200]);
+ assertColorEq(myp5._renderer.states.tint, [100, 126, 0, 200]);
+
myp5.tint([100, 126, 0]);
- assert.deepEqual(myp5._renderer.states.tint, [100, 126, 0, 255]);
+ assertColorEq(myp5._renderer.states.tint, [100, 126, 0, 255]);
+
myp5.tint([100]);
- assert.deepEqual(myp5._renderer.states.tint, [100, 100, 100, 255]);
+ assertColorEq(myp5._renderer.states.tint, [100, 100, 100, 255]);
+
myp5.tint([100, 126]);
- assert.deepEqual(myp5._renderer.states.tint, [100, 100, 100, 126]);
+ assertColorEq(myp5._renderer.states.tint, [100, 100, 100, 126]);
+
myp5.tint(myp5.color(255, 204, 0));
- assert.deepEqual(myp5._renderer.states.tint, [255, 204, 0, 255]);
+ assertColorEq(myp5._renderer.states.tint, [255, 204, 0, 255]);
});
test('tint should be reset after draw loop', function() {
@@ -1533,7 +1554,8 @@ suite('p5.RendererGL', function() {
};
});
}).then(function(_tint) {
- assert.deepEqual(_tint, [255, 255, 255, 255]);
+ assert.deepEqual(_tint._getRGBA([255, 255, 255, 255]),
+ [255, 255, 255, 255]);
});
});
});