//Determines if the mouse was pressed on the previous frame var cl_mouseWasPressed = false; //Last hovered button var cl_lastHovered = null; //Last pressed button var cl_lastClicked = null; //All created buttons var cl_clickables = []; //This function is what makes the magic happen and should be ran after //each draw cycle. p5.prototype.runGUI = function () { for (i = 0; i < cl_clickables.length; ++i) { if (cl_lastHovered != cl_clickables[i]) cl_clickables[i].onOutside(); } if (cl_lastHovered != null) { if (cl_lastClicked != cl_lastHovered) { cl_lastHovered.onHover(); } } if (!cl_mouseWasPressed && cl_lastClicked != null) { cl_lastClicked.onPress(); } if (cl_mouseWasPressed && !mouseIsPressed && cl_lastClicked != null) { if (cl_lastClicked == cl_lastHovered) { cl_lastClicked.onRelease(); } cl_lastClicked = null; } cl_lastHovered = null; cl_mouseWasPressed = mouseIsPressed; } p5.prototype.registerMethod('post', p5.prototype.runGUI); //This function is used to get the bounding size of a //string of text for use in the 'textScaled' property function getTextBounds(m, font, size) { let txt = document.createElement("span"); document.body.appendChild(txt); txt.style.font = font; txt.style.fontSize = size + "px"; txt.style.height = 'auto'; txt.style.width = 'auto'; txt.style.position = 'absolute'; txt.style.whiteSpace = 'no-wrap'; txt.innerHTML = m; let width = Math.ceil(txt.clientWidth); let height = Math.ceil(txt.clientHeight); document.body.removeChild(txt); return [width, height]; } //Button Class function Clickable(x,y) { this.x = x; //X position of the clickable this.y = y; //Y position of the clickable this.width = 100; //Width of the clickable this.height = 50; //Height of the clickable this.color = "#FFFFFF"; //Background color of the clickable this.cornerRadius = 10; //Corner radius of the clickable this.strokeWeight = 2; //Stroke width of the clickable this.stroke = "#000000"; //Border color of the clickable this.text = "Press Me"; //Text of the clickable this.textColor = "#000000"; //Color for the text shown this.textSize = 12; //Size for the text shown this.textFont = "sans-serif"; //Font for the text shown this.textScaled = false; //Scale the text with the size of the clickable // image options this.image = null; // image object from p5loadimage() this.fitImage = false; // when true, image will stretch to fill button this.imageScale = 1.0; this.tint = null; // tint image using color this.noTint = true; // default to disable tinting this.filter = null; // filter effect // MODIFIED this.mode = "CORNER"; //accepts 'CORNER' or 'CENTER' this.updateTextSize = function () { if (this.textScaled) { for (let i = this.height; i > 0; i--) { if (getTextBounds(this.text, this.textFont, i)[0] <= this.width && getTextBounds(this.text, this.textFont, i)[1] <= this.height) { console.log("textbounds: " + getTextBounds(this.text, this.font, i)); console.log("boxsize: " + this.width + ", " + this.height); this.textSize = i / 2; break; } } } } this.updateTextSize(); this.onHover = function () { //This function is ran when the clickable is hovered but not //pressed. } this.onOutside = function () { //This function is ran when the clickable is NOT hovered. } this.onPress = function () { //This function is ran when the clickable is pressed. } this.onRelease = function () { //This function is ran when the cursor was pressed and then //released inside the clickable. If it was pressed inside and //then released outside this won't run. } this.locate = function (x, y) { this.x = x; this.y = y; } this.resize = function (w, h) { this.width = w; this.height = h; this.updateTextSize(); } this.drawImage = function(){ push(); imageMode(CENTER); let centerX = this.x + this.width / 2; let centerY = this.y + this.height / 2; let imgWidth = this.width; let imgHeight = this.height; if(this.fitImage){ let imageAspect = this.image.width / this.image.height; let buttonAspect = this.width / this.height; if(imageAspect > buttonAspect){ // image is wider than button imgWidth = this.width; imgHeight = this.height * (buttonAspect / imageAspect); } else{ imgWidth = this.width * (imageAspect / buttonAspect); imgHeight = this.height; } } image(this.image, centerX, centerY, imgWidth * this.imageScale, imgHeight * this.imageScale); if(this.tint && !this.noTint){ tint(this.tint) } else { noTint(); } if(this.filter){ filter(this.filter); } pop(); } this.draw = function () { push(); fill(this.color); stroke(this.stroke); strokeWeight(this.strokeWeight); // MODIFIED //// let drawX = this.x; let drawY = this.y; if (this.mode === "CENTER") { rectMode(CENTER); drawX = this.x; drawY = this.y; } else { rectMode(CORNER); drawX = this.x; drawY = this.y; } /// rect(drawX, drawY, this.width, this.height, this.cornerRadius); fill(this.textColor); noStroke(); if(this.image){ this.drawImage(); } textAlign(CENTER, CENTER); textSize(this.textSize); textFont(this.textFont); // MODIFIED /// let textX = drawX; let textY = drawY; if (this.mode === "CENTER") { textX = drawX; textY = drawY; } else { textX = drawX + this.width / 2; textY = drawY + this.height / 2; } text(this.text, textX, textY); ///// // text(this.text, this.x + this.width / 2, this.y + this.height / 2); // if (mouseX >= this.x && mouseY >= this.y // && mouseX < this.x + this.width && mouseY < this.y + this.height) { // cl_lastHovered = this; // if (mouseIsPressed && !cl_mouseWasPressed) // cl_lastClicked = this; // } // MODIFIED /// let mouseOver = false; if (this.mode === "CENTER") { mouseOver = ( mouseX >= this.x - this.width / 2 && mouseX <= this.x + this.width / 2 && mouseY >= this.y - this.height / 2 && mouseY <= this.y + this.height / 2 ); } else { mouseOver = ( mouseX >= this.x && mouseX <= this.x + this.width && mouseY >= this.y && mouseY <= this.y + this.height ); } if (mouseOver) { cl_lastHovered = this; if (mouseIsPressed && !cl_mouseWasPressed) { cl_lastClicked = this; } } ///// pop(); } cl_clickables.push(this); }