581 satır
No EOL
18 KiB
JavaScript
581 satır
No EOL
18 KiB
JavaScript
/**
|
|
* Prototype functions to make library
|
|
* method calls more like p5.js.
|
|
*/
|
|
|
|
// Create GUI context
|
|
let imgui;
|
|
|
|
p5.prototype.createGui = function() {
|
|
imgui = new ImGui();
|
|
}
|
|
|
|
// Start GUI
|
|
p5.prototype.startGui = function() {
|
|
imgui.start();
|
|
}
|
|
|
|
// End GUI
|
|
p5.prototype.endGui = function() {
|
|
imgui.end();
|
|
}
|
|
|
|
// Prototype functions for GUI elements
|
|
p5.prototype.button = function(label, x, y, w=128, h=32) {
|
|
return imgui.button(label, x, y, w, h);
|
|
}
|
|
|
|
p5.prototype.checkbox = function(label, value, x, y, w=32, h=32) {
|
|
return imgui.checkbox(label, value, x, y, w, h);
|
|
}
|
|
|
|
p5.prototype.slider = function(label, value, x, y, w=256, h=32, min=0, max=1) {
|
|
return imgui.slider(label, value, x, y, w, h, min, max);
|
|
}
|
|
|
|
p5.prototype.sliderV = function(label, value, x, y, w=32, h=256, min=0, max=1) {
|
|
return imgui.sliderV(label, value, x, y, w, h, min, max);
|
|
}
|
|
|
|
|
|
/**
|
|
* Generates hash code from a string.
|
|
* @see http://stackoverflow.com/q/7616461/940217
|
|
* @return {number}
|
|
*/
|
|
String.prototype.hashCode = function(){
|
|
if (Array.prototype.reduce){
|
|
return this.split("").reduce(function(a,b){a=((a<<5)-a)+b.charCodeAt(0);return a&a},0);
|
|
}
|
|
var hash = 0;
|
|
if (this.length === 0) return hash;
|
|
for (var i = 0; i < this.length; i++) {
|
|
var character = this.charCodeAt(i);
|
|
hash = ((hash<<5)-hash)+character;
|
|
hash = hash & hash; // Convert to 32bit integer
|
|
}
|
|
return hash;
|
|
}
|
|
|
|
|
|
/*******************
|
|
* IMGUI
|
|
*
|
|
*
|
|
*/
|
|
class ImGui {
|
|
constructor() {
|
|
this.hotItem = 0;
|
|
this.activeItem = 0;
|
|
|
|
this.style = new ImGuiStyle();
|
|
// this.style.StyleColorsClassic();
|
|
}
|
|
|
|
// Check whether current mouse position
|
|
// is within a rectangle
|
|
regionHit(x, y, w, h) {
|
|
if (mouseX < x ||
|
|
mouseY < y ||
|
|
mouseX >= x + w ||
|
|
mouseY >= y + h) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
setHit(id) {
|
|
this.hotItem = id;
|
|
if (this.activeItem == 0 && mouseIsPressed) {
|
|
this.activeItem = id;
|
|
}
|
|
}
|
|
|
|
/// Simple checkbox IMGUI widget
|
|
checkbox(label, value, x, y, w=32, h=32) {
|
|
// Create hashed id from label
|
|
let id = label.hashCode();
|
|
// let id = new Error().stack;
|
|
|
|
// Check whether the button should be 'hot' or 'active'
|
|
if (this.regionHit(x, y, w, h)) {
|
|
this.hotItem = id;
|
|
if (this.activeItem == 0 && mouseIsPressed) {
|
|
this.activeItem = id;
|
|
value.val = !value.val;
|
|
}
|
|
}
|
|
|
|
// Render button
|
|
let x8 = x+w/6;
|
|
let y8 = y+h/6;
|
|
let w16 = w-w/3;
|
|
let h16 = h-h/3;
|
|
let xw = x8+w16;
|
|
let yh = y8+h16;
|
|
let strokeMult = map(((w > h) ? w : h), 32, 1000, 2, 20);
|
|
|
|
push();
|
|
rectMode(CORNER);
|
|
stroke(this.style.col_checkOuterStroke);
|
|
strokeWeight(this.style.checkStrokeWt);
|
|
fill(this.style.col_checkOuterFill);
|
|
rect(x, y, w, h, this.style.rounding);
|
|
|
|
|
|
if (this.hotItem == id && !value.val) {
|
|
// Button is 'hot' and 'false'
|
|
fill(this.style.col_checkOuterFillHover);
|
|
rect(x, y, w, h, this.style.rounding);
|
|
}
|
|
else if (this.hotItem == id && value.val) {
|
|
// Button is 'hot' and 'true'
|
|
push();
|
|
stroke(this.style.col_checkInnerStrokeHover);
|
|
strokeWeight(this.style.checkStrokeWt*strokeMult);
|
|
line(x8, y8, xw, yh);
|
|
line(xw, y8, x8, yh);
|
|
pop();
|
|
|
|
if (this.activeItem == id) {
|
|
// Button is also 'active'
|
|
fill(this.style.col_checkOuterFillActive);
|
|
rect(x, y, w, h, this.style.rounding);
|
|
|
|
push();
|
|
stroke(this.style.col_checkInnerStrokeActive);
|
|
strokeWeight(this.style.checkStrokeWt*strokeMult);
|
|
line(x8, y8, xw, yh);
|
|
line(xw, y8, x8, yh);
|
|
pop();
|
|
}
|
|
}
|
|
else if (value.val) {
|
|
// Button is 'true' but not 'hot'
|
|
push();
|
|
stroke(this.style.col_checkInnerStroke);
|
|
strokeWeight(this.style.checkStrokeWt*strokeMult);
|
|
line(x8, y8, xw, yh);
|
|
line(xw, y8, x8, yh);
|
|
pop();
|
|
}
|
|
|
|
pop();
|
|
|
|
// If button is 'hot' and 'active', but mouse button
|
|
// is not down, the user must have clicked the button.
|
|
if (mouseIsPressed &&
|
|
this.hotItem == id &&
|
|
this.activeItem == id) {
|
|
return true;
|
|
}
|
|
|
|
// Otherwise, no clicky.
|
|
return false;
|
|
}
|
|
|
|
/// Simple button IMGUI widget
|
|
button(label, x, y, w=128, h=32) {
|
|
// Create hashed id from stack
|
|
let id = label.hashCode();
|
|
|
|
// Check for 'hot' or 'active'
|
|
if (this.regionHit(x, y, w, h)) {
|
|
this.setHit(id);
|
|
}
|
|
|
|
// Render button
|
|
push();
|
|
stroke(this.style.col_buttonStroke);
|
|
strokeWeight(this.style.buttonStrokeWt);
|
|
rectMode(CORNER);
|
|
|
|
if (this.hotItem == id) {
|
|
if (this.activeItem == id) {
|
|
// Button is both 'hot' and 'active'
|
|
fill(this.style.col_buttonFillActive);
|
|
rect(x, y, w, h, this.style.rounding);
|
|
}
|
|
else {
|
|
// Button is merely 'hot'
|
|
fill(this.style.col_buttonFillHover);
|
|
rect(x, y, w, h, this.style.rounding);
|
|
}
|
|
}
|
|
else {
|
|
// Button is not hot, but it may be active
|
|
fill(this.style.col_buttonFill);
|
|
rect(x, y, w, h, this.style.rounding);
|
|
}
|
|
|
|
// Label rendering.
|
|
push();
|
|
fill(this.style.col_buttonLabel);
|
|
noStroke();
|
|
textAlign(CENTER, CENTER);
|
|
textFont(this.style.labelFont);
|
|
let size = w/10;
|
|
if (size > this.style.labelFontMaxSize) {
|
|
size = this.style.labelFontMaxSize;
|
|
}
|
|
textSize(size);
|
|
text(label, x + w/2, y + h/2);
|
|
pop();
|
|
|
|
pop();
|
|
|
|
// If button is 'hot' and 'active', but mouse button
|
|
// is not down, the user must have clicked the button.
|
|
if (mouseIsPressed &&
|
|
this.hotItem == id &&
|
|
this.activeItem == id) {
|
|
return true;
|
|
}
|
|
|
|
// Otherwise, no clicky.
|
|
return false;
|
|
}
|
|
|
|
/// Simple slider IMGUI widget
|
|
slider(label, value, x, y, w=256, h=32, min=0, max=1) {
|
|
// Create hashed id from label
|
|
let id = label.hashCode();
|
|
|
|
// Calculate mouse cursor's relative x offset
|
|
let xpos = map(value.val, min, max, 0, w-32);
|
|
|
|
// Check for 'hot' or 'active'
|
|
if (this.regionHit(x, y, w, h)) {
|
|
this.setHit(id);
|
|
}
|
|
|
|
// Render the slider
|
|
if (this.activeItem == id) {
|
|
this.drawSlider(xpos, x, y, w, h,
|
|
this.style.col_sliderBgFillActive,
|
|
this.style.col_sliderIndctrFillActive,
|
|
this.style.col_sliderGrabFillActive,
|
|
this.style.col_sliderGrabStroke);
|
|
}
|
|
else if (this.hotItem == id) {
|
|
this.drawSlider(xpos, x, y, w, h,
|
|
this.style.col_sliderBgFillHover,
|
|
this.style.col_sliderIndctrFillHover,
|
|
this.style.col_sliderGrabFillHover,
|
|
this.style.col_sliderGrabStroke);
|
|
}
|
|
else {
|
|
this.drawSlider(xpos, x, y, w, h,
|
|
this.style.col_sliderBgFill,
|
|
this.style.col_sliderIndctrFill,
|
|
this.style.col_sliderGrabFill,
|
|
this.style.col_sliderGrabStroke);
|
|
}
|
|
|
|
// Update widget value
|
|
if (this.activeItem == id) {
|
|
|
|
let mousePos = mouseX - x;
|
|
let v = map(mousePos, 0, w, min, max, true);
|
|
|
|
if (v != value.val) {
|
|
value.val = v;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// Simple vertical slider IMGUI widget
|
|
sliderV(label, value, x, y, w=32, h=256, min=0, max=1) {
|
|
// Create hashed id from label
|
|
let id = label.hashCode();
|
|
|
|
// Calculate mouse cursor's relative y offset
|
|
let ypos = map(value.val, min, max, 0, h-32);
|
|
|
|
// Check for 'hot' or 'active'
|
|
if (this.regionHit(x, y, w, h)) {
|
|
this.setHit(id);
|
|
}
|
|
|
|
// Render the slider
|
|
if (this.activeItem == id) {
|
|
this.drawSliderV(ypos, x, y, w, h,
|
|
this.style.col_sliderBgFillActive,
|
|
this.style.col_sliderIndctrFillActive,
|
|
this.style.col_sliderGrabFillActive,
|
|
this.style.col_sliderGrabStroke);
|
|
}
|
|
else if (this.hotItem == id) {
|
|
this.drawSliderV(ypos, x, y, w, h,
|
|
this.style.col_sliderBgFillHover,
|
|
this.style.col_sliderIndctrFillHover,
|
|
this.style.col_sliderGrabFillHover,
|
|
this.style.col_sliderGrabStroke);
|
|
}
|
|
else {
|
|
this.drawSliderV(ypos, x, y, w, h,
|
|
this.style.col_sliderBgFill,
|
|
this.style.col_sliderIndctrFill,
|
|
this.style.col_sliderGrabFill,
|
|
this.style.col_sliderGrabStroke);
|
|
}
|
|
|
|
// Update widget value
|
|
if (this.activeItem == id) {
|
|
|
|
let mousePos = mouseY - y;
|
|
let v = map(mousePos, 0, h, min, max, true);
|
|
|
|
if (v != value.val) {
|
|
value.val = v;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// Draw function for slider
|
|
drawSlider(xpos, x, y, w, h, bgFill, indctrFill, grabFill, grabStroke) {
|
|
push();
|
|
stroke(this.style.col_sliderStroke);
|
|
strokeWeight(this.style.sliderStrokeWt);
|
|
rectMode(CORNER);
|
|
|
|
// Render bg
|
|
fill(bgFill);
|
|
rect(x, y, w, h, this.style.rounding);
|
|
|
|
// Render indicator
|
|
push();
|
|
noStroke();
|
|
fill(indctrFill);
|
|
// rect(x+0.2*h, y+0.2*h, xpos+0.*h, h-0.4*h,
|
|
// this.style.rounding, 0, 0, this.style.rounding);
|
|
rect(x+10, y+10, xpos+12, h-20,
|
|
this.style.rounding, 0, 0, this.style.rounding);
|
|
pop();
|
|
|
|
// Render grab
|
|
push();
|
|
stroke(grabStroke);
|
|
fill(grabFill);
|
|
rect(x+8+xpos, y+8, 16, h-16, this.style.rounding);
|
|
pop();
|
|
pop();
|
|
}
|
|
|
|
/// Draw function for vertical slider
|
|
drawSliderV(ypos, x, y, w, h, bgFill, indctrFill, grabFill, grabStroke) {
|
|
push();
|
|
stroke(this.style.col_sliderStroke);
|
|
strokeWeight(this.style.sliderStrokeWt);
|
|
rectMode(CORNER);
|
|
|
|
// Render bg
|
|
fill(bgFill);
|
|
rect(x, y, w, h, this.style.rounding);
|
|
|
|
// Render indicator
|
|
push();
|
|
noStroke();
|
|
fill(indctrFill);
|
|
// rect(x+0.2*w, y+ypos+0.1*w, w-0.4*w, h-ypos-0.3*w,
|
|
// 0, 0, this.style.rounding, this.style.rounding);
|
|
rect(x+10, y+ypos+12, w-20, h-ypos-20,
|
|
0, 0, this.style.rounding, this.style.rounding);
|
|
pop();
|
|
|
|
// Render grab
|
|
push();
|
|
stroke(grabStroke);
|
|
fill(grabFill);
|
|
rect(x+8, y+8+ypos, w-16, 16, this.style.rounding);
|
|
pop();
|
|
pop();
|
|
}
|
|
|
|
/// Prepare for start IMGUI code
|
|
start() {
|
|
this.hotItem = 0;
|
|
}
|
|
|
|
/// Finish at end IMGUI code
|
|
end() {
|
|
if (!mouseIsPressed) {
|
|
this.activeItem = 0;
|
|
}
|
|
else {
|
|
if (this.activeItem == 0) {
|
|
this.activeItem = -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*******************
|
|
* IMGUI STYLE
|
|
*
|
|
*
|
|
*/
|
|
|
|
class ImGuiStyle {
|
|
constructor() {
|
|
// Global pars
|
|
this.rounding = 10;
|
|
this.labelFont = 'Arial';
|
|
this.labelFontMaxSize = 30;
|
|
this.strokeWt = 2;
|
|
|
|
// Button pars
|
|
this.buttonStrokeWt = this.strokeWt;
|
|
this.col_buttonStroke = color(0);
|
|
this.col_buttonFill = color(160);
|
|
this.col_buttonFillHover = color(196);
|
|
this.col_buttonFillActive = color(220);
|
|
this.col_buttonLabel = color(0);
|
|
|
|
// Checkbox pars
|
|
this.checkStrokeWt = this.strokeWt;
|
|
this.col_checkOuterStroke = color(0);
|
|
this.col_checkOuterStrokeHover = color(0);
|
|
this.col_checkOuterStrokeActive = color(0);
|
|
this.col_checkOuterFill = color(128);
|
|
this.col_checkOuterFillHover = color(144);
|
|
this.col_checkOuterFillActive = color(160);
|
|
this.col_checkInnerFill = color(200);
|
|
this.col_checkInnerStroke = color(200);
|
|
this.col_checkInnerFillHover = color(220);
|
|
this.col_checkInnerStrokeHover = color(220);
|
|
this.col_checkInnerFillActive = color(240);
|
|
this.col_checkInnerStrokeActive = color(240);
|
|
|
|
// Slider pars
|
|
this.sliderStrokeWt = this.strokeWt;
|
|
this.col_sliderStroke = color(0);
|
|
this.col_sliderBgFill = color(160);
|
|
this.col_sliderBgFillHover = color(175);
|
|
this.col_sliderBgFillActive = color(175);
|
|
this.col_sliderBgStroke = color(0);
|
|
this.col_sliderBgStrokeHover = color(0);
|
|
this.col_sliderBgStrokeActive = color(0);
|
|
this.col_sliderIndctrFill = color(128);
|
|
this.col_sliderIndctrFillHover = color(144);
|
|
this.col_sliderIndctrFillActive = color(144);
|
|
this.col_sliderIndctrStroke = color(128);
|
|
this.col_sliderIndctrStrokeHover = color(144);
|
|
this.col_sliderIndctrStrokeActive = color(144);
|
|
this.col_sliderGrabFill = color(64);
|
|
this.col_sliderGrabFillHover = color(96);
|
|
this.col_sliderGrabFillActive = color(240);
|
|
this.col_sliderGrabStroke = color(64);
|
|
this.col_sliderGrabStrokeHover = color(0);
|
|
this.col_sliderGrabStrokeActive = color(0);
|
|
}
|
|
|
|
StyleColorsGrayscale() {
|
|
this.rounding = 10;
|
|
this.labelFont = 'Arial';
|
|
this.labelFontMaxSize = 30;
|
|
this.strokeWt = 2;
|
|
|
|
// Button pars
|
|
this.buttonStrokeWt = this.strokeWt;
|
|
this.col_buttonStroke = color(0);
|
|
this.col_buttonFill = color(160);
|
|
this.col_buttonFillHover = color(196);
|
|
this.col_buttonFillActive = color(220);
|
|
this.col_buttonLabel = color(0);
|
|
|
|
// Checkbox pars
|
|
this.checkStrokeWt = this.strokeWt;
|
|
this.col_checkOuterStroke = color(0);
|
|
this.col_checkOuterStrokeHover = color(0);
|
|
this.col_checkOuterStrokeActive = color(0);
|
|
this.col_checkOuterFill = color(128);
|
|
this.col_checkOuterFillHover = color(144);
|
|
this.col_checkOuterFillActive = color(160);
|
|
this.col_checkInnerFill = color(200);
|
|
this.col_checkInnerStroke = color(200);
|
|
this.col_checkInnerFillHover = color(220);
|
|
this.col_checkInnerStrokeHover = color(220);
|
|
this.col_checkInnerFillActive = color(240);
|
|
this.col_checkInnerStrokeActive = color(240);
|
|
|
|
// Slider pars
|
|
this.sliderStrokeWt = this.strokeWt;
|
|
this.col_sliderStroke = color(0);
|
|
this.col_sliderBgFill = color(160);
|
|
this.col_sliderBgFillHover = color(175);
|
|
this.col_sliderBgFillActive = color(175);
|
|
this.col_sliderBgStroke = color(0);
|
|
this.col_sliderBgStrokeHover = color(0);
|
|
this.col_sliderBgStrokeActive = color(0);
|
|
this.col_sliderIndctrFill = color(128);
|
|
this.col_sliderIndctrFillHover = color(144);
|
|
this.col_sliderIndctrFillActive = color(144);
|
|
this.col_sliderIndctrStroke = color(128);
|
|
this.col_sliderIndctrStrokeHover = color(144);
|
|
this.col_sliderIndctrStrokeActive = color(144);
|
|
this.col_sliderGrabFill = color(64);
|
|
this.col_sliderGrabFillHover = color(96);
|
|
this.col_sliderGrabFillActive = color(240);
|
|
this.col_sliderGrabStroke = color(64);
|
|
this.col_sliderGrabStrokeHover = color(96);
|
|
this.col_sliderGrabStrokeActive = color(0);
|
|
}
|
|
|
|
StyleColorsClassic() {
|
|
this.rounding = 10;
|
|
this.labelFont = 'Arial';
|
|
this.labelFontMaxSize = 30;
|
|
this.strokeWt = 5;
|
|
|
|
// Button pars
|
|
this.buttonStrokeWt = this.strokeWt;
|
|
this.col_buttonStroke = color('#D5CAD6');
|
|
this.col_buttonFill = color('#EFEFF0');
|
|
this.col_buttonFillHover = color('#F7F7F7');
|
|
this.col_buttonFillActive = color('#C9F0FF');
|
|
this.col_buttonLabel = color('#6B5E62');
|
|
|
|
// Checkbox pars
|
|
this.checkStrokeWt = this.strokeWt;
|
|
this.col_checkOuterStroke = color('#D5CAD6');
|
|
this.col_checkOuterStrokeHover = color('#D5CAD6');
|
|
this.col_checkOuterStrokeActive = color('#D5CAD6');
|
|
this.col_checkOuterFill = color('#EFEFF0');
|
|
this.col_checkOuterFillHover = color('#F7F7F7');
|
|
this.col_checkOuterFillActive = color('#C9F0FF');
|
|
this.col_checkInnerFill = color('#6B5E62');
|
|
this.col_checkInnerStroke = color('#6B5E62');
|
|
this.col_checkInnerFillHover = color('#7A6B70');
|
|
this.col_checkInnerStrokeHover = color('#7A6B70');
|
|
this.col_checkInnerFillActive = color('#7A6B70');
|
|
this.col_checkInnerStrokeActive = color('#7A6B70');
|
|
|
|
// Slider pars
|
|
this.sliderStrokeWt = this.strokeWt;
|
|
this.col_sliderStroke = color('#D5CAD6');
|
|
this.col_sliderBgFill = color('#EFEFF0');
|
|
this.col_sliderBgFillHover = color('#F7F7F7');
|
|
this.col_sliderBgFillActive = color('#F7F7F7');
|
|
this.col_sliderBgStroke = color(0);
|
|
this.col_sliderBgStrokeHover = color(0);
|
|
this.col_sliderBgStrokeActive = color(0);
|
|
this.col_sliderIndctrFill = color('#D5CAD6');
|
|
this.col_sliderIndctrFillHover = color('#D5CAD6');
|
|
this.col_sliderIndctrFillActive = color('#D5CAD6');
|
|
this.col_sliderIndctrStroke = color(128);
|
|
this.col_sliderIndctrStrokeHover = color(144);
|
|
this.col_sliderIndctrStrokeActive = color(144);
|
|
this.col_sliderGrabFill = color('#6B5E62');
|
|
this.col_sliderGrabFillHover = color('#7A6B70');
|
|
this.col_sliderGrabFillActive = color('#C9F0FF');
|
|
this.col_sliderGrabStroke = color('#6B5E62');
|
|
this.col_sliderGrabStrokeHover = color('#7A6B70');
|
|
this.col_sliderGrabStrokeActive = color('#7A6B70');
|
|
}
|
|
} |