diff --git a/preview/index.html b/preview/index.html
index 18f9d06e37..d0f3b329ae 100644
--- a/preview/index.html
+++ b/preview/index.html
@@ -20,14 +20,27 @@
import p5 from '../src/app.js';
const sketch = function (p) {
+ let fbo;
p.setup = async function () {
- p.createCanvas(400, 400);
+ p.createCanvas(400, 400, p.WEBGL);
+ fbo = p.createFramebuffer()
};
p.draw = function () {
+ p.push();
p.background(200);
+ fbo.begin()
+ p.background('blue')
p.strokeWeight(10);
+ p.push()
+ p.stroke('red')
p.line(-100, -100, 100, 100);
+ p.pop()
+ p.translate(200, 200)
+ p.line(-100, -100, 100, 100);
+ fbo.end()
+ p.image(fbo, 0, 0)
+ p.pop();
};
};
diff --git a/src/color/creating_reading.js b/src/color/creating_reading.js
index 026cff0154..4d73073524 100644
--- a/src/color/creating_reading.js
+++ b/src/color/creating_reading.js
@@ -52,15 +52,13 @@ function creatingReading(p5, fn){
[OKLAB]: [100, [-125, 125], [-125, 125], 1],
[OKLCH]: [100, 150, 360, 1],
clone: function(){
- let ret = {};
- for(const key in this){
- if(typeof this[key] !== 'function'){
- ret[key] = structuredClone(this[key]);
- }else{
- ret[key] = this[key];
+ const cloned = { ...this };
+ for (const key in cloned) {
+ if (cloned[key] instanceof Array) {
+ cloned[key] = [...cloned[key]];
}
}
- return ret;
+ return cloned;
}
};
diff --git a/src/color/p5.Color.js b/src/color/p5.Color.js
index 2a2a3824ac..d9f7bb95ff 100644
--- a/src/color/p5.Color.js
+++ b/src/color/p5.Color.js
@@ -33,6 +33,8 @@ import HSBSpace from './color_spaces/hsb.js';
const map = (n, start1, stop1, start2, stop2) =>
((n - start1) / (stop1 - start1) * (stop2 - start2) + start2);
+const serializationMap = {};
+
class Color {
// Reference to underlying color object depending on implementation
// Not meant to be used publicly unless the implementation is known for sure
@@ -242,10 +244,16 @@ class Color {
*
*/
toString(format) {
- // NOTE: memoize
- return serialize(this._color, {
- format
- });
+ const key = `${this._color.space.id}-${this._color.coords.join(",")}-${this._color.alpha}-${format}`;
+ let colorString = serializationMap[key];
+
+ if(!colorString){
+ colorString = serialize(this._color, {
+ format
+ });
+ serializationMap[key] = colorString;
+ }
+ return colorString;
}
/**
diff --git a/src/color/setting.js b/src/color/setting.js
index 1a233ca9bb..0028aebe43 100644
--- a/src/color/setting.js
+++ b/src/color/setting.js
@@ -964,9 +964,10 @@ function setting(p5, fn){
].includes(mode)
) {
// Set color mode.
- this._renderer.states.colorMode = mode;
+ this._renderer.states.setValue('colorMode', mode);
// Set color maxes.
+ this._renderer.states.setValue('colorMaxes', this._renderer.states.colorMaxes.clone());
const maxes = this._renderer.states.colorMaxes[mode];
if (arguments.length === 2) {
maxes[0] = max1; // Red
@@ -1335,7 +1336,7 @@ function setting(p5, fn){
*
*/
fn.noStroke = function() {
- this._renderer.states.strokeColor = null;
+ this._renderer.states.setValue('strokeColor', null);
return this;
};
diff --git a/src/core/States.js b/src/core/States.js
new file mode 100644
index 0000000000..a70a6300c2
--- /dev/null
+++ b/src/core/States.js
@@ -0,0 +1,33 @@
+export class States {
+ #modified = {};
+
+ constructor(initialState) {
+ for (const key in initialState) {
+ this[key] = initialState[key];
+ }
+ }
+
+ setValue(key, value) {
+ if (!(key in this.#modified)) {
+ this.#modified[key] = this[key];
+ }
+ this[key] = value;
+ }
+
+ getDiff() {
+ const diff = this.#modified;
+ this.#modified = {};
+ return diff;
+ }
+
+ getModified() {
+ return this.#modified;
+ }
+
+ applyDiff(prevModified) {
+ for (const key in this.#modified) {
+ this[key] = this.#modified[key];
+ }
+ this.#modified = prevModified;
+ }
+}
diff --git a/src/core/p5.Renderer.js b/src/core/p5.Renderer.js
index e5ba194d63..ea4e875014 100644
--- a/src/core/p5.Renderer.js
+++ b/src/core/p5.Renderer.js
@@ -9,6 +9,7 @@ import * as constants from '../core/constants';
import { Image } from '../image/p5.Image';
import { Vector } from '../math/p5.Vector';
import { Shape } from '../shape/custom_shapes';
+import { States } from './States';
class ClonableObject {
constructor(obj = {}) {
@@ -70,15 +71,7 @@ class Renderer {
}
// Renderer state machine
- this.states = Object.assign({}, Renderer.states);
- // Clone properties that support it
- for (const key in this.states) {
- if (this.states[key] instanceof Array) {
- this.states[key] = this.states[key].slice();
- } else if (this.states[key] && this.states[key].clone instanceof Function) {
- this.states[key] = this.states[key].clone();
- }
- }
+ this.states = new States(Renderer.states);
this.states.strokeColor = new Color([0, 0, 0]);
this.states.fillColor = new Color([255, 255, 255]);
@@ -122,33 +115,25 @@ class Renderer {
// and push it into the push pop stack
push() {
this._pushPopDepth++;
- const currentStates = Object.assign({}, this.states);
- // Clone properties that support it
- for (const key in currentStates) {
- if (currentStates[key] instanceof Array) {
- currentStates[key] = currentStates[key].slice();
- } else if (currentStates[key] && currentStates[key].clone instanceof Function) {
- currentStates[key] = currentStates[key].clone();
- }
- }
- this._pushPopStack.push(currentStates);
- return currentStates;
+ this._pushPopStack.push(this.states.getDiff());
}
// Pop the previous states out of the push pop stack and
// assign it back to the current state
pop() {
this._pushPopDepth--;
- Object.assign(this.states, this._pushPopStack.pop());
- this.updateShapeVertexProperties();
- this.updateShapeProperties();
+ const diff = this._pushPopStack.pop() || {};
+ const modified = this.states.getModified();
+ this.states.applyDiff(diff);
+ this.updateShapeVertexProperties(modified);
+ this.updateShapeProperties(modified);
}
bezierOrder(order) {
if (order === undefined) {
return this.states.bezierOrder;
} else {
- this.states.bezierOrder = order;
+ this.states.setValue('bezierOrder', order);
this.updateShapeProperties();
}
}
@@ -165,6 +150,7 @@ class Renderer {
if (value === undefined) {
return this.states.splineProperties[key];
} else {
+ this.states.setValue('splineProperties', this.states.splineProperties.clone());
this.states.splineProperties[key] = value;
}
this.updateShapeProperties();
@@ -182,7 +168,7 @@ class Renderer {
if (d === undefined) {
return this.states.curveDetail;
} else {
- this.states.curveDetail = d;
+ this.states.setValue('curveDetail', d);
}
}
@@ -277,31 +263,31 @@ class Renderer {
}
fill(...args) {
- this.states.fillSet = true;
- this.states.fillColor = this._pInst.color(...args);
+ this.states.setValue('fillSet', true);
+ this.states.setValue('fillColor', this._pInst.color(...args));
this.updateShapeVertexProperties();
}
noFill() {
- this.states.fillColor = null;
+ this.states.setValue('fillColor', null);
}
strokeWeight(w) {
if (w === undefined) {
return this.states.strokeWeight;
} else {
- this.states.strokeWeight = w;
+ this.states.setValue('strokeWeight', w);
}
}
stroke(...args) {
- this.states.strokeSet = true;
- this.states.strokeColor = this._pInst.color(...args);
+ this.states.setValue('strokeSet', true);
+ this.states.setValue('strokeColor', this._pInst.color(...args));
this.updateShapeVertexProperties();
}
noStroke() {
- this.states.strokeColor = null;
+ this.states.setValue('strokeColor', null);
}
getCommonVertexProperties() {
@@ -314,25 +300,31 @@ class Renderer {
}
}
- updateShapeProperties() {
- this.currentShape.bezierOrder(this.states.bezierOrder);
- this.currentShape.splineProperty('ends', this.states.splineProperties.ends);
- this.currentShape.splineProperty('tightness', this.states.splineProperties.tightness);
+ updateShapeProperties(modified) {
+ if (!modified || modified.bezierOrder || modified.splineProperties) {
+ const shape = this.currentShape;
+ shape.bezierOrder(this.states.bezierOrder);
+ shape.splineProperty('ends', this.states.splineProperties.ends);
+ shape.splineProperty('tightness', this.states.splineProperties.tightness);
+ }
}
- updateShapeVertexProperties() {
+ updateShapeVertexProperties(modified) {
const props = this.getCommonVertexProperties();
- for (const key in props) {
- this.currentShape[key](props[key]);
+ if (!modified || Object.keys(modified).some((k) => k in props)) {
+ const shape = this.currentShape;
+ for (const key in props) {
+ shape[key](props[key]);
+ }
}
}
textSize(s) {
if (typeof s === 'number') {
- this.states.textSize = s;
+ this.states.setValue('textSize', s);
if (!this.states.leadingSet) {
// only use a default value if not previously set (#5181)
- this.states.textLeading = s * constants._DEFAULT_LEADMULT;
+ this.states.setValue('textLeading', s * constants._DEFAULT_LEADMULT);
}
return this._applyTextProperties();
}
@@ -342,8 +334,8 @@ class Renderer {
textLeading (l) {
if (typeof l === 'number') {
- this.states.leadingSet = true;
- this.states.textLeading = l;
+ this.states.setValue('leadingSet', true);
+ this.states.setValue('textLeading', l);
return this._pInst;
}
@@ -358,7 +350,7 @@ class Renderer {
s === constants.BOLD ||
s === constants.BOLDITALIC
) {
- this.states.fontStyle = s;
+ this.states.setValue('fontStyle', s);
}
return this._applyTextProperties();
@@ -383,10 +375,10 @@ class Renderer {
textAlign (h, v) {
if (typeof h !== 'undefined') {
- this.states.textAlign = h;
+ this.states.setValue('textAlign', h);
if (typeof v !== 'undefined') {
- this.states.textBaseline = v;
+ this.states.setValue('textBaseline', v);
}
return this._applyTextProperties();
@@ -399,7 +391,7 @@ class Renderer {
}
textWrap (wrapStyle) {
- this.states.textWrap = wrapStyle;
+ this.states.setValue('textWrap', wrapStyle);
return this.states.textWrap;
}
@@ -647,8 +639,8 @@ class Renderer {
_updateTextMetrics() {
if (this._isOpenType()) {
- this.states.textAscent = this.states.textFont._textAscent();
- this.states.textDescent = this.states.textFont._textDescent();
+ this.states.setValue('textAscent', this.states.textFont._textAscent());
+ this.states.setValue('textDescent', this.states.textFont._textDescent());
return this;
}
@@ -684,8 +676,8 @@ class Renderer {
document.body.removeChild(container);
- this.states.textAscent = ascent;
- this.states.textDescent = descent;
+ this.states.setValue('textAscent', ascent);
+ this.states.setValue('textDescent', descent);
return this;
}
diff --git a/src/core/p5.Renderer2D.js b/src/core/p5.Renderer2D.js
index 84b37034f7..311d5d12fc 100644
--- a/src/core/p5.Renderer2D.js
+++ b/src/core/p5.Renderer2D.js
@@ -119,7 +119,8 @@ class Renderer2D extends Renderer {
}
_applyDefaults() {
- this._cachedFillStyle = this._cachedStrokeStyle = undefined;
+ this.states.setValue('_cachedFillStyle', undefined);
+ this.states.setValue('_cachedStrokeStyle', undefined);
this._cachedBlendMode = constants.BLEND;
this._setFill(constants._DEFAULT_FILL);
this._setStroke(constants._DEFAULT_STROKE);
@@ -163,7 +164,7 @@ class Renderer2D extends Renderer {
//////////////////////////////////////////////
background(...args) {
- this.drawingContext.save();
+ this.push();
this.resetMatrix();
if (args[0] instanceof Image) {
@@ -176,7 +177,6 @@ class Renderer2D extends Renderer {
this._pInst.image(args[0], 0, 0, this.width, this.height);
}
} else {
- const curFill = this._getFill();
// create background rect
const color = this._pInst.color(...args);
@@ -193,14 +193,12 @@ class Renderer2D extends Renderer {
}
this.drawingContext.fillRect(0, 0, this.width, this.height);
- // reset fill
- this._setFill(curFill);
if (this._isErasing) {
this._pInst.erase();
}
}
- this.drawingContext.restore();
+ this.pop();
}
clear() {
@@ -235,12 +233,12 @@ class Renderer2D extends Renderer {
erase(opacityFill, opacityStroke) {
if (!this._isErasing) {
// cache the fill style
- this._cachedFillStyle = this.drawingContext.fillStyle;
+ this.states.setValue('_cachedFillStyle', this.drawingContext.fillStyle);
const newFill = this._pInst.color(255, opacityFill).toString();
this.drawingContext.fillStyle = newFill;
// cache the stroke style
- this._cachedStrokeStyle = this.drawingContext.strokeStyle;
+ this.states.setValue('_cachedStrokeStyle', this.drawingContext.strokeStyle);
const newStroke = this._pInst.color(255, opacityStroke).toString();
this.drawingContext.strokeStyle = newStroke;
@@ -255,8 +253,8 @@ class Renderer2D extends Renderer {
noErase() {
if (this._isErasing) {
- this.drawingContext.fillStyle = this._cachedFillStyle;
- this.drawingContext.strokeStyle = this._cachedStrokeStyle;
+ this.drawingContext.fillStyle = this.states._cachedFillStyle;
+ this.drawingContext.strokeStyle = this.states._cachedStrokeStyle;
this.blendMode(this._cachedBlendMode);
this._isErasing = false;
@@ -282,12 +280,12 @@ class Renderer2D extends Renderer {
super.beginClip(options);
// cache the fill style
- this._cachedFillStyle = this.drawingContext.fillStyle;
+ this.states.setValue('_cachedFillStyle', this.drawingContext.fillStyle);
const newFill = this._pInst.color(255, 0).toString();
this.drawingContext.fillStyle = newFill;
// cache the stroke style
- this._cachedStrokeStyle = this.drawingContext.strokeStyle;
+ this.states.setValue('_cachedStrokeStyle', this.drawingContext.strokeStyle);
const newStroke = this._pInst.color(255, 0).toString();
this.drawingContext.strokeStyle = newStroke;
@@ -330,8 +328,8 @@ class Renderer2D extends Renderer {
super.endClip();
- this.drawingContext.fillStyle = this._cachedFillStyle;
- this.drawingContext.strokeStyle = this._cachedStrokeStyle;
+ this.drawingContext.fillStyle = this.states._cachedFillStyle;
+ this.drawingContext.strokeStyle = this.states._cachedStrokeStyle;
this.blendMode(this._cachedBlendMode);
}
@@ -945,30 +943,30 @@ class Renderer2D extends Renderer {
}
_getFill() {
- if (!this._cachedFillStyle) {
- this._cachedFillStyle = this.drawingContext.fillStyle;
+ if (!this.states._cachedFillStyle) {
+ this.states.setValue('_cachedFillStyle', this.drawingContext.fillStyle);
}
- return this._cachedFillStyle;
+ return this.states._cachedFillStyle;
}
_setFill(fillStyle) {
- if (fillStyle !== this._cachedFillStyle) {
+ if (fillStyle !== this.states._cachedFillStyle) {
this.drawingContext.fillStyle = fillStyle;
- this._cachedFillStyle = fillStyle;
+ this.states.setValue('_cachedFillStyle', fillStyle);
}
}
_getStroke() {
- if (!this._cachedStrokeStyle) {
- this._cachedStrokeStyle = this.drawingContext.strokeStyle;
+ if (!this.states._cachedStrokeStyle) {
+ this.states.setValue('_cachedStrokeStyle', this.drawingContext.strokeStyle);
}
- return this._cachedStrokeStyle;
+ return this.states._cachedStrokeStyle;
}
_setStroke(strokeStyle) {
- if (strokeStyle !== this._cachedStrokeStyle) {
+ if (strokeStyle !== this.states._cachedStrokeStyle) {
this.drawingContext.strokeStyle = strokeStyle;
- this._cachedStrokeStyle = strokeStyle;
+ this.states.setValue('_cachedStrokeStyle', strokeStyle);
}
}
@@ -1104,14 +1102,14 @@ class Renderer2D extends Renderer {
let font;
const p = this._pInst;
- this.states.textAscent = null;
- this.states.textDescent = null;
+ this.states.setValue('textAscent', null);
+ this.states.setValue('textDescent', null);
font = this.states.textFont;
if (this._isOpenType()) {
font = this.states.textFont.font.familyName;
- this.states.textStyle = this._textFont.font.styleName;
+ this.states.setValue('textStyle', this._textFont.font.styleName);
}
let fontNameString = font || 'sans-serif';
@@ -1155,9 +1153,6 @@ class Renderer2D extends Renderer {
// class' pop method
pop(style) {
this.drawingContext.restore();
- // Re-cache the fill / stroke state
- this._cachedFillStyle = this.drawingContext.fillStyle;
- this._cachedStrokeStyle = this.drawingContext.strokeStyle;
super.pop(style);
}
diff --git a/src/image/filterRenderer2D.js b/src/image/filterRenderer2D.js
index 6a3f194466..8d4ac5c274 100644
--- a/src/image/filterRenderer2D.js
+++ b/src/image/filterRenderer2D.js
@@ -184,8 +184,8 @@ class FilterRenderer2D {
this._shader.setUniform('radius', Math.max(1, this.filterParameter));
this._shader.setUniform('filterParameter', this.filterParameter);
- this.pInst.states.rectMode = constants.CORNER;
- this.pInst.states.imageMode = constants.CORNER;
+ this.pInst.states.setValue('rectMode', constants.CORNER);
+ this.pInst.states.setValue('imageMode', constants.CORNER);
this.pInst.blendMode(constants.BLEND);
this.pInst.resetMatrix();
diff --git a/src/image/loading_displaying.js b/src/image/loading_displaying.js
index 677b768464..8b4399129c 100644
--- a/src/image/loading_displaying.js
+++ b/src/image/loading_displaying.js
@@ -1291,7 +1291,7 @@ function loadingDisplaying(p5, fn){
fn.tint = function(...args) {
// p5._validateParameters('tint', args);
const c = this.color(...args);
- this._renderer.states.tint = c._getRGBA([255, 255, 255, 255]);
+ this._renderer.states.setValue('tint', c._getRGBA([255, 255, 255, 255]));
};
/**
@@ -1330,7 +1330,7 @@ function loadingDisplaying(p5, fn){
*
*/
fn.noTint = function() {
- this._renderer.states.tint = null;
+ this._renderer.states.setValue('tint', null);
};
/**
@@ -1449,7 +1449,7 @@ function loadingDisplaying(p5, fn){
m === constants.CORNERS ||
m === constants.CENTER
) {
- this._renderer.states.imageMode = m;
+ this._renderer.states.setValue('imageMode', m);
}
};
}
diff --git a/src/math/Matrices/Matrix.js b/src/math/Matrices/Matrix.js
index 58ee51fd26..3711d87f51 100644
--- a/src/math/Matrices/Matrix.js
+++ b/src/math/Matrices/Matrix.js
@@ -17,55 +17,55 @@ if (typeof Float32Array !== "undefined") {
}
/**
* The `Matrix` class represents a mathematical matrix and provides various methods for matrix operations.
- *
+ *
* This class extends the `MatrixInterface` and includes methods for creating, manipulating, and performing
* operations on matrices. It supports both 3x3 and 4x4 matrices, as well as general NxN matrices.
- *
+ *
* @class
* @extends MatrixInterface
- *
+ *
* @example
* // Creating a 3x3 matrix from an array
* const matrix = new Matrix([1, 2, 3, 4, 5, 6, 7, 8, 9]);
- *
+ *
* // Creating a 4x4 identity matrix
* const identityMatrix = new Matrix(4);
- *
+ *
* // Adding two matrices
* const matrix1 = new Matrix([1, 2, 3, 4, 5, 6, 7, 8, 9]);
* const matrix2 = new Matrix([9, 8, 7, 6, 5, 4, 3, 2, 1]);
* matrix1.add(matrix2); // matrix1 is now [10, 10, 10, 10, 10, 10, 10, 10, 10]
- *
+ *
* // Setting an element in the matrix
* matrix.setElement(0, 10); // matrix is now [10, 2, 3, 4, 5, 6, 7, 8, 9]
- *
+ *
* // Resetting the matrix to an identity matrix
* matrix.reset();
- *
+ *
* // Getting the diagonal elements of the matrix
* const diagonal = matrix.diagonal(); // [1, 1, 1]
- *
+ *
* // Transposing the matrix
* matrix.transpose();
- *
+ *
* // Multiplying two matrices
* matrix1.mult(matrix2);
- *
+ *
* // Inverting the matrix
* matrix.invert();
- *
+ *
* // Scaling the matrix
* matrix.scale(2, 2, 2);
- *
+ *
* // Rotating the matrix around an axis
* matrix.rotate4x4(Math.PI / 4, 1, 0, 0);
- *
+ *
* // Applying a perspective transformation
* matrix.perspective(Math.PI / 4, 1, 0.1, 100);
- *
+ *
* // Applying an orthographic transformation
* matrix.ortho(-1, 1, -1, 1, 0.1, 100);
- *
+ *
* // Multiplying a vector by the matrix
* const vector = new Vector(1, 2, 3);
* const result = matrix.multiplyPoint(vector);
@@ -81,7 +81,7 @@ export class Matrix extends MatrixInterface {
if (isMatrixArray(args[0]) && isPerfectSquare(args[0])) {
const sqDimention = Math.sqrt(Array.from(args[0]).length);
this.#sqDimention = sqDimention;
- this.matrix = Array.from(args[0]);
+ this.matrix = GLMAT_ARRAY_TYPE.from(args[0]);
} else if (typeof args[0] === "number") {
this.#sqDimention = Number(args[0]);
this.matrix = this.#createIdentityMatrix(args[0]);
@@ -91,10 +91,10 @@ export class Matrix extends MatrixInterface {
/**
* Getter for a 3x3 matrix.
- *
- * This method returns the matrix if its dimensions are 3x3.
+ *
+ * This method returns the matrix if its dimensions are 3x3.
* If the matrix is not 3x3, it returns `undefined`.
- *
+ *
* @returns {Array|undefined} The 3x3 matrix or `undefined` if the matrix is not 3x3.
*/
get mat3() {
@@ -107,10 +107,10 @@ export class Matrix extends MatrixInterface {
/**
* Getter for a 4x4 matrix.
- *
+ *
* This method returns the matrix if its dimensions are 4x4.
* If the matrix is not 4x4, it returns `undefined`.
- *
+ *
* @returns {Array|undefined} The 4x4 matrix or `undefined` if the matrix is not 4x4.
*/
get mat4() {
@@ -123,11 +123,11 @@ export class Matrix extends MatrixInterface {
/**
* Adds the corresponding elements of the given matrix to this matrix.
- *
+ *
* @param {Matrix} matrix - The matrix to add to this matrix. It must have the same dimensions as this matrix.
* @returns {Matrix} The resulting matrix after addition.
* @throws {Error} If the matrices do not have the same dimensions.
- *
+ *
* @example
* const matrix1 = new Matrix([1, 2, 3]);
* const matrix2 = new Matrix([4, 5, 6]);
@@ -146,7 +146,7 @@ export class Matrix extends MatrixInterface {
/**
* Sets the value of a specific element in the matrix.
*
- * @param {number} index - The position in the matrix where the value should be set.
+ * @param {number} index - The position in the matrix where the value should be set.
* Must be a non-negative integer less than the length of the matrix.
* @param {*} value - The new value to be assigned to the specified position in the matrix.
* @returns {Matrix} The current instance of the Matrix, allowing for method chaining.
@@ -165,10 +165,10 @@ export class Matrix extends MatrixInterface {
/**
* Resets the current matrix to an identity matrix.
- *
+ *
* This method replaces the current matrix with an identity matrix of the same dimensions.
* An identity matrix is a square matrix with ones on the main diagonal and zeros elsewhere.
- *
+ *
* @returns {Matrix} The current instance of the Matrix class, allowing for method chaining.
*/
reset() {
@@ -192,11 +192,11 @@ export class Matrix extends MatrixInterface {
* @chainable
*/
set(inMatrix) {
- let refArray = Array.from([...arguments]);
+ let refArray = GLMAT_ARRAY_TYPE.from([...arguments]);
if (inMatrix instanceof Matrix) {
- refArray = inMatrix.matrix;
+ refArray = GLMAT_ARRAY_TYPE.from(inMatrix.matrix);
} else if (isMatrixArray(inMatrix)) {
- refArray = inMatrix;
+ refArray = GLMAT_ARRAY_TYPE.from(inMatrix);
}
if (refArray.length !== this.matrix.length) {
p5._friendlyError(
@@ -205,7 +205,7 @@ export class Matrix extends MatrixInterface {
);
return this;
}
- this.matrix = [...refArray];
+ this.matrix = refArray;
return this;
}
@@ -283,16 +283,16 @@ export class Matrix extends MatrixInterface {
return new Vector(...rowVector);
}
-
+
/**
* Transposes the given matrix `a` based on the square dimension of the matrix.
- *
+ *
* This method rearranges the elements of the matrix such that the rows become columns
* and the columns become rows. It handles matrices of different dimensions (4x4, 3x3, NxN)
* by delegating to specific transpose methods for each case.
- *
+ *
* @param {Array} a - The matrix to be transposed. It should be a 2D array where each sub-array represents a row.
* @returns {Array} - The transposed matrix.
*/
@@ -310,17 +310,17 @@ export class Matrix extends MatrixInterface {
}
}
-
+
/**
* Multiplies the current matrix with another matrix or matrix-like array.
- *
+ *
* This method supports several types of input:
* - Another Matrix instance
* - A matrix-like array (must be a perfect square, e.g., 4x4 or 3x3)
* - Multiple arguments that form a perfect square matrix
- *
+ *
* If the input is the same as the current matrix, a copy is made to avoid modifying the original matrix.
- *
+ *
* @param {Matrix|Array|...number} multMatrix - The matrix or matrix-like array to multiply with.
* @returns {Matrix|undefined} The resulting matrix after multiplication, or undefined if the input is invalid.
* @chainable
@@ -368,10 +368,10 @@ export class Matrix extends MatrixInterface {
/**
* Inverts a given matrix.
- *
+ *
* This method inverts a matrix based on its dimensions. Currently, it supports
* 3x3 and 4x4 matrices. If the matrix dimension is greater than 4, an error is thrown.
- *
+ *
* @param {Array} a - The matrix to be inverted. It should be a 2D array representing the matrix.
* @returns {Array} - The inverted matrix.
* @throws {Error} - Throws an error if the matrix dimension is greater than 4.
@@ -687,7 +687,7 @@ export class Matrix extends MatrixInterface {
* Rotates the matrix around the Z-axis by a given angle.
*
* @param {number} a - The angle in radians to rotate the matrix by.
- *
+ *
* This method modifies the current matrix to apply a rotation transformation
* around the Z-axis. The rotation is performed in a 4x4 matrix context, which
* is commonly used in 3D graphics to handle transformations.
@@ -880,12 +880,12 @@ export class Matrix extends MatrixInterface {
/**
* Multiplies the current 4x4 matrix with another 4x4 matrix.
* This method updates the current matrix with the result of the multiplication.
- *
+ *
* @private
* @param {number[]} _src - A 16-element array representing the 4x4 matrix to multiply with.
- *
+ *
* @returns {this} The current instance with the updated matrix.
- *
+ *
* @example
* // Assuming `matrix` is an instance of the Matrix class
* const srcMatrix = [
@@ -1010,7 +1010,7 @@ export class Matrix extends MatrixInterface {
/**
* Transposes a square matrix in place.
* This method swaps the rows and columns of the matrix, effectively flipping it over its diagonal.
- *
+ *
* @private
* @returns {Matrix} The current instance of the Matrix, with the transposed values.
*/
diff --git a/src/shape/attributes.js b/src/shape/attributes.js
index 317d510245..77ea6e0a6e 100644
--- a/src/shape/attributes.js
+++ b/src/shape/attributes.js
@@ -92,7 +92,7 @@ function attributes(p5, fn){
m === constants.RADIUS ||
m === constants.CENTER
) {
- this._renderer.states.ellipseMode = m;
+ this._renderer.states.setValue('ellipseMode', m);
}
return this;
};
@@ -295,7 +295,7 @@ function attributes(p5, fn){
m === constants.RADIUS ||
m === constants.CENTER
) {
- this._renderer.states.rectMode = m;
+ this._renderer.states.setValue('rectMode', m);
}
return this; // return current rectMode ?
};
diff --git a/src/shape/custom_shapes.js b/src/shape/custom_shapes.js
index cb53761d19..ef4104336f 100644
--- a/src/shape/custom_shapes.js
+++ b/src/shape/custom_shapes.js
@@ -609,7 +609,7 @@ class Shape {
}
serializeToArray(val) {
- if (val === null) {
+ if (val === null || val === undefined) {
return [];
} if (val instanceof Number) {
return [val];
diff --git a/src/type/textCore.js b/src/type/textCore.js
index 99aa3f5225..4bf8abe502 100644
--- a/src/type/textCore.js
+++ b/src/type/textCore.js
@@ -199,19 +199,19 @@ function textCore(p5, fn) {
return this.textDrawingContext().measureText('_').fontBoundingBoxDescent;
};
-
+
// setters/getters for text properties //////////////////////////
Renderer.prototype.textAlign = function (h, v) {
// the setter
if (typeof h !== 'undefined') {
- this.states.textAlign = h;
+ this.states.setValue('textAlign', h);
if (typeof v !== 'undefined') {
if (v === fn.CENTER) {
v = fn._CTX_MIDDLE;
}
- this.states.textBaseline = v;
+ this.states.setValue('textBaseline', v);
}
return this._applyTextProperties();
}
@@ -267,7 +267,7 @@ function textCore(p5, fn) {
}
// update font properties in this.states
- this.states.textFont = { font, family, size };
+ this.states.setValue('textFont', { font, family, size });
// convert/update the size in this.states
if (typeof size !== 'undefined') {
@@ -298,17 +298,14 @@ function textCore(p5, fn) {
if (debug) console.log(' this.states.' + prop + '="' + style[prop] + '"');
});
- if (debug) console.log(' this.states.textFont="' + style.fontFamily + '"');
- if (debug) console.log(' this.states.textSize="' + style.fontSize + '"');
-
return { family: style.fontFamily, size: style.fontSize };
}
Renderer.prototype.textLeading = function (leading) {
// the setter
if (typeof leading === 'number') {
- this.states.leadingSet = true;
- this.states.textLeading = leading;
+ this.states.setValue('leadingSet', true);
+ this.states.setValue('textLeading', leading);
return this._applyTextProperties();
}
// the getter
@@ -318,7 +315,7 @@ function textCore(p5, fn) {
Renderer.prototype.textWeight = function (weight) {
// the setter
if (typeof weight === 'number') {
- this.states.fontWeight = weight;
+ this.states.setValue('fontWeight', weight);
this._applyTextProperties();
this._setCanvasStyleProperty('font-variation-settings', `"wght" ${weight}`);
return;
@@ -345,7 +342,7 @@ function textCore(p5, fn) {
// the setter
if (typeof style !== 'undefined') {
- this.states.fontStyle = style;
+ this.states.setValue('fontStyle', style);
return this._applyTextProperties();
}
// the getter
@@ -355,7 +352,7 @@ function textCore(p5, fn) {
Renderer.prototype.textWrap = function (wrapStyle) {
if (wrapStyle === fn.WORD || wrapStyle === fn.CHAR) {
- this.states.textWrap = wrapStyle;
+ this.states.setValue('textWrap', wrapStyle);
// no need to apply text properties here as not a context property
return this._pInst;
}
@@ -365,7 +362,7 @@ function textCore(p5, fn) {
Renderer.prototype.textDirection = function (direction) {
if (typeof direction !== 'undefined') {
- this.states.direction = direction;
+ this.states.setValue('direction', direction);
return this._applyTextProperties();
}
return this.states.direction;
@@ -621,7 +618,7 @@ function textCore(p5, fn) {
const min = Math.min.apply(Math, indexArr)
let idx = indexArr.indexOf(min);
let stretch = Object.keys(FontStretchMap)[idx];
- this.states.fontStretch = stretch;
+ this.states.setValue('fontStretch', stretch);
}
break;
case 'ital':
@@ -933,11 +930,11 @@ function textCore(p5, fn) {
// set it in `this.states` if its been changed
if (this.states.textSize !== theSize) {
- this.states.textSize = theSize;
+ this.states.setValue('textSize', theSize);
// handle leading here, if not set otherwise
if (!this.states.leadingSet) {
- this.states.textLeading = this.states.textSize * LeadingScale;
+ this.states.setValue('textLeading', this.states.textSize * LeadingScale);
}
return true; // size was changed
}
diff --git a/src/webgl/3d_primitives.js b/src/webgl/3d_primitives.js
index 1c880d87d0..377021ad03 100644
--- a/src/webgl/3d_primitives.js
+++ b/src/webgl/3d_primitives.js
@@ -1712,11 +1712,11 @@ function primitives3D(p5, fn){
x1, y1, 0, 1 // the resulting origin
]).mult(this.states.uModelMatrix);
- this.states.uModelMatrix = mult;
+ this.states.setValue('uModelMatrix', mult);
this._drawGeometry(this.geometryBufferCache.getGeometryByID(gid));
} finally {
- this.states.uModelMatrix = uModelMatrix;
+ this.states.setValue('uModelMatrix', uModelMatrix);
}
return this;
@@ -1839,7 +1839,8 @@ function primitives3D(p5, fn){
this.geometryBufferCache.ensureCached(arcGeom);
}
- const uModelMatrix = this.states.uModelMatrix.copy();
+ const uModelMatrix = this.states.uModelMatrix;
+ this.states.setValue('uModelMatrix', this.states.uModelMatrix.clone());
try {
this.states.uModelMatrix.translate([x, y, 0]);
@@ -1847,7 +1848,7 @@ function primitives3D(p5, fn){
this._drawGeometry(this.geometryBufferCache.getGeometryByID(gid));
} finally {
- this.states.uModelMatrix = uModelMatrix;
+ this.states.setValue('uModelMatrix', uModelMatrix);
}
return this;
@@ -1900,14 +1901,15 @@ function primitives3D(p5, fn){
// opposite corners at (0,0) & (1,1).
//
// before rendering, this square is scaled & moved to the required location.
- const uModelMatrix = this.states.uModelMatrix.copy();
+ const uModelMatrix = this.states.uModelMatrix;
+ this.states.setValue('uModelMatrix', this.states.uModelMatrix.copy());
try {
this.states.uModelMatrix.translate([x, y, 0]);
this.states.uModelMatrix.scale(width, height, 1);
this._drawGeometry(this.geometryBufferCache.getGeometryByID(gid));
} finally {
- this.states.uModelMatrix = uModelMatrix;
+ this.states.setValue('uModelMatrix', uModelMatrix);
}
} else {
// Use Immediate mode to round the rectangle corner,
@@ -1949,7 +1951,7 @@ function primitives3D(p5, fn){
let y2 = d;
const prevMode = this.states.textureMode;
- this.states.textureMode = constants.NORMAL;
+ this.states.setValue('textureMode', constants.NORMAL);
const prevOrder = this.bezierOrder();
this.bezierOrder(2);
this.beginShape();
@@ -1984,7 +1986,7 @@ function primitives3D(p5, fn){
}
this.endShape(constants.CLOSE);
- this.states.textureMode = prevMode;
+ this.states.setValue('textureMode', prevMode);
this.bezierOrder(prevOrder);
}
return this;
@@ -2184,10 +2186,10 @@ function primitives3D(p5, fn){
this.push();
this.noLights();
- this.states.strokeColor = null;;
+ this.states.setValue('strokeColor', null);
this.texture(img);
- this.states.textureMode = constants.NORMAL;
+ this.states.setValue('textureMode', constants.NORMAL);
let u0 = 0;
if (sx <= img.width) {
diff --git a/src/webgl/GeometryBuilder.js b/src/webgl/GeometryBuilder.js
index 5cb4862168..83d2fb90de 100644
--- a/src/webgl/GeometryBuilder.js
+++ b/src/webgl/GeometryBuilder.js
@@ -12,7 +12,7 @@ class GeometryBuilder {
this.renderer = renderer;
renderer._pInst.push();
this.identityMatrix = new Matrix(4);
- renderer.states.uModelMatrix = new Matrix(4);
+ renderer.states.setValue('uModelMatrix', new Matrix(4));
this.geometry = new Geometry(undefined, undefined, undefined, this.renderer);
this.geometry.gid = `_p5_GeometryBuilder_${GeometryBuilder.nextGeometryId}`;
GeometryBuilder.nextGeometryId++;
diff --git a/src/webgl/interaction.js b/src/webgl/interaction.js
index 1b257ce6fd..60af792069 100644
--- a/src/webgl/interaction.js
+++ b/src/webgl/interaction.js
@@ -364,6 +364,7 @@ function interaction(p5, fn){
10, -this._renderer.zoomVelocity
);
// modify uPMatrix
+ this._renderer.states.setValue('uPMatrix', this._renderer.states.uPMatrix.clone());
this._renderer.states.uPMatrix.mat4[0] = cam.projMatrix.mat4[0];
this._renderer.states.uPMatrix.mat4[5] = cam.projMatrix.mat4[5];
}
@@ -814,6 +815,7 @@ function interaction(p5, fn){
this._renderer.states.curStrokeColor[1] * 255,
this._renderer.states.curStrokeColor[2] * 255
);
+ this._renderer.states.setValue('uModelMatrix', this._renderer.states.uModelMatrix.clone());
this._renderer.states.uModelMatrix.reset();
// Lines along X axis
@@ -861,6 +863,7 @@ function interaction(p5, fn){
return function() {
this.push();
+ this._renderer.states.setValue('uModelMatrix', this.states.uModelMatrix.clone());
this._renderer.states.uModelMatrix.reset();
// X axis
diff --git a/src/webgl/light.js b/src/webgl/light.js
index ba125d3784..7a4c52fd9c 100644
--- a/src/webgl/light.js
+++ b/src/webgl/light.js
@@ -1457,23 +1457,24 @@ function light(p5, fn){
RendererGL.prototype.ambientLight = function(v1, v2, v3, a) {
const color = this._pInst.color(...arguments);
+ this.states.setValue('ambientLightColors', [...this.states.ambientLightColors]);
this.states.ambientLightColors.push(
color._array[0],
color._array[1],
color._array[2]
);
- this.states.enableLighting = true;
+ this.states.setValue('enableLighting', true);
}
RendererGL.prototype.specularColor = function(v1, v2, v3) {
const color = this._pInst.color(...arguments);
- this.states.specularColors = [
+ this.states.setValue('specularColors', [
color._array[0],
color._array[1],
color._array[2]
- ];
+ ]);
}
RendererGL.prototype.directionalLight = function(v1, v2, v3, x, y, z) {
@@ -1498,19 +1499,23 @@ function light(p5, fn){
// normalize direction
const l = Math.sqrt(_x * _x + _y * _y + _z * _z);
+ this.states.setValue('directionalLightDirections', [...this.states.directionalLightDirections]);
this.states.directionalLightDirections.push(_x / l, _y / l, _z / l);
+ this.states.setValue('directionalLightDiffuseColors', [...this.states.directionalLightDiffuseColors]);
this.states.directionalLightDiffuseColors.push(
color._array[0],
color._array[1],
color._array[2]
);
+
+ this.states.setValue('directionalLightSpecularColors', [...this.states.directionalLightSpecularColors]);
Array.prototype.push.apply(
this.states.directionalLightSpecularColors,
this.states.specularColors
);
- this.states.enableLighting = true;
+ this.states.setValue('enableLighting', true);
}
RendererGL.prototype.pointLight = function(v1, v2, v3, x, y, z) {
@@ -1533,25 +1538,30 @@ function light(p5, fn){
_z = v.z;
}
+ this.states.setValue('pointLightPositions', [...this.states.pointLightPositions]);
this.states.pointLightPositions.push(_x, _y, _z);
+
+ this.states.setValue('pointLightDiffuseColors', [...this.states.pointLightDiffuseColors]);
this.states.pointLightDiffuseColors.push(
color._array[0],
color._array[1],
color._array[2]
);
+
+ this.states.setValue('pointLightSpecularColors', [...this.states.pointLightSpecularColors]);
Array.prototype.push.apply(
this.states.pointLightSpecularColors,
this.states.specularColors
);
- this.states.enableLighting = true;
+ this.states.setValue('enableLighting', true);
}
RendererGL.prototype.imageLight = function(img) {
// activeImageLight property is checked by _setFillUniforms
// for sending uniforms to the fillshader
- this.states.activeImageLight = img;
- this.states.enableLighting = true;
+ this.states.setValue('activeImageLight', img);
+ this.states.setValue('enableLighting', true);
}
RendererGL.prototype.lights = function() {
@@ -1596,9 +1606,9 @@ function light(p5, fn){
);
}
- this.states.constantAttenuation = constantAttenuation;
- this.states.linearAttenuation = linearAttenuation;
- this.states.quadraticAttenuation = quadraticAttenuation;
+ this.states.setValue('constantAttenuation', constantAttenuation);
+ this.states.setValue('linearAttenuation', linearAttenuation);
+ this.states.setValue('quadraticAttenuation', quadraticAttenuation);
}
RendererGL.prototype.spotLight = function(
@@ -1770,23 +1780,23 @@ function light(p5, fn){
);
return;
}
- this.states.spotLightDiffuseColors = [
+ this.states.setValue('spotLightDiffuseColors', [
color._array[0],
color._array[1],
color._array[2]
- ];
+ ]);
- this.states.spotLightSpecularColors = [
+ this.states.setValue('spotLightSpecularColors', [
...this.states.specularColors
- ];
+ ]);
- this.states.spotLightPositions = [position.x, position.y, position.z];
+ this.states.setValue('spotLightPositions', [position.x, position.y, position.z]);
direction.normalize();
- this.states.spotLightDirections = [
+ this.states.setValue('spotLightDirections', [
direction.x,
direction.y,
direction.z
- ];
+ ]);
if (angle === undefined) {
angle = Math.PI / 3;
@@ -1802,39 +1812,39 @@ function light(p5, fn){
}
angle = this._pInst._toRadians(angle);
- this.states.spotLightAngle = [Math.cos(angle)];
- this.states.spotLightConc = [concentration];
+ this.states.setValue('spotLightAngle', [Math.cos(angle)]);
+ this.states.setValue('spotLightConc', [concentration]);
- this.states.enableLighting = true;
+ this.states.setValue('enableLighting', true);
}
RendererGL.prototype.noLights = function() {
- this.states.activeImageLight = null;
- this.states.enableLighting = false;
-
- this.states.ambientLightColors.length = 0;
- this.states.specularColors = [1, 1, 1];
-
- this.states.directionalLightDirections.length = 0;
- this.states.directionalLightDiffuseColors.length = 0;
- this.states.directionalLightSpecularColors.length = 0;
-
- this.states.pointLightPositions.length = 0;
- this.states.pointLightDiffuseColors.length = 0;
- this.states.pointLightSpecularColors.length = 0;
-
- this.states.spotLightPositions.length = 0;
- this.states.spotLightDirections.length = 0;
- this.states.spotLightDiffuseColors.length = 0;
- this.states.spotLightSpecularColors.length = 0;
- this.states.spotLightAngle.length = 0;
- this.states.spotLightConc.length = 0;
-
- this.states.constantAttenuation = 1;
- this.states.linearAttenuation = 0;
- this.states.quadraticAttenuation = 0;
- this.states._useShininess = 1;
- this.states._useMetalness = 0;
+ this.states.setValue('activeImageLight', null);
+ this.states.setValue('enableLighting', false);
+
+ this.states.setValue('ambientLightColors', []);
+ this.states.setValue('specularColors', [1, 1, 1]);
+
+ this.states.setValue('directionalLightDirections', []);
+ this.states.setValue('directionalLightDiffuseColors', []);
+ this.states.setValue('directionalLightSpecularColors', []);
+
+ this.states.setValue('pointLightPositions', []);
+ this.states.setValue('pointLightDiffuseColors', []);
+ this.states.setValue('pointLightSpecularColors', []);
+
+ this.states.setValue('spotLightPositions', []);
+ this.states.setValue('spotLightDirections', []);
+ this.states.setValue('spotLightDiffuseColors', []);
+ this.states.setValue('spotLightSpecularColors', []);
+ this.states.setValue('spotLightAngle', []);
+ this.states.setValue('spotLightConc', []);
+
+ this.states.setValue('constantAttenuation', 1);
+ this.states.setValue('linearAttenuation', 0);
+ this.states.setValue('quadraticAttenuation', 0);
+ this.states.setValue('_useShininess', 1);
+ this.states.setValue('_useMetalness', 0);
}
}
diff --git a/src/webgl/material.js b/src/webgl/material.js
index cd9b444e06..b0770cbc78 100644
--- a/src/webgl/material.js
+++ b/src/webgl/material.js
@@ -2521,7 +2521,7 @@ function material(p5, fn){
`You tried to set ${mode} textureMode only supports IMAGE & NORMAL `
);
} else {
- this._renderer.states.textureMode = mode;
+ this._renderer.states.setValue('textureMode', mode);
}
};
@@ -2800,8 +2800,8 @@ function material(p5, fn){
*
*/
fn.textureWrap = function (wrapX, wrapY = wrapX) {
- this._renderer.states.textureWrapX = wrapX;
- this._renderer.states.textureWrapY = wrapY;
+ this._renderer.states.setValue('textureWrapX', wrapX);
+ this._renderer.states.setValue('textureWrapY', wrapY);
for (const texture of this._renderer.textures.values()) {
texture.setWrapMode(wrapX, wrapY);
@@ -3078,11 +3078,11 @@ function material(p5, fn){
// p5._validateParameters('ambientMaterial', arguments);
const color = fn.color.apply(this, arguments);
- this._renderer.states._hasSetAmbient = true;
- this._renderer.states.curAmbientColor = color._array;
- this._renderer.states._useNormalMaterial = false;
- this._renderer.states.enableLighting = true;
- this._renderer.states.fillColor = true;
+ this._renderer.states.setValue('_hasSetAmbient', true);
+ this._renderer.states.setValue('curAmbientColor', color._array);
+ this._renderer.states.setValue('_useNormalMaterial', false);
+ this._renderer.states.setValue('enableLighting', true);
+ this._renderer.states.setValue('fillColor', true);
return this;
};
@@ -3174,10 +3174,10 @@ function material(p5, fn){
// p5._validateParameters('emissiveMaterial', arguments);
const color = fn.color.apply(this, arguments);
- this._renderer.states.curEmissiveColor = color._array;
- this._renderer.states._useEmissiveMaterial = true;
- this._renderer.states._useNormalMaterial = false;
- this._renderer.states.enableLighting = true;
+ this._renderer.states.setValue('curEmissiveColor', color._array);
+ this._renderer.states.setValue('_useEmissiveMaterial', true);
+ this._renderer.states.setValue('_useNormalMaterial', false);
+ this._renderer.states.setValue('enableLighting', true);
return this;
};
@@ -3429,10 +3429,10 @@ function material(p5, fn){
// p5._validateParameters('specularMaterial', arguments);
const color = fn.color.apply(this, arguments);
- this._renderer.states.curSpecularColor = color._array;
- this._renderer.states._useSpecularMaterial = true;
- this._renderer.states._useNormalMaterial = false;
- this._renderer.states.enableLighting = true;
+ this._renderer.states.setValue('curSpecularColor', color._array);
+ this._renderer.states.setValue('_useSpecularMaterial', true);
+ this._renderer.states.setValue('_useNormalMaterial', false);
+ this._renderer.states.setValue('enableLighting', true);
return this;
};
@@ -3749,45 +3749,45 @@ function material(p5, fn){
RendererGL.prototype.shader = function(s) {
// Always set the shader as a fill shader
- this.states.userFillShader = s;
- this.states._useNormalMaterial = false;
+ this.states.setValue('userFillShader', s);
+ this.states.setValue('_useNormalMaterial', false);
s.ensureCompiledOnContext(this);
s.setDefaultUniforms();
}
RendererGL.prototype.strokeShader = function(s) {
- this.states.userStrokeShader = s;
+ this.states.setValue('userStrokeShader', s);
s.ensureCompiledOnContext(this);
s.setDefaultUniforms();
}
RendererGL.prototype.imageShader = function(s) {
- this.states.userImageShader = s;
+ this.states.setValue('userImageShader', s);
s.ensureCompiledOnContext(this);
s.setDefaultUniforms();
}
RendererGL.prototype.resetShader = function() {
- this.states.userFillShader = null;
- this.states.userStrokeShader = null;
- this.states.userImageShader = null;
+ this.states.setValue('userFillShader', null);
+ this.states.setValue('userStrokeShader', null);
+ this.states.setValue('userImageShader', null);
}
RendererGL.prototype.texture = function(tex) {
- this.states.drawMode = constants.TEXTURE;
- this.states._useNormalMaterial = false;
- this.states._tex = tex;
- this.states.fillColor = new Color([1, 1, 1]);
+ this.states.setValue('drawMode', constants.TEXTURE);
+ this.states.setValue('_useNormalMaterial', false);
+ this.states.setValue('_tex', tex);
+ this.states.setValue('fillColor', new Color([1, 1, 1]));
};
RendererGL.prototype.normalMaterial = function(...args) {
- this.states.drawMode = constants.FILL;
- this.states._useSpecularMaterial = false;
- this.states._useEmissiveMaterial = false;
- this.states._useNormalMaterial = true;
- this.states.curFillColor = [1, 1, 1, 1];
- this.states.fillColor = new Color([1, 1, 1]);
- this.states.strokeColor = null;
+ this.states.setValue('drawMode', constants.FILL);
+ this.states.setValue('_useSpecularMaterial', false);
+ this.states.setValue('_useEmissiveMaterial', false);
+ this.states.setValue('_useNormalMaterial', true);
+ this.states.setValue('curFillColor', [1, 1, 1, 1]);
+ this.states.setValue('fillColor', new Color([1, 1, 1]));
+ this.states.setValue('strokeColor', null);
}
// RendererGL.prototype.ambientMaterial = function(v1, v2, v3) {
@@ -3803,12 +3803,12 @@ function material(p5, fn){
if (shine < 1) {
shine = 1;
}
- this.states._useShininess = shine;
+ this.states.setValue('_useShininess', shine);
}
RendererGL.prototype.metalness = function(metallic) {
const metalMix = 1 - Math.exp(-metallic / 100);
- this.states._useMetalness = metalMix;
+ this.states.setValue('_useMetalness', metalMix);
}
}
diff --git a/src/webgl/p5.Camera.js b/src/webgl/p5.Camera.js
index aa0a41e40c..aa35fba5b4 100644
--- a/src/webgl/p5.Camera.js
+++ b/src/webgl/p5.Camera.js
@@ -1195,6 +1195,7 @@ class Camera {
/* eslint-enable indent */
if (this._isActive()) {
+ this._renderer.states.setValue('uPMatrix', this._renderer.states.uPMatrix.clone());
this._renderer.states.uPMatrix.set(this.projMatrix);
}
}
@@ -1382,6 +1383,7 @@ class Camera {
tx, ty, tz, 1);
/* eslint-enable indent */
if (this._isActive()) {
+ this._renderer.states.setValue('uPMatrix', this._renderer.states.uPMatrix.clone());
this._renderer.states.uPMatrix.set(this.projMatrix);
}
this.cameraType = 'custom';
@@ -1520,6 +1522,7 @@ class Camera {
/* eslint-enable indent */
if (this._isActive()) {
+ this._renderer.states.setValue('uPMatrix', this._renderer.states.uPMatrix.clone());
this._renderer.states.uPMatrix.set(this.projMatrix);
}
@@ -2094,6 +2097,7 @@ class Camera {
this.cameraMatrix.translate([tx, ty, tz]);
if (this._isActive()) {
+ this._renderer.states.setValue('uViewMatrix', this._renderer.states.uViewMatrix.clone());
this._renderer.states.uViewMatrix.set(this.cameraMatrix);
}
return this;
@@ -2419,6 +2423,9 @@ class Camera {
this.projMatrix = cam.projMatrix.copy();
if (this._isActive()) {
+ this._renderer.states.setValue('uModelMatrix', this._renderer.states.uModelMatrix.clone());
+ this._renderer.states.setValue('uViewMatrix', this._renderer.states.uViewMatrix.clone());
+ this._renderer.states.setValue('uPMatrix', this._renderer.states.uPMatrix.clone());
this._renderer.states.uModelMatrix.reset();
this._renderer.states.uViewMatrix.set(this.cameraMatrix);
this._renderer.states.uPMatrix.set(this.projMatrix);
@@ -2524,6 +2531,7 @@ class Camera {
);
// If the camera is active, make uPMatrix reflect changes in projMatrix.
if (this._isActive()) {
+ this._renderer.states.setValue('uPMatrix', this._renderer.states.uPMatrix.clone());
this._renderer.states.uPMatrix.mat4 = this.projMatrix.mat4.slice();
}
}
@@ -3911,10 +3919,12 @@ function camera(p5, fn){
}
RendererGL.prototype.setCamera = function(cam) {
- this.states.curCamera = cam;
+ this.states.setValue('curCamera', cam);
// set the projection matrix (which is not normally updated each frame)
+ this.states.setValue('uPMatrix', this.states.uPMatrix.clone());
this.states.uPMatrix.set(cam.projMatrix);
+ this.states.setValue('uViewMatrix', this.states.uViewMatrix.clone());
this.states.uViewMatrix.set(cam.cameraMatrix);
}
}
diff --git a/src/webgl/p5.Framebuffer.js b/src/webgl/p5.Framebuffer.js
index 7d46af86e8..2155ac75bf 100644
--- a/src/webgl/p5.Framebuffer.js
+++ b/src/webgl/p5.Framebuffer.js
@@ -129,7 +129,7 @@ class Framebuffer {
const prevCam = this.renderer.states.curCamera;
this.defaultCamera = this.createCamera();
this.filterCamera = this.createCamera();
- this.renderer.states.curCamera = prevCam;
+ this.renderer.states.setValue('curCamera', prevCam);
this.draw(() => this.renderer.clear());
}
@@ -905,7 +905,6 @@ class Framebuffer {
const cam = new FramebufferCamera(this);
cam._computeCameraDefaultSettings();
cam._setDefaultCamera();
- this.renderer.states.curCamera = cam;
return cam;
}
@@ -1067,9 +1066,11 @@ class Framebuffer {
// RendererGL.reset() does, but this does not try to clear any buffers;
// it only sets the camera.
// this.renderer.setCamera(this.defaultCamera);
- this.renderer.states.curCamera = this.defaultCamera;
+ this.renderer.states.setValue('curCamera', this.defaultCamera);
// set the projection matrix (which is not normally updated each frame)
+ this.renderer.states.setValue('uPMatrix', this.renderer.states.uPMatrix.clone());
this.renderer.states.uPMatrix.set(this.defaultCamera.projMatrix);
+ this.renderer.states.setValue('uViewMatrix', this.renderer.states.uViewMatrix.clone());
this.renderer.states.uViewMatrix.set(this.defaultCamera.cameraMatrix);
this.renderer.resetMatrix();
@@ -1557,10 +1558,10 @@ class Framebuffer {
this.begin();
this.renderer.push();
// this.renderer.imageMode(constants.CENTER);
- this.renderer.states.imageMode = constants.CORNER;
+ this.renderer.states.setValue('imageMode', constants.CORNER);
this.renderer.setCamera(this.filterCamera);
this.renderer.resetMatrix();
- this.renderer.states.strokeColor = null;
+ this.renderer.states.setValue('strokeColor', null);
this.renderer.clear();
this.renderer._drawingFilter = true;
this.renderer.image(
diff --git a/src/webgl/p5.RendererGL.js b/src/webgl/p5.RendererGL.js
index c845a1effb..f41f39cdf0 100644
--- a/src/webgl/p5.RendererGL.js
+++ b/src/webgl/p5.RendererGL.js
@@ -181,6 +181,8 @@ class RendererGL extends Renderer {
this.states.uPMatrix = new Matrix(4);
this.states.curCamera = new Camera(this);
+ this.states.uPMatrix.set(this.states.curCamera.projMatrix);
+ this.states.uViewMatrix.set(this.states.curCamera.cameraMatrix);
this.states.enableLighting = false;
this.states.ambientLightColors = [];
@@ -286,9 +288,9 @@ class RendererGL extends Renderer {
this._drawingFilter = false;
this._drawingImage = false;
- this.states.specularShader = undefined;
+ this.specularShader = undefined;
this.sphereMapping = undefined;
- this.states.diffusedShader = undefined;
+ this.diffusedShader = undefined;
this._defaultLightShader = undefined;
this._defaultImmediateModeShader = undefined;
this._defaultNormalShader = undefined;
@@ -500,7 +502,7 @@ class RendererGL extends Renderer {
if (d === undefined) {
return this.states.curveDetail;
} else {
- this.states.curveDetail = d;
+ this.states.setValue('curveDetail', d);
}
}
@@ -578,9 +580,9 @@ class RendererGL extends Renderer {
normal(xorv, y, z) {
if (xorv instanceof Vector) {
- this.states._currentNormal = xorv;
+ this.states.setValue('_currentNormal', xorv);
} else {
- this.states._currentNormal = new Vector(xorv, y, z);
+ this.states.setValue('_currentNormal', new Vector(xorv, y, z));
}
this.updateShapeVertexProperties();
}
@@ -634,7 +636,8 @@ class RendererGL extends Renderer {
}
_drawGeometryScaled(model, scaleX, scaleY, scaleZ) {
- let originalModelMatrix = this.states.uModelMatrix.copy();
+ let originalModelMatrix = this.states.uModelMatrix;
+ this.states.setValue('uModelMatrix', this.states.uModelMatrix.clone());
try {
this.states.uModelMatrix.scale(scaleX, scaleY, scaleZ);
@@ -644,7 +647,7 @@ class RendererGL extends Renderer {
this._drawGeometry(model);
}
} finally {
- this.states.uModelMatrix = originalModelMatrix;
+ this.states.setValue('uModelMatrix', originalModelMatrix);
}
}
@@ -977,33 +980,35 @@ class RendererGL extends Renderer {
_update() {
// reset model view and apply initial camera transform
// (containing only look at info; no projection).
+ this.states.setValue('uModelMatrix', this.states.uModelMatrix.clone());
this.states.uModelMatrix.reset();
+ this.states.setValue('uViewMatrix', this.states.uViewMatrix.clone());
this.states.uViewMatrix.set(this.states.curCamera.cameraMatrix);
// reset light data for new frame.
- this.states.ambientLightColors.length = 0;
- this.states.specularColors = [1, 1, 1];
+ this.states.setValue('ambientLightColors', []);
+ this.states.setValue('specularColors', [1, 1, 1]);
- this.states.directionalLightDirections.length = 0;
- this.states.directionalLightDiffuseColors.length = 0;
- this.states.directionalLightSpecularColors.length = 0;
+ this.states.setValue('directionalLightDirections', []);
+ this.states.setValue('directionalLightDiffuseColors', []);
+ this.states.setValue('directionalLightSpecularColors', []);
- this.states.pointLightPositions.length = 0;
- this.states.pointLightDiffuseColors.length = 0;
- this.states.pointLightSpecularColors.length = 0;
+ this.states.setValue('pointLightPositions', []);
+ this.states.setValue('pointLightDiffuseColors', []);
+ this.states.setValue('pointLightSpecularColors', []);
- this.states.spotLightPositions.length = 0;
- this.states.spotLightDirections.length = 0;
- this.states.spotLightDiffuseColors.length = 0;
- this.states.spotLightSpecularColors.length = 0;
- this.states.spotLightAngle.length = 0;
- this.states.spotLightConc.length = 0;
+ this.states.setValue('spotLightPositions', []);
+ this.states.setValue('spotLightDirections', []);
+ this.states.setValue('spotLightDiffuseColors', []);
+ this.states.setValue('spotLightSpecularColors', []);
+ this.states.setValue('spotLightAngle', []);
+ this.states.setValue('spotLightConc', []);
- this.states.enableLighting = false;
+ this.states.setValue('enableLighting', false);
//reset tint value for new frame
- this.states.tint = [255, 255, 255, 255];
+ this.states.setValue('tint', [255, 255, 255, 255]);
//Clear depth every frame
this.GL.clearStencil(0);
@@ -1065,10 +1070,10 @@ class RendererGL extends Renderer {
//see material.js for more info on color blending in webgl
// const color = fn.color.apply(this._pInst, arguments);
const color = this.states.fillColor;
- this.states.curFillColor = color._array;
- this.states.drawMode = constants.FILL;
- this.states._useNormalMaterial = false;
- this.states._tex = null;
+ this.states.setValue('curFillColor', color._array);
+ this.states.setValue('drawMode', constants.FILL);
+ this.states.setValue('_useNormalMaterial', false);
+ this.states.setValue('_tex', null);
}
/**
@@ -1103,10 +1108,11 @@ class RendererGL extends Renderer {
stroke(...args) {
super.stroke(...args);
// const color = fn.color.apply(this._pInst, arguments);
- this.states.curStrokeColor = this.states.strokeColor._array;
+ this.states.setValue('curStrokeColor', this.states.strokeColor._array);
}
getCommonVertexProperties() {
+ if (!this.states) debugger
return {
...super.getCommonVertexProperties(),
stroke: this.states.strokeColor,
@@ -1173,11 +1179,11 @@ class RendererGL extends Renderer {
filterShaderFrags[operation],
);
}
- this.states.filterShader = this.defaultFilterShaders[operation];
+ this.states.setValue('filterShader', this.defaultFilterShaders[operation]);
}
// use custom user-supplied shader
else {
- this.states.filterShader = args[0];
+ this.states.setValue('filterShader', args[0]);
}
// Setting the target to the framebuffer when applying a filter to a framebuffer.
@@ -1202,7 +1208,7 @@ class RendererGL extends Renderer {
this.matchSize(tmp, target);
// setup
this.push();
- this.states.strokeColor = null;
+ this.states.setValue('strokeColor', null);
this.blendMode(constants.BLEND);
// draw main to temp buffer
@@ -1242,7 +1248,7 @@ class RendererGL extends Renderer {
// every other non-blur shader uses single pass
else {
fbo.draw(() => {
- this.states.strokeColor = null;
+ this.states.setValue('strokeColor', null);
this.blendMode(constants.BLEND);
this.shader(this.states.filterShader);
this.states.filterShader.setUniform("tex0", target);
@@ -1260,10 +1266,10 @@ class RendererGL extends Renderer {
}
// draw fbo contents onto main renderer.
this.push();
- this.states.strokeColor = null;
+ this.states.setValue('strokeColor', null);
this.clear();
this.push();
- this.states.imageMode = constants.CORNER;
+ this.states.setValue('imageMode', constants.CORNER);
this.blendMode(constants.BLEND);
target.filterCamera._resize();
this.setCamera(target.filterCamera);
@@ -1309,7 +1315,7 @@ class RendererGL extends Renderer {
mode === constants.MULTIPLY ||
mode === constants.REMOVE
)
- this.states.curBlendMode = mode;
+ this.states.setValue('curBlendMode', mode);
else if (
mode === constants.BURN ||
mode === constants.OVERLAY ||
@@ -1329,19 +1335,19 @@ class RendererGL extends Renderer {
this._isErasing = true;
this.blendMode(constants.REMOVE);
this._cachedFillStyle = this.states.curFillColor.slice();
- this.states.curFillColor = [1, 1, 1, opacityFill / 255];
+ this.states.setValue('curFillColor', [1, 1, 1, opacityFill / 255]);
this._cachedStrokeStyle = this.states.curStrokeColor.slice();
- this.states.curStrokeColor = [1, 1, 1, opacityStroke / 255];
+ this.states.setValue('curStrokeColor', [1, 1, 1, opacityStroke / 255]);
}
}
noErase() {
if (this._isErasing) {
// Restore colors
- this.states.curFillColor = this._cachedFillStyle.slice();
- this.states.curStrokeColor = this._cachedStrokeStyle.slice();
+ this.states.setValue('curFillColor', this._cachedFillStyle.slice());
+ this.states.setValue('curStrokeColor', this._cachedStrokeStyle.slice());
// Restore blend mode
- this.states.curBlendMode = this.preEraseBlend;
+ this.states.setValue('curBlendMode', this.preEraseBlend);
this.blendMode(this.preEraseBlend);
// Ensure that _applyBlendMode() sets preEraseBlend back to the original blend mode
this._isErasing = false;
@@ -1468,7 +1474,7 @@ class RendererGL extends Renderer {
this.push();
this.resetMatrix();
this.clear();
- this.states.imageMode = constants.CORNER;
+ this.states.setValue('imageMode', constants.CORNER);
this.image(
fbo,
0,
@@ -1621,6 +1627,7 @@ class RendererGL extends Renderer {
}
applyMatrix(a, b, c, d, e, f) {
+ this.states.setValue('uModelMatrix', this.states.uModelMatrix.clone());
if (arguments.length === 16) {
// this.states.uModelMatrix.apply(arguments);
Matrix.prototype.apply.apply(this.states.uModelMatrix, arguments);
@@ -1661,6 +1668,7 @@ class RendererGL extends Renderer {
y = x.y;
x = x.x;
}
+ this.states.setValue('uModelMatrix', this.states.uModelMatrix.clone());
this.states.uModelMatrix.translate([x, y, z]);
return this;
}
@@ -1674,6 +1682,7 @@ class RendererGL extends Renderer {
* @chainable
*/
scale(x, y, z) {
+ this.states.setValue('uModelMatrix', this.states.uModelMatrix.clone());
this.states.uModelMatrix.scale(x, y, z);
return this;
}
@@ -1682,6 +1691,7 @@ class RendererGL extends Renderer {
if (typeof axis === "undefined") {
return this.rotateZ(rad);
}
+ this.states.setValue('uModelMatrix', this.states.uModelMatrix.clone());
Matrix.prototype.rotate4x4.apply(this.states.uModelMatrix, arguments);
return this;
}
@@ -1724,7 +1734,9 @@ class RendererGL extends Renderer {
}
}
resetMatrix() {
+ this.states.setValue('uModelMatrix', this.states.uModelMatrix.clone());
this.states.uModelMatrix.reset();
+ this.states.setValue('uViewMatrix', this.states.uViewMatrix.clone());
this.states.uViewMatrix.set(this.states.curCamera.cameraMatrix);
return this;
}
@@ -2100,16 +2112,16 @@ class RendererGL extends Renderer {
});
// create framebuffer is like making a new sketch, all functions on main
// sketch it would be available on framebuffer
- if (!this.states.diffusedShader) {
- this.states.diffusedShader = this._pInst.createShader(
+ if (!this.diffusedShader) {
+ this.diffusedShader = this._pInst.createShader(
defaultShaders.imageLightVert,
defaultShaders.imageLightDiffusedFrag,
);
}
newFramebuffer.draw(() => {
- this.shader(this.states.diffusedShader);
- this.states.diffusedShader.setUniform("environmentMap", input);
- this.states.strokeColor = null;
+ this.shader(this.diffusedShader);
+ this.diffusedShader.setUniform("environmentMap", input);
+ this.states.setValue('strokeColor', null);
this.noLights();
this.plane(width, height);
});
@@ -2142,8 +2154,8 @@ class RendererGL extends Renderer {
density: 1,
});
let count = Math.log(size) / Math.log(2);
- if (!this.states.specularShader) {
- this.states.specularShader = this._pInst.createShader(
+ if (!this.specularShader) {
+ this.specularShader = this._pInst.createShader(
defaultShaders.imageLightVert,
defaultShaders.imageLightSpecularFrag,
);
@@ -2158,11 +2170,11 @@ class RendererGL extends Renderer {
let currCount = Math.log(w) / Math.log(2);
let roughness = 1 - currCount / count;
framebuffer.draw(() => {
- this.shader(this.states.specularShader);
+ this.shader(this.specularShader);
this.clear();
- this.states.specularShader.setUniform("environmentMap", input);
- this.states.specularShader.setUniform("roughness", roughness);
- this.states.strokeColor = null;
+ this.specularShader.setUniform("environmentMap", input);
+ this.specularShader.setUniform("roughness", roughness);
+ this.states.setValue('strokeColor', null);
this.noLights();
this.plane(w, w);
});
@@ -2623,9 +2635,7 @@ function rendererGL(p5, fn) {
}
}
- this.push();
this._renderer._resetContext();
- this.pop();
if (this._renderer.states.curCamera) {
this._renderer.states.curCamera._renderer = this._renderer;
diff --git a/src/webgl/text.js b/src/webgl/text.js
index a9cec5fa1f..d2c95b889e 100644
--- a/src/webgl/text.js
+++ b/src/webgl/text.js
@@ -669,8 +669,8 @@ function text(p5, fn){
const doStroke = this.states.strokeColor;
const drawMode = this.states.drawMode;
- this.states.strokeColor = null;
- this.states.drawMode = constants.TEXTURE;
+ this.states.setValue('strokeColor', null);
+ this.states.setValue('drawMode', constants.TEXTURE);
// get the cached FontInfo object
const { font } = this.states.textFont;
@@ -766,8 +766,8 @@ function text(p5, fn){
// clean up
sh.unbindShader();
- this.states.strokeColor = doStroke;
- this.states.drawMode = drawMode;
+ this.states.setValue('strokeColor', doStroke);
+ this.states.setValue('drawMode', drawMode);
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
this.pop();
diff --git a/test/js/mocks.js b/test/js/mocks.js
index 80a4cd68f8..5de4e4a1ec 100644
--- a/test/js/mocks.js
+++ b/test/js/mocks.js
@@ -1,6 +1,7 @@
import { vi } from 'vitest';
import { http, HttpResponse, passthrough } from 'msw';
import { setupWorker } from 'msw/browser';
+import { States } from '../../src/core/States';
// HTTP requests mocks
const httpMocks = [
@@ -18,7 +19,7 @@ const httpMocks = [
export const httpMock = setupWorker(...httpMocks);
// p5.js module mocks
-const rendererStates = {};
+const rendererStates = new States({});
export const mockP5 = vi.fn();
Object.assign(mockP5, {
_validateParameters: vi.fn(),
diff --git a/test/unit/color/setting.js b/test/unit/color/setting.js
index 12a44f195d..53e86d1174 100644
--- a/test/unit/color/setting.js
+++ b/test/unit/color/setting.js
@@ -4,6 +4,7 @@ import { vi } from 'vitest';
import { mockP5, mockP5Prototype } from '../../js/mocks';
import creatingReading from '../../../src/color/creating_reading';
import setting from '../../../src/color/setting';
+import { States } from '../../../src/core/States';
// NOTE: Require ESM compatible libtess
suite('color/Setting', function() {
@@ -57,14 +58,18 @@ suite('color/Setting', function() {
beforeEach(() => {
mockP5Prototype._renderer = {
erase: vi.fn(),
- states: {
+ states: new States({
colorMode: 'rgb',
colorMaxes: {
rgb: [255, 255, 255, 255],
hsb: [360, 100, 100, 1],
- hsl: [360, 100, 100, 1]
+ hsl: [360, 100, 100, 1],
+ clone: function() {
+ // Quick incorrect implementation for this test
+ return this;
+ }
}
- }
+ })
}
});
diff --git a/test/unit/core/curves.js b/test/unit/core/curves.js
index 4840e273b1..dbad66940d 100644
--- a/test/unit/core/curves.js
+++ b/test/unit/core/curves.js
@@ -1,14 +1,15 @@
import { mockP5, mockP5Prototype } from '../../js/mocks';
import curves from '../../../src/shape/curves';
+import { States } from '../../../src/core/States';
suite('Curves', function() {
beforeAll(function() {
mockP5Prototype._renderer = {
- states: {
+ states: new States({
splineProperties: {
tightness: 0
}
- }
+ })
};
curves(mockP5, mockP5Prototype);
});
diff --git a/test/unit/math/p5.Matrix.js b/test/unit/math/p5.Matrix.js
index 51e684db18..88b31d5b27 100644
--- a/test/unit/math/p5.Matrix.js
+++ b/test/unit/math/p5.Matrix.js
@@ -3,11 +3,11 @@ import p5 from "../../../src/app.js";
const toArray = (typedArray) => Array.from(typedArray);
/* eslint-disable indent */
-var mat4 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
+var mat4 = Float32Array.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
-var other = [1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16];
+var other = Float32Array.from([1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16]);
-var mat3 = [1, 2, 3, 4, 5, 6, 7, 8, 9];
+var mat3 = Float32Array.from([1, 2, 3, 4, 5, 6, 7, 8, 9]);
/* eslint-enable indent */
suite("p5.Matrix", function () {
@@ -49,7 +49,7 @@ suite("p5.Matrix", function () {
var m = new p5.Matrix(mat3);
assert.instanceOf(m, p5.Matrix);
assert.isUndefined(m.mat4);
- assert.deepEqual([].slice.call(m.mat3), mat3);
+ assert.deepEqual(m.mat3, mat3);
});
test("identity()", function () {
@@ -93,13 +93,13 @@ suite("p5.Matrix", function () {
test("array", function () {
var m = new p5.Matrix(4);
m.set(mat4);
- assert.deepEqual([].slice.call(m.mat4), mat4);
+ assert.deepEqual(m.mat4, mat4);
});
test("arguments", function () {
var m = new p5.Matrix(4);
m.set(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6);
- expect(m.mat4).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6]);
+ expect(Array.from(m.mat4)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6]);
});
});
@@ -118,7 +118,7 @@ suite("p5.Matrix", function () {
const clone = original.clone();
expect(clone).not.toBe(original);
- expect(toArray(clone.mat3)).toEqual(original.mat3);
+ expect(clone.mat3).toEqual(original.mat3);
});
it("should clone an identity matrix correctly", () => {
@@ -262,31 +262,31 @@ suite("p5.Matrix", function () {
suite("rotate", function () {
/* eslint-disable max-len */
- var rm = [
+ var rm = Float32Array.from([
1.433447866601989, 2.5241247073503885, 3.6148015480987885,
4.7054783888471885, 6.460371405020393, 7.054586073938033,
7.648800742855675, 8.243015411773316, 7.950398010346969,
9.157598472697025, 10.36479893504708, 11.571999397397136, 13, 14, 15, 16,
- ];
+ ]);
/* eslint-enable max-len */
test("p5.Vector", function () {
var m = new p5.Matrix(mat4.slice());
var v = myp5.createVector(2, 3, 5);
m.rotate4x4(45 * myp5.DEG_TO_RAD, v);
- assert.deepEqual([].slice.call(m.mat4), rm);
+ assert.deepEqual(m.mat4, rm);
});
test("array", function () {
var m = new p5.Matrix(mat4.slice());
m.rotate4x4(45 * myp5.DEG_TO_RAD, [2, 3, 5]);
- assert.deepEqual([].slice.call(m.mat4), rm);
+ assert.deepEqual(m.mat4, rm);
});
test("arguments", function () {
var m = new p5.Matrix(mat4.slice());
m.rotate4x4(45 * myp5.DEG_TO_RAD, 2, 3, 5);
- assert.deepEqual([].slice.call(m.mat4), rm);
+ assert.deepEqual([].slice.call(m.mat4), Array.from(rm));
});
});
@@ -323,19 +323,19 @@ suite("p5.Matrix", function () {
const multMatrix = new p5.Matrix([1, 1, 1, 0, 1, 1, 1, 0, 1]);
// When taking a matrix as an argument
m.mult(multMatrix);
- expect(m.mat3).toEqual([ 4, 3, 6, 10, 9, 15, 16, 15, 24 ]);
+ expect(toArray(m.mat3)).toEqual([ 4, 3, 6, 10, 9, 15, 16, 15, 24 ]);
});
-
+
test("mult a 3x3 matrix with array as argument", function () {
const m = new p5.Matrix([1, 2, 3, 4, 5, 6, 7, 8, 9]);
m.mult([1, 1, 1, 0, 1, 1, 1, 0, 1])
- expect(m.mat3).toEqual([ 4, 3, 6, 10, 9, 15, 16, 15, 24 ]);
+ expect(toArray(m.mat3)).toEqual([ 4, 3, 6, 10, 9, 15, 16, 15, 24 ]);
});
test("mult a 3x3 matrix with arguments non array", function () {
const m = new p5.Matrix([1, 2, 3, 4, 5, 6, 7, 8, 9]);
m.mult(1, 1, 1, 0, 1, 1, 1, 0, 1)
- expect(m.mat3).toEqual([ 4, 3, 6, 10, 9, 15, 16, 15, 24 ]);
+ expect(toArray(m.mat3)).toEqual([ 4, 3, 6, 10, 9, 15, 16, 15, 24 ]);
});
test("column() and row()", function () {
@@ -396,7 +396,7 @@ suite("p5.Matrix", function () {
mat.transpose(mat);
- expect(mat.mat4).toEqual([
+ expect(toArray(mat.mat4)).toEqual([
1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16,
]);
});
@@ -408,7 +408,7 @@ suite("p5.Matrix", function () {
mat.transpose([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
- expect(mat.mat4).toEqual([
+ expect(toArray(mat.mat4)).toEqual([
1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 4, 8, 12, 16,
]);
});
@@ -455,7 +455,7 @@ suite("p5.Matrix", function () {
const invertedMatrix = matrix.invert(matrix);
- expect(invertedMatrix.mat4).toEqual([
+ expect(toArray(invertedMatrix.mat4)).toEqual([
1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
]);
});
@@ -477,7 +477,7 @@ suite("p5.Matrix", function () {
const invertedMatrix = matrix.invert(matrix);
- expect(invertedMatrix.mat4).toEqual([
+ expect(toArray(invertedMatrix.mat4)).toEqual([
0, 0, 0, 1, 0, 0, 1, -1, 0, 1, 1, -2, 1, -1, -2, 2,
]);
});
@@ -488,7 +488,7 @@ suite("p5.Matrix", function () {
const matrix = new p5.Matrix([1, 2, 3, 0, 1, 4, 5, 6, 0]);
const invertedMatrix = matrix.invert();
- expect(invertedMatrix.mat3).toEqual([-24, 18, 5, 20, -15, -4, -5, 4, 1]);
+ expect(toArray(invertedMatrix.mat3)).toEqual([-24, 18, 5, 20, -15, -4, -5, 4, 1]);
});
it("should return null for a non-invertible 3x3 matrix", () => {
@@ -502,7 +502,7 @@ suite("p5.Matrix", function () {
const matrix = new p5.Matrix([1, 0, 0, 0, 1, 0, 0, 0, 1]);
const invertedMatrix = matrix.invert();
- expect(invertedMatrix.mat3).toEqual([1, 0, 0, 0, 1, 0, 0, 0, 1]);
+ expect(toArray(invertedMatrix.mat3)).toEqual([1, 0, 0, 0, 1, 0, 0, 0, 1]);
});
});
@@ -513,7 +513,7 @@ suite("p5.Matrix", function () {
]);
const invertedMatrix = matrix.setElement(2, 0);
- expect(invertedMatrix.mat4).toEqual([
+ expect(toArray(invertedMatrix.mat4)).toEqual([
1, 2, 0, 5, 0, 1, 4, 5, 5, 6, 0, 5, 5, 6, 0, 5,
]);
});
@@ -522,7 +522,7 @@ suite("p5.Matrix", function () {
const matrix = new p5.Matrix([1, 2, 3, 0, 1, 4, 5, 6, 0]);
const invertedMatrix = matrix.setElement(2, 0);
- expect(invertedMatrix.mat3).toEqual([1, 2, 0, 0, 1, 4, 5, 6, 0]);
+ expect(toArray(invertedMatrix.mat3)).toEqual([1, 2, 0, 0, 1, 4, 5, 6, 0]);
});
});
});
diff --git a/test/unit/visual/cases/typography.js b/test/unit/visual/cases/typography.js
index 63cd0f9452..46fbab5777 100644
--- a/test/unit/visual/cases/typography.js
+++ b/test/unit/visual/cases/typography.js
@@ -279,7 +279,7 @@ visualSuite("Typography", function () {
p5.createCanvas(150, 100, mode === 'webgl' ? p5.WEBGL : undefined);
if (mode === 'webgl') p5.translate(-p5.width/2, -p5.height/2);
- p5.textSize(20);
+ p5.textSize(19);
p5.textWrap(p5.CHAR);
const font = await p5.loadFont(
'/unit/assets/Inconsolata-Bold.ttf'
diff --git a/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/000.png b/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/000.png
index 8c532567f2..972bc839ab 100644
Binary files a/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/000.png and b/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/000.png differ
diff --git a/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/001.png b/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/001.png
index 8c532567f2..ee7d540a28 100644
Binary files a/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/001.png and b/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/001.png differ
diff --git a/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/002.png b/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/002.png
index 8c532567f2..d5ece8e022 100644
Binary files a/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/002.png and b/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/002.png differ
diff --git a/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/003.png b/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/003.png
index aa31ca421c..de9ed8e90d 100644
Binary files a/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/003.png and b/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/003.png differ
diff --git a/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/004.png b/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/004.png
index aa31ca421c..a722b39ab3 100644
Binary files a/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/004.png and b/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/004.png differ
diff --git a/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/005.png b/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/005.png
index aa31ca421c..5e0a9ebfad 100644
Binary files a/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/005.png and b/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/005.png differ
diff --git a/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/006.png b/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/006.png
index 24c31bf9f0..7d20ef1af4 100644
Binary files a/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/006.png and b/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/006.png differ
diff --git a/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/007.png b/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/007.png
index 24c31bf9f0..f0ba0feadf 100644
Binary files a/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/007.png and b/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/007.png differ
diff --git a/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/008.png b/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/008.png
index 24c31bf9f0..009a33e472 100644
Binary files a/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/008.png and b/test/unit/visual/screenshots/Typography/textAlign/2d mode/all alignments with multi-lines and wrap char/008.png differ
diff --git a/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/000.png b/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/000.png
index a85c0d7e3f..150c342587 100644
Binary files a/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/000.png and b/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/000.png differ
diff --git a/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/001.png b/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/001.png
index a85c0d7e3f..b61a7788c9 100644
Binary files a/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/001.png and b/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/001.png differ
diff --git a/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/002.png b/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/002.png
index a85c0d7e3f..a353f6a37f 100644
Binary files a/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/002.png and b/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/002.png differ
diff --git a/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/003.png b/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/003.png
index d3986bad49..9012e58b30 100644
Binary files a/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/003.png and b/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/003.png differ
diff --git a/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/004.png b/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/004.png
index d3986bad49..3e9fb83840 100644
Binary files a/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/004.png and b/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/004.png differ
diff --git a/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/005.png b/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/005.png
index d3986bad49..f493557a75 100644
Binary files a/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/005.png and b/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/005.png differ
diff --git a/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/006.png b/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/006.png
index 75490d5dad..128c72195b 100644
Binary files a/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/006.png and b/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/006.png differ
diff --git a/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/007.png b/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/007.png
index 75490d5dad..2c4f829b64 100644
Binary files a/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/007.png and b/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/007.png differ
diff --git a/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/008.png b/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/008.png
index 75490d5dad..9239857a40 100644
Binary files a/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/008.png and b/test/unit/visual/screenshots/Typography/textAlign/webgl mode/all alignments with multi-lines and wrap char/008.png differ