X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=_Internals.pde;h=7eb5f938a11f976c9baccc3771dd029115b3494c;hb=e037f60f518373c3bb952f79a2ae66950e55a52f;hp=3aa9f3a209077f8a1bd82cf164e3c789958e34d5;hpb=242b19ad70677a9954365cbd2aaa700e06f63277;p=SugarCubes.git diff --git a/_Internals.pde b/_Internals.pde index 3aa9f3a..7eb5f93 100644 --- a/_Internals.pde +++ b/_Internals.pde @@ -4,7 +4,7 @@ * //\\ //\\ //\\ //\\ * ///\\\ ///\\\ ///\\\ ///\\\ * \\\/// \\\/// \\\/// \\\/// - * \\// \\// \\// \\// + * \\// \\// \\// \\//H * * EXPERTS ONLY!! EXPERTS ONLY!! * @@ -14,22 +14,22 @@ */ import glucose.*; -import glucose.control.*; -import glucose.effect.*; import glucose.model.*; -import glucose.pattern.*; -import glucose.transform.*; -import glucose.transition.*; import heronarts.lx.*; -import heronarts.lx.control.*; import heronarts.lx.effect.*; import heronarts.lx.modulator.*; +import heronarts.lx.parameter.*; import heronarts.lx.pattern.*; +import heronarts.lx.transform.*; import heronarts.lx.transition.*; +import heronarts.lx.ui.*; +import heronarts.lx.ui.component.*; +import heronarts.lx.ui.control.*; import ddf.minim.*; import ddf.minim.analysis.*; import processing.opengl.*; import rwmidi.*; +import java.lang.reflect.*; final int VIEWPORT_WIDTH = 900; final int VIEWPORT_HEIGHT = 700; @@ -39,40 +39,36 @@ final float TRAILER_WIDTH = 240; final float TRAILER_DEPTH = 97; final float TRAILER_HEIGHT = 33; -final int MaxCubeHeight = 7; -final int NumBackTowers = 9; - int targetFramerate = 60; int startMillis, lastMillis; // Core engine variables GLucose glucose; -HeronLX lx; +LX lx; +Model model; LXPattern[] patterns; +Effects effects; MappingTool mappingTool; -PandaDriver[] pandaBoards; +GrizzlyOutput[] grizzlies; +PresetManager presetManager; MidiEngine midiEngine; -GridController gridController; // Display configuration mode boolean mappingMode = false; boolean debugMode = false; -DebugUI debugUI; -boolean uiOn = true; +boolean simulationOn = true; +boolean diagnosticsOn = false; LXPattern restoreToPattern = null; PImage logo; float[] hsb = new float[3]; // Handles to UI objects -UIContext[] overlays; UIPatternDeck uiPatternA; UICrossfader uiCrossfader; UIMidi uiMidi; UIMapping uiMapping; UIDebugText uiDebugText; - -// Camera variables -float eyeR, eyeA, eyeX, eyeY, eyeZ, midX, midY, midZ; +UISpeed uiSpeed; /** * Engine construction and initialization. @@ -101,6 +97,19 @@ LXPattern[] _rightPatterns(GLucose glucose) { return rightPatterns; } +LXEffect[] _effectsArray(Effects effects) { + List effectList = new ArrayList(); + for (Field f : effects.getClass().getDeclaredFields()) { + try { + Object val = f.get(effects); + if (val instanceof LXEffect) { + effectList.add((LXEffect)val); + } + } catch (IllegalAccessException iax) {} + } + return effectList.toArray(new LXEffect[]{}); +} + void logTime(String evt) { int now = millis(); println(evt + ": " + (now - lastMillis) + "ms"); @@ -118,106 +127,199 @@ void setup() { logTime("Created viewport"); // Create the GLucose engine to run the cubes - glucose = new GLucose(this, buildModel()); + glucose = new GLucose(this, model = buildModel()); lx = glucose.lx; lx.enableKeyboardTempo(); logTime("Built GLucose engine"); - + // Set the patterns - Engine engine = lx.engine; + LXEngine engine = lx.engine; engine.setPatterns(patterns = _leftPatterns(glucose)); engine.addDeck(_rightPatterns(glucose)); logTime("Built patterns"); glucose.setTransitions(transitions(glucose)); logTime("Built transitions"); - glucose.lx.addEffects(effects(glucose)); + glucose.lx.addEffects(_effectsArray(effects = new Effects())); logTime("Built effects"); + // Preset manager + presetManager = new PresetManager(); + logTime("Loaded presets"); + // MIDI devices midiEngine = new MidiEngine(); logTime("Setup MIDI devices"); // Build output driver - PandaMapping[] pandaMappings = buildPandaList(); - pandaBoards = new PandaDriver[pandaMappings.length]; - int pbi = 0; - for (PandaMapping pm : pandaMappings) { - pandaBoards[pbi++] = new PandaDriver(pm.ip, glucose.model, pm); + grizzlies = new GrizzlyOutput[]{}; + try { + grizzlies = buildGrizzlies(); + for (LXOutput output : grizzlies) { + lx.addOutput(output); + } + } catch (Exception x) { + x.printStackTrace(); } - mappingTool = new MappingTool(glucose, pandaMappings); - logTime("Built PandaDriver"); - + logTime("Built Grizzly Outputs"); + + // Mapping tools + mappingTool = new MappingTool(glucose); + // Build overlay UI - debugUI = new DebugUI(pandaMappings); - overlays = new UIContext[] { - uiPatternA = new UIPatternDeck(lx.engine.getDeck(0), "PATTERN A", 4, 4, 140, 324), + UILayer[] layers = new UILayer[] { + // Camera layer + new UICameraLayer(lx.ui) + .setCenter(TRAILER_WIDTH/2., glucose.model.yMax/2, TRAILER_DEPTH/2.) + .setRadius(290).addComponent(new UICubesLayer()), + + // Left controls + uiPatternA = new UIPatternDeck(lx.ui, lx.engine.getDeck(GLucose.LEFT_DECK), "PATTERN A", 4, 4, 140, 324), new UIBlendMode(4, 332, 140, 86), new UIEffects(4, 422, 140, 144), new UITempo(4, 570, 140, 50), - new UISpeed(4, 624, 140, 50), + uiSpeed = new UISpeed(4, 624, 140, 50), - new UIPatternDeck(lx.engine.getDeck(1), "PATTERN B", width-144, 4, 140, 324), + // Right controls + new UIPatternDeck(lx.ui, lx.engine.getDeck(GLucose.RIGHT_DECK), "PATTERN B", width-144, 4, 140, 324), uiMidi = new UIMidi(midiEngine, width-144, 332, 140, 158), - new UIOutput(width-144, 494, 140, 106), + new UIOutput(grizzlies, width-144, 494, 140, 106), + // Crossfader uiCrossfader = new UICrossfader(width/2-90, height-90, 180, 86), + // Overlays uiDebugText = new UIDebugText(148, height-138, width-304, 44), - uiMapping = new UIMapping(mappingTool, 4, 4, 140, 324), + uiMapping = new UIMapping(mappingTool, 4, 4, 140, 324) }; - uiMapping.setVisible(false); - logTime("Built overlay UI"); + uiMapping.setVisible(false); + for (UILayer layer : layers) { + lx.ui.addLayer(layer); + } + logTime("Built UI"); // Load logo image logo = loadImage("data/logo.png"); - - // Setup camera - midX = TRAILER_WIDTH/2.; - midY = glucose.model.yMax/2; - midZ = TRAILER_DEPTH/2.; - eyeR = -290; - eyeA = .15; - eyeY = midY + 70; - eyeX = midX + eyeR*sin(eyeA); - eyeZ = midZ + eyeR*cos(eyeA); - - // Add mouse scrolling event support - addMouseWheelListener(new java.awt.event.MouseWheelListener() { - public void mouseWheelMoved(java.awt.event.MouseWheelEvent mwe) { - mouseWheel(mwe.getWheelRotation()); - }}); - + logTime("Loaded logo image"); + println("Total setup: " + (millis() - startMillis) + "ms"); - println("Hit the 'p' key to toggle Panda Board output"); + println("Hit the 'o' key to toggle live output"); } /** * Core render loop and drawing functionality. */ void draw() { - // Draws the simulation and the 2D UI overlay + long drawStart = System.nanoTime(); + + // Set background background(40); + + // Send colors + color[] sendColors = glucose.getColors(); + long gammaStart = System.nanoTime(); + // Gamma correction here. Apply a cubic to the brightness + // for better representation of dynamic range + for (int i = 0; i < sendColors.length; ++i) { + lx.RGBtoHSB(sendColors[i], hsb); + float b = hsb[2]; + sendColors[i] = lx.hsb(360.*hsb[0], 100.*hsb[1], 100.*(b*b*b)); + } + long gammaNanos = System.nanoTime() - gammaStart; + + // Always draw FPS meter + drawFPS(); + + // TODO(mcslee): fix + long drawNanos = System.nanoTime() - drawStart; + + long simulationNanos = 0, uiNanos = 0; + if (diagnosticsOn) { + drawDiagnostics(drawNanos, simulationNanos, uiNanos, gammaNanos); + } +} + +class UICubesLayer extends UICameraComponent { + void onDraw(UI ui) { + color[] simulationColors = glucose.getColors(); + String displayMode = uiCrossfader.getDisplayMode(); + if (displayMode == "A") { + simulationColors = lx.engine.getDeck(GLucose.LEFT_DECK).getColors(); + } else if (displayMode == "B") { + simulationColors = lx.engine.getDeck(GLucose.RIGHT_DECK).getColors(); + } + + long simulationStart = System.nanoTime(); + if (simulationOn) { + drawSimulation(simulationColors); + } + long simulationNanos = System.nanoTime() - simulationStart; + + camera(); + javax.media.opengl.GL gl = ((PGraphicsOpenGL)g).beginGL(); + gl.glClear(javax.media.opengl.GL.GL_DEPTH_BUFFER_BIT); + ((PGraphicsOpenGL)g).endGL(); + strokeWeight(1); + } +} - color[] simulationColors; - color[] sendColors; - simulationColors = sendColors = glucose.getColors(); - String displayMode = uiCrossfader.getDisplayMode(); - if (displayMode == "A") { - simulationColors = lx.engine.getDeck(0).getColors(); - } else if (displayMode == "B") { - simulationColors = lx.engine.getDeck(1).getColors(); +void drawDiagnostics(long drawNanos, long simulationNanos, long uiNanos, long gammaNanos) { + float ws = 4 / 1000000.; + int thirtyfps = 1000000000 / 30; + int sixtyfps = 1000000000 / 60; + int x = width - 138; + int y = height - 14; + int h = 10; + noFill(); + stroke(#999999); + rect(x, y, thirtyfps * ws, h); + noStroke(); + int xp = x; + float hv = 0; + for (long val : new long[] {lx.timer.drawNanos, simulationNanos, uiNanos, gammaNanos, lx.timer.outputNanos }) { + fill(lx.hsb(hv % 360, 100, 80)); + rect(xp, y, val * ws, h-1); + hv += 140; + xp += val * ws; + } + noFill(); + stroke(#333333); + line(x+sixtyfps*ws, y+1, x+sixtyfps*ws, y+h-1); + + y = y - 14; + xp = x; + float tw = thirtyfps * ws; + noFill(); + stroke(#999999); + rect(x, y, tw, h); + h = 5; + noStroke(); + for (long val : new long[] { + lx.engine.timer.deckNanos, + lx.engine.timer.copyNanos, + lx.engine.timer.fxNanos}) { + float amt = val / (float) lx.timer.drawNanos; + fill(lx.hsb(hv % 360, 100, 80)); + rect(xp, y, amt * tw, h-1); + hv += 140; + xp += amt * tw; } - if (debugMode) { - debugUI.maskColors(simulationColors); - debugUI.maskColors(sendColors); + + xp = x; + y += h; + hv = 120; + for (long val : new long[] { + lx.engine.getDeck(0).timer.runNanos, + lx.engine.getDeck(1).timer.runNanos, + lx.engine.getDeck(1).getFaderTransition().timer.blendNanos}) { + float amt = val / (float) lx.timer.drawNanos; + fill(lx.hsb(hv % 360, 100, 80)); + rect(xp, y, amt * tw, h-1); + hv += 140; + xp += amt * tw; } +} - camera( - eyeX, eyeY, eyeZ, - midX, midY, midZ, - 0, -1, 0 - ); - +void drawSimulation(color[] simulationColors) { translate(0, 40, 0); noStroke(); @@ -254,27 +356,11 @@ void draw() { noFill(); strokeWeight(2); beginShape(POINTS); - for (Point p : glucose.model.points) { + for (LXPoint p : glucose.model.points) { stroke(simulationColors[p.index]); vertex(p.x, p.y, p.z); } endShape(); - - // 2D Overlay UI - drawUI(); - - // Gamma correction here. Apply a cubic to the brightness - // for better representation of dynamic range - for (int i = 0; i < sendColors.length; ++i) { - lx.RGBtoHSB(sendColors[i], hsb); - float b = hsb[2]; - sendColors[i] = lx.hsb(360.*hsb[0], 100.*hsb[1], 100.*(b*b*b)); - } - - // TODO(mcslee): move into GLucose engine - for (PandaDriver p : pandaBoards) { - p.send(sendColors); - } } void drawBassBox(BassBox b, boolean hasSub) { @@ -386,28 +472,12 @@ void drawBox(float x, float y, float z, float rx, float ry, float rz, float xd, popMatrix(); } -void drawUI() { - camera(); - javax.media.opengl.GL gl = ((PGraphicsOpenGL)g).beginGL(); - gl.glClear(javax.media.opengl.GL.GL_DEPTH_BUFFER_BIT); - ((PGraphicsOpenGL)g).endGL(); - strokeWeight(1); - - if (uiOn) { - for (UIContext context : overlays) { - context.draw(); - } - } - +void drawFPS() { // Always draw FPS meter fill(#555555); textSize(9); textAlign(LEFT, BASELINE); text("FPS: " + ((int) (frameRate*10)) / 10. + " / " + targetFramerate + " (-/+)", 4, height-4); - - if (debugMode) { - debugUI.draw(); - } } @@ -419,6 +489,44 @@ void keyPressed() { mappingTool.keyPressed(uiMapping); } switch (key) { + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + if (!midiEngine.isQwertyEnabled()) { + presetManager.select(midiEngine.getFocusedDeck(), key - '1'); + } + break; + + case '!': + if (!midiEngine.isQwertyEnabled()) presetManager.store(midiEngine.getFocusedDeck(), 0); + break; + case '@': + if (!midiEngine.isQwertyEnabled()) presetManager.store(midiEngine.getFocusedDeck(), 1); + break; + case '#': + if (!midiEngine.isQwertyEnabled()) presetManager.store(midiEngine.getFocusedDeck(), 2); + break; + case '$': + if (!midiEngine.isQwertyEnabled()) presetManager.store(midiEngine.getFocusedDeck(), 3); + break; + case '%': + if (!midiEngine.isQwertyEnabled()) presetManager.store(midiEngine.getFocusedDeck(), 4); + break; + case '^': + if (!midiEngine.isQwertyEnabled()) presetManager.store(midiEngine.getFocusedDeck(), 5); + break; + case '&': + if (!midiEngine.isQwertyEnabled()) presetManager.store(midiEngine.getFocusedDeck(), 6); + break; + case '*': + if (!midiEngine.isQwertyEnabled()) presetManager.store(midiEngine.getFocusedDeck(), 7); + break; + case '-': case '_': frameRate(--targetFramerate); @@ -428,7 +536,7 @@ void keyPressed() { frameRate(++targetFramerate); break; case 'b': - EFF_boom.trigger(); + effects.boom.trigger(); break; case 'd': if (!midiEngine.isQwertyEnabled()) { @@ -458,69 +566,22 @@ void keyPressed() { lx.engine.setThreaded(!lx.engine.isThreaded()); } break; + case 'o': case 'p': - for (PandaDriver p : pandaBoards) { - p.toggle(); + for (LXOutput output : grizzlies) { + output.enabled.toggle(); } break; - case 'u': + case 'q': if (!midiEngine.isQwertyEnabled()) { - uiOn = !uiOn; + diagnosticsOn = !diagnosticsOn; + } + break; + case 's': + if (!midiEngine.isQwertyEnabled()) { + simulationOn = !simulationOn; } break; } } -/** - * Top-level mouse event handling - */ -int mx, my; -void mousePressed() { - boolean debugged = false; - if (debugMode) { - debugged = debugUI.mousePressed(); - } - if (!debugged) { - for (UIContext context : overlays) { - context.mousePressed(mouseX, mouseY); - } - } - mx = mouseX; - my = mouseY; -} - -void mouseDragged() { - boolean dragged = false; - for (UIContext context : overlays) { - dragged |= context.mouseDragged(mouseX, mouseY); - } - if (!dragged) { - int dx = mouseX - mx; - int dy = mouseY - my; - mx = mouseX; - my = mouseY; - eyeA += dx*.003; - eyeX = midX + eyeR*sin(eyeA); - eyeZ = midZ + eyeR*cos(eyeA); - eyeY += dy; - } -} - -void mouseReleased() { - for (UIContext context : overlays) { - context.mouseReleased(mouseX, mouseY); - } -} - -void mouseWheel(int delta) { - boolean wheeled = false; - for (UIContext context : overlays) { - wheeled |= context.mouseWheel(mouseX, mouseY, delta); - } - - if (!wheeled) { - eyeR = constrain(eyeR - delta, -500, -80); - eyeX = midX + eyeR*sin(eyeA); - eyeZ = midZ + eyeR*cos(eyeA); - } -}