Skip to content
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

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

Draft
wants to merge 24 commits into
base: dev-2.0
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
09f57c9
Set up states machine in p5.Renderer
limzykenneth Sep 15, 2024
ab22f1d
Expose p5.Element methods to p5.Renderer2D directly
limzykenneth Sep 17, 2024
c5441dc
Move more things into state
davepagurek Sep 17, 2024
e93cbd5
Start converting WebGL state
davepagurek Sep 17, 2024
94e8267
Move more properties into states
davepagurek Sep 17, 2024
c80e364
Merge branch 'dev-2.0' into 2.0-modules
davepagurek Sep 18, 2024
f0b3766
Fix some uses of .elt
davepagurek Sep 18, 2024
7299220
Minor cleanup
limzykenneth Sep 18, 2024
84ecc61
Rework how variables are exposed in global mode
limzykenneth Sep 18, 2024
282cabb
Global functions now also use getter
limzykenneth Sep 18, 2024
3a356d5
Move DOM initialization from p5.Renderer to individual renderers
limzykenneth Sep 19, 2024
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
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
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@davepagurek Probably shouldn't update right away but just to let you know in advanced. The refactor for Renderer2D moves all DOM related operation and references to be handled by the renderer's createCanvas method along with reshuffling of the initialization logic around default canvas and others. As such WebGL renderer will also need updating accordingly.

I'm working on getting p5.Graphics to work first before I do a round of clean up refactoring.

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