udatinos/libs/p5.imgui.js
2021-04-02 13:17:45 +02:00

581 行
无行尾
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');
}
}