Fix key/mouse interactivity in processing 2
[SugarCubes.git] / UIImplementation.pde
CommitLineData
d626bc9b
MS
1/**
2 * DOUBLE BLACK DIAMOND DOUBLE BLACK DIAMOND
3 *
4 * //\\ //\\ //\\ //\\
5 * ///\\\ ///\\\ ///\\\ ///\\\
6 * \\\/// \\\/// \\\/// \\\///
7 * \\// \\// \\// \\//
8 *
9 * EXPERTS ONLY!! EXPERTS ONLY!!
10 *
11 * Custom UI components using the framework.
12 */
b5d6d7a0
BM
13
14import java.nio.*;
7d60f6f6 15import java.util.Arrays;
36e19b7b 16class UICubesLayer extends UICameraComponent {
b5d6d7a0
BM
17
18int nvert = 200000;
19int SIZEOF_INT = Integer.SIZE / 8;
20int SIZEOF_FLOAT = Float.SIZE / 8;
21
22PGL pgl;
23PShader sh;
24
25int vertLoc;
26int colorLoc;
27
28IntBuffer vboName;
29FloatBuffer vertData;
30
31 boolean initted = false;
32 PShape sha1;
33 int numPoints = 10000;
34
35 void initme()
36 {
37 nvert = model.points.size();
38 sh = loadShader("frag.glsl", "vert.glsl");
39 /*color[] simulationColors = lx.getColors();
40 sha1= createShape();
41 sha1.beginShape(POINTS);
42 for (LXPoint p : model.points) {
43 stroke(simulationColors[p.index]);
44 //pointColor(simulationColors[p.index]);
45 gl2.glPointColor=100;
46 sha1.vertex(p.x, p.y, p.z);
47 }
48 sha1.endShape();*/
49 float[] temp = new float[nvert * 7];
50 for (LXPoint p : model.points) {
51 // position
52 temp[p.index * 7 + 0] = p.x;
53 temp[p.index * 7 + 1] = p.y;
54 temp[p.index * 7 + 2] = p.z;
55
56 // color
57 temp[p.index * 7 + 3] = 0.0;
58 temp[p.index * 7 + 4] = 0.0;
59 temp[p.index * 7 + 5] = 0.0;
60 temp[p.index * 7 + 6] = 1.0;
61 }
62
63 vertData = allocateDirectFloatBuffer(nvert * 7);
64 vertData.rewind();
65 vertData.put(temp);
66 vertData.position(0);
67 vboName = allocateDirectIntBuffer(1);
68 initVBO();
69 }
36e19b7b 70 void onDraw(UI ui) {
b5d6d7a0
BM
71 if(!initted)
72 {
73 initted=true;
74 initme();
75 }
36e19b7b
MS
76 color[] simulationColors = lx.getColors();
77 String displayMode = uiCrossfader.getDisplayMode();
78 if (displayMode == "A") {
79 simulationColors = lx.engine.getDeck(LEFT_DECK).getColors();
80 } else if (displayMode == "B") {
81 simulationColors = lx.engine.getDeck(RIGHT_DECK).getColors();
d626bc9b 82 }
36e19b7b
MS
83
84 long simulationStart = System.nanoTime();
85 if (simulationOn) {
30673de2 86 hint(DISABLE_DEPTH_TEST);
36e19b7b 87 drawSimulation(simulationColors);
30673de2 88 hint(ENABLE_DEPTH_TEST);
36e19b7b
MS
89 }
90 simulationNanos = System.nanoTime() - simulationStart;
b5d6d7a0 91 camera();
36e19b7b 92 strokeWeight(1);
d626bc9b 93 }
30673de2 94
36e19b7b
MS
95 void drawSimulation(color[] simulationColors) {
96 translate(0, 30, 0);
b5d6d7a0 97
36e19b7b 98 fill(#141414);
30673de2 99 drawBox(0, -TRAILER_HEIGHT, 0, 0, 0, 0, TRAILER_WIDTH, TRAILER_HEIGHT, TRAILER_DEPTH, TRAILER_HEIGHT/2.);
36e19b7b
MS
100 fill(#070707);
101 stroke(#222222);
102 beginShape();
103 vertex(0, 0, 0);
104 vertex(TRAILER_WIDTH, 0, 0);
105 vertex(TRAILER_WIDTH, 0, TRAILER_DEPTH);
106 vertex(0, 0, TRAILER_DEPTH);
107 endShape();
108
109 // Draw the logo on the front of platform
110 pushMatrix();
111 translate(0, 0, -1);
112 float s = .07;
113 scale(s, -s, s);
114 image(logo, TRAILER_WIDTH/2/s-logo.width/2, TRAILER_HEIGHT/2/s-logo.height/2-2/s);
115 popMatrix();
d626bc9b 116
36e19b7b
MS
117 noStroke();
118 for (Cube c : model.cubes) {
119 drawCube(c);
d626bc9b 120 }
b5d6d7a0 121
36e19b7b 122 noFill();
b5d6d7a0
BM
123 //strokeWeight(2);
124 int count=0;
125
126 ///magic:
127
128 pgl = beginPGL();
129
130
131 sh.bind();
132
133 vertLoc = pgl.getAttribLocation(sh.glProgram, "vertex");
134 colorLoc = pgl.getAttribLocation(sh.glProgram, "color");
135
136 pgl.bindBuffer(PGL.ARRAY_BUFFER, vboName.get(0));
137 pgl.enableVertexAttribArray(vertLoc);
138 pgl.enableVertexAttribArray(colorLoc);
139
140 pgl.vertexAttribPointer(vertLoc, 3, PGL.FLOAT, false, 7 * SIZEOF_FLOAT, 0);
141 pgl.vertexAttribPointer(colorLoc, 4, PGL.FLOAT, false, 7 * SIZEOF_FLOAT, 3 * SIZEOF_FLOAT);
142
143 pgl.drawArrays(PGL.POINTS, 0, nvert);
144
145 pgl.disableVertexAttribArray(vertLoc);
146 pgl.disableVertexAttribArray(colorLoc);
147 pgl.bindBuffer(PGL.ARRAY_BUFFER, 0);
148
149 sh.unbind();
150 endPGL();
151 createGeometry(simulationColors);
152 pgl.bindBuffer(PGL.ARRAY_BUFFER, vboName.get(0));
153 pgl.bufferData(PGL.ARRAY_BUFFER, nvert * 7 * SIZEOF_FLOAT, vertData, PGL.STATIC_DRAW);
154 }
155
156 void createGeometry(color[] simulationColors) {
36e19b7b 157 for (LXPoint p : model.points) {
b5d6d7a0
BM
158 vertData.put(p.index * 7 + 3, ((simulationColors[p.index] >> 16) & 0xFF)/255.0);
159 vertData.put(p.index * 7 + 4, ((simulationColors[p.index] >> 8) & 0xFF)/255.0);
160 vertData.put(p.index * 7 + 5, (simulationColors[p.index]& 0xFF)/255.0);
161 }
36e19b7b 162 }
b5d6d7a0
BM
163void initVBO() {
164
165 pgl = beginPGL();
166 pgl.genBuffers(1, vboName);
167 pgl.bindBuffer(PGL.ARRAY_BUFFER, vboName.get(0));
168 pgl.bufferData(PGL.ARRAY_BUFFER, nvert * 7 * SIZEOF_FLOAT, vertData, PGL.DYNAMIC_DRAW);
169 pgl.bindBuffer(PGL.ARRAY_BUFFER, 0);
170 endPGL();
171}
172
173IntBuffer allocateDirectIntBuffer(int n) {
174 return ByteBuffer.allocateDirect(n * SIZEOF_INT).order(ByteOrder.nativeOrder()).asIntBuffer();
175}
176
177FloatBuffer allocateDirectFloatBuffer(int n) {
178 return ByteBuffer.allocateDirect(n * SIZEOF_FLOAT).order(ByteOrder.nativeOrder()).asFloatBuffer();
179}
36e19b7b
MS
180
181 void drawCube(Cube c) {
182 float in = .15;
183 noStroke();
184 fill(#393939);
30673de2 185 drawBox(c.x+in, c.y+in, c.z+in, c.rx, c.ry, c.rz, Cube.EDGE_WIDTH-in*2, Cube.EDGE_HEIGHT-in*2, Cube.EDGE_WIDTH-in*2, Cube.CHANNEL_WIDTH-in);
36e19b7b
MS
186 }
187
188 void drawBox(float x, float y, float z, float rx, float ry, float rz, float xd, float yd, float zd, float sw) {
189 pushMatrix();
190 translate(x, y, z);
191 rotate(rx / 180. * PI, -1, 0, 0);
192 rotate(ry / 180. * PI, 0, -1, 0);
193 rotate(rz / 180. * PI, 0, 0, -1);
194 for (int i = 0; i < 4; ++i) {
195 float wid = (i % 2 == 0) ? xd : zd;
196
197 beginShape();
198 vertex(0, 0);
199 vertex(wid, 0);
200 vertex(wid, yd);
201 vertex(wid - sw, yd);
202 vertex(wid - sw, sw);
203 vertex(0, sw);
204 endShape();
205 beginShape();
206 vertex(0, sw);
207 vertex(0, yd);
208 vertex(wid - sw, yd);
209 vertex(wid - sw, yd - sw);
210 vertex(sw, yd - sw);
211 vertex(sw, sw);
212 endShape();
213
214 translate(wid, 0, 0);
215 rotate(HALF_PI, 0, -1, 0);
d626bc9b 216 }
36e19b7b 217 popMatrix();
d626bc9b
MS
218 }
219}
220
a8d55ade
MS
221class UIBlendMode extends UIWindow {
222 public UIBlendMode(float x, float y, float w, float h) {
4e6626a9
MS
223 super(lx.ui, "BLEND MODE", x, y, w, h);
224 List<UIScrollList.Item> items = new ArrayList<UIScrollList.Item>();
3f16fd02 225 for (LXTransition t : transitions) {
d626bc9b 226 items.add(new TransitionScrollItem(t));
a898d79b
MS
227 }
228 final UIScrollList tList;
4e6626a9 229 (tList = new UIScrollList(1, UIWindow.TITLE_LABEL_HEIGHT, w-2, 60)).setItems(items).addToContainer(this);
a8d55ade 230
0c7bfdb5 231 lx.engine.getDeck(RIGHT_DECK).addListener(new LXDeck.AbstractListener() {
42a424d7 232 public void faderTransitionDidChange(LXDeck deck, LXTransition transition) {
a898d79b 233 tList.redraw();
d626bc9b 234 }
a898d79b
MS
235 });
236 }
a8d55ade 237
4e6626a9 238 class TransitionScrollItem extends UIScrollList.AbstractItem {
a8d55ade 239 private final LXTransition transition;
3f16fd02 240 private final String label;
a8d55ade
MS
241
242 TransitionScrollItem(LXTransition transition) {
243 this.transition = transition;
3f16fd02 244 this.label = className(transition, "Transition");
a8d55ade
MS
245 }
246
247 public String getLabel() {
248 return label;
249 }
250
251 public boolean isSelected() {
0c7bfdb5 252 return this.transition == lx.engine.getDeck(RIGHT_DECK).getFaderTransition();
a8d55ade
MS
253 }
254
255 public boolean isPending() {
256 return false;
257 }
258
259 public void onMousePressed() {
0c7bfdb5 260 lx.engine.getDeck(RIGHT_DECK).setFaderTransition(this.transition);
a8d55ade 261 }
d626bc9b 262 }
a8d55ade 263
d626bc9b
MS
264}
265
a8d55ade 266class UICrossfader extends UIWindow {
d626bc9b 267
a8d55ade 268 private final UIToggleSet displayMode;
d626bc9b 269
a8d55ade 270 public UICrossfader(float x, float y, float w, float h) {
4e6626a9 271 super(lx.ui, "CROSSFADER", x, y, w, h);
a8d55ade 272
0c7bfdb5 273 new UISlider(4, UIWindow.TITLE_LABEL_HEIGHT, w-9, 32).setParameter(lx.engine.getDeck(RIGHT_DECK).getFader()).addToContainer(this);
4e6626a9 274 (displayMode = new UIToggleSet(4, UIWindow.TITLE_LABEL_HEIGHT + 36, w-9, 20)).setOptions(new String[] { "A", "COMP", "B" }).setValue("COMP").addToContainer(this);
d626bc9b
MS
275 }
276
88a3dd9e
MS
277 public UICrossfader setDisplayMode(String value) {
278 displayMode.setValue(value);
279 return this;
280 }
281
a8d55ade
MS
282 public String getDisplayMode() {
283 return displayMode.getValue();
d626bc9b
MS
284 }
285}
286
287class UIEffects extends UIWindow {
288 UIEffects(float x, float y, float w, float h) {
4e6626a9 289 super(lx.ui, "FX", x, y, w, h);
d626bc9b 290
4e6626a9
MS
291 int yp = UIWindow.TITLE_LABEL_HEIGHT;
292 List<UIScrollList.Item> items = new ArrayList<UIScrollList.Item>();
0c7bfdb5
MS
293 int i = 0;
294 for (LXEffect fx : effectsArr) {
295 items.add(new FXScrollItem(fx, i++));
d626bc9b
MS
296 }
297 final UIScrollList effectsList = new UIScrollList(1, yp, w-2, 60).setItems(items);
298 effectsList.addToContainer(this);
4e6626a9 299 yp += effectsList.getHeight() + 10;
d626bc9b 300
4e6626a9 301 final UIKnob[] parameterKnobs = new UIKnob[4];
d626bc9b 302 for (int ki = 0; ki < parameterKnobs.length; ++ki) {
4e6626a9 303 parameterKnobs[ki] = new UIKnob(5 + 34*(ki % 4), yp + (ki/4) * 48);
d626bc9b
MS
304 parameterKnobs[ki].addToContainer(this);
305 }
306
0c7bfdb5
MS
307 LXParameterListener fxListener = new LXParameterListener() {
308 public void onParameterChanged(LXParameter parameter) {
d626bc9b 309 int i = 0;
0c7bfdb5 310 for (LXParameter p : getSelectedEffect().getParameters()) {
d626bc9b
MS
311 if (i >= parameterKnobs.length) {
312 break;
313 }
4e6626a9
MS
314 if (p instanceof BasicParameter) {
315 parameterKnobs[i++].setParameter((BasicParameter) p);
316 }
d626bc9b
MS
317 }
318 while (i < parameterKnobs.length) {
319 parameterKnobs[i++].setParameter(null);
320 }
321 }
322 };
323
0c7bfdb5
MS
324 selectedEffect.addListener(fxListener);
325 fxListener.onParameterChanged(null);
d626bc9b
MS
326
327 }
328
4e6626a9 329 class FXScrollItem extends UIScrollList.AbstractItem {
d626bc9b 330
0c7bfdb5
MS
331 private final LXEffect effect;
332 private final int index;
333 private final String label;
d626bc9b 334
0c7bfdb5 335 FXScrollItem(LXEffect effect, int index) {
d626bc9b 336 this.effect = effect;
0c7bfdb5
MS
337 this.index = index;
338 this.label = className(effect, "Effect");
d626bc9b
MS
339 }
340
341 public String getLabel() {
342 return label;
343 }
344
345 public boolean isSelected() {
0c7bfdb5 346 return !effect.isEnabled() && (effect == getSelectedEffect());
d626bc9b
MS
347 }
348
349 public boolean isPending() {
350 return effect.isEnabled();
351 }
352
d626bc9b 353 public void onMousePressed() {
0c7bfdb5 354 if (effect == getSelectedEffect()) {
d626bc9b
MS
355 if (effect.isMomentary()) {
356 effect.enable();
357 } else {
358 effect.toggle();
359 }
8f7f055d 360 } else {
0c7bfdb5 361 selectedEffect.setValue(index);
d626bc9b
MS
362 }
363 }
364
365 public void onMouseReleased() {
366 if (effect.isMomentary()) {
367 effect.disable();
368 }
369 }
370
371 }
372
373}
374
375class UIOutput extends UIWindow {
e037f60f 376 public UIOutput(GrizzlyOutput[] grizzlies, float x, float y, float w, float h) {
4e6626a9
MS
377 super(lx.ui, "OUTPUT", x, y, w, h);
378 float yp = UIWindow.TITLE_LABEL_HEIGHT;
1f42cce7 379
4e6626a9 380 final UIScrollList outputs = new UIScrollList(1, UIWindow.TITLE_LABEL_HEIGHT, w-2, 80);
1f42cce7 381
4e6626a9 382 List<UIScrollList.Item> items = new ArrayList<UIScrollList.Item>();
e037f60f
MS
383 for (GrizzlyOutput grizzly : grizzlies) {
384 items.add(new GrizzlyScrollItem(grizzly));
385 grizzly.enabled.addListener(new LXParameterListener() {
386 public void onParameterChanged(LXParameter parameter) {
1f42cce7 387 outputs.redraw();
d626bc9b
MS
388 }
389 });
d626bc9b 390 }
1f42cce7
MS
391 outputs.setItems(items).addToContainer(this);
392 }
393
e037f60f
MS
394 class GrizzlyScrollItem extends UIScrollList.AbstractItem {
395 final GrizzlyOutput output;
396
397 GrizzlyScrollItem(GrizzlyOutput output) {
398 this.output = output;
1f42cce7
MS
399 }
400
401 public String getLabel() {
e037f60f 402 return output.ipAddress;
1f42cce7
MS
403 }
404
405 public boolean isSelected() {
e037f60f 406 return output.enabled.isOn();
1f42cce7
MS
407 }
408
8f7f055d 409 public void onMousePressed() {
4749563e 410 output.enabled.setValue(!isSelected());
1f42cce7
MS
411 }
412 }
d626bc9b
MS
413}
414
415class UITempo extends UIWindow {
416
417 private final UIButton tempoButton;
418
419 UITempo(float x, float y, float w, float h) {
4e6626a9
MS
420 super(lx.ui, "TEMPO", x, y, w, h);
421 tempoButton = new UIButton(4, UIWindow.TITLE_LABEL_HEIGHT, w-10, 20) {
d626bc9b
MS
422 protected void onToggle(boolean active) {
423 if (active) {
424 lx.tempo.tap();
425 }
426 }
427 }.setMomentary(true);
428 tempoButton.addToContainer(this);
4e6626a9 429 new UITempoBlipper(8, UIWindow.TITLE_LABEL_HEIGHT + 5, 12, 12).addToContainer(this);
d626bc9b
MS
430 }
431
4e6626a9
MS
432 class UITempoBlipper extends UIObject {
433 UITempoBlipper(float x, float y, float w, float h) {
434 super(x, y, w, h);
435 }
d626bc9b 436
4e6626a9
MS
437 void onDraw(UI ui, PGraphics pg) {
438 tempoButton.setLabel("" + ((int)(lx.tempo.bpm() * 10)) / 10.);
439
440 // Overlay tempo thing with openGL, redraw faster than button UI
441 pg.fill(color(0, 0, 24 - 8*lx.tempo.rampf()));
442 pg.noStroke();
443 pg.rect(0, 0, width, height);
444
445 redraw();
446 }
d626bc9b 447 }
4e6626a9 448
d626bc9b
MS
449}
450
451class UIMapping extends UIWindow {
452
453 private static final String MAP_MODE_ALL = "ALL";
454 private static final String MAP_MODE_CHANNEL = "CHNL";
455 private static final String MAP_MODE_CUBE = "CUBE";
456
457 private static final String CUBE_MODE_ALL = "ALL";
458 private static final String CUBE_MODE_STRIP = "SNGL";
459 private static final String CUBE_MODE_PATTERN = "PTRN";
460
461 private final MappingTool mappingTool;
462
463 private final UIIntegerBox channelBox;
464 private final UIIntegerBox cubeBox;
465 private final UIIntegerBox stripBox;
466
467 UIMapping(MappingTool tool, float x, float y, float w, float h) {
4e6626a9 468 super(lx.ui, "MAPPING", x, y, w, h);
d626bc9b
MS
469 mappingTool = tool;
470
4e6626a9 471 int yp = UIWindow.TITLE_LABEL_HEIGHT;
78a44a1b 472 new UIToggleSet(4, yp, w-10, 20) {
d626bc9b
MS
473 protected void onToggle(String value) {
474 if (value == MAP_MODE_ALL) mappingTool.mappingMode = mappingTool.MAPPING_MODE_ALL;
475 else if (value == MAP_MODE_CHANNEL) mappingTool.mappingMode = mappingTool.MAPPING_MODE_CHANNEL;
476 else if (value == MAP_MODE_CUBE) mappingTool.mappingMode = mappingTool.MAPPING_MODE_SINGLE_CUBE;
477 }
478 }.setOptions(new String[] { MAP_MODE_ALL, MAP_MODE_CHANNEL, MAP_MODE_CUBE }).addToContainer(this);
479 yp += 24;
78a44a1b 480 new UILabel(4, yp+8, w-10, 20).setLabel("CHANNEL ID").addToContainer(this);
d626bc9b 481 yp += 24;
78a44a1b 482 (channelBox = new UIIntegerBox(4, yp, w-10, 20) {
d626bc9b
MS
483 protected void onValueChange(int value) {
484 mappingTool.setChannel(value-1);
485 }
486 }).setRange(1, mappingTool.numChannels()).addToContainer(this);
487 yp += 24;
488
78a44a1b 489 new UILabel(4, yp+8, w-10, 20).setLabel("CUBE ID").addToContainer(this);
d626bc9b 490 yp += 24;
78a44a1b 491 (cubeBox = new UIIntegerBox(4, yp, w-10, 20) {
d626bc9b
MS
492 protected void onValueChange(int value) {
493 mappingTool.setCube(value-1);
494 }
b9b7b3d4 495 }).setRange(1, model.cubes.size()).addToContainer(this);
d626bc9b
MS
496 yp += 24;
497
a8d55ade
MS
498 yp += 10;
499
4e6626a9 500 new UIScrollList(1, yp, w-2, 60).setItems(Arrays.asList(new UIScrollList.Item[] {
d626bc9b
MS
501 new ColorScrollItem(ColorScrollItem.COLOR_RED),
502 new ColorScrollItem(ColorScrollItem.COLOR_GREEN),
503 new ColorScrollItem(ColorScrollItem.COLOR_BLUE),
504 })).addToContainer(this);
505 yp += 64;
506
78a44a1b 507 new UILabel(4, yp+8, w-10, 20).setLabel("STRIP MODE").addToContainer(this);
d626bc9b
MS
508 yp += 24;
509
78a44a1b 510 new UIToggleSet(4, yp, w-10, 20) {
d626bc9b
MS
511 protected void onToggle(String value) {
512 if (value == CUBE_MODE_ALL) mappingTool.cubeMode = mappingTool.CUBE_MODE_ALL;
513 else if (value == CUBE_MODE_STRIP) mappingTool.cubeMode = mappingTool.CUBE_MODE_SINGLE_STRIP;
514 else if (value == CUBE_MODE_PATTERN) mappingTool.cubeMode = mappingTool.CUBE_MODE_STRIP_PATTERN;
515 }
516 }.setOptions(new String[] { CUBE_MODE_ALL, CUBE_MODE_STRIP, CUBE_MODE_PATTERN }).addToContainer(this);
517
518 yp += 24;
78a44a1b 519 new UILabel(4, yp+8, w-10, 20).setLabel("STRIP ID").addToContainer(this);
d626bc9b
MS
520
521 yp += 24;
78a44a1b 522 (stripBox = new UIIntegerBox(4, yp, w-10, 20) {
d626bc9b
MS
523 protected void onValueChange(int value) {
524 mappingTool.setStrip(value-1);
525 }
526 }).setRange(1, Cube.STRIPS_PER_CUBE).addToContainer(this);
527
528 }
529
530 public void setChannelID(int value) {
531 channelBox.setValue(value);
532 }
533
534 public void setCubeID(int value) {
535 cubeBox.setValue(value);
536 }
537
538 public void setStripID(int value) {
539 stripBox.setValue(value);
540 }
541
4e6626a9 542 class ColorScrollItem extends UIScrollList.AbstractItem {
d626bc9b
MS
543
544 public static final int COLOR_RED = 1;
545 public static final int COLOR_GREEN = 2;
546 public static final int COLOR_BLUE = 3;
547
548 private final int colorChannel;
549
550 ColorScrollItem(int colorChannel) {
551 this.colorChannel = colorChannel;
552 }
553
554 public String getLabel() {
555 switch (colorChannel) {
556 case COLOR_RED: return "Red";
557 case COLOR_GREEN: return "Green";
558 case COLOR_BLUE: return "Blue";
559 }
560 return "";
561 }
562
563 public boolean isSelected() {
564 switch (colorChannel) {
565 case COLOR_RED: return mappingTool.channelModeRed;
566 case COLOR_GREEN: return mappingTool.channelModeGreen;
567 case COLOR_BLUE: return mappingTool.channelModeBlue;
568 }
569 return false;
570 }
571
a8d55ade 572 public void onMousePressed() {
d626bc9b
MS
573 switch (colorChannel) {
574 case COLOR_RED: mappingTool.channelModeRed = !mappingTool.channelModeRed; break;
575 case COLOR_GREEN: mappingTool.channelModeGreen = !mappingTool.channelModeGreen; break;
576 case COLOR_BLUE: mappingTool.channelModeBlue = !mappingTool.channelModeBlue; break;
577 }
578 }
579 }
580}
581
582class UIDebugText extends UIContext {
583
584 private String line1 = "";
585 private String line2 = "";
586
587 UIDebugText(float x, float y, float w, float h) {
4e6626a9 588 super(lx.ui, x, y, w, h);
d626bc9b
MS
589 }
590
591 public UIDebugText setText(String line1) {
592 return setText(line1, "");
593 }
594
595 public UIDebugText setText(String line1, String line2) {
596 if (!line1.equals(this.line1) || !line2.equals(this.line2)) {
597 this.line1 = line1;
598 this.line2 = line2;
599 setVisible(line1.length() + line2.length() > 0);
600 redraw();
601 }
602 return this;
603 }
604
4e6626a9
MS
605 protected void onDraw(UI ui, PGraphics pg) {
606 super.onDraw(ui, pg);
d626bc9b
MS
607 if (line1.length() + line2.length() > 0) {
608 pg.noStroke();
609 pg.fill(#444444);
4e6626a9
MS
610 pg.rect(0, 0, width, height);
611 pg.textFont(ui.getItemFont());
a8d55ade 612 pg.textSize(10);
d626bc9b
MS
613 pg.textAlign(LEFT, TOP);
614 pg.fill(#cccccc);
615 pg.text(line1, 4, 4);
616 pg.text(line2, 4, 24);
617 }
618 }
619}
620
34327c96 621class UISpeed extends UIWindow {
fa4f822d
MS
622
623 final BasicParameter speed;
624
34327c96 625 UISpeed(float x, float y, float w, float h) {
4e6626a9 626 super(lx.ui, "SPEED", x, y, w, h);
fa4f822d 627 speed = new BasicParameter("SPEED", 0.5);
4e6626a9 628 speed.addListener(new LXParameterListener() {
34327c96
MS
629 public void onParameterChanged(LXParameter parameter) {
630 lx.setSpeed(parameter.getValuef() * 2);
631 }
4e6626a9
MS
632 });
633 new UISlider(4, UIWindow.TITLE_LABEL_HEIGHT, w-10, 20).setParameter(speed).addToContainer(this);
34327c96
MS
634 }
635}
636
a8d55ade
MS
637class UIMidi extends UIWindow {
638
9692dc7b
MS
639 private final UIToggleSet deckMode;
640 private final UIButton logMode;
a8d55ade 641
d6ac1ee8 642 UIMidi(final MidiEngine midiEngine, float x, float y, float w, float h) {
4e6626a9 643 super(lx.ui, "MIDI", x, y, w, h);
d6ac1ee8 644
a8d55ade 645 // Processing compiler doesn't seem to get that list of class objects also conform to interface
4e6626a9 646 List<UIScrollList.Item> scrollItems = new ArrayList<UIScrollList.Item>();
d6ac1ee8 647 for (SCMidiInput mc : midiEngine.getControllers()) {
30bf6510 648 scrollItems.add(mc);
a8d55ade 649 }
30bf6510 650 final UIScrollList scrollList;
4e6626a9 651 (scrollList = new UIScrollList(1, UIWindow.TITLE_LABEL_HEIGHT, w-2, 100)).setItems(scrollItems).addToContainer(this);
d6ac1ee8
MS
652 (deckMode = new UIToggleSet(4, 130, 90, 20) {
653 protected void onToggle(String value) {
654 midiEngine.setFocusedDeck(value == "A" ? 0 : 1);
655 }
656 }).setOptions(new String[] { "A", "B" }).addToContainer(this);
4df91daf 657 (logMode = new UIButton(98, 130, w-103, 20)).setLabel("LOG").addToContainer(this);
30bf6510
MS
658
659 SCMidiInputListener listener = new SCMidiInputListener() {
660 public void onEnabled(SCMidiInput controller, boolean enabled) {
661 scrollList.redraw();
662 }
663 };
d6ac1ee8 664 for (SCMidiInput mc : midiEngine.getControllers()) {
30bf6510
MS
665 mc.addListener(listener);
666 }
d6ac1ee8
MS
667
668 midiEngine.addListener(new MidiEngineListener() {
669 public void onFocusedDeck(int deckIndex) {
670 deckMode.setValue(deckIndex == 0 ? "A" : "B");
671 }
672 });
30bf6510 673
9692dc7b
MS
674 }
675
676 public boolean logMidi() {
677 return logMode.isActive();
a8d55ade
MS
678 }
679
42a424d7 680 public LXDeck getFocusedDeck() {
0c7bfdb5 681 return lx.engine.getDeck(deckMode.getValue() == "A" ? LEFT_DECK : RIGHT_DECK);
a8d55ade
MS
682 }
683}
684
d626bc9b
MS
685String className(Object p, String suffix) {
686 String s = p.getClass().getName();
687 int li;
688 if ((li = s.lastIndexOf(".")) > 0) {
689 s = s.substring(li + 1);
690 }
691 if (s.indexOf("SugarCubes$") == 0) {
692 s = s.substring("SugarCubes$".length());
693 }
694 if ((suffix != null) && ((li = s.indexOf(suffix)) != -1)) {
695 s = s.substring(0, li);
696 }
697 return s;
698}