X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=_Overlay.pde;h=0950b91c03b93e61beb8fafc545143bddf738b0f;hb=ae80d37a7fc19c8bce45067cdcf4e041808f9339;hp=5ee02a4a3349a1567b7237ad4ac4374fddbed03d;hpb=0a9f99cc0140d7ff58b5b900b4cc63b4266302a9;p=SugarCubes.git diff --git a/_Overlay.pde b/_Overlay.pde index 5ee02a4..0950b91 100644 --- a/_Overlay.pde +++ b/_Overlay.pde @@ -30,8 +30,10 @@ abstract class OverlayUI { protected final float knobIndent = .4; protected final int knobSpacing = 6; protected final int knobLabelHeight = 14; + protected final int scrollWidth = 14; protected final color lightBlue = #666699; protected final color lightGreen = #669966; + protected final int toggleButtonSize = 10; private PImage logo; @@ -39,6 +41,13 @@ abstract class OverlayUI { protected final int STATE_ACTIVE = 1; protected final int STATE_PENDING = 2; + protected int[] pandaLeft = new int[pandaBoards.length]; + protected final int pandaWidth = 64; + protected final int pandaHeight = 13; + protected final int pandaTop = height-16; + + protected int eligibleLeft; + protected OverlayUI() { leftPos = width - w; leftTextPos = leftPos + 4; @@ -70,29 +79,72 @@ abstract class OverlayUI { textFont(titleFont); textAlign(LEFT); fill(#666666); - text("FPS: " + (((int)(frameRate * 10)) / 10.), 4, height-6); - text("Target (-/+):", 50, height-6); + int lPos = 4; + String fps = "FPS: " + (((int)(frameRate * 10)) / 10.); + text(fps, lPos, height-6); + lPos += 48; + + String target = "Target (-/+):"; + text(target, lPos, height-6); fill(#000000); - rect(104, height-16, 20, 12); + lPos += textWidth(target) + 4; + rect(lPos, height-16, 24, 13); fill(#666666); - text("" + targetFramerate, 108, height-6); + text("" + targetFramerate, lPos + (24 - textWidth("" + targetFramerate))/2, height-6); + lPos += 32; + String pandaOutput = "PandaOutput (p):"; + text(pandaOutput, lPos, height-6); + lPos += textWidth(pandaOutput)+4; + int pi = 0; + for (PandaDriver p : pandaBoards) { + pandaLeft[pi++] = lPos; + fill(p.enabled ? #666666 : #000000); + rect(lPos, pandaTop, pandaWidth, pandaHeight); + fill(p.enabled ? #000000 : #666666); + text(p.ip, lPos + (pandaWidth - textWidth(p.ip)) / 2, height-6); + lPos += pandaWidth + 8; + } + } protected int drawObjectList(int yPos, String title, Object[] items, Method stateMethod) { - return drawObjectList(yPos, title, items, classNameArray(items, null), stateMethod); + int sz = (items != null) ? items.length : 0; + return drawObjectList(yPos, title, items, stateMethod, sz, 0); } - + + protected int drawObjectList(int yPos, String title, Object[] items, Method stateMethod, int scrollLength, int scrollPos) { + return drawObjectList(yPos, title, items, classNameArray(items, null), stateMethod, scrollLength, scrollPos); + } + protected int drawObjectList(int yPos, String title, Object[] items, String[] names, Method stateMethod) { + int sz = (items != null) ? items.length : 0; + return drawObjectList(yPos, title, items, names, stateMethod, sz, 0); + } + + protected void drawToggleButton(float x, float y, boolean eligible, color textColor) { + noFill(); + stroke(textColor); + rect(x, y, toggleButtonSize, toggleButtonSize); + if (eligible) { + noStroke(); + fill(textColor); + rect(x + 2, y + 2, toggleButtonSize - 4, toggleButtonSize - 4); + } + } + + protected int drawObjectList(int yPos, String title, Object[] items, String[] names, Method stateMethod, int scrollLength, int scrollPos) { noStroke(); fill(titleColor); textFont(titleFont); textAlign(LEFT); text(title, leftTextPos, yPos += lineHeight); if (items != null) { + boolean hasScroll = (scrollPos > 0) || (scrollLength < items.length); textFont(itemFont); color textColor; boolean even = true; - for (int i = 0; i < items.length; ++i) { + int yTop = yPos+6; + for (int i = scrollPos; i < items.length && i < (scrollPos + scrollLength); ++i) { Object o = items[i]; int state = STATE_DEFAULT; try { @@ -114,11 +166,27 @@ abstract class OverlayUI { fill(even ? #666666 : #777777); break; } - rect(leftPos, yPos+6, width, lineHeight); + noStroke(); + rect(leftPos, yPos+6, w, lineHeight); fill(textColor); text(names[i], leftTextPos, yPos += lineHeight); + if (lx.isAutoTransitionEnabled() && items[i] instanceof LXPattern) { + boolean eligible = ((LXPattern)items[i]).isEligible(); + eligibleLeft = leftPos + w - (hasScroll ? scrollWidth : 0) - 15; + drawToggleButton(eligibleLeft, yPos-8, eligible, textColor); + } even = !even; } + if (hasScroll) { + int yHere = yPos+6; + noStroke(); + fill(color(0, 0, 0, 50)); + rect(leftPos + w - scrollWidth, yTop, scrollWidth, yHere - yTop); + fill(#666666); + rect(leftPos + w - scrollWidth + 2, yTop + (yHere-yTop) * (scrollPos / (float)items.length), scrollWidth - 4, (yHere - yTop) * (scrollLength / (float)items.length)); + + } + } return yPos; } @@ -157,6 +225,7 @@ abstract class OverlayUI { abstract public void mousePressed(); abstract public void mouseDragged(); abstract public void mouseReleased(); + abstract public void mouseWheel(int delta); } /** @@ -173,6 +242,12 @@ class ControlUI extends OverlayUI { private int firstTransitionKnobY; private int firstEffectY; private int firstEffectKnobY; + + private int autoRotateX; + private int autoRotateY; + + private final int PATTERN_LIST_LENGTH = 8; + private int patternScrollPos = 0; private int tempoY; @@ -197,8 +272,13 @@ class ControlUI extends OverlayUI { public void draw() { drawLogoAndBackground(); int yPos = 0; + autoRotateX = leftPos + w - 29; + autoRotateY = yPos + 12; + drawToggleButton(autoRotateX, autoRotateY, lx.isAutoTransitionEnabled(), #999999); + fill(lx.isAutoTransitionEnabled() ? #222222: #999999); + text("A", autoRotateX + 2, autoRotateY + 9); firstPatternY = yPos + lineHeight + 6; - yPos = drawObjectList(yPos, "PATTERN", patterns, patternNames, patternStateMethod); + yPos = drawObjectList(yPos, "PATTERN", patterns, patternNames, patternStateMethod, PATTERN_LIST_LENGTH, patternScrollPos); yPos += controlSpacing; firstPatternKnobY = yPos; int xPos = leftTextPos; @@ -327,6 +407,7 @@ class ControlUI extends OverlayUI { private int patternKnobIndex = -1; private int transitionKnobIndex = -1; private int effectKnobIndex = -1; + private boolean patternScrolling = false; private int lastY; private int releaseEffect = -1; @@ -336,6 +417,36 @@ class ControlUI extends OverlayUI { lastY = mouseY; patternKnobIndex = transitionKnobIndex = effectKnobIndex = -1; releaseEffect = -1; + patternScrolling = false; + + for (int p = 0; p < pandaLeft.length; ++p) { + int xp = pandaLeft[p]; + if ((mouseX >= xp) && + (mouseX < xp + pandaWidth) && + (mouseY >= pandaTop) && + (mouseY < pandaTop + pandaHeight)) { + pandaBoards[p].toggle(); + } + } + + if (mouseX < leftPos) { + return; + } + + if ((mouseX >= autoRotateX) && + (mouseX < autoRotateX + toggleButtonSize) && + (mouseY >= autoRotateY) && + (mouseY < autoRotateY + toggleButtonSize)) { + if (lx.isAutoTransitionEnabled()) { + lx.disableAutoTransition(); + println("Auto pattern transition disabled"); + } else { + lx.enableAutoTransition(60000); + println("Auto pattern transition enabled"); + } + return; + } + if (mouseY > tempoY) { if (mouseY - tempoY < tempoHeight) { lx.tempo.tap(); @@ -365,15 +476,25 @@ class ControlUI extends OverlayUI { patternKnobIndex += glucose.NUM_PATTERN_KNOBS / 2; } } else if (mouseY > firstPatternY) { - int patternIndex = objectClickIndex(firstPatternY); - if (patternIndex < patterns.length) { - lx.goIndex(patternIndex); + if ((patterns.length > PATTERN_LIST_LENGTH) && (mouseX > width - scrollWidth)) { + patternScrolling = true; + } else { + int patternIndex = objectClickIndex(firstPatternY); + if (patternIndex < patterns.length) { + if (lx.isAutoTransitionEnabled() && (mouseX > eligibleLeft)) { + patterns[patternIndex + patternScrollPos].toggleEligible(); + } else { + lx.goIndex(patternIndex + patternScrollPos); + } + } } } } + int scrolldy = 0; public void mouseDragged() { int dy = lastY - mouseY; + scrolldy += dy; lastY = mouseY; if (patternKnobIndex >= 0 && patternKnobIndex < glucose.NUM_PATTERN_KNOBS) { LXParameter p = glucose.patternKnobs.get(patternKnobIndex); @@ -384,10 +505,15 @@ class ControlUI extends OverlayUI { } else if (transitionKnobIndex >= 0 && transitionKnobIndex < glucose.NUM_TRANSITION_KNOBS) { LXParameter p = glucose.transitionKnobs.get(transitionKnobIndex); p.setValue(constrain(p.getValuef() + dy*.01, 0, 1)); + } else if (patternScrolling) { + int scroll = scrolldy / lineHeight; + scrolldy = scrolldy % lineHeight; + patternScrollPos = constrain(patternScrollPos - scroll, 0, patterns.length - PATTERN_LIST_LENGTH); } } public void mouseReleased() { + patternScrolling = false; tempoDown = false; if (releaseEffect >= 0) { effects[releaseEffect].trigger(); @@ -395,6 +521,15 @@ class ControlUI extends OverlayUI { } } + public void mouseWheel(int delta) { + if (mouseY > firstPatternY) { + int patternIndex = objectClickIndex(firstPatternY); + if (patternIndex < PATTERN_LIST_LENGTH) { + patternScrollPos = constrain(patternScrollPos + delta, 0, patterns.length - PATTERN_LIST_LENGTH); + } + } + } + } /** @@ -546,6 +681,11 @@ class MappingUI extends OverlayUI { public void mousePressed() { dragCube = dragStrip = dragChannel = false; lastY = mouseY; + + if (mouseX < leftPos) { + return; + } + if (mouseY >= stripFieldY) { if (mouseY < stripFieldY + lineHeight) { dragStrip = true; @@ -582,8 +722,8 @@ class MappingUI extends OverlayUI { } } - public void mouseReleased() { - } + public void mouseReleased() {} + public void mouseWheel(int delta) {} public void mouseDragged() { final int DRAG_THRESHOLD = 5; @@ -614,3 +754,207 @@ class MappingUI extends OverlayUI { } } +class DebugUI { + + final ChannelMapping[] channelList; + final int debugX = 10; + final int debugY = 42; + final int debugXSpacing = 28; + final int debugYSpacing = 22; + final int[][] debugState = new int[17][6]; + + final int DEBUG_STATE_ANIM = 0; + final int DEBUG_STATE_WHITE = 1; + final int DEBUG_STATE_OFF = 2; + + DebugUI(PandaMapping[] pandaMappings) { + int totalChannels = pandaMappings.length * PandaMapping.CHANNELS_PER_BOARD; + channelList = new ChannelMapping[totalChannels]; + int channelIndex = 0; + for (PandaMapping pm : pandaMappings) { + for (ChannelMapping channel : pm.channelList) { + channelList[channelIndex++] = channel; + } + } + for (int i = 0; i < debugState.length; ++i) { + for (int j = 0; j < debugState[i].length; ++j) { + debugState[i][j] = DEBUG_STATE_ANIM; + } + } + } + + void draw() { + noStroke(); + int xBase = debugX; + int yPos = debugY; + + fill(color(0, 0, 0, 80)); + rect(4, 32, 172, 388); + + int channelNum = 0; + for (ChannelMapping channel : channelList) { + int xPos = xBase; + drawNumBox(xPos, yPos, channelNum+1, debugState[channelNum][0]); + xPos += debugXSpacing; + + switch (channel.mode) { + case ChannelMapping.MODE_CUBES: + int stateIndex = 0; + boolean first = true; + for (int rawCubeIndex : channel.objectIndices) { + if (rawCubeIndex < 0) { + break; + } + if (first) { + first = false; + } else { + stroke(#999999); + line(xPos - 12, yPos + 8, xPos, yPos + 8); + } + drawNumBox(xPos, yPos, rawCubeIndex, debugState[channelNum][stateIndex+1]); + ++stateIndex; + xPos += debugXSpacing; + } + break; + case ChannelMapping.MODE_BASS: + drawNumBox(xPos, yPos, "B", debugState[channelNum][1]); + break; + case ChannelMapping.MODE_SPEAKER: + drawNumBox(xPos, yPos, "S" + channel.objectIndices[0], debugState[channelNum][1]); + break; + case ChannelMapping.MODE_FLOOR: + drawNumBox(xPos, yPos, "F", debugState[channelNum][1]); + break; + case ChannelMapping.MODE_NULL: + break; + default: + throw new RuntimeException("Unhandled channel mapping mode: " + channel.mode); + } + + yPos += debugYSpacing; + ++channelNum; + } + drawNumBox(xBase, yPos, "A", debugState[channelNum][0]); + } + + void drawNumBox(int xPos, int yPos, int label, int state) { + drawNumBox(xPos, yPos, "" + label, state); + } + + void drawNumBox(int xPos, int yPos, String label, int state) { + noFill(); + color textColor = #cccccc; + switch (state) { + case DEBUG_STATE_ANIM: + noStroke(); + fill(#880000); + rect(xPos, yPos, 16, 8); + fill(#000088); + rect(xPos, yPos+8, 16, 8); + noFill(); + stroke(textColor); + rect(xPos, yPos, 16, 16); + break; + case DEBUG_STATE_WHITE: + stroke(textColor); + fill(#e9e9e9); + rect(xPos, yPos, 16, 16); + textColor = #333333; + break; + case DEBUG_STATE_OFF: + stroke(textColor); + rect(xPos, yPos, 16, 16); + break; + } + + noStroke(); + fill(textColor); + text(label, xPos + 2, yPos + 12); + + } + + void maskColors(color[] colors) { + color white = #FFFFFF; + color off = #000000; + int channelIndex = 0; + int state; + for (ChannelMapping channel : channelList) { + switch (channel.mode) { + case ChannelMapping.MODE_CUBES: + int cubeIndex = 1; + for (int rawCubeIndex : channel.objectIndices) { + if (rawCubeIndex >= 0) { + state = debugState[channelIndex][cubeIndex]; + if (state != DEBUG_STATE_ANIM) { + color debugColor = (state == DEBUG_STATE_WHITE) ? white : off; + Cube cube = glucose.model.getCubeByRawIndex(rawCubeIndex); + for (Point p : cube.points) { + colors[p.index] = debugColor; + } + } + } + ++cubeIndex; + } + break; + + case ChannelMapping.MODE_BASS: + state = debugState[channelIndex][1]; + if (state != DEBUG_STATE_ANIM) { + color debugColor = (state == DEBUG_STATE_WHITE) ? white : off; + for (Point p : glucose.model.bassBox.points) { + colors[p.index] = debugColor; + } + } + break; + + case ChannelMapping.MODE_FLOOR: + state = debugState[channelIndex][1]; + if (state != DEBUG_STATE_ANIM) { + color debugColor = (state == DEBUG_STATE_WHITE) ? white : off; + for (Point p : glucose.model.boothFloor.points) { + colors[p.index] = debugColor; + } + } + break; + + case ChannelMapping.MODE_SPEAKER: + state = debugState[channelIndex][1]; + if (state != DEBUG_STATE_ANIM) { + color debugColor = (state == DEBUG_STATE_WHITE) ? white : off; + for (Point p : glucose.model.speakers.get(channel.objectIndices[0]).points) { + colors[p.index] = debugColor; + } + } + break; + + case ChannelMapping.MODE_NULL: + break; + + default: + throw new RuntimeException("Unhandled channel mapping mode: " + channel.mode); + } + ++channelIndex; + } + } + + void mousePressed() { + int dx = (mouseX - debugX) / debugXSpacing; + int dy = (mouseY - debugY) / debugYSpacing; + if ((dy >= 0) && (dy < debugState.length)) { + if ((dx >= 0) && (dx < debugState[dy].length)) { + int newState = debugState[dy][dx] = (debugState[dy][dx] + 1) % 3; + if (dy == 16) { + for (int[] states : debugState) { + for (int i = 0; i < states.length; ++i) { + states[i] = newState; + } + } + } else if (dx == 0) { + for (int i = 0; i < debugState[dy].length; ++i) { + debugState[dy][i] = newState; + } + } + } + } + } +}