//contains the GUI (ie CP5) in the secondapplet. also contains 3 classes: shaderManager, Brick and Slider /* todo: implement "solo" and "only up till here" button on bricks */ PImage bin; int maxSurfaceHeight = 500; int nativeResoX, nativeResoY; boolean renderSizeChanged = true; public class SecondApplet extends PApplet { ControlP5 cp5; shaderManager shaderManager = new shaderManager(); ArrayList shaderList = new ArrayList(); ArrayList bricks = new ArrayList(); ArrayList slider = new ArrayList(); //brick int binX, binY, binS; //PApplet parent; /*SecondApplet(PApplet _parent){ super(); this.parent = _parent; }*/ public void settings() { size(275, 120); } //Toggle webcam, auto; Toggle auto; public void setup() { surface.setLocation(285, 240); //List l = Arrays.asList(availableFx); List l = Arrays.asList(FX); cp5 = new ControlP5(this); cp5.addScrollableList("") .setPosition(10, height-110) .setSize(80, 100) .setBarHeight(0) .setItemHeight(20) .plugTo(this, "CP5_listActions") .addItems(l) .setType(ControlP5.LIST); Toggle rec = cp5.addToggle("record") .setPosition(100, height-110) .setSize(12, 12) .plugTo(this, "CP5_recordAction"); rec.getCaptionLabel().getStyle().setMargin(-17, 0, 0, 20); auto = cp5.addToggle("spawn playing") .setPosition(100, height-95) .setSize(12, 12) .setValue(false) .plugTo(this, "CP5_spawnPlayingAction"); auto.getCaptionLabel().getStyle().setMargin(-17, 0, 0, 20); Bang pauseAll = cp5.addBang("pause all") .setPosition(100, height-80) .setSize(12, 12) .plugTo(this, "CP5_pauseAllAction"); pauseAll.getCaptionLabel().getStyle().setMargin(-17, 0, 0, 20); /* webcam = cp5.addToggle("webcam") .setPosition(100, height-65) .setSize(12, 12) .setValue(false) .plugTo(this, "CP5_webcamAction"); webcam.getCaptionLabel().getStyle().setMargin(-17, 0, 0, 20);*/ Toggle robot = cp5.addToggle("autoPlay") .setPosition(100, height-50) .setSize(12, 12) .setValue(false) .plugTo(this, "CP5_robotAction"); robot.getCaptionLabel().getStyle().setMargin(-17, 0, 0, 20); Bang nativeReso = cp5.addBang("native reso") .setPosition(220, height-35) .setSize(12, 12) .plugTo(this, "CP5_nativeResoAction"); nativeReso.getCaptionLabel().getStyle().setMargin(-17, 0, 0, 20); /* Toggle saveParams = cp5.addToggle("save parameters") .setPosition(100, height-45) .setSize(15, 15) .plugTo(this, "CP5_saveParamsAction"); saveParams.getCaptionLabel().getStyle().setMargin(-17,0,0,20); */ binX = width-55; binY = height-85; binS = 40; } void CP5_robotAction()  { startRobot = true; autoPlay = !autoPlay; } /* void CP5_webcamAction()  { webcamMode = !webcamMode; if (webcamMode) sourceManager.startWebcam(); else { sourceManager.stopWebcam(); source = null; //to trigger auto-fallback next frame } } */ void CP5_nativeResoAction() { renderSize = max(nativeResoX, nativeResoY); //renderer.setSize(nativeResoX, nativeResoY); } void CP5_recordAction() { recording = !recording; } void CP5_spawnPlayingAction() { spawnPlaying = !spawnPlaying; } void CP5_pauseAllAction() { for (int i = 0; i < bricks.size(); i++) { if (!bricks.get(i).paused) bricks.get(i).playPause(); } } int totalBrickHeight; public void draw() { background(68, 68, 68); pushMatrix(); if (heightOverLimit) { translate(0, scrollAmount); } totalBrickHeight = 0; for (int i = 0; i < bricks.size(); i++) { bricks.get(i).update(); bricks.get(i).display(); //bricks.get(i).y = totalBrickHeight; ????? what was that for totalBrickHeight+= bricks.get(i).h; } popMatrix(); if (heightOverLimit) { strokeWeight(3); fill(255); line(width-5, -scrollAmount+4, width-5, height-120+(maxSurfaceHeight-120-totalBrickHeight)-scrollAmount-4); //-scrollAmount + (-1*(maxSurfaceHeight-120-totalBrickHeight))); } fill(68, 68, 68); noStroke(); rect(0, height-120, width, 120); image(bin, binX, binY, binS, binS); stroke(255); strokeWeight(1); textSize(25); fill(255); text(renderer.width + "x" + renderer.height, 100, height-15); if (typingNumber) { rect(100, height - 35, textWidth(str(renderer.width) + "x" + str(renderer.height)), 25); fill(0); text(newResoString, 100, height-15); fill(255); if (frameCount >= numberTypedFrame+90) { setTypedReso(); } } textSize(10); line(0, height-120, width, height-120); if (pressedBrick != -1) { fill(255); noStroke(); rect(mouseX, mouseY, 35, 15); } } boolean heightOverLimit; void refreshSurface(int mode) { int currentBrickHeight = 0; if (shaderList.size() > 0) { if (mode == 0) { currentBrickHeight = totalBrickHeight + bricks.get(shaderList.size()-1).h; surface.setSize(width, height+bricks.get(shaderList.size()-1).h); } else if (mode == 1) { currentBrickHeight = totalBrickHeight - bricks.get(pressedBrick).h; if (heightOverLimit) { surface.setSize(width, currentBrickHeight+120); } else { surface.setSize(width, height-bricks.get(pressedBrick).h); } } } else { surface.setSize(width, 120); } if (currentBrickHeight + 120 > maxSurfaceHeight) { surface.setSize(width, maxSurfaceHeight); heightOverLimit = true; } else { heightOverLimit = false; scrollAmount = 0; } cp5.setPosition(0, height-120); binY = height-87; } class shaderManager { void addShader(Shader shader) { shaderList.add(shader); shader.pos = shaderList.size()-1; bricks.add(new Brick(shaderList.size()-1, shaderList.get(shaderList.size()-1).params, shader.name)); refreshSurface(0); //if (!spawnPlaying) bricks.get(shaderList.size()-1).pauseAllSliders(); println("Added " + shader + " to fxList at spot. List length: " + shaderList.size()); } void swapShader(int pos1, int pos2) { Collections.swap(shaderList, pos1, pos2); Collections.swap(bricks, pos1, pos2); shaderList.get(pos1).pos = pos1; shaderList.get(pos2).pos = pos2; bricks.get(pos1).setPos(pos1); bricks.get(pos2).setPos(pos2); for (int i = 0; i < bricks.size(); i++) { bricks.get(i).updateSliderPos(); } for (int i = min(pos1, pos2); i < shaderList.size(); i++) { //println(i); //shaderList.get(i).change = true; } } void moveShader(int pos1, int pos2) { if (pos2 > pos1) { pos2 -=1; for (int i = pos1; i < pos2; i++) { swapShader(i, i+1); } } else { for (int i = pos1; i > pos2; i--) { swapShader(i, i-1); } } for (int i = max(pos1, pos2); i > 0; i--) { //println(i); //shaderList.get(i).change = true; } } void removeShader(int pos) { if (pos >= 0 && shaderList.size() > pos) { refreshSurface(1); shaderList.remove(pos); bricks.remove(pos); for (int i = shaderList.size()-1; i > -1; i--) { bricks.get(i).setPos(i); bricks.get(i).updateSliderPos(); shaderList.get(i).pos = i; } } for (int i = pos; i < shaderList.size(); i++) { //shaderList.get(i).change = true; } } int previousRenderSize = renderSize; void applyShader() { renderSizeChanged = true; if (previousRenderSize != renderSize) previousRenderSize = renderSize; else renderSizeChanged = false; for (int i = 0; i < shaderList.size(); i++) { try { shaderList.get(i).getValuesFromGUI(); if (bricks.get(i).active) { //shaderList.get(i).getValuesFromGUI(); shaderList.get(i).shade(); } } catch(Exception e) { println("Warning: Brick not yet loaded"); } if (i > maxFx) break; } } } int pressedBrick = -1; class Brick { ArrayList slider = new ArrayList(); ArrayList params = new ArrayList(); boolean active, paused, dragging, dragHovering, hovering, hoveringLineAbove, hoveringLineBelow, hoverActiveButton, hoverPauseButton; boolean[] pauseStates; color brickBGcol; int pos; int h, y; String name; Brick(int pos_, ArrayList params_, String name_) { name = name_; pos = pos_; params = params_; active = true; y = totalBrickHeight; h = 20 + params.size() * 20; for (int i = 0; i < params.size(); i++) { slider.add(new Slider(10, 20+(20*i)+y, 230, 12, params.get(i).minValue, params.get(i).maxValue, params.get(i).name, params.get(i).type, params.get(i).osciModes)); //add possible waves to slider } pauseStates = new boolean[slider.size()]; for (int i = 0; i < pauseStates.length; i++) { pauseStates[i] = false; } if (!spawnPlaying) { playPause(); } } void setPos(int pos_) { pos = pos_; } void updateSliderPos() { y = 0; for (int i = 0; i < pos; i++) { y += bricks.get(i).h; } for (int i = 0; i < slider.size(); i++) { slider.get(i).y = 20+(20*i)+y; } } void exchangeSlider(int sliderNo, Param param) { slider.get(sliderNo).setMinMax(param.minValue, param.maxValue); slider.get(sliderNo).setMode(param.type); slider.get(sliderNo).setLabel(param.name); } void playPause() { paused = !paused; if (paused) { pauseAllSliders(); } else { resumeAllSliders(); } } void toggleActive() { active = !active; //for (int i = pos; i < shaderList.size(); i++) { // shaderList.get(i).change = true; //} } void pauseAllSliders() { for (int i = 0; i < slider.size(); i++) { pauseStates[i] = slider.get(i).animated; slider.get(i).animated = false; } } void resumeAllSliders() { for (int i = 0; i < slider.size(); i++) { slider.get(i).animated = pauseStates[i]; } } void update() { boolean sliderHover = false; for (int i = 0; i < slider.size(); i++) { if (slider.get(i).hovering || slider.get(i).hovering_anim_btn) sliderHover = true; if (paused && slider.get(i).animated) paused = false; } if (mouseX > 10 && mouseX < 22 && mouseY > 4+totalBrickHeight+scrollAmount && mouseY < 4+totalBrickHeight+13+scrollAmount) { hoverActiveButton = true; } else { hoverActiveButton = false; } if (mouseX > 25 && mouseX < 37 && mouseY > 4+totalBrickHeight+scrollAmount && mouseY < 4+totalBrickHeight+13+scrollAmount) { hoverPauseButton = true; } else { hoverPauseButton = false; } if (mouseY > y-5+scrollAmount && mouseY < y+5+scrollAmount && pressedBrick != -1) { hoveringLineAbove = true; if (pos > 0) { bricks.get(pos-1).hovering = false; } } else if (pos == bricks.size()-1 && mouseY > y+h-5+scrollAmount && mouseY < y+h+5+scrollAmount && pressedBrick != -1) { hoveringLineBelow = true; } else { hoveringLineBelow = false; hoveringLineAbove = false; if (mouseY > totalBrickHeight+scrollAmount && mouseY < totalBrickHeight+h+scrollAmount && !sliderHover && !hoverActiveButton && !hoverPauseButton) { hovering = true; } else { hovering = false; } } for (int i = 0; i < slider.size(); i++) { slider.get(i).update(); params.get(i).value = slider.get(i).value; } brickBGcol = color(85, 85, 85); } void press() { pressedBrick = pos; } void display() { noStroke(); if (active) { if (dragging) brickBGcol = color(51, 51, 51); else if (dragHovering && !hoveringLineBelow && !hoveringLineAbove) brickBGcol= color (105, 105, 105); else brickBGcol = color(85, 85, 85); } else { brickBGcol = color(0); } fill(brickBGcol); rect(0, totalBrickHeight, width, h); fill(255); text(name, 40, 13+totalBrickHeight, 10); stroke(255); strokeWeight(1); if (active) fill(185); else noFill(); rect(10, 4+totalBrickHeight, 10, 10); if (paused) fill(185); else noFill(); rect(25, 4+totalBrickHeight, 10, 10); for (int i = 0; i < slider.size(); i++) { slider.get(i).display(); } stroke(150); strokeWeight(1); line(0, totalBrickHeight+h-1, width, totalBrickHeight+h-1); if (hoveringLineAbove) { stroke(200); strokeWeight(5); line(0, y, width, y); } if (hoveringLineBelow) { stroke(200); strokeWeight(5); line(0, y+h, width, y+h); } } } int pressedSlider = -1; //class Slider extends Brick{ class Slider { int x, y, w, h, mode; int[] osciModes; float minVal, maxVal, value; //should be private but doesnt work lol boolean hovering, hovering_anim_btn, animated; String label; Oscillator osci; Slider(int x_, int y_, int w_, int h_, float minVal_, float maxVal_, String label_, int mode_, int[] osciModes_) { x = x_; y = y_; w = w_; h = h_; minVal = minVal_; maxVal = maxVal_; mode = mode_; label = label_ + (mode == INTVAL ? " (INT)" : " (FLOAT)"); osciModes = osciModes_; osci = new Oscillator(int(random(2, 5)), osciModes); osci.amplitude(minVal, maxVal); osci.update(); setValue(osci.value); animated = true; slider.add(this); } void setPosX(int x_) { x = x_; } void setMinMax(float min, float max) { float cval = map(value, minVal, maxVal, 0, 10000); minVal = min; maxVal = max; osci.amplitude(minVal, maxVal); setValue(map(cval, 0, 10000, minVal, maxVal)); } void setLabel(String lab) { label = lab + (mode == INTVAL ? " (INT)" : " (FLOAT)"); } void setMode(int mode_) { mode = mode_; } void press(int myId_) { pressedSlider = myId_; animated = false; setValue(map(mouseX, x, x+w, minVal, maxVal)); } void setValue(float value_) { value = value_; value = constrain(value, minVal, maxVal); if (mode == INTVAL) value = int(round(value)); } float getValue() { return(value); } void update() { osci.update(); if (animated) { setValue(osci.value); } if (mouseX >= x && mouseX <= x+w && mouseY >= y+scrollAmount && mouseY <= y+h+scrollAmount) { hovering = true; } else { hovering = false; } if (mouseX >= x+w+5 && mouseX <= x+w+5+15 && mouseY >= y+scrollAmount && mouseY <= y+h+scrollAmount) { hovering_anim_btn = true; } else { hovering_anim_btn = false; } } void display() { stroke(255); strokeWeight(1); fill(100+(40*int(hovering))); rect(x, y, w, h); fill(185+(40*int(hovering))); rect(x, y, map(value, minVal, maxVal, 0, w), h); fill(255); text(label, x+5, y+10); if (animated) { fill(185+(40*int(hovering_anim_btn))); } else { fill(100+(40*int(hovering_anim_btn))); } rect(x+w+5, y, h, h); } } //CP5 void CP5_listActions(int n) { addByID(n); } boolean startRobot; void robot() { if (startRobot) { if (!spawnPlaying) { auto.setValue(true); } } startRobot = false; if (renderFrameRate > 5) { renderSize+=2; } else { if (renderSize >= 45) renderSize-=15; } if (shaderList.size() == 0) { println("adding"); addByID((int)random(FX.length)); } if (random(1)<0.01) { println("adding"); addByID((int)random(FX.length)); } if (random(1)<0.01) { int removeMe = int(random(shaderList.size()-1)); println("removing" + removeMe); bricks.get(removeMe).press(); shaderManager.removeShader(removeMe); pressedBrick = -1; } } void addByName(String name) { Class shaderChildClass = null; Shader s = null; try { shaderChildClass = Class.forName(sketchClass.getName() + "$" + name); s = (Shader) shaderChildClass.getDeclaredConstructor(sketchClass).newInstance(mainApplet); shaderManager.addShader(s); } catch (final ReflectiveOperationException ex) { System.err.println(ex); } } void addByID(int id) { addByName(FX[id]); } void mousePressed() { for (int i = slider.size()-1; i >= 0; i--) { Slider s = slider.get(i); if (s.hovering) s.press(i); if (s.hovering_anim_btn) s.animated = !s.animated; } for (int i = bricks.size()-1; i >= 0; i--) { if (bricks.get(i).hovering) { bricks.get(i).press(); } if (bricks.get(i).hoverActiveButton) { bricks.get(i).toggleActive(); } if (bricks.get(i).hoverPauseButton) bricks.get(i).playPause(); } } void mouseDragged() { if (pressedSlider != -1) { Slider s = slider.get(pressedSlider); s.setValue(map(mouseX, s.x, s.x+s.w, s.minVal, s.maxVal)); } if (pressedBrick != -1) { bricks.get(pressedBrick).dragging = true; for (int i = 0; i < bricks.size(); i++) { if (pressedBrick != i && bricks.get(i).hovering && mouseY < height-120) { bricks.get(i).dragHovering = true; } else { bricks.get(i).dragHovering = false; } } } } void mouseReleased() { if (pressedBrick != -1) { bricks.get(pressedBrick).dragging = false; for (int i = 0; i < bricks.size(); i++) { bricks.get(i).dragHovering = false; if (mouseY < height-120) { if (pressedBrick != i) { if (bricks.get(i).hovering && !bricks.get(i).hoveringLineAbove && !bricks.get(i).hoveringLineBelow) { shaderManager.swapShader(pressedBrick, i); } if (pressedBrick != i-1 && bricks.get(i).hoveringLineAbove) { shaderManager.moveShader(pressedBrick, i); break; } if (bricks.get(i).hoveringLineBelow) { shaderManager.moveShader(pressedBrick, bricks.size()); //move to last } } } } if (mouseX > binX && mouseX < binX+binS && mouseY > binY && mouseY < binY+binS) { println("removing"); shaderManager.removeShader(pressedBrick); } } pressedSlider = -1; pressedBrick = -1; } int scrollAmount; void mouseWheel(MouseEvent event) { textSize(25); if (mouseX > 100 && mouseX < textWidth(str(renderer.width) + "x" + str(renderer.height)) + 100 && mouseY > height - 40 && mouseY < height) { if (event.getCount() < 0) renderSize += 8; else renderSize -= 8; renderSize = constrain(renderSize, 8, 15000); } if (heightOverLimit && mouseX > 0 && mouseX < width && mouseY > 0 && mouseY < height-120) { for (int i = 0; i < bricks.size(); i++) { scrollAmount -= event.getCount(); scrollAmount = constrain(scrollAmount, maxSurfaceHeight-120-totalBrickHeight, 0); //bricks.get(i).y += event.getCount(); //bricks.get(i).updateSliderPos(); } } textSize(10); } int numberTypedFrame; boolean typingNumber; String newResoString; void keyPressed() { if (keyIsNumber(key) || key == BACKSPACE) { numberTypedFrame = frameCount; if (!typingNumber) { typingNumber = true; newResoString = ""; } if (keyIsNumber(key)) newResoString += str(key); else if ((newResoString != null) && (newResoString.length() > 0)) newResoString = newResoString.substring(0, newResoString.length() - 1); } if (typingNumber && key == ENTER) { setTypedReso(); } } void setTypedReso() { typingNumber = false; if (newResoString != "") { renderSize = constrain(int(newResoString), 8, 15000); } } boolean keyIsNumber(int k) { if (k == '0' ||k == '1' || k == '2' || k == '3' || k == '4' || k == '5' || k == '6' || k == '7' || k == '8' || k == '9') { return true; } else { return false; } } }