Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
76 changes: 76 additions & 0 deletions src/core/loading.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/**
* @module Loading
* @for p5
* @private
*
* Handles the logic for creating a loading indicator.
* Currently, the loading indicator is basic and can be extended in the future.
*/

/**
* Creates a loading indicator when the sketch's setup() function is running.
* It is called and removed automatically using the presetup and postsetup lifecycles hooks.
*
* @param {*} p5 The p5 constructor
* @param {*} fn The p5 prototype object
* @param {*} lifecycles Lifecycle hooks for the sketch
*/
export default function loading(p5, fn, lifecycles) {
lifecycles.presetup = function() {
if (typeof window === 'undefined' || this._loadingIndicator) {
return;
}

const canvasParent = this.canvas?.parentElement;
let container = this._userNode || canvasParent || document.body;

if (typeof container === 'string') {
container = document.getElementById(container) || document.body;
}

this._loadingIndicator = createLoadingIndicator(container);
};

lifecycles.postsetup = function() {
if (this._loadingIndicator) {
this._loadingIndicator.remove();
this._loadingIndicator = null;
}
};
}

/**
* Creates and stylizes the loading indicator.
* As a helper function, it can be extensible and modified in future versions.
*
* @private
* @param {HTMLElement} container The HTML element to append the indicator to
* @returns {HTMLElement} The loading indicator div element
*/
function createLoadingIndicator(container) {
if (!document.getElementById('p5-loading-style')) {
const loadingStyle = document.createElement('style');
loadingStyle.id = 'p5-loading-style';
loadingStyle.textContent = '@keyframes p5-loading-spin { to { transform: rotate(360deg); } }';
document.head.appendChild(loadingStyle);
}

const indicator = document.createElement('div');
indicator.className = 'loading-indicator';
indicator.style.cssText = `
position: fixed;
inset: 0;
margin: auto;
width: 30px;
height: 30px;
border-radius: 50%;

border: 3px solid rgba(0, 0, 0, 0.1);
border-top-color: rgba(0, 0, 0, 0.8);
animation: p5-loading-spin 1s linear infinite;
z-index: 9999;
`;

container.appendChild(indicator);
return indicator;
}
2 changes: 2 additions & 0 deletions src/core/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,7 @@ import rendering from './rendering';
import renderer from './p5.Renderer';
import renderer2D from './p5.Renderer2D';
import graphics from './p5.Graphics';
import loading from './loading';

p5.registerAddon(transform);
p5.registerAddon(structure);
Expand All @@ -646,6 +647,7 @@ p5.registerAddon(rendering);
p5.registerAddon(renderer);
p5.registerAddon(renderer2D);
p5.registerAddon(graphics);
p5.registerAddon(loading);

export default p5;

Expand Down
34 changes: 22 additions & 12 deletions src/core/p5.Renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ class Renderer {
this._clipInvert = false;

this._currentShape = undefined; // Lazily generate current shape

// Lazily cached by _individualTextureCoordinates(); initialized here
// (rather than computed) so subclasses can rely on their own
// constructor state when getSupportedIndividualVertexProperties()
// is first consulted.
this._supportsIndividualTextureCoordinates = undefined;
}

get currentShape() {
Expand Down Expand Up @@ -158,12 +164,22 @@ class Renderer {
}
}

bezierVertex(x, y, z = 0, u = 0, v = 0) {
const position = new Vector(x, y, z);
const textureCoordinates = this.getSupportedIndividualVertexProperties()
.textureCoordinates
// Builds the per-vertex texture-coordinates argument, caching whether
// the renderer supports them so the descriptor object isn't rebuilt on
// every vertex call.
_individualTextureCoordinates(u, v) {
if (this._supportsIndividualTextureCoordinates === undefined) {
this._supportsIndividualTextureCoordinates =
this.getSupportedIndividualVertexProperties().textureCoordinates;
}
return this._supportsIndividualTextureCoordinates
? new Vector(u, v)
: undefined;
}

bezierVertex(x, y, z = 0, u = 0, v = 0) {
const position = new Vector(x, y, z);
const textureCoordinates = this._individualTextureCoordinates(u, v);
this.currentShape.bezierVertex(position, textureCoordinates);
}

Expand All @@ -189,10 +205,7 @@ class Renderer {

splineVertex(x, y, z = 0, u = 0, v = 0) {
const position = new Vector(x, y, z);
const textureCoordinates = this.getSupportedIndividualVertexProperties()
.textureCoordinates
? new Vector(u, v)
: undefined;
const textureCoordinates = this._individualTextureCoordinates(u, v);
this.currentShape.splineVertex(position, textureCoordinates);
}

Expand Down Expand Up @@ -229,10 +242,7 @@ class Renderer {

vertex(x, y, z = 0, u = 0, v = 0) {
const position = new Vector(x, y, z);
const textureCoordinates = this.getSupportedIndividualVertexProperties()
.textureCoordinates
? new Vector(u, v)
: undefined;
const textureCoordinates = this._individualTextureCoordinates(u, v);
this.currentShape.vertex(position, textureCoordinates);
}

Expand Down
4 changes: 3 additions & 1 deletion src/core/p5.Renderer2D.js
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,9 @@ class Renderer2D extends Renderer {

drawShape(shape) {
const visitor = new PrimitiveToPath2DConverter({
strokeWeight: this.states.strokeWeight
strokeWeight: this.states.strokeWeight,
hasFill: !this._clipping && !!this.states.fillColor,
hasStroke: !this._clipping && !!this.states.strokeColor
});
shape.accept(visitor);
if (this._clipping) {
Expand Down
Loading
Loading