+ private PImage logo;
+
+ protected final int STATE_DEFAULT = 0;
+ protected final int STATE_ACTIVE = 1;
+ protected final int STATE_PENDING = 2;
+
+ protected OverlayUI() {
+ leftPos = width - w;
+ leftTextPos = leftPos + 4;
+ logo = loadImage("logo-sm.png");
+ }
+
+ protected void drawLogoAndBackground() {
+ image(logo, 4, 4);
+ stroke(color(0, 0, 100));
+ // fill(color(0, 0, 50, 50)); // alpha is bad for perf
+ fill(color(0, 0, 30));
+ rect(leftPos-1, -1, w+2, height+2);
+ }
+
+ protected void drawToggleTip(String s) {
+ fill(#999999);
+ textFont(itemFont);
+ textAlign(LEFT);
+ text(s, leftTextPos, height-6);
+ }
+
+ protected void drawHelpTip() {
+ textFont(itemFont);
+ textAlign(RIGHT);
+ text("Tap 'u' to restore UI", width-4, height-6);
+ }
+
+ public void drawFPS() {
+ textFont(titleFont);
+ textAlign(LEFT);
+ fill(#666666);
+ text("FPS: " + (((int)(frameRate * 10)) / 10.), 4, height-6);
+ text("Target (-/+):", 50, height-6);
+ fill(#000000);
+ rect(104, height-16, 20, 12);
+ fill(#666666);
+ text("" + targetFramerate, 108, height-6);
+ }
+
+ protected int drawObjectList(int yPos, String title, Object[] items, Method stateMethod) {
+ return drawObjectList(yPos, title, items, classNameArray(items, null), stateMethod);
+ }
+
+ protected int drawObjectList(int yPos, String title, Object[] items, String[] names, Method stateMethod) {
+ noStroke();
+ fill(titleColor);
+ textFont(titleFont);
+ textAlign(LEFT);
+ text(title, leftTextPos, yPos += lineHeight);
+ if (items != null) {
+ textFont(itemFont);
+ color textColor;
+ boolean even = true;
+ for (int i = 0; i < items.length; ++i) {
+ Object o = items[i];
+ int state = STATE_DEFAULT;
+ try {
+ state = ((Integer) stateMethod.invoke(this, o)).intValue();
+ } catch (Exception x) {
+ throw new RuntimeException(x);
+ }
+ switch (state) {
+ case STATE_ACTIVE:
+ fill(lightGreen);
+ textColor = #eeeeee;
+ break;
+ case STATE_PENDING:
+ fill(lightBlue);
+ textColor = color(0, 0, 75 + 15*sin(millis()/200.));;
+ break;
+ default:
+ textColor = 0;
+ fill(even ? #666666 : #777777);
+ break;
+ }
+ rect(leftPos, yPos+6, width, lineHeight);
+ fill(textColor);
+ text(names[i], leftTextPos, yPos += lineHeight);
+ even = !even;
+ }
+ }
+ return yPos;
+ }
+
+ protected String[] classNameArray(Object[] objects, String suffix) {
+ if (objects == null) {
+ return null;
+ }
+ String[] names = new String[objects.length];
+ for (int i = 0; i < objects.length; ++i) {
+ names[i] = className(objects[i], suffix);
+ }
+ return names;
+ }
+
+ protected String className(Object p, String suffix) {
+ String s = p.getClass().getName();
+ int li;
+ if ((li = s.lastIndexOf(".")) > 0) {
+ s = s.substring(li + 1);
+ }
+ if (s.indexOf("SugarCubes$") == 0) {
+ s = s.substring("SugarCubes$".length());
+ }
+ if ((suffix != null) && ((li = s.indexOf(suffix)) != -1)) {
+ s = s.substring(0, li);
+ }
+ return s;
+ }
+
+ protected int objectClickIndex(int firstItemY) {
+ return (mouseY - firstItemY) / lineHeight;
+ }
+
+ abstract public void draw();
+ abstract public void mousePressed();
+ abstract public void mouseDragged();
+ abstract public void mouseReleased();
+}
+
+/**
+ * UI for control of patterns, transitions, effects.
+ */
+class ControlUI extends OverlayUI {