Commit | Line | Data |
---|---|---|
e73ef85d MS |
1 | import java.lang.reflect.*; |
2 | ||
49815cc0 | 3 | /** |
1ecdb44a MS |
4 | * DOUBLE BLACK DIAMOND DOUBLE BLACK DIAMOND |
5 | * | |
6 | * //\\ //\\ //\\ //\\ | |
7 | * ///\\\ ///\\\ ///\\\ ///\\\ | |
8 | * \\\/// \\\/// \\\/// \\\/// | |
9 | * \\// \\// \\// \\// | |
10 | * | |
11 | * EXPERTS ONLY!! EXPERTS ONLY!! | |
12 | * | |
49815cc0 MS |
13 | * Overlay UI that indicates pattern control, etc. This will be moved |
14 | * into the Processing library once it is stabilized and need not be | |
15 | * regularly modified. | |
16 | */ | |
bf551144 MS |
17 | abstract class OverlayUI { |
18 | protected final PFont titleFont = createFont("Myriad Pro", 10); | |
19 | protected final color titleColor = #AAAAAA; | |
20 | protected final PFont itemFont = createFont("Lucida Grande", 11); | |
21 | protected final PFont knobFont = titleFont; | |
22 | protected final int w = 140; | |
23 | protected final int leftPos; | |
24 | protected final int leftTextPos; | |
25 | protected final int lineHeight = 20; | |
26 | protected final int sectionSpacing = 12; | |
27 | protected final int controlSpacing = 18; | |
28 | protected final int tempoHeight = 20; | |
29 | protected final int knobSize = 28; | |
30 | protected final float knobIndent = .4; | |
31 | protected final int knobSpacing = 6; | |
32 | protected final int knobLabelHeight = 14; | |
0ba6ac44 | 33 | protected final int scrollWidth = 14; |
bf551144 MS |
34 | protected final color lightBlue = #666699; |
35 | protected final color lightGreen = #669966; | |
6c1a9e53 | 36 | protected final int toggleButtonSize = 10; |
49815cc0 | 37 | |
bf551144 MS |
38 | private PImage logo; |
39 | ||
40 | protected final int STATE_DEFAULT = 0; | |
41 | protected final int STATE_ACTIVE = 1; | |
42 | protected final int STATE_PENDING = 2; | |
43 | ||
79ae8245 | 44 | protected int[] pandaLeft = new int[pandaBoards.length]; |
ae80d37a | 45 | protected final int pandaWidth = 64; |
79ae8245 MS |
46 | protected final int pandaHeight = 13; |
47 | protected final int pandaTop = height-16; | |
48 | ||
6c1a9e53 MS |
49 | protected int eligibleLeft; |
50 | ||
bf551144 MS |
51 | protected OverlayUI() { |
52 | leftPos = width - w; | |
53 | leftTextPos = leftPos + 4; | |
54 | logo = loadImage("logo-sm.png"); | |
55 | } | |
56 | ||
57 | protected void drawLogoAndBackground() { | |
58 | image(logo, 4, 4); | |
59 | stroke(color(0, 0, 100)); | |
60 | // fill(color(0, 0, 50, 50)); // alpha is bad for perf | |
61 | fill(color(0, 0, 30)); | |
62 | rect(leftPos-1, -1, w+2, height+2); | |
63 | } | |
64 | ||
65 | protected void drawToggleTip(String s) { | |
66 | fill(#999999); | |
67 | textFont(itemFont); | |
68 | textAlign(LEFT); | |
69 | text(s, leftTextPos, height-6); | |
70 | } | |
71 | ||
72 | protected void drawHelpTip() { | |
73 | textFont(itemFont); | |
74 | textAlign(RIGHT); | |
75 | text("Tap 'u' to restore UI", width-4, height-6); | |
76 | } | |
77 | ||
e28f168c AG |
78 | public void drawDanText() { |
79 | textFont(itemFont); | |
80 | textAlign(LEFT); | |
81 | fill(#FFFFFF); | |
82 | text(DanTextLine1, 4, height-50); | |
83 | text(DanTextLine2, 4, height-30); | |
84 | } | |
85 | ||
bf551144 MS |
86 | public void drawFPS() { |
87 | textFont(titleFont); | |
88 | textAlign(LEFT); | |
90166032 | 89 | noStroke(); |
bf551144 | 90 | fill(#666666); |
ae80d37a MS |
91 | int lPos = 4; |
92 | String fps = "FPS: " + (((int)(frameRate * 10)) / 10.); | |
93 | text(fps, lPos, height-6); | |
94 | lPos += 48; | |
95 | ||
96 | String target = "Target (-/+):"; | |
97 | text(target, lPos, height-6); | |
0e3c5542 | 98 | fill(#000000); |
ae80d37a MS |
99 | lPos += textWidth(target) + 4; |
100 | rect(lPos, height-16, 24, 13); | |
0e3c5542 | 101 | fill(#666666); |
ae80d37a MS |
102 | text("" + targetFramerate, lPos + (24 - textWidth("" + targetFramerate))/2, height-6); |
103 | lPos += 32; | |
104 | String pandaOutput = "PandaOutput (p):"; | |
105 | text(pandaOutput, lPos, height-6); | |
106 | lPos += textWidth(pandaOutput)+4; | |
79ae8245 MS |
107 | int pi = 0; |
108 | for (PandaDriver p : pandaBoards) { | |
109 | pandaLeft[pi++] = lPos; | |
110 | fill(p.enabled ? #666666 : #000000); | |
111 | rect(lPos, pandaTop, pandaWidth, pandaHeight); | |
112 | fill(p.enabled ? #000000 : #666666); | |
ae80d37a MS |
113 | text(p.ip, lPos + (pandaWidth - textWidth(p.ip)) / 2, height-6); |
114 | lPos += pandaWidth + 8; | |
79ae8245 | 115 | } |
bfff6bc2 | 116 | |
bf551144 MS |
117 | } |
118 | ||
119 | protected int drawObjectList(int yPos, String title, Object[] items, Method stateMethod) { | |
0ba6ac44 MS |
120 | int sz = (items != null) ? items.length : 0; |
121 | return drawObjectList(yPos, title, items, stateMethod, sz, 0); | |
bf551144 | 122 | } |
0ba6ac44 MS |
123 | |
124 | protected int drawObjectList(int yPos, String title, Object[] items, Method stateMethod, int scrollLength, int scrollPos) { | |
125 | return drawObjectList(yPos, title, items, classNameArray(items, null), stateMethod, scrollLength, scrollPos); | |
126 | } | |
127 | ||
bf551144 | 128 | protected int drawObjectList(int yPos, String title, Object[] items, String[] names, Method stateMethod) { |
0ba6ac44 MS |
129 | int sz = (items != null) ? items.length : 0; |
130 | return drawObjectList(yPos, title, items, names, stateMethod, sz, 0); | |
131 | } | |
132 | ||
6c1a9e53 MS |
133 | protected void drawToggleButton(float x, float y, boolean eligible, color textColor) { |
134 | noFill(); | |
135 | stroke(textColor); | |
136 | rect(x, y, toggleButtonSize, toggleButtonSize); | |
137 | if (eligible) { | |
138 | noStroke(); | |
139 | fill(textColor); | |
140 | rect(x + 2, y + 2, toggleButtonSize - 4, toggleButtonSize - 4); | |
141 | } | |
142 | } | |
143 | ||
0ba6ac44 | 144 | protected int drawObjectList(int yPos, String title, Object[] items, String[] names, Method stateMethod, int scrollLength, int scrollPos) { |
bf551144 MS |
145 | noStroke(); |
146 | fill(titleColor); | |
147 | textFont(titleFont); | |
148 | textAlign(LEFT); | |
149 | text(title, leftTextPos, yPos += lineHeight); | |
150 | if (items != null) { | |
6c1a9e53 | 151 | boolean hasScroll = (scrollPos > 0) || (scrollLength < items.length); |
bf551144 MS |
152 | textFont(itemFont); |
153 | color textColor; | |
154 | boolean even = true; | |
0ba6ac44 MS |
155 | int yTop = yPos+6; |
156 | for (int i = scrollPos; i < items.length && i < (scrollPos + scrollLength); ++i) { | |
bf551144 MS |
157 | Object o = items[i]; |
158 | int state = STATE_DEFAULT; | |
159 | try { | |
160 | state = ((Integer) stateMethod.invoke(this, o)).intValue(); | |
161 | } catch (Exception x) { | |
162 | throw new RuntimeException(x); | |
163 | } | |
164 | switch (state) { | |
165 | case STATE_ACTIVE: | |
166 | fill(lightGreen); | |
167 | textColor = #eeeeee; | |
168 | break; | |
169 | case STATE_PENDING: | |
170 | fill(lightBlue); | |
171 | textColor = color(0, 0, 75 + 15*sin(millis()/200.));; | |
172 | break; | |
173 | default: | |
174 | textColor = 0; | |
175 | fill(even ? #666666 : #777777); | |
176 | break; | |
177 | } | |
6c1a9e53 | 178 | noStroke(); |
0ba6ac44 | 179 | rect(leftPos, yPos+6, w, lineHeight); |
bf551144 MS |
180 | fill(textColor); |
181 | text(names[i], leftTextPos, yPos += lineHeight); | |
6c1a9e53 MS |
182 | if (lx.isAutoTransitionEnabled() && items[i] instanceof LXPattern) { |
183 | boolean eligible = ((LXPattern)items[i]).isEligible(); | |
184 | eligibleLeft = leftPos + w - (hasScroll ? scrollWidth : 0) - 15; | |
185 | drawToggleButton(eligibleLeft, yPos-8, eligible, textColor); | |
186 | } | |
bf551144 MS |
187 | even = !even; |
188 | } | |
6c1a9e53 | 189 | if (hasScroll) { |
0ba6ac44 MS |
190 | int yHere = yPos+6; |
191 | noStroke(); | |
192 | fill(color(0, 0, 0, 50)); | |
193 | rect(leftPos + w - scrollWidth, yTop, scrollWidth, yHere - yTop); | |
194 | fill(#666666); | |
195 | rect(leftPos + w - scrollWidth + 2, yTop + (yHere-yTop) * (scrollPos / (float)items.length), scrollWidth - 4, (yHere - yTop) * (scrollLength / (float)items.length)); | |
196 | ||
197 | } | |
198 | ||
bf551144 MS |
199 | } |
200 | return yPos; | |
201 | } | |
202 | ||
203 | protected String[] classNameArray(Object[] objects, String suffix) { | |
204 | if (objects == null) { | |
205 | return null; | |
206 | } | |
207 | String[] names = new String[objects.length]; | |
208 | for (int i = 0; i < objects.length; ++i) { | |
209 | names[i] = className(objects[i], suffix); | |
210 | } | |
211 | return names; | |
212 | } | |
213 | ||
214 | protected String className(Object p, String suffix) { | |
215 | String s = p.getClass().getName(); | |
216 | int li; | |
217 | if ((li = s.lastIndexOf(".")) > 0) { | |
218 | s = s.substring(li + 1); | |
219 | } | |
220 | if (s.indexOf("SugarCubes$") == 0) { | |
221 | s = s.substring("SugarCubes$".length()); | |
222 | } | |
223 | if ((suffix != null) && ((li = s.indexOf(suffix)) != -1)) { | |
224 | s = s.substring(0, li); | |
225 | } | |
226 | return s; | |
227 | } | |
228 | ||
229 | protected int objectClickIndex(int firstItemY) { | |
230 | return (mouseY - firstItemY) / lineHeight; | |
231 | } | |
49815cc0 | 232 | |
0e3c5542 | 233 | abstract public void draw(); |
bf551144 MS |
234 | abstract public void mousePressed(); |
235 | abstract public void mouseDragged(); | |
236 | abstract public void mouseReleased(); | |
0ba6ac44 | 237 | abstract public void mouseWheel(int delta); |
bf551144 MS |
238 | } |
239 | ||
240 | /** | |
241 | * UI for control of patterns, transitions, effects. | |
242 | */ | |
243 | class ControlUI extends OverlayUI { | |
49815cc0 MS |
244 | private final String[] patternNames; |
245 | private final String[] transitionNames; | |
246 | private final String[] effectNames; | |
49815cc0 MS |
247 | |
248 | private int firstPatternY; | |
3f8be614 | 249 | private int firstPatternKnobY; |
49815cc0 | 250 | private int firstTransitionY; |
3f8be614 | 251 | private int firstTransitionKnobY; |
49815cc0 | 252 | private int firstEffectY; |
3f8be614 | 253 | private int firstEffectKnobY; |
0ba6ac44 | 254 | |
6c1a9e53 MS |
255 | private int autoRotateX; |
256 | private int autoRotateY; | |
257 | ||
0ba6ac44 MS |
258 | private final int PATTERN_LIST_LENGTH = 8; |
259 | private int patternScrollPos = 0; | |
3f8be614 | 260 | |
49815cc0 MS |
261 | private int tempoY; |
262 | ||
263 | private Method patternStateMethod; | |
264 | private Method transitionStateMethod; | |
265 | private Method effectStateMethod; | |
b11ff42b | 266 | |
bf551144 | 267 | ControlUI() { |
3f8be614 MS |
268 | patternNames = classNameArray(patterns, "Pattern"); |
269 | transitionNames = classNameArray(transitions, "Transition"); | |
270 | effectNames = classNameArray(effects, "Effect"); | |
271 | ||
49815cc0 MS |
272 | try { |
273 | patternStateMethod = getClass().getMethod("getState", LXPattern.class); | |
274 | effectStateMethod = getClass().getMethod("getState", LXEffect.class); | |
275 | transitionStateMethod = getClass().getMethod("getState", LXTransition.class); | |
276 | } catch (Exception x) { | |
277 | throw new RuntimeException(x); | |
278 | } | |
279 | } | |
bf551144 MS |
280 | |
281 | public void draw() { | |
282 | drawLogoAndBackground(); | |
283 | int yPos = 0; | |
6c1a9e53 MS |
284 | autoRotateX = leftPos + w - 29; |
285 | autoRotateY = yPos + 12; | |
286 | drawToggleButton(autoRotateX, autoRotateY, lx.isAutoTransitionEnabled(), #999999); | |
287 | fill(lx.isAutoTransitionEnabled() ? #222222: #999999); | |
288 | text("A", autoRotateX + 2, autoRotateY + 9); | |
49815cc0 | 289 | firstPatternY = yPos + lineHeight + 6; |
0ba6ac44 | 290 | yPos = drawObjectList(yPos, "PATTERN", patterns, patternNames, patternStateMethod, PATTERN_LIST_LENGTH, patternScrollPos); |
3f8be614 MS |
291 | yPos += controlSpacing; |
292 | firstPatternKnobY = yPos; | |
49815cc0 | 293 | int xPos = leftTextPos; |
cc9fcf4b MS |
294 | for (int i = 0; i < glucose.NUM_PATTERN_KNOBS/2; ++i) { |
295 | drawKnob(xPos, yPos, knobSize, glucose.patternKnobs.get(i)); | |
296 | drawKnob(xPos, yPos + knobSize + knobSpacing + knobLabelHeight, knobSize, glucose.patternKnobs.get(glucose.NUM_PATTERN_KNOBS/2 + i)); | |
49815cc0 MS |
297 | xPos += knobSize + knobSpacing; |
298 | } | |
299 | yPos += 2*(knobSize + knobLabelHeight) + knobSpacing; | |
300 | ||
301 | yPos += sectionSpacing; | |
302 | firstTransitionY = yPos + lineHeight + 6; | |
303 | yPos = drawObjectList(yPos, "TRANSITION", transitions, transitionNames, transitionStateMethod); | |
3f8be614 MS |
304 | yPos += controlSpacing; |
305 | firstTransitionKnobY = yPos; | |
306 | xPos = leftTextPos; | |
cc9fcf4b MS |
307 | for (VirtualTransitionKnob knob : glucose.transitionKnobs) { |
308 | drawKnob(xPos, yPos, knobSize, knob); | |
3f8be614 MS |
309 | xPos += knobSize + knobSpacing; |
310 | } | |
311 | yPos += knobSize + knobLabelHeight; | |
49815cc0 MS |
312 | |
313 | yPos += sectionSpacing; | |
314 | firstEffectY = yPos + lineHeight + 6; | |
315 | yPos = drawObjectList(yPos, "FX", effects, effectNames, effectStateMethod); | |
3f8be614 MS |
316 | yPos += controlSpacing; |
317 | firstEffectKnobY = yPos; | |
318 | xPos = leftTextPos; | |
cc9fcf4b MS |
319 | for (VirtualEffectKnob knob : glucose.effectKnobs) { |
320 | drawKnob(xPos, yPos, knobSize, knob); | |
3f8be614 MS |
321 | xPos += knobSize + knobSpacing; |
322 | } | |
323 | yPos += knobSize + knobLabelHeight; | |
49815cc0 MS |
324 | |
325 | yPos += sectionSpacing; | |
326 | yPos = drawObjectList(yPos, "TEMPO", null, null, null); | |
327 | yPos += 6; | |
328 | tempoY = yPos; | |
329 | stroke(#111111); | |
330 | fill(tempoDown ? lightGreen : color(0, 0, 35 - 8*lx.tempo.rampf())); | |
331 | rect(leftPos + 4, yPos, w - 8, tempoHeight); | |
332 | fill(0); | |
333 | textAlign(CENTER); | |
334 | text("" + ((int)(lx.tempo.bpmf() * 100) / 100.), leftPos + w/2., yPos + tempoHeight - 6); | |
335 | yPos += tempoHeight; | |
336 | ||
bf551144 | 337 | drawToggleTip("Tap 'u' to hide"); |
49815cc0 MS |
338 | } |
339 | ||
3f8be614 | 340 | public LXParameter getOrNull(List<LXParameter> items, int index) { |
49815cc0 MS |
341 | if (index < items.size()) { |
342 | return items.get(index); | |
343 | } | |
344 | return null; | |
345 | } | |
346 | ||
49815cc0 MS |
347 | public int getState(LXPattern p) { |
348 | if (p == lx.getPattern()) { | |
349 | return STATE_ACTIVE; | |
350 | } else if (p == lx.getNextPattern()) { | |
351 | return STATE_PENDING; | |
352 | } | |
353 | return STATE_DEFAULT; | |
354 | } | |
355 | ||
356 | public int getState(LXEffect e) { | |
3f8be614 MS |
357 | if (e.isEnabled()) { |
358 | return STATE_PENDING; | |
cc9fcf4b | 359 | } else if (e == glucose.getSelectedEffect()) { |
3f8be614 MS |
360 | return STATE_ACTIVE; |
361 | } | |
362 | return STATE_DEFAULT; | |
49815cc0 MS |
363 | } |
364 | ||
365 | public int getState(LXTransition t) { | |
366 | if (t == lx.getTransition()) { | |
367 | return STATE_PENDING; | |
cc9fcf4b | 368 | } else if (t == glucose.getSelectedTransition()) { |
49815cc0 MS |
369 | return STATE_ACTIVE; |
370 | } | |
371 | return STATE_DEFAULT; | |
372 | } | |
49815cc0 | 373 | |
3f8be614 | 374 | private void drawKnob(int xPos, int yPos, int knobSize, LXParameter knob) { |
49815cc0 MS |
375 | final float knobValue = knob.getValuef(); |
376 | String knobLabel = knob.getLabel(); | |
3f8be614 | 377 | if (knobLabel == null) { |
49815cc0 | 378 | knobLabel = "-"; |
3f8be614 MS |
379 | } else if (knobLabel.length() > 4) { |
380 | knobLabel = knobLabel.substring(0, 4); | |
49815cc0 MS |
381 | } |
382 | ||
383 | ellipseMode(CENTER); | |
87f6fa39 | 384 | noStroke(); |
49815cc0 | 385 | fill(#222222); |
3f8be614 MS |
386 | // For some reason this arc call really crushes drawing performance. Presumably |
387 | // because openGL is drawing it and when we overlap the second set of arcs it | |
388 | // does a bunch of depth buffer intersection tests? Ellipse with a trapezoid cut out is faster | |
389 | // arc(xPos + knobSize/2, yPos + knobSize/2, knobSize, knobSize, HALF_PI + knobIndent, HALF_PI + knobIndent + (TWO_PI-2*knobIndent)); | |
390 | ellipse(xPos + knobSize/2, yPos + knobSize/2, knobSize, knobSize); | |
391 | ||
392 | float endArc = HALF_PI + knobIndent + (TWO_PI-2*knobIndent)*knobValue; | |
49815cc0 | 393 | fill(lightGreen); |
3f8be614 MS |
394 | arc(xPos + knobSize/2, yPos + knobSize/2, knobSize, knobSize, HALF_PI + knobIndent, endArc); |
395 | ||
3f8be614 MS |
396 | // Mask notch out of knob |
397 | fill(color(0, 0, 30)); | |
398 | beginShape(); | |
4eae387e MS |
399 | vertex(xPos + knobSize/2, yPos + knobSize/2.); |
400 | vertex(xPos + knobSize/2 - 6, yPos + knobSize); | |
401 | vertex(xPos + knobSize/2 + 6, yPos + knobSize); | |
3f8be614 | 402 | endShape(); |
4eae387e MS |
403 | |
404 | // Center circle of knob | |
405 | fill(#333333); | |
406 | ellipse(xPos + knobSize/2, yPos + knobSize/2, knobSize/2, knobSize/2); | |
49815cc0 MS |
407 | |
408 | fill(0); | |
409 | rect(xPos, yPos + knobSize + 2, knobSize, knobLabelHeight - 2); | |
410 | fill(#999999); | |
411 | textAlign(CENTER); | |
412 | textFont(knobFont); | |
413 | text(knobLabel, xPos + knobSize/2, yPos + knobSize + knobLabelHeight - 2); | |
49815cc0 | 414 | } |
3f8be614 MS |
415 | |
416 | private int patternKnobIndex = -1; | |
417 | private int transitionKnobIndex = -1; | |
418 | private int effectKnobIndex = -1; | |
0ba6ac44 | 419 | private boolean patternScrolling = false; |
49815cc0 | 420 | |
49815cc0 MS |
421 | private int lastY; |
422 | private int releaseEffect = -1; | |
423 | private boolean tempoDown = false; | |
424 | ||
425 | public void mousePressed() { | |
426 | lastY = mouseY; | |
3f8be614 | 427 | patternKnobIndex = transitionKnobIndex = effectKnobIndex = -1; |
49815cc0 | 428 | releaseEffect = -1; |
0ba6ac44 | 429 | patternScrolling = false; |
79ae8245 MS |
430 | |
431 | for (int p = 0; p < pandaLeft.length; ++p) { | |
432 | int xp = pandaLeft[p]; | |
433 | if ((mouseX >= xp) && | |
434 | (mouseX < xp + pandaWidth) && | |
435 | (mouseY >= pandaTop) && | |
436 | (mouseY < pandaTop + pandaHeight)) { | |
437 | pandaBoards[p].toggle(); | |
438 | } | |
439 | } | |
440 | ||
441 | if (mouseX < leftPos) { | |
442 | return; | |
443 | } | |
444 | ||
6c1a9e53 MS |
445 | if ((mouseX >= autoRotateX) && |
446 | (mouseX < autoRotateX + toggleButtonSize) && | |
447 | (mouseY >= autoRotateY) && | |
448 | (mouseY < autoRotateY + toggleButtonSize)) { | |
449 | if (lx.isAutoTransitionEnabled()) { | |
450 | lx.disableAutoTransition(); | |
451 | println("Auto pattern transition disabled"); | |
452 | } else { | |
453 | lx.enableAutoTransition(60000); | |
454 | println("Auto pattern transition enabled"); | |
455 | } | |
456 | return; | |
457 | } | |
458 | ||
49815cc0 MS |
459 | if (mouseY > tempoY) { |
460 | if (mouseY - tempoY < tempoHeight) { | |
461 | lx.tempo.tap(); | |
462 | tempoDown = true; | |
463 | } | |
3f8be614 MS |
464 | } else if ((mouseY >= firstEffectKnobY) && (mouseY < firstEffectKnobY + knobSize + knobLabelHeight)) { |
465 | effectKnobIndex = (mouseX - leftTextPos) / (knobSize + knobSpacing); | |
49815cc0 | 466 | } else if (mouseY > firstEffectY) { |
bf551144 | 467 | int effectIndex = objectClickIndex(firstEffectY); |
49815cc0 | 468 | if (effectIndex < effects.length) { |
cc9fcf4b | 469 | if (effects[effectIndex] == glucose.getSelectedEffect()) { |
49815cc0 MS |
470 | effects[effectIndex].enable(); |
471 | releaseEffect = effectIndex; | |
49815cc0 | 472 | } |
cc9fcf4b | 473 | glucose.setSelectedEffect(effectIndex); |
49815cc0 | 474 | } |
3f8be614 MS |
475 | } else if ((mouseY >= firstTransitionKnobY) && (mouseY < firstTransitionKnobY + knobSize + knobLabelHeight)) { |
476 | transitionKnobIndex = (mouseX - leftTextPos) / (knobSize + knobSpacing); | |
49815cc0 | 477 | } else if (mouseY > firstTransitionY) { |
bf551144 | 478 | int transitionIndex = objectClickIndex(firstTransitionY); |
49815cc0 | 479 | if (transitionIndex < transitions.length) { |
cc9fcf4b | 480 | glucose.setSelectedTransition(transitionIndex); |
49815cc0 | 481 | } |
3f8be614 MS |
482 | } else if ((mouseY >= firstPatternKnobY) && (mouseY < firstPatternKnobY + 2*(knobSize+knobLabelHeight) + knobSpacing)) { |
483 | patternKnobIndex = (mouseX - leftTextPos) / (knobSize + knobSpacing); | |
484 | if (mouseY >= firstPatternKnobY + knobSize + knobLabelHeight + knobSpacing) { | |
cc9fcf4b | 485 | patternKnobIndex += glucose.NUM_PATTERN_KNOBS / 2; |
49815cc0 MS |
486 | } |
487 | } else if (mouseY > firstPatternY) { | |
0ba6ac44 MS |
488 | if ((patterns.length > PATTERN_LIST_LENGTH) && (mouseX > width - scrollWidth)) { |
489 | patternScrolling = true; | |
490 | } else { | |
491 | int patternIndex = objectClickIndex(firstPatternY); | |
492 | if (patternIndex < patterns.length) { | |
775d3394 | 493 | if (lx.isAutoTransitionEnabled() && (mouseX > eligibleLeft)) { |
6c1a9e53 MS |
494 | patterns[patternIndex + patternScrollPos].toggleEligible(); |
495 | } else { | |
496 | lx.goIndex(patternIndex + patternScrollPos); | |
497 | } | |
0ba6ac44 | 498 | } |
49815cc0 MS |
499 | } |
500 | } | |
501 | } | |
502 | ||
0ba6ac44 | 503 | int scrolldy = 0; |
49815cc0 MS |
504 | public void mouseDragged() { |
505 | int dy = lastY - mouseY; | |
0ba6ac44 | 506 | scrolldy += dy; |
49815cc0 | 507 | lastY = mouseY; |
cc9fcf4b MS |
508 | if (patternKnobIndex >= 0 && patternKnobIndex < glucose.NUM_PATTERN_KNOBS) { |
509 | LXParameter p = glucose.patternKnobs.get(patternKnobIndex); | |
3f8be614 | 510 | p.setValue(constrain(p.getValuef() + dy*.01, 0, 1)); |
cc9fcf4b MS |
511 | } else if (effectKnobIndex >= 0 && effectKnobIndex < glucose.NUM_EFFECT_KNOBS) { |
512 | LXParameter p = glucose.effectKnobs.get(effectKnobIndex); | |
3f8be614 | 513 | p.setValue(constrain(p.getValuef() + dy*.01, 0, 1)); |
cc9fcf4b MS |
514 | } else if (transitionKnobIndex >= 0 && transitionKnobIndex < glucose.NUM_TRANSITION_KNOBS) { |
515 | LXParameter p = glucose.transitionKnobs.get(transitionKnobIndex); | |
3f8be614 | 516 | p.setValue(constrain(p.getValuef() + dy*.01, 0, 1)); |
0ba6ac44 MS |
517 | } else if (patternScrolling) { |
518 | int scroll = scrolldy / lineHeight; | |
519 | scrolldy = scrolldy % lineHeight; | |
520 | patternScrollPos = constrain(patternScrollPos - scroll, 0, patterns.length - PATTERN_LIST_LENGTH); | |
49815cc0 MS |
521 | } |
522 | } | |
523 | ||
524 | public void mouseReleased() { | |
0ba6ac44 | 525 | patternScrolling = false; |
49815cc0 MS |
526 | tempoDown = false; |
527 | if (releaseEffect >= 0) { | |
528 | effects[releaseEffect].trigger(); | |
529 | releaseEffect = -1; | |
530 | } | |
531 | } | |
3f8be614 | 532 | |
0ba6ac44 MS |
533 | public void mouseWheel(int delta) { |
534 | if (mouseY > firstPatternY) { | |
535 | int patternIndex = objectClickIndex(firstPatternY); | |
536 | if (patternIndex < PATTERN_LIST_LENGTH) { | |
537 | patternScrollPos = constrain(patternScrollPos + delta, 0, patterns.length - PATTERN_LIST_LENGTH); | |
538 | } | |
539 | } | |
540 | } | |
541 | ||
49815cc0 MS |
542 | } |
543 | ||
bf551144 MS |
544 | /** |
545 | * UI for control of mapping. | |
546 | */ | |
547 | class MappingUI extends OverlayUI { | |
548 | ||
549 | private MappingTool mappingTool; | |
550 | ||
551 | private final String MAPPING_MODE_ALL = "All On"; | |
2bae07c9 | 552 | private final String MAPPING_MODE_CHANNEL = "Channel"; |
bf551144 | 553 | private final String MAPPING_MODE_SINGLE_CUBE = "Single Cube"; |
2bae07c9 | 554 | |
bf551144 MS |
555 | private final String[] mappingModes = { |
556 | MAPPING_MODE_ALL, | |
2bae07c9 MS |
557 | MAPPING_MODE_CHANNEL, |
558 | MAPPING_MODE_SINGLE_CUBE | |
bf551144 MS |
559 | }; |
560 | private final Method mappingModeStateMethod; | |
561 | ||
562 | private final String CUBE_MODE_ALL = "All Strips"; | |
563 | private final String CUBE_MODE_SINGLE_STRIP = "Single Strip"; | |
564 | private final String CUBE_MODE_STRIP_PATTERN = "Strip Pattern"; | |
565 | private final String[] cubeModes = { | |
566 | CUBE_MODE_ALL, | |
567 | CUBE_MODE_SINGLE_STRIP, | |
568 | CUBE_MODE_STRIP_PATTERN | |
569 | }; | |
570 | private final Method cubeModeStateMethod; | |
571 | ||
572 | private final String CHANNEL_MODE_RED = "Red"; | |
573 | private final String CHANNEL_MODE_GREEN = "Green"; | |
574 | private final String CHANNEL_MODE_BLUE = "Blue"; | |
575 | private final String[] channelModes = { | |
576 | CHANNEL_MODE_RED, | |
577 | CHANNEL_MODE_GREEN, | |
578 | CHANNEL_MODE_BLUE, | |
579 | }; | |
580 | private final Method channelModeStateMethod; | |
581 | ||
582 | private int firstMappingY; | |
583 | private int firstCubeY; | |
584 | private int firstChannelY; | |
2bae07c9 | 585 | private int channelFieldY; |
bf551144 MS |
586 | private int cubeFieldY; |
587 | private int stripFieldY; | |
588 | ||
589 | private boolean dragCube; | |
590 | private boolean dragStrip; | |
2bae07c9 | 591 | private boolean dragChannel; |
bf551144 MS |
592 | |
593 | MappingUI(MappingTool mappingTool) { | |
594 | this.mappingTool = mappingTool; | |
595 | try { | |
596 | mappingModeStateMethod = getClass().getMethod("getMappingState", Object.class); | |
597 | channelModeStateMethod = getClass().getMethod("getChannelState", Object.class); | |
598 | cubeModeStateMethod = getClass().getMethod("getCubeState", Object.class); | |
599 | } catch (Exception x) { | |
600 | throw new RuntimeException(x); | |
601 | } | |
602 | } | |
603 | ||
604 | public int getMappingState(Object mappingMode) { | |
2bae07c9 MS |
605 | boolean active = false; |
606 | if (mappingMode == MAPPING_MODE_ALL) { | |
607 | active = mappingTool.mappingMode == mappingTool.MAPPING_MODE_ALL; | |
608 | } else if (mappingMode == MAPPING_MODE_CHANNEL) { | |
609 | active = mappingTool.mappingMode == mappingTool.MAPPING_MODE_CHANNEL; | |
610 | } else if (mappingMode == MAPPING_MODE_SINGLE_CUBE) { | |
611 | active = mappingTool.mappingMode == mappingTool.MAPPING_MODE_SINGLE_CUBE; | |
612 | } | |
bf551144 MS |
613 | return active ? STATE_ACTIVE : STATE_DEFAULT; |
614 | } | |
615 | ||
616 | public int getChannelState(Object channelMode) { | |
617 | boolean active = false; | |
618 | if (channelMode == CHANNEL_MODE_RED) { | |
619 | active = mappingTool.channelModeRed; | |
620 | } else if (channelMode == CHANNEL_MODE_GREEN) { | |
621 | active = mappingTool.channelModeGreen; | |
622 | } else if (channelMode == CHANNEL_MODE_BLUE) { | |
623 | active = mappingTool.channelModeBlue; | |
624 | } | |
625 | return active ? STATE_ACTIVE : STATE_DEFAULT; | |
626 | } | |
627 | ||
628 | public int getCubeState(Object cubeMode) { | |
629 | boolean active = false; | |
630 | if (cubeMode == CUBE_MODE_ALL) { | |
631 | active = mappingTool.cubeMode == mappingTool.CUBE_MODE_ALL; | |
632 | } else if (cubeMode == CUBE_MODE_SINGLE_STRIP) { | |
633 | active = mappingTool.cubeMode == mappingTool.CUBE_MODE_SINGLE_STRIP; | |
634 | } else if (cubeMode == CUBE_MODE_STRIP_PATTERN) { | |
635 | active = mappingTool.cubeMode == mappingTool.CUBE_MODE_STRIP_PATTERN; | |
636 | } | |
637 | return active ? STATE_ACTIVE : STATE_DEFAULT; | |
638 | } | |
639 | ||
640 | public void draw() { | |
641 | drawLogoAndBackground(); | |
e28f168c | 642 | |
bf551144 MS |
643 | int yPos = 0; |
644 | firstMappingY = yPos + lineHeight + 6; | |
645 | yPos = drawObjectList(yPos, "MAPPING MODE", mappingModes, mappingModes, mappingModeStateMethod); | |
646 | yPos += sectionSpacing; | |
647 | ||
648 | firstCubeY = yPos + lineHeight + 6; | |
649 | yPos = drawObjectList(yPos, "CUBE MODE", cubeModes, cubeModes, cubeModeStateMethod); | |
650 | yPos += sectionSpacing; | |
651 | ||
652 | firstChannelY = yPos + lineHeight + 6; | |
653 | yPos = drawObjectList(yPos, "CHANNELS", channelModes, channelModes, channelModeStateMethod); | |
654 | yPos += sectionSpacing; | |
2bae07c9 MS |
655 | |
656 | channelFieldY = yPos + lineHeight + 6; | |
657 | yPos = drawValueField(yPos, "CHANNEL ID", mappingTool.channelIndex + 1); | |
658 | yPos += sectionSpacing; | |
bf551144 MS |
659 | |
660 | cubeFieldY = yPos + lineHeight + 6; | |
661 | yPos = drawValueField(yPos, "CUBE ID", glucose.model.getRawIndexForCube(mappingTool.cubeIndex)); | |
662 | yPos += sectionSpacing; | |
663 | ||
664 | stripFieldY = yPos + lineHeight + 6; | |
665 | yPos = drawValueField(yPos, "STRIP ID", mappingTool.stripIndex + 1); | |
666 | ||
667 | drawToggleTip("Tap 'm' to return"); | |
668 | } | |
669 | ||
670 | private int drawValueField(int yPos, String label, int value) { | |
671 | yPos += lineHeight; | |
672 | textAlign(LEFT); | |
673 | textFont(titleFont); | |
674 | fill(titleColor); | |
675 | text(label, leftTextPos, yPos); | |
676 | fill(0); | |
677 | yPos += 6; | |
678 | rect(leftTextPos, yPos, w-8, lineHeight); | |
679 | yPos += lineHeight; | |
680 | ||
681 | fill(#999999); | |
682 | textAlign(CENTER); | |
683 | textFont(itemFont); | |
684 | text("" + value, leftTextPos + (w-8)/2, yPos - 5); | |
685 | ||
686 | return yPos; | |
687 | } | |
688 | ||
689 | private int lastY; | |
690 | ||
691 | public void mousePressed() { | |
2bae07c9 | 692 | dragCube = dragStrip = dragChannel = false; |
bf551144 | 693 | lastY = mouseY; |
79ae8245 MS |
694 | |
695 | if (mouseX < leftPos) { | |
696 | return; | |
697 | } | |
698 | ||
bf551144 MS |
699 | if (mouseY >= stripFieldY) { |
700 | if (mouseY < stripFieldY + lineHeight) { | |
701 | dragStrip = true; | |
702 | } | |
703 | } else if (mouseY >= cubeFieldY) { | |
704 | if (mouseY < cubeFieldY + lineHeight) { | |
705 | dragCube = true; | |
706 | } | |
2bae07c9 MS |
707 | } else if (mouseY >= channelFieldY) { |
708 | if (mouseY < channelFieldY + lineHeight) { | |
709 | dragChannel = true; | |
710 | } | |
bf551144 MS |
711 | } else if (mouseY >= firstChannelY) { |
712 | int index = objectClickIndex(firstChannelY); | |
713 | switch (index) { | |
714 | case 0: mappingTool.channelModeRed = !mappingTool.channelModeRed; break; | |
715 | case 1: mappingTool.channelModeGreen = !mappingTool.channelModeGreen; break; | |
716 | case 2: mappingTool.channelModeBlue = !mappingTool.channelModeBlue; break; | |
717 | } | |
718 | } else if (mouseY >= firstCubeY) { | |
719 | int index = objectClickIndex(firstCubeY); | |
720 | switch (index) { | |
721 | case 0: mappingTool.cubeMode = mappingTool.CUBE_MODE_ALL; break; | |
722 | case 1: mappingTool.cubeMode = mappingTool.CUBE_MODE_SINGLE_STRIP; break; | |
723 | case 2: mappingTool.cubeMode = mappingTool.CUBE_MODE_STRIP_PATTERN; break; | |
724 | } | |
725 | } else if (mouseY >= firstMappingY) { | |
726 | int index = objectClickIndex(firstMappingY); | |
2bae07c9 MS |
727 | switch (index) { |
728 | case 0: mappingTool.mappingMode = mappingTool.MAPPING_MODE_ALL; break; | |
729 | case 1: mappingTool.mappingMode = mappingTool.MAPPING_MODE_CHANNEL; break; | |
730 | case 2: mappingTool.mappingMode = mappingTool.MAPPING_MODE_SINGLE_CUBE; break; | |
bf551144 MS |
731 | } |
732 | } | |
733 | } | |
734 | ||
0ba6ac44 MS |
735 | public void mouseReleased() {} |
736 | public void mouseWheel(int delta) {} | |
bf551144 MS |
737 | |
738 | public void mouseDragged() { | |
739 | final int DRAG_THRESHOLD = 5; | |
740 | int dy = lastY - mouseY; | |
741 | if (abs(dy) >= DRAG_THRESHOLD) { | |
742 | lastY = mouseY; | |
743 | if (dragCube) { | |
744 | if (dy < 0) { | |
745 | mappingTool.decCube(); | |
746 | } else { | |
747 | mappingTool.incCube(); | |
748 | } | |
749 | } else if (dragStrip) { | |
750 | if (dy < 0) { | |
751 | mappingTool.decStrip(); | |
752 | } else { | |
753 | mappingTool.incStrip(); | |
754 | } | |
2bae07c9 MS |
755 | } else if (dragChannel) { |
756 | if (dy < 0) { | |
757 | mappingTool.decChannel(); | |
758 | } else { | |
759 | mappingTool.incChannel(); | |
760 | } | |
bf551144 MS |
761 | } |
762 | } | |
763 | ||
764 | } | |
49815cc0 MS |
765 | } |
766 | ||
554e38ff MS |
767 | class DebugUI { |
768 | ||
84086fa3 | 769 | final ChannelMapping[] channelList; |
1627a617 MS |
770 | final int debugX = 5; |
771 | final int debugY = 5; | |
554e38ff | 772 | final int debugXSpacing = 28; |
1627a617 | 773 | final int debugYSpacing = 21; |
95c50032 | 774 | final int[][] debugState; |
18a18c15 | 775 | final int[] indexState; |
51227786 | 776 | |
18a18c15 AK |
777 | final int CUBE_STATE_UNUSED = 0; |
778 | final int CUBE_STATE_USED = 1; | |
51227786 | 779 | final int CUBE_STATE_DUPLICATED = 2; |
554e38ff MS |
780 | |
781 | final int DEBUG_STATE_ANIM = 0; | |
782 | final int DEBUG_STATE_WHITE = 1; | |
783 | final int DEBUG_STATE_OFF = 2; | |
51227786 | 784 | final int DEBUG_STATE_UNUSED = 3; |
554e38ff | 785 | |
45f43cc2 | 786 | DebugUI(PandaMapping[] pandaMappings) { |
1685dc84 | 787 | int totalChannels = pandaMappings.length * PandaMapping.CHANNELS_PER_BOARD; |
95c50032 | 788 | debugState = new int[totalChannels+1][ChannelMapping.CUBES_PER_CHANNEL+1]; |
18a18c15 | 789 | indexState = new int[glucose.model.cubes.size()+1]; |
95c50032 | 790 | |
84086fa3 | 791 | channelList = new ChannelMapping[totalChannels]; |
45f43cc2 MS |
792 | int channelIndex = 0; |
793 | for (PandaMapping pm : pandaMappings) { | |
84086fa3 | 794 | for (ChannelMapping channel : pm.channelList) { |
45f43cc2 MS |
795 | channelList[channelIndex++] = channel; |
796 | } | |
554e38ff MS |
797 | } |
798 | for (int i = 0; i < debugState.length; ++i) { | |
799 | for (int j = 0; j < debugState[i].length; ++j) { | |
800 | debugState[i][j] = DEBUG_STATE_ANIM; | |
801 | } | |
802 | } | |
18a18c15 | 803 | |
51227786 | 804 | for (int rawIndex = 0; rawIndex < glucose.model.cubes.size()+1; ++rawIndex) { |
18a18c15 AK |
805 | indexState[rawIndex] = CUBE_STATE_UNUSED; |
806 | } | |
807 | for (ChannelMapping channel : channelList) { | |
808 | for (int rawCubeIndex : channel.objectIndices) { | |
809 | if (rawCubeIndex > 0) | |
51227786 | 810 | ++indexState[rawCubeIndex]; |
18a18c15 AK |
811 | } |
812 | } | |
554e38ff MS |
813 | } |
814 | ||
51227786 | 815 | void draw() { |
554e38ff MS |
816 | noStroke(); |
817 | int xBase = debugX; | |
818 | int yPos = debugY; | |
819 | ||
1627a617 MS |
820 | fill(#000000); |
821 | rect(0, 0, debugX + 5*debugXSpacing, height); | |
554e38ff MS |
822 | |
823 | int channelNum = 0; | |
84086fa3 | 824 | for (ChannelMapping channel : channelList) { |
554e38ff MS |
825 | int xPos = xBase; |
826 | drawNumBox(xPos, yPos, channelNum+1, debugState[channelNum][0]); | |
84086fa3 | 827 | xPos += debugXSpacing; |
554e38ff | 828 | |
84086fa3 MS |
829 | switch (channel.mode) { |
830 | case ChannelMapping.MODE_CUBES: | |
831 | int stateIndex = 0; | |
832 | boolean first = true; | |
833 | for (int rawCubeIndex : channel.objectIndices) { | |
834 | if (rawCubeIndex < 0) { | |
835 | break; | |
836 | } | |
837 | if (first) { | |
838 | first = false; | |
839 | } else { | |
840 | stroke(#999999); | |
841 | line(xPos - 12, yPos + 8, xPos, yPos + 8); | |
842 | } | |
18a18c15 | 843 | drawNumBox(xPos, yPos, rawCubeIndex, debugState[channelNum][stateIndex+1], indexState[rawCubeIndex]); |
84086fa3 MS |
844 | ++stateIndex; |
845 | xPos += debugXSpacing; | |
846 | } | |
554e38ff | 847 | break; |
84086fa3 MS |
848 | case ChannelMapping.MODE_BASS: |
849 | drawNumBox(xPos, yPos, "B", debugState[channelNum][1]); | |
850 | break; | |
851 | case ChannelMapping.MODE_SPEAKER: | |
852 | drawNumBox(xPos, yPos, "S" + channel.objectIndices[0], debugState[channelNum][1]); | |
853 | break; | |
1d75c8a9 | 854 | case ChannelMapping.MODE_STRUTS_AND_FLOOR: |
84086fa3 MS |
855 | drawNumBox(xPos, yPos, "F", debugState[channelNum][1]); |
856 | break; | |
857 | case ChannelMapping.MODE_NULL: | |
858 | break; | |
859 | default: | |
860 | throw new RuntimeException("Unhandled channel mapping mode: " + channel.mode); | |
861 | } | |
554e38ff MS |
862 | |
863 | yPos += debugYSpacing; | |
864 | ++channelNum; | |
865 | } | |
866 | drawNumBox(xBase, yPos, "A", debugState[channelNum][0]); | |
18a18c15 AK |
867 | yPos += debugYSpacing * 2; |
868 | ||
869 | noFill(); | |
18a18c15 | 870 | fill(#CCCCCC); |
51227786 | 871 | text("Unused Cubes", xBase, yPos + 12); |
18a18c15 AK |
872 | yPos += debugYSpacing; |
873 | ||
51227786 MS |
874 | int xIndex = 0; |
875 | for (int rawIndex = 1; rawIndex <= glucose.model.cubes.size(); ++rawIndex) { | |
876 | if (indexState[rawIndex] == CUBE_STATE_UNUSED) { | |
877 | drawNumBox(xBase + (xIndex * debugXSpacing), yPos, rawIndex, DEBUG_STATE_UNUSED); | |
878 | ++xIndex; | |
879 | if (xIndex > 4) { | |
880 | xIndex = 0; | |
18a18c15 AK |
881 | yPos += debugYSpacing + 2; |
882 | } | |
883 | } | |
884 | } | |
554e38ff | 885 | } |
18a18c15 | 886 | |
554e38ff MS |
887 | |
888 | void drawNumBox(int xPos, int yPos, int label, int state) { | |
889 | drawNumBox(xPos, yPos, "" + label, state); | |
890 | } | |
891 | ||
51227786 MS |
892 | void drawNumBox(int xPos, int yPos, String label, int state) { |
893 | drawNumBox(xPos, yPos, "" + label, state, CUBE_STATE_USED); | |
894 | } | |
895 | ||
896 | void drawNumBox(int xPos, int yPos, int label, int state, int cubeState) { | |
897 | drawNumBox(xPos, yPos, "" + label, state, cubeState); | |
18a18c15 AK |
898 | } |
899 | ||
51227786 | 900 | void drawNumBox(int xPos, int yPos, String label, int state, int cubeState) { |
554e38ff MS |
901 | noFill(); |
902 | color textColor = #cccccc; | |
903 | switch (state) { | |
904 | case DEBUG_STATE_ANIM: | |
905 | noStroke(); | |
906 | fill(#880000); | |
907 | rect(xPos, yPos, 16, 8); | |
908 | fill(#000088); | |
909 | rect(xPos, yPos+8, 16, 8); | |
910 | noFill(); | |
911 | stroke(textColor); | |
554e38ff MS |
912 | break; |
913 | case DEBUG_STATE_WHITE: | |
914 | stroke(textColor); | |
915 | fill(#e9e9e9); | |
554e38ff MS |
916 | textColor = #333333; |
917 | break; | |
918 | case DEBUG_STATE_OFF: | |
919 | stroke(textColor); | |
51227786 MS |
920 | break; |
921 | case DEBUG_STATE_UNUSED: | |
922 | stroke(textColor); | |
923 | fill(#880000); | |
554e38ff MS |
924 | break; |
925 | } | |
926 | ||
51227786 MS |
927 | if (cubeState >= CUBE_STATE_DUPLICATED) { |
928 | stroke(textColor = #FF0000); | |
929 | } | |
930 | ||
931 | rect(xPos, yPos, 16, 16); | |
554e38ff MS |
932 | noStroke(); |
933 | fill(textColor); | |
934 | text(label, xPos + 2, yPos + 12); | |
554e38ff MS |
935 | } |
936 | ||
937 | void maskColors(color[] colors) { | |
938 | color white = #FFFFFF; | |
939 | color off = #000000; | |
940 | int channelIndex = 0; | |
84086fa3 MS |
941 | int state; |
942 | for (ChannelMapping channel : channelList) { | |
943 | switch (channel.mode) { | |
944 | case ChannelMapping.MODE_CUBES: | |
945 | int cubeIndex = 1; | |
946 | for (int rawCubeIndex : channel.objectIndices) { | |
947 | if (rawCubeIndex >= 0) { | |
948 | state = debugState[channelIndex][cubeIndex]; | |
949 | if (state != DEBUG_STATE_ANIM) { | |
950 | color debugColor = (state == DEBUG_STATE_WHITE) ? white : off; | |
951 | Cube cube = glucose.model.getCubeByRawIndex(rawCubeIndex); | |
952 | for (Point p : cube.points) { | |
953 | colors[p.index] = debugColor; | |
954 | } | |
955 | } | |
554e38ff | 956 | } |
84086fa3 | 957 | ++cubeIndex; |
554e38ff | 958 | } |
84086fa3 MS |
959 | break; |
960 | ||
961 | case ChannelMapping.MODE_BASS: | |
962 | state = debugState[channelIndex][1]; | |
963 | if (state != DEBUG_STATE_ANIM) { | |
964 | color debugColor = (state == DEBUG_STATE_WHITE) ? white : off; | |
1d75c8a9 MS |
965 | for (Strip s : glucose.model.bassBox.boxStrips) { |
966 | for (Point p : s.points) { | |
967 | colors[p.index] = debugColor; | |
968 | } | |
84086fa3 MS |
969 | } |
970 | } | |
971 | break; | |
972 | ||
1d75c8a9 | 973 | case ChannelMapping.MODE_STRUTS_AND_FLOOR: |
84086fa3 MS |
974 | state = debugState[channelIndex][1]; |
975 | if (state != DEBUG_STATE_ANIM) { | |
976 | color debugColor = (state == DEBUG_STATE_WHITE) ? white : off; | |
977 | for (Point p : glucose.model.boothFloor.points) { | |
978 | colors[p.index] = debugColor; | |
979 | } | |
1d75c8a9 MS |
980 | for (Strip s : glucose.model.bassBox.struts) { |
981 | for (Point p : s.points) { | |
982 | colors[p.index] = debugColor; | |
983 | } | |
984 | } | |
84086fa3 MS |
985 | } |
986 | break; | |
987 | ||
988 | case ChannelMapping.MODE_SPEAKER: | |
989 | state = debugState[channelIndex][1]; | |
990 | if (state != DEBUG_STATE_ANIM) { | |
991 | color debugColor = (state == DEBUG_STATE_WHITE) ? white : off; | |
992 | for (Point p : glucose.model.speakers.get(channel.objectIndices[0]).points) { | |
993 | colors[p.index] = debugColor; | |
994 | } | |
995 | } | |
996 | break; | |
997 | ||
998 | case ChannelMapping.MODE_NULL: | |
999 | break; | |
1000 | ||
1001 | default: | |
1002 | throw new RuntimeException("Unhandled channel mapping mode: " + channel.mode); | |
554e38ff MS |
1003 | } |
1004 | ++channelIndex; | |
1005 | } | |
1006 | } | |
1007 | ||
1008 | void mousePressed() { | |
1009 | int dx = (mouseX - debugX) / debugXSpacing; | |
1010 | int dy = (mouseY - debugY) / debugYSpacing; | |
1011 | if ((dy >= 0) && (dy < debugState.length)) { | |
1012 | if ((dx >= 0) && (dx < debugState[dy].length)) { | |
1013 | int newState = debugState[dy][dx] = (debugState[dy][dx] + 1) % 3; | |
95c50032 | 1014 | if (dy == debugState.length-1) { |
554e38ff MS |
1015 | for (int[] states : debugState) { |
1016 | for (int i = 0; i < states.length; ++i) { | |
1017 | states[i] = newState; | |
1018 | } | |
1019 | } | |
1020 | } else if (dx == 0) { | |
1021 | for (int i = 0; i < debugState[dy].length; ++i) { | |
1022 | debugState[dy][i] = newState; | |
1023 | } | |
1024 | } | |
1025 | } | |
1026 | } | |
1027 | } | |
1028 | } |