Skip to content

[p5.js 2.0] State machines and renderer refactoring #7270

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 58 commits into from
Nov 2, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
6ef1afc
Concentrate DOM creation of renderer in the createCanvas method
limzykenneth Sep 20, 2024
2f7f824
Indentation
limzykenneth Sep 20, 2024
9c47a4c
Fix p5.Graphics creation
limzykenneth Sep 21, 2024
c39cfa6
p5.Graphics acts as wrapper of p5.Renderer
limzykenneth Sep 21, 2024
263ae57
Fix p5.Graphics.remove and simplify it
limzykenneth Sep 21, 2024
8427978
Fix webgl canvas creation
limzykenneth Sep 21, 2024
5c68e24
Minor adjustment to p5.Renderer and p5.Graphics remove
limzykenneth Sep 21, 2024
e3c3683
Make resizeCanvas() independent of DOM
limzykenneth Sep 22, 2024
f1d8735
Remove renderer createCanvas() method as it is redundant with constru…
limzykenneth Sep 22, 2024
7a91e53
Global width/height read directly from renderer
limzykenneth Sep 22, 2024
b07b438
Move ownership of pixel density to renderer
limzykenneth Sep 22, 2024
55c45ed
Fix a few tests
limzykenneth Sep 22, 2024
beb432f
Fix a few more tests
limzykenneth Sep 22, 2024
8a60cf3
Include p5 instance methods on p5.Graphics
limzykenneth Sep 23, 2024
40b621d
Refactor some WebGL sections to try to fix tests
limzykenneth Sep 23, 2024
418251b
Visual test use constants from direct import
limzykenneth Sep 23, 2024
eff9ac4
Refactor shape out into its own module
limzykenneth Sep 25, 2024
db6e599
Use new module API to attach methods to p5.Graphics
limzykenneth Sep 26, 2024
7cd3fb3
Attach more functions to p5.Graphics
limzykenneth Sep 27, 2024
104bd32
Move blendMode() to color/setting module
limzykenneth Sep 28, 2024
5c70636
Merge branch 'dev-2.0' into 2.0-modules
limzykenneth Oct 8, 2024
27326fe
Convert renderers to use new syntax modules
limzykenneth Oct 11, 2024
0c71618
Change how all classes are defined to be more exportable
limzykenneth Oct 13, 2024
cfa67aa
Use class imports wherever possible
limzykenneth Oct 15, 2024
5cc1555
Fix enableLighting state name inconsistency
limzykenneth Oct 15, 2024
7b59c31
Inline webgl nostroke call
limzykenneth Oct 15, 2024
beb947a
Convert a few more class usage, fix a few more tests
limzykenneth Oct 18, 2024
1ea4e25
Fix for before refactors
limzykenneth Oct 21, 2024
90bcbc0
Duplicate pixels implementation in p5.Image from p5.Renderer2D
limzykenneth Oct 21, 2024
59e5cb1
Unindent to try to reduce merge conflicts
davepagurek Oct 22, 2024
c34a511
Merge branch 'dev-2.0' into 2.0-modules
davepagurek Oct 22, 2024
a68e4c3
Put indentation back
davepagurek Oct 22, 2024
ae12ade
Move 3D primitives implementation into RendererGL
limzykenneth Oct 23, 2024
be38743
Move some lights implementation to RendererGL
limzykenneth Oct 23, 2024
1941150
Move material implementation to RendererGL
limzykenneth Oct 23, 2024
b249cb5
Fix incorrect reference to renderer
limzykenneth Oct 23, 2024
0021fa4
Move camera implementation to RendererGL
limzykenneth Oct 23, 2024
f69ad65
Fix vertexProperty
limzykenneth Oct 25, 2024
9642ee5
Fix direct call to change renderer imagemode
limzykenneth Oct 25, 2024
545621f
Fix incorrect reference to state
limzykenneth Oct 25, 2024
1f811b9
Remove some references to pInst in RendererGL
limzykenneth Oct 27, 2024
da70a0e
Fix p5.Graphics overwriting default drawing context
limzykenneth Oct 27, 2024
4314ec0
Fix text rendering
limzykenneth Oct 27, 2024
c402baa
Remove more references to pInst in RendererGL
limzykenneth Oct 27, 2024
8a3f364
Make sure ensureCompiledOnContext is called for internal shader() calls
davepagurek Oct 29, 2024
6fc9e8d
Fix createFilterShader context
davepagurek Oct 29, 2024
fd02fe4
Load images before creating canvas
davepagurek Oct 29, 2024
0f44413
Clear cached maxTextureSize for tests with stubbed value
davepagurek Oct 29, 2024
bea4d02
Make internal stroke and fill also enable stroke and fill
davepagurek Oct 29, 2024
9ae00f4
Make sure default attributes are loaded before initializing WebGL con…
davepagurek Oct 30, 2024
c0ec064
Make p5 also expose properties from the renderer like graphics do
davepagurek Nov 2, 2024
3130090
Just expose pixels on the main instance, actually
davepagurek Nov 2, 2024
fe0d85a
Refactor out need for pInst in p5.Color
limzykenneth Nov 2, 2024
24525f9
Remove console.log
limzykenneth Nov 2, 2024
d85876c
Move rest of light implementation to Renderer3D
limzykenneth Nov 2, 2024
7fd3c4f
Fix updatePixels incorrect on WebGL mode
davepagurek Nov 2, 2024
468ab53
Fix constant usage on graphic that should be on the main instance
davepagurek Nov 2, 2024
2641218
Merge branch 'dev-2.0' into 2.0-modules
limzykenneth Nov 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions src/core/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,6 @@ class p5 {
this._lcg_random_state = null; // NOTE: move to random.js
this._gaussian_previous = false; // NOTE: move to random.js

this._loadingScreenId = 'p5_loading';

if (window.DeviceOrientationEvent) {
this._events.deviceorientation = null;
}
Expand Down Expand Up @@ -351,10 +349,7 @@ class p5 {
if(this._startListener){
window.removeEventListener('load', this._startListener, false);
}
const loadingScreen = document.getElementById(this._loadingScreenId);
if (loadingScreen) {
loadingScreen.parentNode.removeChild(loadingScreen);
}

if (this._curElement) {
// stop draw
this._loop = false;
Expand Down
4 changes: 4 additions & 0 deletions src/core/p5.Renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ p5.Renderer = class Renderer {
this._pInst.height = this.height;
}

remove() {

}

// Makes a shallow copy of the current states
// and push it into the push pop stack
push() {
Expand Down
80 changes: 61 additions & 19 deletions src/core/p5.Renderer2D.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,20 @@ const styleEmpty = 'rgba(0,0,0,0)';
class Renderer2D extends Renderer {
constructor(elt, pInst, isMainCanvas) {
super(elt, pInst, isMainCanvas);
this.elt = elt;
this.canvas = elt;
this.drawingContext = this.canvas.getContext('2d');
this._pInst.drawingContext = this.drawingContext;

if (isMainCanvas) {
// for pixel method sharing with pimage
this._pInst._curElement = this;
this._pInst.canvas = this.canvas;
} else {
// hide if offscreen buffer by default
this.canvas.style.display = 'none';
}
this._isMainCanvas = isMainCanvas;

// if (isMainCanvas) {
// // for pixel method sharing with pimage
// this._pInst._curElement = this;
// this._pInst.canvas = this.canvas;
// } else {
// // hide if offscreen buffer by default
// this.canvas.style.display = 'none';
// }

// Extend renderer with methods of p5.Element with getters
this.wrappedElt = new p5.Element(elt, pInst);
// this.wrappedElt = new p5.Element(elt, pInst);
for (const p of Object.getOwnPropertyNames(p5.Element.prototype)) {
if (p !== 'constructor' && p[0] !== '_') {
Object.defineProperty(this, p, {
Expand All @@ -42,18 +40,58 @@ class Renderer2D extends Renderer {
}
}

// NOTE: renderer won't be created until instance createCanvas was called
// This createCanvas should handle the HTML stuff while other createCanvas
// be generic
createCanvas(w, h, canvas) {
super.createCanvas(w, h);
// this.canvas = this.elt = canvas || document.createElement('canvas');
// this.drawingContext = this.canvas.getContext('2d');
// this._pInst.drawingContext = this.drawingContext;

// Create new canvas
this.canvas = this.elt = canvas || document.createElement('canvas');
////////
if (this._isMainCanvas) {
// for pixel method sharing with pimage
this._pInst._curElement = this;
this._pInst.canvas = this.canvas;
} else {
// hide if offscreen buffer by default
this.canvas.style.display = 'none';
}
////////
this.elt.id = 'defaultCanvas0';
this.elt.classList.add('p5Canvas');

// Set canvas size
this.elt.width = w * this._pInst._pixelDensity;
this.elt.height = h * this._pInst._pixelDensity;
this.elt.style.width = `${w}px`;
this.elt.style.height = `${h}px`;

// Attach canvas element to DOM
if (this._pInst._userNode) {
// user input node case
this._pInst._userNode.appendChild(this.elt);
} else {
//create main element
if (document.getElementsByTagName('main').length === 0) {
let m = document.createElement('main');
document.body.appendChild(m);
}
//append canvas to main
document.getElementsByTagName('main')[0].appendChild(this.elt);
}

// Get and store drawing context
this.drawingContext = this.canvas.getContext('2d');
this._pInst.drawingContext = this.drawingContext;

// Set and return p5.Element
this.wrappedElt = new p5.Element(this.elt, this._pInst);

return this.wrappedElt;
}

remove(){
this.wrappedElt.remove();
}

getFilterGraphicsLayer() {
// create hidden webgl renderer if it doesn't exist
if (!this.filterGraphicsLayer) {
Expand Down Expand Up @@ -142,6 +180,8 @@ class Renderer2D extends Renderer {
this.blendMode(this._cachedBlendMode);
}

console.log('background', this.drawingContext.fillStyle, this.drawingContext.canvas);
console.trace();
this.drawingContext.fillRect(0, 0, this.width, this.height);
// reset fill
this._setFill(curFill);
Expand Down Expand Up @@ -1205,6 +1245,8 @@ class Renderer2D extends Renderer {
_setFill(fillStyle) {
if (fillStyle !== this._cachedFillStyle) {
this.drawingContext.fillStyle = fillStyle;
// console.log('here', this.drawingContext.fillStyle);
// console.trace();
this._cachedFillStyle = fillStyle;
}
}
Expand Down
167 changes: 90 additions & 77 deletions src/core/rendering.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ p5.prototype.createCanvas = function (w, h, renderer, canvas) {
}



/////////////////////////////////
let r;
if (arguments[2] instanceof HTMLCanvasElement) {
renderer = constants.P2D;
Expand All @@ -149,90 +149,103 @@ p5.prototype.createCanvas = function (w, h, renderer, canvas) {
r = renderer || constants.P2D;
}

let c;
// let c;

if (canvas) {
// NOTE: this is to guard against multiple default canvas being created
c = document.getElementById(defaultId);
if (c) {
c.parentNode.removeChild(c); //replace the existing defaultCanvas
}
c = canvas;
this._defaultGraphicsCreated = false;
} else {
if (r === constants.WEBGL) {
c = document.getElementById(defaultId);
if (c) {
//if defaultCanvas already exists
c.parentNode.removeChild(c); //replace the existing defaultCanvas
const thisRenderer = this._renderer;
this._elements = this._elements.filter(e => e !== thisRenderer);
}
c = document.createElement('canvas');
c.id = defaultId;
c.classList.add(defaultClass);
} else {
if (!this._defaultGraphicsCreated) {
if (canvas) {
c = canvas;
} else {
c = document.createElement('canvas');
}
let i = 0;
while (document.getElementById(`defaultCanvas${i}`)) {
i++;
}
defaultId = `defaultCanvas${i}`;
c.id = defaultId;
c.classList.add(defaultClass);
} else if (
this._renderer &&
Object.getPrototypeOf(this._renderer) !== renderers[r].prototype
) {
// Handle createCanvas() called with 2D mode after a 3D canvas is made
if (this.canvas.parentNode) {
this.canvas.parentNode.removeChild(this.canvas); //replace the existing defaultCanvas
}
const thisRenderer = this._renderer;
this._elements = this._elements.filter(e => e !== thisRenderer);
c = document.createElement('canvas');
c.id = defaultId;
c.classList.add(defaultClass);
} else {
// resize the default canvas if new one is created
c = this.canvas;
}
}
// if (canvas) {
// // NOTE: this is to guard against multiple default canvas being created
// c = document.getElementById(defaultId);
// if (c) {
// c.parentNode.removeChild(c); //replace the existing defaultCanvas
// }
// c = canvas;
// this._defaultGraphicsCreated = false;
// } else {
// if (r === constants.WEBGL) {
// c = document.getElementById(defaultId);
// if (c) {
// //if defaultCanvas already exists
// c.parentNode.removeChild(c); //replace the existing defaultCanvas
// const thisRenderer = this._renderer;
// this._elements = this._elements.filter(e => e !== thisRenderer);
// }
// c = document.createElement('canvas');
// c.id = defaultId;
// c.classList.add(defaultClass);
// } else {
// if (!this._defaultGraphicsCreated) {
// if (canvas) {
// c = canvas;
// } else {
// c = document.createElement('canvas');
// }
// let i = 0;
// while (document.getElementById(`defaultCanvas${i}`)) {
// i++;
// }
// defaultId = `defaultCanvas${i}`;
// c.id = defaultId;
// c.classList.add(defaultClass);
// } else if (
// this._renderer &&
// Object.getPrototypeOf(this._renderer) !== renderers[r].prototype
// ) {
// // Handle createCanvas() called with 2D mode after a 3D canvas is made
// if (this.canvas.parentNode) {
// this.canvas.parentNode.removeChild(this.canvas); //replace the existing defaultCanvas
// }
// const thisRenderer = this._renderer;
// this._elements = this._elements.filter(e => e !== thisRenderer);
// c = document.createElement('canvas');
// c.id = defaultId;
// c.classList.add(defaultClass);
// } else {
// // resize the default canvas if new one is created
// c = this.canvas;
// }
// }

// set to invisible if still in setup (to prevent flashing with manipulate)
if (!this._setupDone) {
c.dataset.hidden = true; // tag to show later
c.style.visibility = 'hidden';
}
// // set to invisible if still in setup (to prevent flashing with manipulate)
// // if (!this._setupDone) {
// // c.dataset.hidden = true; // tag to show later
// // c.style.visibility = 'hidden';
// // }

if (this._userNode) {
// user input node case
this._userNode.appendChild(c);
} else {
//create main element
if (document.getElementsByTagName('main').length === 0) {
let m = document.createElement('main');
document.body.appendChild(m);
}
//append canvas to main
document.getElementsByTagName('main')[0].appendChild(c);
}
}
// if (this._userNode) {
// // user input node case
// this._userNode.appendChild(c);
// } else {
// //create main element
// if (document.getElementsByTagName('main').length === 0) {
// let m = document.createElement('main');
// document.body.appendChild(m);
// }
// //append canvas to main
// document.getElementsByTagName('main')[0].appendChild(c);
// }
// }

// if (this._userNode) {
// // user input node case
// this._userNode.appendChild(canvas);
// } else {
// //create main element
// if (document.getElementsByTagName('main').length === 0) {
// let m = document.createElement('main');
// document.body.appendChild(m);
// }
// //append canvas to main
// document.getElementsByTagName('main')[0].appendChild(canvas);
// }

// Init our graphics renderer
this._renderer = new renderers[r](c, this, true);
if(this._renderer) this._renderer.remove();
this._renderer = new renderers[r](canvas, this, true);
const element = this._renderer.createCanvas(w, h, canvas);
this._defaultGraphicsCreated = true;
this._elements.push(this._renderer);
this._renderer.resize(w, h);
this._renderer._applyDefaults();
this._renderer.createCanvas(w, h, canvas);
// return this._renderer.createCanvas(w, h, canvas);
return this._renderer;
// return this._renderer;
return element;
};

/**
Expand Down
6 changes: 6 additions & 0 deletions src/webgl/p5.RendererGL.js
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,7 @@ p5.RendererGL = class RendererGL extends Renderer {
super(elt, pInst, isMainCanvas);
this.elt = elt;
this.canvas = elt;
this.wrappedElt = new p5.Element(elt, pInst);
this._setAttributeDefaults(pInst);
this._initContext();
this.isP3D = true; //lets us know we're in 3d mode
Expand Down Expand Up @@ -678,6 +679,11 @@ p5.RendererGL = class RendererGL extends Renderer {
this._curShader = undefined;
}

createCanvas(w, h, canvas){
super.createCanvas(w, h);
return this.wrappedElt;
}

/**
* Starts creating a new p5.Geometry. Subsequent shapes drawn will be added
* to the geometry and then returned when
Expand Down