redo with new anti-GLucose
authorBen Morrow <childoftv@gmail.com>
Mon, 3 Mar 2014 06:02:04 +0000 (22:02 -0800)
committerBen Morrow <childoftv@gmail.com>
Mon, 3 Mar 2014 06:02:04 +0000 (22:02 -0800)
43 files changed:
AlexGreen.pde
AlexGreen.pde.orig [deleted file]
AntonK.pde
ArjunBanker.pde
BenMorrow.pde
DanHorwitz.pde
DanKaminsky.pde
DanUtil.pde
DebugUI.pde [deleted file]
GranimPattern.pde
Grizzly.pde [new file with mode: 0644]
Internals.pde
JR.pde
JackStahl.pde
JackieBavaro.pde
L8onWallace.pde
MIDI.pde
Mappings.pde
MarkSlee.pde
Model.pde [new file with mode: 0644]
PandaDriver.pde [deleted file]
SamMorrow.pde
ShaheenGandhi.pde
SugarCubes.pde
SugarCubes.pde.orig [deleted file]
TestPatterns.pde
TimBavaro.pde
TobySegaran.pde
UIFramework.pde [deleted file]
UIImplementation.pde
VincentSiao.pde
build-tmp/source/SugarCubes.java [deleted file]
code/GLucose.jar [deleted file]
code/HeronLX.jar
code/JGraphT.jar [new file with mode: 0644]
code/oscP5.jar [deleted file]
libraries/HeronLX.jar [new file with mode: 0755]
libraries/JGraphT.jar [new file with mode: 0644]
libraries/ScreenShot.dll [new file with mode: 0755]
libraries/ScreenShot.jar [new file with mode: 0755]
libraries/rwmidi.jar [new file with mode: 0755]
libraries/toxiclibscore.jar [new file with mode: 0755]
sketch.properties [new file with mode: 0644]

index 3e164d8bff34509891657cf09d585d69026c3f8a..5a35b3e31bc24edb50b352d2d69d198569220436 100644 (file)
@@ -1,3 +1,4 @@
+
 class SineSphere extends APat {
   float modelrad = sqrt((model.xMax)*(model.xMax) + (model.yMax)*(model.yMax) + (model.zMax)*(model.zMax));
   private BasicParameter yrotspeed = new BasicParameter("yspeed", 3000, 1, 10000);
@@ -11,15 +12,15 @@ class SineSphere extends APat {
   public BasicParameter widthparameter= new BasicParameter("Width", 20, 1, 60);
   public BasicParameter vibration_magnitude = new BasicParameter("Vmag", 20, 2, modelrad/2);
   public BasicParameter scale = new BasicParameter("Scale", 1, .1, 5);
-  private int pitch = 0; 
-  private int channel = 0; 
-  private int velocity = 0; 
-  private int cur = 0; 
-  public final LXProjection sinespin; 
+  private int pitch = 0;
+  private int channel = 0;
+  private int velocity = 0;
+  private int cur = 0;
+  public final LXProjection sinespin;
   public final LXProjection sinespin2;
   public final LXProjection sinespin3;
  
-  Pick Galaxy, STime; 
+  Pick Galaxy, STime;
 
   public BasicParameter rotationx = new BasicParameter("rotx", 0, 0, 1 );
   public BasicParameter rotationy = new BasicParameter("roty", 1, 0, 1);
@@ -29,8 +30,8 @@ class SineSphere extends APat {
 
   class Sphery {
   float f1xcenter, f1ycenter, f1zcenter, f2xcenter , f2ycenter, f2zcenter; //second three are for an ellipse with two foci
-  private  SinLFO vibration; 
-  private  SinLFO surfacewave;
+  private SinLFO vibration;
+  private SinLFO surfacewave;
 
   private SinLFO xbounce;
   public SinLFO ybounce;
@@ -43,22 +44,22 @@ class SineSphere extends APat {
   public BasicParameter vibrationrate;
   public final PVector circlecenter;
  
-  public Sphery(float f1xcenter, float f1ycenter, float f1zcenter, float radius, float vibration_magnitude , float vperiod) 
+  public Sphery(float f1xcenter, float f1ycenter, float f1zcenter, float radius, float vibration_magnitude , float vperiod)
   {
    this.f1xcenter = f1xcenter;
    this.f1ycenter = f1ycenter;
    this.f1zcenter = f1zcenter;
-   this.radius = radius; 
+   this.radius = radius;
    this.circlecenter= new PVector(f1xcenter,f1ycenter,f1zcenter);
 
    this.vibration_magnitude = vibration_magnitude;
    
    this.vperiod = vperiod;
    //addParameter(bounceamp = new BasicParameter("Amp", .5));
-   //addParameter(bouncerate = new BasicParameter("Rate", .5));  //ybounce.modulateDurationBy(bouncerate);
+   //addParameter(bouncerate = new BasicParameter("Rate", .5)); //ybounce.modulateDurationBy(bouncerate);
    //addParameter(vibrationrate = new BasicParameter("vibration", 1000, 10000));
     //addParameter(widthparameter = new BasicParameter("Width", .2));
-     //addModulator(xbounce = new SinLFO(model.xMax/3, 2*model.yMax/3, 2000)).trigger(); 
+     //addModulator(xbounce = new SinLFO(model.xMax/3, 2*model.yMax/3, 2000)).trigger();
    addModulator(ybounce= new SinLFO(model.yMax/3, 2*model.yMax/3, 240000)).trigger(); //bounce.modulateDurationBy
     
    //addModulator(bounceamp); //ybounce.setMagnitude(bouncerate);
@@ -67,44 +68,44 @@ class SineSphere extends APat {
       
   }
 
-  //  public Sphery(float f1xcenter, float f1ycenter, float f1zcenter, float vibration_magnitude, float vperiod) 
+  // public Sphery(float f1xcenter, float f1ycenter, float f1zcenter, float vibration_magnitude, float vperiod)
   // {
-  //  this.f1xcenter = f1xcenter;
-  //  this.f1ycenter = f1ycenter;
-  //  this.f1zcenter = f1zcenter;
-  //  this.vibration_magnitude = vibration_magnitude;
+  // this.f1xcenter = f1xcenter;
+  // this.f1ycenter = f1ycenter;
+  // this.f1zcenter = f1zcenter;
+  // this.vibration_magnitude = vibration_magnitude;
   // this.vperiod = vperiod;
-  //  addModulator(ybounce= new SinLFO(model.yMax/3, 2*model.yMax/3, 240000)).trigger(); //bounce.modulateDurationBy
-  //   addModulator( vibration = new SinLFO( modelrad/10 - vibration_magnitude , modelrad/10 + vibration_magnitude, vperiod)).trigger(); //vibration.setPeriod(240000/lx.tempo.bpm());
+  // addModulator(ybounce= new SinLFO(model.yMax/3, 2*model.yMax/3, 240000)).trigger(); //bounce.modulateDurationBy
+  // addModulator( vibration = new SinLFO( modelrad/10 - vibration_magnitude , modelrad/10 + vibration_magnitude, vperiod)).trigger(); //vibration.setPeriod(240000/lx.tempo.bpm());
       
   // }
 
   //for an ellipse
-//  public Sphery(float f1xcenter, float f1ycenter, float f1zcenter, float f2xcenter, float f2ycenter, float f2zcenter, 
-//   float vibration_min, float vibration_max, float vperiod)  
+// public Sphery(float f1xcenter, float f1ycenter, float f1zcenter, float f2xcenter, float f2ycenter, float f2zcenter,
+// float vibration_min, float vibration_max, float vperiod)
  
-//  {
-//     this.f1xcenter = f1xcenter;
-//    this.f1ycenter = f1ycenter;
-//    this.f1zcenter = f1zcenter;
-//    this.f2xcenter = f2xcenter;
-//    this.f2ycenter = f2ycenter;
-//    this.f2zcenter = f2zcenter;
-//    this.vibration_min = vibration_min;
-//    this.vibration_max = vibration_max;
-//    this.vperiod = vperiod;
-//    //addModulator(xbounce = new SinLFO(model.xMax/3, 2*model.yMax/3, 2000)).trigger(); 
-//    addModulator(ybounce).trigger(); 
-//    addModulator( vibration = new SinLFO(vibration_min , vibration_max, lx.tempo.rampf())).trigger(); //vibration.modulateDurationBy(vx);
-//    addParameter(widthparameter = new BasicParameter("Width", .1));
-//    //addParameter(huespread = new BasicParameter("bonk", .2));
+// {
+// this.f1xcenter = f1xcenter;
+// this.f1ycenter = f1ycenter;
+// this.f1zcenter = f1zcenter;
+// this.f2xcenter = f2xcenter;
+// this.f2ycenter = f2ycenter;
+// this.f2zcenter = f2zcenter;
+// this.vibration_min = vibration_min;
+// this.vibration_max = vibration_max;
+// this.vperiod = vperiod;
+// //addModulator(xbounce = new SinLFO(model.xMax/3, 2*model.yMax/3, 2000)).trigger();
+// addModulator(ybounce).trigger();
+// addModulator( vibration = new SinLFO(vibration_min , vibration_max, lx.tempo.rampf())).trigger(); //vibration.modulateDurationBy(vx);
+// addParameter(widthparameter = new BasicParameter("Width", .1));
+// //addParameter(huespread = new BasicParameter("bonk", .2));
   
 // }
  
-public int     c1c    (float a)              { return round(100*constrain(a,0,1));               }
+public int c1c (float a) { return round(100*constrain(a,0,1)); }
 
 void setVibrationPeriod(double period){
-// to-do:  make this conditional upon time signature
+// to-do: make this conditional upon time signature
 
 this.vibration.setPeriod(period);
 }
@@ -116,33 +117,33 @@ this.vibration.setRange(-mag,mag);
 }
 
 
-float distfromcirclecenter(float px, float py, float pz, float f1x, float f1y, float f1z) 
+float distfromcirclecenter(float px, float py, float pz, float f1x, float f1y, float f1z)
 {
    return dist(px, py, pz, f1x, f1y, f1z);
     }
  //void updatespherey(deltaMs, )
 
  float quadrant(PVector q) {
-   float qtheta = atan2(  (q.x-f1xcenter) , (q.z - f1zcenter) ); 
-   float qphi = acos( (q.z-f1zcenter)/(PVector.dist(q,circlecenter)) );  
+   float qtheta = atan2( (q.x-f1xcenter) , (q.z - f1zcenter) );
+   float qphi = acos( (q.z-f1zcenter)/(PVector.dist(q,circlecenter)) );
 
 
     return map(qtheta, -PI/2, PI/2, 200-huespread.getValuef(), 240+huespread.getValuef());
   //if (q.x > f1xcenter ) {return 140 ;}
-    //else  {return 250;}  
+    //else {return 250;}
  }
 
  // float noisesat(PVector q) {
    
 
- //  return noise()
+ // return noise()
 
  // }
  color spheryvalue (PVector p) {
-   circlecenter.set(this.f1xcenter, this.f1ycenter, this.f1zcenter); 
+   circlecenter.set(this.f1xcenter, this.f1ycenter, this.f1zcenter);
 
   
-//switch(sShpape.cur() ) {}  
+//switch(sShpape.cur() ) {}
 
    float b = max(0, 100 - widthparameter.getValuef()*abs(p.dist(circlecenter)
       - vibration.getValuef()) );
@@ -156,49 +157,49 @@ float distfromcirclecenter(float px, float py, float pz, float f1x, float f1y, f
      // constrain(100*noise(quadrant(p)), 0, 100),
      100,
       b
-   ); 
+   );
  }
  color ellipsevalue(float px, float py, float pz , float f1xc, float f1yc, float f1zc, float f2xc, float f2yc, float f2zc)
   {
-//switch(sShpape.cur() ) {}  
-   return lx.hsb(huespread.getValuef()*5*px, dist(model.xMax-px, model.yMax-py, model.zMax-pz, f1xc, f1yc, f1zc) , 
+//switch(sShpape.cur() ) {}
+   return lx.hsb(huespread.getValuef()*5*px, dist(model.xMax-px, model.yMax-py, model.zMax-pz, f1xc, f1yc, f1zc) ,
     max(0, 100 - 100*widthparameter.getValuef() *
-      abs( (dist(px, py, pz, f1xc, ybounce.getValuef(), f1zc) + 
-        (dist(px, py , pz, f2xc, ybounce.getValuef(), f2zc) ) )/2  
-      - 1.2*vibration.getValuef() ) ) ) ; 
+      abs( (dist(px, py, pz, f1xc, ybounce.getValuef(), f1zc) +
+        (dist(px, py , pz, f2xc, ybounce.getValuef(), f2zc) ) )/2
+      - 1.2*vibration.getValuef() ) ) ) ;
   }
 
   
-}  
+}
 
 boolean noteOn(Note note) {
     int row = note.getPitch(), col = note.getChannel();
-  //  if (row == 57) {KeyPressed = col; return true; }
+  // if (row == 57) {KeyPressed = col; return true; }
     return super.noteOn(note);
   }
 
 
-// public boolean noteOn(Note note)  {
-// pitch= note.getPitch();  
+// public boolean noteOn(Note note) {
+// pitch= note.getPitch();
 // velocity=note.getVelocity();
 // channel=note.getChannel();
 // return true;
 // }
 
 // public boolean gridPressed(int row, int col) {
-//  pitch = row; channel = col; 
-//  cur = NumApcCols*(pitch-53)+col; 
-// //setState(row, col, 0 ? 1 : 0); 
+// pitch = row; channel = col;
+// cur = NumApcCols*(pitch-53)+col;
+// //setState(row, col, 0 ? 1 : 0);
 // return true;
 // }
 
 //public grid
 final Sphery[] spherys;
  
-  SineSphere(GLucose glucose) 
+  SineSphere(LX lx)
   {
-    super(glucose);
-    println("modelrad  " + modelrad);   
+    super(lx);
+    println("modelrad " + modelrad);
     sinespin = new LXProjection(model);
     sinespin2 = new LXProjection(model);
     sinespin3= new LXProjection(model);
@@ -214,7 +215,7 @@ final Sphery[] spherys;
     addParameter(vibration_magnitude);
     addParameter(scale);
     addModulator(yrot).trigger();
-    addModulator(yrot2).trigger(); 
+    addModulator(yrot2).trigger();
     addModulator(yrot3).trigger();
     //Galaxy = addPick("Galaxy", 1, 3, new String[] {"home", "vertical","single","aquarium"});
     STime =addPick("Time", 1, 4, new String[]{"half", "triplet", "beat", "2x", "3x" });
@@ -222,47 +223,36 @@ final Sphery[] spherys;
     spherys = new Sphery[] {
     new Sphery(model.xMax/4, model.yMax/2, model.zMax/2, modelrad/12, modelrad/25, 3000),
     new Sphery(.75*model.xMax, model.yMax/2, model.zMax/2, modelrad/14, modelrad/28, 2000),
-    new Sphery(model.cx, model.cy, model.cz,  modelrad/5, modelrad/15, 2300),
+    new Sphery(model.cx, model.cy, model.cz, modelrad/5, modelrad/15, 2300),
     new Sphery(.7*model.xMax, .65*model.yMax, .5*model.zMax, modelrad/11, modelrad/25, 3500),
     new Sphery(.75*model.xMax, .8*model.yMax, .7*model.zMax, modelrad/12, modelrad/30, 2000)
     
-            
-
-
-
-      // new Sphery(model.xMax/4, model.yMax/2, model.zMax/2, modelrad/16, modelrad/8, 3000),
-      // new Sphery(.75*model.xMax, model.yMax/2, model.zMax/2, modelrad/20, modelrad/10, 2000),
-      // new Sphery(model.xMax/2, model.yMax/2, model.zMax/2,  modelrad/4, modelrad/8, 2300),
-
-      // new Sphery(.7*model.xMax, .65*model.yMax, .5*model.zMax, modelrad/14, modelrad/7, 3500),
-      // new Sphery(.75*model.xMax, .8*model.yMax, .7*model.zMax, modelrad/20, modelrad/10, 2000),
-      // new Sphery(model.xMax/2, model.yMax/2, model.zMax/2,  modelrad/4, modelrad/8, 2300),
-      
-    };  
+          
+    };
   }
 
 // public void onParameterChanged(LXParameter parameter)
 // {
 
 
-//     for (Sphery s : spherys) {
-//       if (s == null) continue;
-//       double bampv = s.bounceamp.getValue();
-//       double brv = s.bouncerate.getValue();
-//       double tempobounce = lx.tempo.bpm();
-//       if (parameter == s.bounceamp) 
-//       {
-//         s.ybounce.setRange(bampv*model.yMax/3 , bampv*2*model.yMax/3, brv);
-//       }
-//       else if ( parameter == s.bouncerate )   
-//       {
-//         s.ybounce.setDuration(120000./tempobounce);
-//       }
-//     }
-//   }
+// for (Sphery s : spherys) {
+// if (s == null) continue;
+// double bampv = s.bounceamp.getValue();
+// double brv = s.bouncerate.getValue();
+// double tempobounce = lx.tempo.bpm();
+// if (parameter == s.bounceamp)
+// {
+// s.ybounce.setRange(bampv*model.yMax/3 , bampv*2*model.yMax/3, brv);
+// }
+// else if ( parameter == s.bouncerate )
+// {
+// s.ybounce.setDuration(120000./tempobounce);
+// }
+// }
+// }
 
     public void run( double deltaMs) {
-     float  t = lx.tempo.rampf();
+     float t = lx.tempo.rampf();
      float bpm = lx.tempo.bpmf();
      float scalevalue = scale.getValuef();
      int spherytime= STime.Cur();
@@ -270,28 +260,26 @@ final Sphery[] spherys;
      
      switch (spherytime) {
 
-     case 0: t = map(.5*t ,0,.5, 0,1);   bpm = .5*bpm;  break;
+     case 0: t = map(.5*t ,0,.5, 0,1); bpm = .5*bpm; break;
 
-     case 1: t = t;   bpm = bpm;   break;
+     case 1: t = t; bpm = bpm; break;
 
-     case 2: t = map(2*t,0,2,0,1);  bpm = 2*bpm; break;
+     case 2: t = map(2*t,0,2,0,1); bpm = 2*bpm; break;
 
-     default: t= t;   bpm = bpm; 
+     default: t= t; bpm = bpm;
      }
 
      //switch(sphery.colorscheme)
         
       for ( Sphery s: spherys){
-      
-      //s.vibration.setBasis(t);
       s.setVibrationPeriod(vibrationrate.getValuef());
-    //  s.setVibrationMagnitude(vibration_magnitude.getValuef());
+    // s.setVibrationMagnitude(vibration_magnitude.getValuef());
      
        }
       
 
       sinespin.reset()
-      // Translate so the center of the car is the origin, offset 
+      // Translate so the center of the car is the origin, offset
       .center()
        .scale(scalevalue, scalevalue, scalevalue)
       // Rotate around the origin (now the center of the car) about an y-vector
@@ -324,21 +312,21 @@ final Sphery[] spherys;
    .translate(model.cx,model.cy,model.cz);
 
     for (LXVector p: sinespin2)
-    {   color c = 0;
+    { color c = 0;
       // PVector P = new PVector(p.x, p.y, p.z);
         P.set(p.x, p.y, p.z);
         c = blendIfColor(c, spherys[3].spheryvalue(P),ADD);
          
         colors[p.index] = blendIfColor(colors[p.index], c , ADD);
 
-    }  
+    }
     sinespin3.reset()
     .center()
     .scale(scalevalue,scalevalue,scalevalue)
     .rotate(yrot3.getValuef(),-1 + rotationx.getValuef(), rotationy.getValuef(), rotationz.getValuef())
     .translate(model.cx, model.cy, model.cz);
    for (LXVector p: sinespin3)
-    {   color c = 0;
+    { color c = 0;
       // PVector P = new PVector(p.x, p.y, p.z);
         P.set(p.x, p.y, p.z);
         c = blendIfColor(c, spherys[4].spheryvalue(P),ADD);
@@ -363,116 +351,116 @@ final Sphery[] spherys;
   }
   
 
-      //   color c = 0;
-      //   c = blendColor(c, spherys[3].ellipsevalue(Px.x, Px.y, Px.z, model.xMax/4, model.yMax/4, model.zMax/4, 3*model.xMax/4, 3*model.yMax/4, 3*model.zMax/4),ADD);
-      //   return c; 
+      // color c = 0;
+      // c = blendColor(c, spherys[3].ellipsevalue(Px.x, Px.y, Px.z, model.xMax/4, model.yMax/4, model.zMax/4, 3*model.xMax/4, 3*model.yMax/4, 3*model.zMax/4),ADD);
+      // return c;
       // }
       // return lx.hsb(0,0,0);
-      //  // else if(spheremode ==2)
+      // // else if(spheremode ==2)
        // { color c = 0;
-       //   return lx.hsb(CalcCone( (xyz by = new xyz(0,spherys[2].ybounce.getValuef(),0) ), Px, mid) );
+       // return lx.hsb(CalcCone( (xyz by = new xyz(0,spherys[2].ybounce.getValuef(),0) ), Px, mid) );
 
        // }
 
   
-       //   } 
+       // }
         
   }
 /*This just takes all of Dan Horwitz's code that I want to inherit and leaves the rest behind.
- A work in progress. */
+A work in progress. */
 
 public class APat extends SCPattern
 
 
 {
-  ArrayList<Pick>   picks  = new ArrayList<Pick>  ();
-  ArrayList<DBool>  bools  = new ArrayList<DBool> ();
-
-  PVector   mMax, mCtr, mHalf;
-
-  MidiOutput  APCOut;
-  int     nMaxRow   = 53;
-  float   LastJog = -1;
-  float[]   xWaveNz, yWaveNz;
-  int     nPoint  , nPoints;
-  PVector   xyzJog = new PVector(), modmin;
-
-  float     NoiseMove = random(10000);
-  BasicParameter  pSpark, pWave, pRotX, pRotY, pRotZ, pSpin, pTransX, pTransY;
-  DBool     pXsym, pYsym, pRsym, pXdup, pXtrip, pJog, pGrey;
-
-  float   lxh   ()                  { return lx.getBaseHuef();                      }
-  int     c1c    (float a)              { return round(100*constrain(a,0,1));               }
-  float     interpWv(float i, float[] vals)       { return interp(i-floor(i), vals[floor(i)], vals[ceil(i)]);     }
-  void    setNorm (PVector vec)           { vec.set(vec.x/mMax.x, vec.y/mMax.y, vec.z/mMax.z);        }
-  void    setRand (PVector vec)           { vec.set(random(mMax.x), random(mMax.y), random(mMax.z));      }
-  void    setVec  (PVector vec, LXPoint p)        { vec.set(p.x, p.y, p.z);                       }
-  void    interpolate(float i, PVector a, PVector b)  { a.set(interp(i,a.x,b.x), interp(i,a.y,b.y), interp(i,a.z,b.z));   }
-  //void      StartRun(double deltaMs)          { }
-  float     val   (BasicParameter p)          { return p.getValuef();                       }
-  //color   CalcPoint(PVector p)            { return lx.hsb(0,0,0);                       }
-  color   blend3(color c1, color c2, color c3)    { return blendColor(c1,blendColor(c2,c3,ADD),ADD);          }
-
-  void  rotateZ (PVector p, PVector o, float nSin, float nCos) { p.set(    nCos*(p.x-o.x) - nSin*(p.y-o.y) + o.x    , nSin*(p.x-o.x) + nCos*(p.y-o.y) + o.y,p.z); }
-  void  rotateX (PVector p, PVector o, float nSin, float nCos) { p.set(p.x,nCos*(p.y-o.y) - nSin*(p.z-o.z) + o.y    , nSin*(p.y-o.y) + nCos*(p.z-o.z) + o.z    ); }
-  void  rotateY (PVector p, PVector o, float nSin, float nCos) { p.set(    nSin*(p.z-o.z) + nCos*(p.x-o.x) + o.x,p.y, nCos*(p.z-o.z) - nSin*(p.x-o.x) + o.z    ); }
-
-  BasicParameter  addParam(String label, double value)  { BasicParameter p = new BasicParameter(label, value); addParameter(p); return p; }
-
-  PVector   vT1 = new PVector(), vT2 = new PVector();
-  float     calcCone (PVector v1, PVector v2, PVector c)  { vT1.set(v1); vT2.set(v2); vT1.sub(c); vT2.sub(c);
+  ArrayList<Pick> picks = new ArrayList<Pick> ();
+  ArrayList<DBool> bools = new ArrayList<DBool> ();
+
+  PVector mMax, mCtr, mHalf;
+
+  MidiOutput APCOut;
+  int nMaxRow = 53;
+  float LastJog = -1;
+  float[] xWaveNz, yWaveNz;
+  int nPoint , nPoints;
+  PVector xyzJog = new PVector(), modmin;
+
+  float NoiseMove = random(10000);
+  BasicParameter pSpark, pWave, pRotX, pRotY, pRotZ, pSpin, pTransX, pTransY;
+  DBool pXsym, pYsym, pRsym, pXdup, pXtrip, pJog, pGrey;
+
+  float lxh () { return lx.getBaseHuef(); }
+  int c1c (float a) { return round(100*constrain(a,0,1)); }
+  float interpWv(float i, float[] vals) { return interp(i-floor(i), vals[floor(i)], vals[ceil(i)]); }
+  void setNorm (PVector vec) { vec.set(vec.x/mMax.x, vec.y/mMax.y, vec.z/mMax.z); }
+  void setRand (PVector vec) { vec.set(random(mMax.x), random(mMax.y), random(mMax.z)); }
+  void setVec (PVector vec, LXPoint p) { vec.set(p.x, p.y, p.z); }
+  void interpolate(float i, PVector a, PVector b) { a.set(interp(i,a.x,b.x), interp(i,a.y,b.y), interp(i,a.z,b.z)); }
+  void StartRun(double deltaMs) { }
+  float val (BasicParameter p) { return p.getValuef(); }
+  color CalcPoint(PVector p) { return lx.hsb(0,0,0); }
+  color blend3(color c1, color c2, color c3) { return blendColor(c1,blendColor(c2,c3,ADD),ADD); }
+
+  void rotateZ (PVector p, PVector o, float nSin, float nCos) { p.set( nCos*(p.x-o.x) - nSin*(p.y-o.y) + o.x , nSin*(p.x-o.x) + nCos*(p.y-o.y) + o.y,p.z); }
+  void rotateX (PVector p, PVector o, float nSin, float nCos) { p.set(p.x,nCos*(p.y-o.y) - nSin*(p.z-o.z) + o.y , nSin*(p.y-o.y) + nCos*(p.z-o.z) + o.z ); }
+  void rotateY (PVector p, PVector o, float nSin, float nCos) { p.set( nSin*(p.z-o.z) + nCos*(p.x-o.x) + o.x,p.y, nCos*(p.z-o.z) - nSin*(p.x-o.x) + o.z ); }
+
+  BasicParameter addParam(String label, double value) { BasicParameter p = new BasicParameter(label, value); addParameter(p); return p; }
+
+  PVector vT1 = new PVector(), vT2 = new PVector();
+  float calcCone (PVector v1, PVector v2, PVector c) { vT1.set(v1); vT2.set(v2); vT1.sub(c); vT2.sub(c);
                                   return degrees(PVector.angleBetween(vT1,vT2)); }
 
-  Pick    addPick(String name, int def, int _max, String[] desc) {
-    Pick P    = new Pick(name, def, _max+1, nMaxRow, desc); 
-    nMaxRow   = P.EndRow + 1;
+  Pick addPick(String name, int def, int _max, String[] desc) {
+    Pick P = new Pick(name, def, _max+1, nMaxRow, desc);
+    nMaxRow = P.EndRow + 1;
     picks.add(P);
     return P;
   }
 
-    boolean   noteOff(Note note) {
+    boolean noteOff(Note note) {
     int row = note.getPitch(), col = note.getChannel();
     for (int i=0; i<bools.size(); i++) if (bools.get(i).set(row, col, false)) { presetManager.dirty(this); return true; }
     updateLights(); return false;
   }
 
-    boolean   noteOn(Note note) {
+    boolean noteOn(Note note) {
     int row = note.getPitch(), col = note.getChannel();
-    for (int i=0; i<picks.size(); i++) if (picks.get(i).set(row, col))        { presetManager.dirty(this); return true; }
-    for (int i=0; i<bools.size(); i++) if (bools.get(i).set(row, col, true))  { presetManager.dirty(this); return true; }
-    println("row: " + row + "  col:   " + col); return false;
+    for (int i=0; i<picks.size(); i++) if (picks.get(i).set(row, col)) { presetManager.dirty(this); return true; }
+    for (int i=0; i<bools.size(); i++) if (bools.get(i).set(row, col, true)) { presetManager.dirty(this); return true; }
+    println("row: " + row + " col: " + col); return false;
   }
 
-  void    onInactive()      { uiDebugText.setText(""); }
-  void    onReset()         {
+  void onInactive() { uiDebugText.setText(""); }
+  void onReset() {
     for (int i=0; i<bools .size(); i++) bools.get(i).reset();
     for (int i=0; i<picks .size(); i++) picks.get(i).reset();
-    presetManager.dirty(this); 
-    updateLights(); 
+    presetManager.dirty(this);
+    updateLights();
   }
 
-  APat(GLucose glucose) {
-    super(glucose);
+  APat(LX lx) {
+    super(lx);
 
     
 
-    nPoints   = model.points.size();
-    pXsym     = new DBool("X-SYM", false, 48, 0); bools.add(pXsym );
-    pYsym     = new DBool("Y-SYM", false, 48, 1); bools.add(pYsym );
-    pRsym     = new DBool("R-SYM", false, 48, 2); bools.add(pRsym );
-    pXdup   = new DBool("X-DUP", false, 48, 3); bools.add(pXdup );
-    pJog    = new DBool("JOG"  , false, 48, 4); bools.add(pJog  );
-    pGrey   = new DBool("GREY" , false, 48, 5); bools.add(pGrey );
-
-    modmin    = new PVector(model.xMin, model.yMin, model.zMin);
-    mMax    =   new PVector(model.xMax, model.yMax, model.zMax); mMax.sub(modmin);
-    mCtr    =   new PVector(); mCtr.set(mMax); mCtr.mult(.5);
-    mHalf   =   new PVector(.5,.5,.5);
-    xWaveNz   = new float[ceil(mMax.y)+1];
-    yWaveNz   = new float[ceil(mMax.x)+1];
-
-    //println (model.xMin + " " + model.yMin + " " +  model.zMin);
-    //println (model.xMax + " " + model.yMax + " " +  model.zMax);
+    nPoints = model.points.size();
+    pXsym = new DBool("X-SYM", false, 48, 0); bools.add(pXsym );
+    pYsym = new DBool("Y-SYM", false, 48, 1); bools.add(pYsym );
+    pRsym = new DBool("R-SYM", false, 48, 2); bools.add(pRsym );
+    pXdup = new DBool("X-DUP", false, 48, 3); bools.add(pXdup );
+    pJog = new DBool("JOG" , false, 48, 4); bools.add(pJog );
+    pGrey = new DBool("GREY" , false, 48, 5); bools.add(pGrey );
+
+    modmin = new PVector(model.xMin, model.yMin, model.zMin);
+    mMax = new PVector(model.xMax, model.yMax, model.zMax); mMax.sub(modmin);
+    mCtr = new PVector(); mCtr.set(mMax); mCtr.mult(.5);
+    mHalf = new PVector(.5,.5,.5);
+    xWaveNz = new float[ceil(mMax.y)+1];
+    yWaveNz = new float[ceil(mMax.x)+1];
+
+    //println (model.xMin + " " + model.yMin + " " + model.zMin);
+    //println (model.xMax + " " + model.yMax + " " + model.zMax);
     //for (MidiOutputDevice o: RWMidi.getOutputDevices()) { if (o.toString().contains("APC")) { APCOut = o.createOutput(); break;}}
   }
 
@@ -491,11 +479,11 @@ public class APat extends SCPattern
   }
 
   void updateLights() { if (APCOut == null) return;
-      for (int i = 0; i < NumApcRows; ++i) 
-        for (int j = 0; j < 8; ++j)     APCOut.sendNoteOn(j, 53+i,  0);
-    for (int i=0; i<picks .size(); i++)   APCOut.sendNoteOn(picks.get(i).CurCol, picks.get(i).CurRow, 3);
-    for (int i=0; i<bools .size(); i++)   if (bools.get(i).b)   APCOut.sendNoteOn (bools.get(i).col, bools.get(i).row, 1);
-                        else          APCOut.sendNoteOff  (bools.get(i).col, bools.get(i).row, 0);
+      for (int i = 0; i < NumApcRows; ++i)
+        for (int j = 0; j < 8; ++j) APCOut.sendNoteOn(j, 53+i, 0);
+    for (int i=0; i<picks .size(); i++) APCOut.sendNoteOn(picks.get(i).CurCol, picks.get(i).CurRow, 3);
+    for (int i=0; i<bools .size(); i++) if (bools.get(i).b) APCOut.sendNoteOn (bools.get(i).col, bools.get(i).row, 1);
+                        else APCOut.sendNoteOff (bools.get(i).col, bools.get(i).row, 0);
   }
 
   void run(double deltaMs)
@@ -504,12 +492,52 @@ public class APat extends SCPattern
 
     if (this == midiEngine.getFocusedDeck().getActivePattern()) {
       String Text1="", Text2="";
-      for (int i=0; i<bools.size(); i++) if (bools.get(i).b) Text1 += " " + bools.get(i).tag       + "   ";
-      for (int i=0; i<picks.size(); i++) Text1 += picks.get(i).tag + ": " + picks.get(i).CurDesc() + "   ";
+      for (int i=0; i<bools.size(); i++) if (bools.get(i).b) Text1 += " " + bools.get(i).tag + " ";
+      for (int i=0; i<picks.size(); i++) Text1 += picks.get(i).tag + ": " + picks.get(i).CurDesc() + " ";
       uiDebugText.setText(Text1, Text2);
     }
 
-    
+   NoiseMove += deltaMs; NoiseMove = NoiseMove % 1e7;
+    StartRun (deltaMs);
+    PVector P = new PVector(), tP = new PVector(), pSave = new PVector();
+    PVector pTrans = new PVector(val(pTransX)*200-100, val(pTransY)*100-50,0);
+    nPoint = 0;
+
+    if (pJog.b) {
+      float tRamp = (lx.tempo.rampf() % .25);
+      if (tRamp < LastJog) xyzJog.set(randctr(mMax.x*.2), randctr(mMax.y*.2), randctr(mMax.z*.2));
+      LastJog = tRamp;
+    }
+
+    // precalculate this stuff
+    float wvAmp = val(pWave), sprk = val(pSpark);
+    if (wvAmp > 0) {
+      for (int i=0; i<ceil(mMax.x)+1; i++)
+        yWaveNz[i] = wvAmp * (noise(i/(mMax.x*.3)-(2e3+NoiseMove)/1500.) - .5) * (mMax.y/2.);
+
+      for (int i=0; i<ceil(mMax.y)+1; i++)
+        xWaveNz[i] = wvAmp * (noise(i/(mMax.y*.3)-(1e3+NoiseMove)/1500.) - .5) * (mMax.x/2.);
+    }
+
+    for (LXPoint p : model.points) { nPoint++;
+      setVec(P,p);
+      P.sub(modmin);
+      P.sub(pTrans);
+      if (sprk > 0) {P.y += sprk*randctr(50); P.x += sprk*randctr(50); P.z += sprk*randctr(50); }
+      if (wvAmp > 0) P.y += interpWv(p.x-modmin.x, yWaveNz);
+      if (wvAmp > 0) P.x += interpWv(p.y-modmin.y, xWaveNz);
+      if (pJog.b) P.add(xyzJog);
+
+
+      color cNew, cOld = colors[p.index];
+              { tP.set(P); cNew = CalcPoint(tP); }
+      if (pXsym.b) { tP.set(mMax.x-P.x,P.y,P.z); cNew = blendColor(cNew, CalcPoint(tP), ADD); }
+      if (pYsym.b) { tP.set(P.x,mMax.y-P.y,P.z); cNew = blendColor(cNew, CalcPoint(tP), ADD); }
+      if (pRsym.b) { tP.set(mMax.x-P.x,mMax.y-P.y,mMax.z-P.z); cNew = blendColor(cNew, CalcPoint(tP), ADD); }
+      if (pXdup.b) { tP.set((P.x+mMax.x*.5)%mMax.x,P.y,P.z); cNew = blendColor(cNew, CalcPoint(tP), ADD); }
+      if (pGrey.b) { cNew = lx.hsb(0, 0, lx.b(cNew)); }
+      colors[p.index] = cNew;
+    }
   }
 }
 
@@ -517,12 +545,12 @@ class CubeCurl extends SCPattern{
 float CH, CW, diag;
 ArrayList<PVector> cubeorigin = new ArrayList<PVector>();
 ArrayList<PVector> centerlist = new ArrayList<PVector>();
-private SinLFO curl = new SinLFO(0, Cube.EDGE_HEIGHT, 5000 ); 
+private SinLFO curl = new SinLFO(0, Cube.EDGE_HEIGHT, 5000 );
 
 private SinLFO bg = new SinLFO(180, 220, 3000);
 
-CubeCurl(GLucose glucose){
-super(glucose);
+CubeCurl(LX lx){
+super(lx);
 addModulator(curl).trigger();
 addModulator(bg).trigger();
  this.CH = Cube.EDGE_HEIGHT;
@@ -536,11 +564,11 @@ for (int i = 0; i < model.cubes.size(); i++){
   cubeorigin.add(new PVector(a.x, a.y, a.z));
   centerlist.add(new PVector(a.cx, a.cy, a.cz) );
   
-} 
+}
 
 }
 //there is definitely a better way of doing this!
-PVector centerofcube(int i) { 
+PVector centerofcube(int i) {
 Cube c = model.cubes.get(i);
 PVector cubecenter = new PVector(c.cx, c.cy, c.cz);
 
@@ -549,36 +577,36 @@ return cubecenter;
 
 
 void run(double deltaMs){
-for (int i =0; i < model.cubes.size(); i++)  {
+for (int i =0; i < model.cubes.size(); i++) {
 Cube c = model.cubes.get(i);
 float cfloor = c.y;
-
+    
 // if (i%3 == 0){
 
 // for (LXPoint p : c.points ){
-//  // colors[p.index]=color(0,0,0);
-//   //float dif = (p.y - c.y);
-//   //colors[p.index] = color( bg.getValuef() , 80 , dif < curl.getValuef() ? 80 : 0, ADD);
-//    }
-//  }
+// // colors[p.index]=color(0,0,0);
+// //float dif = (p.y - c.y);
+// //colors[p.index] = color( bg.getValuef() , 80 , dif < curl.getValuef() ? 80 : 0, ADD);
+// }
+// }
 
 // else if (i%3 == 1) {
   
-//  for (LXPoint p: c.points){
-//   colors[p.index]=color(0,0,0);
-//   float dif = (p.y - c.y);
-//   // colors[p.index] = 
-//   // color(bg.getValuef(),
-//   //   map(curl.getValuef(), 0, Cube.EDGE_HEIGHT, 20, 100), 
-//   //   100 - 10*abs(dif - curl.getValuef()), ADD );
-//      }
-//     }
+// for (LXPoint p: c.points){
+// colors[p.index]=color(0,0,0);
+// float dif = (p.y - c.y);
+// // colors[p.index] =
+// // color(bg.getValuef(),
+// // map(curl.getValuef(), 0, Cube.EDGE_HEIGHT, 20, 100),
+// // 100 - 10*abs(dif - curl.getValuef()), ADD );
+// }
+// }
 // else if (i%3 == 2){
  // centerlist[i].sub(cubeorigin(i);
    for (LXPoint p: c.points) {
     PVector pv = new PVector(p.x, p.y, p.z);
-     colors[p.index] =color( constrain(4* pv.dist(centerlist.get(i)), 0, 360)  , 50, 100 );
-   // colors[p.index] =color(constrain(centerlist[i].x, 0, 360), constrain(centerlist[i].y, 0, 100),  );
+     colors[p.index] =color( constrain(4* pv.dist(centerlist.get(i)), 0, 360) , 50, 100 );
+   // colors[p.index] =color(constrain(centerlist[i].x, 0, 360), constrain(centerlist[i].y, 0, 100), );
 
 
     }
@@ -589,14 +617,130 @@ float cfloor = c.y;
    }
   }
  }
+  JGraphAdapterDemo graph1; 
+  
+
+// class SpinningCube extends SCPattern{
+// LXProjection spin1, spin2, spin3; 
+// SawLFO 
+
+//}
+
+
+
+
+
+class PixelGraph implements EdgeFactory<dPixel, dVertex> {
+
+dPixel p0; dPixel p1; dVertex v0;
+
+public dVertex createEdge(dPixel p0, dPixel p1) {
+
+  return v0;
+
+}
+
+
+}
+
+ class GraphTest extends SCPattern {
+  JGraphAdapterDemo graph1;
+  
+GraphTest( LX lx) {super(lx); JGraphAdapterDemo graph1 = new JGraphAdapterDemo();}
+  void run(double deltaMs){
+  }
+}
+
+class SpinningCube extends SCPattern{
+ LXProjection spin1, spin2, spin3;
+ SawLFO spinx, spiny, spinz;
+ SinLFO spinx1, spiny1, spinz1, cubesize;
+ BasicParameter xoff = new BasicParameter("xoff", 10, 0, 100);
+ BasicParameter toff = new BasicParameter("toff", 10,0,1000);
+ BasicParameter huev = new BasicParameter("hue", 200, 0, 360);
+ BasicParameter density = new BasicParameter("density", 0, 0, 1);
+ BasicParameter Vsize = new BasicParameter("size", model.xMax/3,0, model.xMax);
+ VirtualCube V1, V2, V3;
+ PVector P = new PVector();
+ float noisetime=0.;
+  class VirtualCube {
+  float x,y,z,d;
+  PVector center;
+
+  VirtualCube(float x, float y, float z, float d) {
+    this.x=x;
+    this.y= y;
+    this.z=z;
+    this.d=d;
+    this.center=new PVector(x,y,z);
+      }
+    
+    color getcolor(LXVector q) {
+     if ( q.x > this.x + d/2 || q.x < this.x - d/2 || q.y > this.y + d/2 || q.y < this.y - d/2 || q.z > this.z + d/2 || q.z < this.z - d/2 )
+     {return 0;}
+      else {
+      return lx.hsb(huev.getValuef()*noise(xoff.getValuef()*.001*noisetime ) , constrain(100*noise(xoff.getValuef()*.001*q.x*noisetime), 0, 100), max(100*(noise(xoff.getValuef()*.001*q.x*noisetime)-density.getValuef()), 0) );
+      }
+    }
+    void setcenter(float x, float y, float z) {this.x=x; this.y = y; this.z=z; }
+    void setsize(float din){ this.d=din ; }
+
+    }
+
+SpinningCube(LX lx) {
+  super(lx);
+  addParameter(xoff);
+  addParameter(toff);
+  addParameter(Vsize);
+  addParameter(huev);
+  addParameter(density);
+  //addModulator()
+  V1 = new VirtualCube(model.cx, model.cy, model.cz, model.xMax/2);
+  spinx= new SawLFO(0, TWO_PI, 8000);
+  spin1 = new LXProjection(model);
+   
+}
+
+
+void run(double deltaMs) {
+  
+  noisetime+= deltaMs*.0001*toff.getValuef();
+
+spin1.reset()
+.center()
+//.scale ()
+.rotate(spinx.getValuef(),0, 1, 0)
+.translate(model.cx, model.cy, model.cz);
+
+for (LXVector p: spin1) {
+  P.set(p.x, p.y, p.z);
+
+ colors[p.index] = V1.getcolor(p);
+
+}
+
+V1.setsize(Vsize.getValuef());
+
+
+};
+
+
+}
+
+
+
+
+
 
  class HueTestHSB extends SCPattern{
   BasicParameter HueT = new BasicParameter("Hue", .5);
   BasicParameter SatT = new BasicParameter("Sat", .5);
   BasicParameter BriT = new BasicParameter("Bright", .5);
 
-HueTestHSB(GLucose glucose) {
-  super(glucose);
+HueTestHSB(LX lx) {
+  super(lx);
   addParameter(HueT);
   addParameter(SatT);
   addParameter(BriT);
@@ -611,7 +755,7 @@ HueTestHSB(GLucose glucose) {
    int now= millis();
    if (now % 1000 <= 20)
    {
-   println("Hue: " + 360*HueT.getValuef() + "Sat: " + 100*SatT.getValuef() + "Bright:  " + 100*BriT.getValuef());
+   println("Hue: " + 360*HueT.getValuef() + "Sat: " + 100*SatT.getValuef() + "Bright: " + 100*BriT.getValuef());
    }
   }
 
diff --git a/AlexGreen.pde.orig b/AlexGreen.pde.orig
deleted file mode 100644 (file)
index 9d657e9..0000000
+++ /dev/null
@@ -1,446 +0,0 @@
-class SineSphere extends SCPattern {
-<<<<<<< HEAD
-  private SawLFO yrot = new SawLFO(0, TWO_PI, 3000);
-  private SawLFO yrot2 = new SawLFO(0, -TWO_PI,  8000);
-  public BasicParameter huespread = new BasicParameter("Hue", 0, 180);
-  public BasicParameter widthparameter= new BasicParameter("Width", .2);
-  private int pitch = 0; 
-  private int channel = 0; 
-  private int velocity = 0; 
-  public final Projection sinespin;
-  public final Projection sinespin2; 
-  
-  //to-do:  how to sync all hues across sphery's via one basicparameter 
-  //public BasicParameter huespread = new BasicParameter("HueSpread", 180, 360);
-  public BasicParameter rotationx = new BasicParameter("rotx", 0, 0, 1 );
-  public BasicParameter rotationy = new BasicParameter("roty", 1, 0, 1);
-  public BasicParameter rotationz = new BasicParameter("rotz", 0, 0, 1);
-  
-=======
-  private SinLFO yrot = new SinLFO(0, TWO_PI, 2000);
-  public final LXProjection sinespin; 
->>>>>>> b8bb27489db7dc687bf150576e9d9439f1fa17a6
- float modelrad = sqrt((model.xMax)*(model.xMax) + (model.yMax)*(model.yMax) + (model.zMax)*(model.zMax));
-  Pick Sshape; 
-  public final PVector P = new PVector();
-
-  class Sphery {
-  float f1xcenter, f1ycenter, f1zcenter, f2xcenter , f2ycenter, f2zcenter; //second three are for an ellipse with two foci
-  private  SinLFO vibration; 
-  private  SinLFO surface;
-  private  SinLFO vx;
-  private SinLFO xbounce;
-  public SinLFO ybounce;
-  private SinLFO zbounce;
-  float vibration_min, vibration_max, vperiod;
-  
-  //public BasicParameter huespread;
-  public BasicParameter bouncerate;
-  public BasicParameter bounceamp;
-  public BasicParameter vibrationrate;
-  public final PVector circlecenter = new PVector(); 
-  public Sphery(float f1xcenter, float f1ycenter, float f1zcenter, float vibration_min, float vibration_max, float vperiod) 
-  {
-   this.f1xcenter = f1xcenter;
-   this.f1ycenter = f1ycenter;
-   this.f1zcenter = f1zcenter;
-   this.vibration_min = vibration_min;
-   this.vibration_max = vibration_max;
-   this.vperiod = vperiod;
-   //addParameter(bounceamp = new BasicParameter("Amp", .5));
-   //addParameter(bouncerate = new BasicParameter("Rate", .5));  //ybounce.modulateDurationBy(bouncerate);
-   //addParameter(vibrationrate = new BasicParameter("vibration", 1000, 10000));
-    //addParameter(widthparameter = new BasicParameter("Width", .2));
-    
-   
-   addModulator( vx = new SinLFO(500, 10000, 100000)).trigger() ;
-   //addModulator(xbounce = new SinLFO(model.xMax/3, 2*model.yMax/3, 2000)).trigger(); 
-   addModulator(ybounce= new SinLFO(model.yMax/3, 2*model.yMax/3, 240000./lx.tempo.bpm())).trigger(); //bounce.modulateDurationBy
-    
-   //addModulator(bounceamp); //ybounce.setMagnitude(bouncerate);
-   addModulator( vibration = new SinLFO(vibration_min , vibration_max, 10000)).trigger(); //vibration.setPeriod(240000/lx.tempo.bpm());
-      
-  }
-
-  //for an ellipse
-//  public Sphery(float f1xcenter, float f1ycenter, float f1zcenter, float f2xcenter, float f2ycenter, float f2zcenter, 
-//   float vibration_min, float vibration_max, float vperiod)  
-//  {
-//     this.f1xcenter = f1xcenter;
-//    this.f1ycenter = f1ycenter;
-//    this.f1zcenter = f1zcenter;
-//    this.f2xcenter = f2xcenter;
-//    this.f2ycenter = f2ycenter;
-//    this.f2zcenter = f2zcenter;
-//    this.vibration_min = vibration_min;
-//    this.vibration_max = vibration_max;
-//    this.vperiod = vperiod;
-//    //addModulator(xbounce = new SinLFO(model.xMax/3, 2*model.yMax/3, 2000)).trigger(); 
-//    addModulator(ybounce).trigger(); 
-//    addModulator( vibration = new SinLFO(vibration_min , vibration_max, lx.tempo.rampf())).trigger(); //vibration.modulateDurationBy(vx);
-//    addParameter(widthparameter = new BasicParameter("Width", .1));
-//    //addParameter(huespread = new BasicParameter("bonk", .2));
-  
-// }
-
-
-void setVibrationPeriod(double period){
-// to-do:  make this conditional upon time signature
-
-vibration.setPeriod(period);
-
-}
-
-
-float distfromcirclecenter(float px, float py, float pz, float f1x, float f1y, float f1z) 
-{
-   return dist(px, py, pz, f1x, f1y, f1z);
-    }
- //void updatespherey(deltaMs, )
-
- float quadrant(PVector q) {
-   float qtheta = atan2(  (q.x-f1xcenter) , (q.z - f1zcenter) ); 
-
-
-    return map(qtheta, -PI/2, PI/2, 160-huespread.getValuef(), 240 +huespread.getValuef());
-  //if (q.x > f1xcenter ) {return 140 ;}
-    //else  {return 250;}  
- }
- color spheryvalue (PVector p, float f1xcenter, float f1ycenter, float f1zcenter) {
-   circlecenter.set(f1xcenter, f1ycenter, f1zcenter); 
-
-  
-//switch(sShpape.cur() ) {}  
-
-   float b = max(0, 100 - 100*widthparameter.getValuef()*abs(p.dist(circlecenter)
-      - vibration.getValuef() ) );
-
-   if (b <= 0) {
-     return 0;
-   }
-
-   return lx.hsb(
-     constrain(quadrant(p), 0, 360),
-     80,
-     b
-   ); 
- }
- color ellipsevalue(float px, float py, float pz , float f1xc, float f1yc, float f1zc, float f2xc, float f2yc, float f2zc)
-  {
-//switch(sShpape.cur() ) {}  
-   return lx.hsb(huespread.getValuef()*5*px, dist(model.xMax-px, model.yMax-py, model.zMax-pz, f1xc, f1yc, f1zc) , 
-    max(0, 100 - 100*widthparameter.getValuef() *
-      abs( (dist(px, py, pz, f1xc, ybounce.getValuef(), f1zc) + 
-        (dist(px, py , pz, f2xc, ybounce.getValuef(), f2zc) ) )/2  
-      - 1.2*vibration.getValuef() ) ) ) ; 
-  }
-
-void run(double deltaMs) {
-      float vv = vibration.getValuef();
-      float ybv = ybounce.getValuef();
-      
-    }
-  
-}  
-
-// public boolean gridPressed(int row, int co){
-// midiengine.grid.setState();
-
-// return true;
-
-// }
-
-public boolean noteOn(Note note)  {
-pitch= note.getPitch();  
-velocity=note.getVelocity();
-channel=note.getChannel();
-return true;
-}
-
-final Sphery[] spherys;
-  SineSphere(GLucose glucose) 
-  {
-    super(glucose);
-<<<<<<< HEAD
-    sinespin = new Projection(model);
-    sinespin2 = new Projection(model);
-    addParameter(huespread);
-    addParameter(rotationx);
-    addParameter(rotationy);
-    addParameter(rotationz);
-=======
-    sinespin = new LXProjection(model);
->>>>>>> b8bb27489db7dc687bf150576e9d9439f1fa17a6
-    addModulator(yrot).trigger();
-    addModulator(yrot2).trigger(); 
-    
-    //addParameter(huespread);
-    //Sshape = addPick("Shape", , 1);
-    spherys = new Sphery[] {
-      new Sphery(model.xMax/4, model.yMax/2, model.zMax/2, modelrad/16, modelrad/8, 3000),
-      new Sphery(.75*model.xMax, model.yMax/2, model.zMax/2, modelrad/20, modelrad/10, 2000),
-      new Sphery(model.xMax/2, model.yMax/2, model.zMax/2,  modelrad/4, modelrad/8, 2300),
-
-      new Sphery(.3*model.xMax, .4*model.yMax, .6*model.zMax, modelrad/16, modelrad/8, 4000),
-      new Sphery(.75*model.xMax, model.yMax/2, model.zMax/2, modelrad/20, modelrad/10, 2000),
-      new Sphery(model.xMax/2, model.yMax/2, model.zMax/2,  modelrad/4, modelrad/8, 2300),
-      
-    };  
-  }
-
-// public void onParameterChanged(LXParameter parameter)
-// {
-
-
-//     for (Sphery s : spherys) {
-//       if (s == null) continue;
-//       double bampv = s.bounceamp.getValue();
-//       double brv = s.bouncerate.getValue();
-//       double tempobounce = lx.tempo.bpm();
-//       if (parameter == s.bounceamp) 
-//       {
-//         s.ybounce.setRange(bampv*model.yMax/3 , bampv*2*model.yMax/3, brv);
-//       }
-//       else if ( parameter == s.bouncerate )   
-//       {
-//         s.ybounce.setDuration(120000./tempobounce);
-//       }
-//     }
-//   }
-
-<<<<<<< HEAD
-    public void run( double deltaMs) {
-     double t = lx.tempo.ramp();
-     double bpm = lx.tempo.bpm();
-     spherys[0].run(deltaMs);
-     spherys[1].run(deltaMs);
-     spherys[2].run(deltaMs);
-     spherys[3].run(deltaMs);
-     
-
-     switch (pitch) 
-    {
-     case 53: t = .5*t;   bpm = .5*bpm;  break;
-=======
-     void run( double deltaMs) {
-     float t = lx.tempo.rampf();
-     float bpm = lx.tempo.bpmf();
-     //spherys[1].run(deltaMs);
-     //spherys[2].run(deltaMs);
-     //spherys[3].run(deltaMs);]
-     sinespin.reset()
-
-     // Translate so the center of the car is the origin, offset by yPos
-      .center()
->>>>>>> b8bb27489db7dc687bf150576e9d9439f1fa17a6
-
-     case 54: t = t;   bpm = bpm;   break;
-
-     case 55: t = 2*t;  bpm = 2*bpm; break;
-
-     default: t= t;   bpm = bpm; 
-
-<<<<<<< HEAD
-=======
-     for (LXPoint p : model.points){
-    color c = 0;
-    c = blendColor(c, spherys[1].spheryvalue(p.x, p.y, p.z, .75*model.xMax, model.yMax/2, model.zMax/2), ADD);
-    c = blendColor(c, spherys[0].spheryvalue(p.x, p.y, p.z, model.xMax/4, model.yMax/4, model.zMax/2), ADD);
-    c = blendColor(c, spherys[2].spheryvalue(p.x, p.y, p.z, model.xMax/2, model.yMax/2, model.zMax/2),ADD);
->>>>>>> b8bb27489db7dc687bf150576e9d9439f1fa17a6
-     
-      }
-      
-      for ( Sphery s: spherys){
-      s.setVibrationPeriod(480000/bpm);
-      s.vibration.setBasis(t);
-       }
-     sinespin.reset(model)
-     
-    
-     // Translate so the center of the car is the origin, offset 
-      .translateCenter(model, 0, 0, 0)
-     // .scale(1.3,1.3,1.3)
-      // Rotate around the origin (now the center of the car) about an y-vector
-      .rotate(yrot.getValuef(), rotationx.getValuef(), rotationy.getValuef() , rotationz.getValuef())
-      .translate(model.cx, model.cy, model.cz);
-      
-
-   
-   
-
-     for (Coord p: sinespin)
-   // for (Point p: model.points)
-     {
-       P.set(p.x, p.y, p.z);
-      // PVector P = new PVector(p.x, p.y, p.z);
-    color c = #000000;
-    c = blendIfColor(c, spherys[1].spheryvalue(P, .75*model.xMax, model.yMax/2, model.zMax/2), ADD);
-    c = blendIfColor(c, spherys[0].spheryvalue(P, model.xMax/4, model.yMax/4, model.zMax/2), ADD);
-    c = blendIfColor(c, spherys[2].spheryvalue(P, model.xMax/2, model.yMax/2, model.zMax/2),ADD);
-    
-
-    colors[p.index] = c;
-    
-      
-               }
-   sinespin2.reset(model).
-   translateCenter(model,0,0,0).
-   rotate(yrot2.getValuef(), 0, 1, 0).
-   translate(model.cx,model.cy,model.cz);
-
-    for (Coord p: sinespin2)
-    {   color c = 0;
-      // PVector P = new PVector(p.x, p.y, p.z);
-        P.set(p.x, p.y, p.z);
-        c = blendIfColor(c, spherys[3].spheryvalue(P, .3*model.xMax, .7*model.yMax, .6*model.zMax),ADD);
-         
-        colors[p.index] = blendIfColor(colors[p.index], c , ADD);
-
-    }  
-
-
-
-  }
-  
-  color blendIfColor(color c1, color c2, int mode) {
-    if (c2 != 0) {
-      return blendColor(c1, c2, mode);
-    }
-    return c1;
-  }
-  
-
-      //   color c = 0;
-      //   c = blendColor(c, spherys[3].ellipsevalue(Px.x, Px.y, Px.z, model.xMax/4, model.yMax/4, model.zMax/4, 3*model.xMax/4, 3*model.yMax/4, 3*model.zMax/4),ADD);
-      //   return c; 
-      // }
-      // return lx.hsb(0,0,0);
-      //  // else if(spheremode ==2)
-       // { color c = 0;
-       //   return lx.hsb(CalcCone( (xyz by = new xyz(0,spherys[2].ybounce.getValuef(),0) ), Px, mid) );
-
-       // }
-
-  
-       //   } 
-        
-  }
-
-class CubeCurl extends SCPattern{
-float CH, CW, diag;
-ArrayList<PVector> cubeorigin = new ArrayList<PVector>();
-ArrayList<PVector> centerlist = new ArrayList<PVector>();
-private SinLFO curl = new SinLFO(0, Cube.EDGE_HEIGHT, 5000 ); 
-
-private SinLFO bg = new SinLFO(180, 220, 3000);
-
-CubeCurl(GLucose glucose){
-super(glucose);
-addModulator(curl).trigger();
-addModulator(bg).trigger();
- this.CH = Cube.EDGE_HEIGHT;
- this.CW = Cube.EDGE_WIDTH;
- this.diag = sqrt(CW*CW + CW*CW);
-
-
-ArrayList<PVector> centerlistrelative = new ArrayList<PVector>();
-for (int i = 0; i < model.cubes.size(); i++){
-  Cube a = model.cubes.get(i);
-  cubeorigin.add(new PVector(a.x, a.y, a.z));
-  centerlist.add(new PVector(a.cx, a.cy, a.cz) );
-  
-} 
-
-}
-//there is definitely a better way of doing this!
-PVector centerofcube(int i) { 
-Cube c = model.cubes.get(i);
-
-println(" cube #:  " + i + " c.x  "  +  c.x  + "  c.y   "  + c.y   + "  c.z  "  +   c.z  );
-// PVector cubeangle = new PVector(c.rx, c.ry, c.rz);
-println("raw x angle:  " + c.rx + "raw y angle:  " + c.ry + "raw z angle:  " + c.rz);
-PVector cubecenter = new PVector(c.x + CW/2, c.y + CH/2, c.z + CW/2);
-println("cubecenter unrotated:  "  + cubecenter.x + "  "  +cubecenter.y + "  " +cubecenter.z );
-PVector centerrot = new PVector(cos(c.rx)*CW/2 - sin(c.rx)*CW/2, cubecenter.y, cos(c.rz)*CW/2 + sin(c.rz)*CW/2);
- // nCos*(y-o.y) - nSin*(z-o.z) + o.y
-cubecenter = PVector.add(new PVector(c.x, c.y, c.z), centerrot);
-println( "  cubecenter.x  " + cubecenter.x  + " cubecenter.y  " +  cubecenter.y + " cubecenter.z  "   +  cubecenter.z  + "   ");
-
-
-return cubecenter;
-}
-
-
-void run(double deltaMs){
-for (int i =0; i < model.cubes.size(); i++)  {
-Cube c = model.cubes.get(i);
-float cfloor = c.y;
-
-// if (i%3 == 0){
-
-// for (LXPoint p : c.points ){
-//  // colors[p.index]=color(0,0,0);
-//   //float dif = (p.y - c.y);
-//   //colors[p.index] = color( bg.getValuef() , 80 , dif < curl.getValuef() ? 80 : 0, ADD);
-//    }
-//  }
-
-// else if (i%3 == 1) {
-  
-//  for (LXPoint p: c.points){
-//   colors[p.index]=color(0,0,0);
-//   float dif = (p.y - c.y);
-//   // colors[p.index] = 
-//   // color(bg.getValuef(),
-//   //   map(curl.getValuef(), 0, Cube.EDGE_HEIGHT, 20, 100), 
-//   //   100 - 10*abs(dif - curl.getValuef()), ADD );
-//      }
-//     }
-// else if (i%3 == 2){
- // centerlist[i].sub(cubeorigin(i);
-   for (LXPoint p: c.points) {
-    PVector pv = new PVector(p.x, p.y, p.z);
-     colors[p.index] =color( constrain(4* pv.dist(centerlist.get(i)), 0, 360)  , 50, 100 );
-   // colors[p.index] =color(constrain(centerlist[i].x, 0, 360), constrain(centerlist[i].y, 0, 100),  );
-
-
-    }
-
-
-  //}
-
-   }
-  }
- }
-
- class HueTestHSB extends SCPattern{
-  BasicParameter HueT = new BasicParameter("Hue", .5);
-  BasicParameter SatT = new BasicParameter("Sat", .5);
-  BasicParameter BriT = new BasicParameter("Bright", .5);
-
-HueTestHSB(GLucose glucose) {
-  super(glucose);
-  addParameter(HueT);
-  addParameter(SatT);
-  addParameter(BriT);
-}
-  void run(double deltaMs){
-
-  for (LXPoint p : model.points) {
-    color c = 0;
-    c = blendColor(c, lx.hsb(360*HueT.getValuef(), 100*SatT.getValuef(), 100*BriT.getValuef()), ADD);
-    colors[p.index]= c;
-  }
-   int now= millis();
-   if (now % 1000 <= 20)
-   {
-   println("Hue: " + 360*HueT.getValuef() + "Sat: " + 100*SatT.getValuef() + "Bright:  " + 100*BriT.getValuef());
-   }
-  }
-
- }
index 33f4f5d0dd26f6df6e08834be011fa5ecb4dd543..5b286f1c3c49c18d8eff9a36e9b7b291d69a7838 100644 (file)
@@ -122,9 +122,9 @@ class AKPong extends SCPattern
         return true;
     }
 
-    public AKPong(GLucose glucose)
+    public AKPong(LX lx)
     {
-        super(glucose);
+        super(lx);
         addParameter(speed);
         addParameter(leftKnob);
         addParameter(rightKnob);
@@ -171,9 +171,9 @@ class AKPong extends SCPattern
 class AKInvader extends SCPattern
 {
     private final SawLFO h = new SawLFO(0, 1, 5000);
-    public AKInvader(GLucose glucose)
+    public AKInvader(LX lx)
     {
-        super(glucose);
+        super(lx);
         addModulator(h).trigger();
     }
     
@@ -320,9 +320,9 @@ class AKTetris extends SCPattern
         }
     }
     
-    public AKTetris(GLucose glucose)
+    public AKTetris(LX lx)
     {
-        super(glucose);
+        super(lx);
     }
     
     public boolean noteOn(Note note)
@@ -373,9 +373,9 @@ class AKMatrix extends SCPattern
         }
     }
 
-    public AKMatrix(GLucose glucose)
+    public AKMatrix(LX lx)
     {
-        super(glucose);
+        super(lx);
 //        for (Tower t : model.towers)
         {
             Tower t = model.towers.get(0);
@@ -416,9 +416,9 @@ class AKEgg extends SCPattern
     private final float Y = model.yMax / 2;
     private final float Z = model.zMax / 2;
 
-    public AKEgg(GLucose glucose)
+    public AKEgg(LX lx)
     {
-        super(glucose);
+        super(lx);
         addModulator(xRadius).trigger();
         addModulator(yRadius).trigger();
         addModulator(zRadius).trigger();
@@ -447,9 +447,9 @@ class AKCubes extends SCPattern
     private Cube cube;
     private int sec;
     
-    public AKCubes(GLucose glucose)
+    public AKCubes(LX lx)
     {
-        super(glucose);
+        super(lx);
         cube = model.cubes.get((int) random(model.cubes.size()));
         sec = 0;
     }
@@ -474,9 +474,9 @@ class AKCubes extends SCPattern
 class AKSpiral extends SCPattern
 {
     private int ms;
-    public AKSpiral(GLucose glucose)
+    public AKSpiral(LX lx)
     {
-        super(glucose);
+        super(lx);
         ms = 0;
     }
     
@@ -538,9 +538,9 @@ class AKSpace extends SCPattern
         }
     }
     
-    public AKSpace(GLucose glucose)
+    public AKSpace(LX lx)
     {
-        super(glucose);
+        super(lx);
         stars = new LinkedList<Star>();
         for (int i = 0; i < 50; ++i)
             stars.add(new Star());
index 4709bdcfe9c86ba16974ce1f9712ec8e1d479550..e4f1ec984acfad474f23a489c445084a8cd8fc44 100644 (file)
@@ -5,8 +5,8 @@ class TelevisionStatic extends SCPattern {
   BasicParameter hueParameter = new BasicParameter("HUE", 1.0);
   SinLFO direction = new SinLFO(0, 10, 3000);
   
-  public TelevisionStatic(GLucose glucose) {
-    super(glucose);
+  public TelevisionStatic(LX lx) {
+    super(lx);
     addModulator(direction).trigger();
     addParameter(brightParameter);
     addParameter(saturationParameter);
@@ -28,8 +28,8 @@ class AbstractPainting extends SCPattern {
   SinLFO colorMod = new SinLFO(0, 360, 5000);
   SinLFO brightMod = new SinLFO(0, model.zMax, 2000);
     
-  public AbstractPainting(GLucose glucose) {
-    super(glucose);
+  public AbstractPainting(LX lx) {
+    super(lx);
     addModulator(colorMod).trigger();
     addModulator(brightMod).trigger();
     
@@ -52,8 +52,8 @@ class Spirality extends SCPattern {
   float rad = 0;
   int direction = 1;
   
-  Spirality(GLucose glucose) {
-    super(glucose);   
+  Spirality(LX lx) {
+    super(lx);   
     addParameter(r);
     for (LXPoint p : model.points) {  
       colors[p.index] = lx.hsb(0, 0, 0);
index f88e20857da377cfe5e67f41e4d98147025368d6..081da539b947c07ffcdc47d129d63eff3a7d7bf7 100644 (file)
@@ -9,8 +9,8 @@ class XYZPixel extends SCPattern
        float ym2 = model.yMin+cubeWidth;
        float zm2 = model.zMin+cubeWidth;
 
-       XYZPixel(GLucose glucose) {
-               super(glucose);
+       XYZPixel(LX lx) {
+               super(lx);
                //myP = new LXPoint(20,20,20);
        }
 
@@ -50,8 +50,8 @@ class MultipleCubes extends SCPattern
 
        float minIS;
 
-       MultipleCubes(GLucose glucose) {
-               super(glucose);
+       MultipleCubes(LX lx) {
+               super(lx);
                minIS = 200;
        }
 
@@ -130,8 +130,8 @@ class TowerParams extends SCPattern
        ArrayList<BasicParameter> towerParams;
        int towerSize;
        int colorSpan;
-       TowerParams(GLucose glucose) {
-               super(glucose);
+       TowerParams(LX lx) {
+               super(lx);
 
                towerParams = new ArrayList<BasicParameter>();
                addParameter(hueoff);
@@ -199,8 +199,8 @@ class Sandbox extends SCPattern
        int towerrange = model.towers.size();
        int counter=0;
 
-       Sandbox(GLucose glucose) {
-               super(glucose);
+       Sandbox(LX lx) {
+               super(lx);
                println("points "+pointrange);
                println("strips "+striprange);
                println("faces "+facerange);
@@ -234,9 +234,9 @@ class Sandbox extends SCPattern
 
 class GranimTestPattern extends GranimPattern
 {
-       GranimTestPattern(GLucose glucose)
+       GranimTestPattern(LX lx)
        {
-               super(glucose);
+               super(lx);
                addGraphic("myReds",new RedsGraphic(100));
                int[] dots = {0,128,0,128,0,128,0,128,0,128,0,128};
                addGraphic("myOtherColors",new ColorDotsGraphic(dots));
@@ -270,9 +270,9 @@ class GranimTestPattern extends GranimPattern
 
 class GranimTestPattern2 extends GranimPattern
 {
-       GranimTestPattern2(GLucose glucose)
+       GranimTestPattern2(LX lx)
        {
-               super(glucose);
+               super(lx);
                /*for(int i = 0;i < 100; i++)
                {
                        Graphic g = addGraphic("myReds_"+i,new RedsGraphic(Math.round(Math.random() * 100)));
@@ -310,8 +310,8 @@ class DriveableCrossSections extends CrossSections
        BasicParameter zd;
        BasicParameter mode; 
 
-       DriveableCrossSections(GLucose glucose) {
-               super(glucose); 
+       DriveableCrossSections(LX lx) {
+               super(lx);      
        }
 
        public void addParams()
index ab23fa5ddd69805b312811cb9211278a93f7b1a1..cdec36b6b1d160b44e8e3aeeda1a1d1c62a76621 100644 (file)
@@ -5,8 +5,8 @@ public class Pong extends DPat {
        Pick    pChoose;
        PVector v = new PVector(), vMir =  new PVector();
 
-       Pong(GLucose glucose) {
-               super(glucose);
+       Pong(LX lx) {
+               super(lx);
                cRad = mMax.x/10;
                addModulator(dx = new SinLFO(6000,  500, 30000  )).trigger();
                addModulator(dy = new SinLFO(3000,  500, 22472  )).trigger();
@@ -57,8 +57,8 @@ public class Noise extends DPat
        int                             _ND = 4;
        NDat                    N[] = new NDat[_ND];
 
-       Noise(GLucose glucose) {
-               super(glucose);
+       Noise(LX lx) {
+               super(lx);
                pSpeed          = addParam("Fast"       , .55);
                pDensity        = addParam("Dens"        , .5);
                pSharp          = addParam("Shrp"        ,  0);
@@ -175,8 +175,8 @@ public class Play extends DPat
        float   LastBeat=3, LastMeasure=3;
        int             curRandTempo = 1, curRandTPat = 1;
 
-       Play(GLucose glucose) {
-               super(glucose);
+       Play(LX lx) {
+               super(lx);
            pRadius             = addParam("Rad"        , .1    );
                pBounce         = addParam("Bnc"        , .2    );
            pAmp                = addParam("Amp"        , .2    );
@@ -452,8 +452,8 @@ class Worms extends SCPattern {
                                                                new PVector(randX(), random(2)<1 ? model.yMin:model.yMax, zMidLat)      ;
        }
 
-       Worms(GLucose glucose) {
-               super(glucose); 
+       Worms(LX lx) {
+               super(lx); 
            addModulator(moveChase).start();
            addParameter(pBeat);    addParameter(pSpeed);
            addParameter(pBlur);    addParameter(pWorms);
index 8e236a2a611d6b43aa9cc5902a65d4c8c587c2a9..cf77504f6db438c991e5146842dc5d1ab523e2fe 100644 (file)
-class GenericController {
-    GenericController(){}
-    public void RotateKnob(int type, int num, float val){
-      LXParameter p = null;
-      if(type==0) {
-        p = glucose.getPattern().getParameters().get(num);
-        if(p!=null) { p.setValue(val); }
-      }
-      if(type==1) {
-        p = glucose.getSelectedTransition().getParameters().get(num);
-        if(p!=null) { p.setValue(val); }
-      }
-      if(type==2) {
-        p = glucose.getSelectedEffect().getParameters().get(num);
-        if(p!=null) { p.setValue(val); }
-      }
-    }
-}
-
-class MidiController extends GenericController {
-  MidiController() {
-     super();
-  }  
-}
-//PApplet xparent;  // be sure to set
-
-
-
-OscP5 listener;
-// Setup OSC
-//listener = new OscP5(this,7022);
-
-//boolean[] noteState = new boolean[16];
-//
-//void controllerChangeReceived(rwmidi.Controller cc) {
-//  if (debugMode) {
-//    println("CC: " + cc.toString());
-//  }
-//  if(cc.getCC()==1){
-//    for(int i=0; i<16; i++){
-//      if(noteState[i] && i<8)  { LXParameter p = glucose.getPattern().getParameters().get(i); p.setValue(cc.getValue()/127.0); }
-//      else if(noteState[i] && i<12) { LXParameter p = glucose.getSelectedTransition().getParameters().get(i-8); p.setValue(cc.getValue()/127.0); }
-//      else if(noteState[i] && i<16) { LXParameter p = glucose.getSelectedEffect().getParameters().get(i-12); p.setValue(cc.getValue()/127.0); }
-//    }
-//  }
-//}
-//
-//void noteOnReceived(Note note) {
-//  if (debugMode) {
-//    println("Note On: " + note.toString());
-//  }
-//  int pitch = note.getPitch();
-//  if(pitch>=36 && pitch <36+16){
-//    noteState[pitch-36]=true;
-//  }
-//}
-//
-//void noteOffReceived(Note note) {
-//  if (debugMode) {
-//    println("Note Off: " + note.toString());
-//  }
-//  int pitch = note.getPitch();
-//  if(pitch>=36 && pitch <36+16){
-//    noteState[pitch-36]=false;
-//  }
-//}
-//
-//void oscEvent(OscMessage theOscMessage) {
-//  println(theOscMessage);
-//  LXPattern currentPattern = lx.getPattern();
-//  if (currentPattern instanceof OSCPattern) {
-//    ((OSCPattern)currentPattern).oscEvent(theOscMessage);
-//  }
-//}
-//
-
-
-class ObjectMuckerEffect extends SCEffect {
-  ObjectMuckerEffect(GLucose glucose) {
-    super(glucose);
-  }
-  public void apply(int[] colors){
-    /*for(Strip s: model.strips){
-      for(int i=0; i<s.points.size(); i++){
-         int index = s.points.get(i).index;
-         color c = colors[index];
-         colors[index] = lx.hsb((i*22.5), saturation(c), brightness(c));
-      }
-    }*/
-  }
-}
-
-class BlendFrames extends SCEffect {
-  int fcount;
-  int frames[][];
-  int maxfbuf;
-  int blendfactor;
-  BlendFrames(GLucose glucose) {
-    super(glucose);
-    maxfbuf = 30;
-    blendfactor=30;
-    fcount=0;
-    frames = new int[maxfbuf][];
-    for(int i=0; i<maxfbuf; i++){
-       frames[i] = new int[model.points.size()];       
-    }
-  }
-  public void apply(int[] colors) {
-    if(fcount<maxfbuf){
-      for(int i=0; i<colors.length; i++){
-        frames[(maxfbuf-1)-fcount][i]=colors[i];
-      }
-      fcount++;
-      return;
-    } else {
-      for(int i=maxfbuf-1; i>0; i--){
-        frames[i] = frames[i-1];
-      }
-      frames[0] = new int[model.points.size()];
+// class GenericController {
+//     GenericController(){}
+//     public void RotateKnob(int type, int num, float val){
+//       LXParameter p = null;
+//       if(type==0) {
+//         p = getPattern().getParameters().get(num);
+//         if(p!=null) { p.setValue(val); }
+//       }
+//       if(type==1) {
+//         p = lx.engine.getDeck(RIGHT_DECK).getFaderTransition().getParameters().get(num);
+//         if(p!=null) { p.setValue(val); }
+//       }
+//       if(type==2) {
+//         p = getSelectedEffect().getParameters().get(num);
+//         if(p!=null) { p.setValue(val); }
+//       }
+//     }
+// }
+
+// class MidiController extends GenericController {
+//   MidiController() {
+//      super();
+//   }  
+// }
+// //PApplet xparent;  // be sure to set
+
+
+
+// OscP5 listener;
+// // Setup OSC
+// //listener = new OscP5(this,7022);
+
+// //boolean[] noteState = new boolean[16];
+// //
+// //void controllerChangeReceived(rwmidi.Controller cc) {
+// //  if (debugMode) {
+// //    println("CC: " + cc.toString());
+// //  }
+// //  if(cc.getCC()==1){
+// //    for(int i=0; i<16; i++){
+// //      if(noteState[i] && i<8)  { LXParameter p = glucose.getPattern().getParameters().get(i); p.setValue(cc.getValue()/127.0); }
+// //      else if(noteState[i] && i<12) { LXParameter p = glucose.getSelectedTransition().getParameters().get(i-8); p.setValue(cc.getValue()/127.0); }
+// //      else if(noteState[i] && i<16) { LXParameter p = glucose.getSelectedEffect().getParameters().get(i-12); p.setValue(cc.getValue()/127.0); }
+// //    }
+// //  }
+// //}
+// //
+// //void noteOnReceived(Note note) {
+// //  if (debugMode) {
+// //    println("Note On: " + note.toString());
+// //  }
+// //  int pitch = note.getPitch();
+// //  if(pitch>=36 && pitch <36+16){
+// //    noteState[pitch-36]=true;
+// //  }
+// //}
+// //
+// //void noteOffReceived(Note note) {
+// //  if (debugMode) {
+// //    println("Note Off: " + note.toString());
+// //  }
+// //  int pitch = note.getPitch();
+// //  if(pitch>=36 && pitch <36+16){
+// //    noteState[pitch-36]=false;
+// //  }
+// //}
+// //
+// //void oscEvent(OscMessage theOscMessage) {
+// //  println(theOscMessage);
+// //  LXPattern currentPattern = lx.getPattern();
+// //  if (currentPattern instanceof OSCPattern) {
+// //    ((OSCPattern)currentPattern).oscEvent(theOscMessage);
+// //  }
+// //}
+// //
+
+
+// class ObjectMuckerEffect extends LXEffect {
+//   ObjectMuckerEffect(LX lx) {
+//     super(lx);
+//   }
+//   public void apply(int[] colors){
+//     /*for(Strip s: model.strips){
+//       for(int i=0; i<s.points.size(); i++){
+//          int index = s.points.get(i).index;
+//          color c = colors[index];
+//          colors[index] = lx.hsb((i*22.5), saturation(c), brightness(c));
+//       }
+//     }*/
+//   }
+// }
+
+// class BlendFrames extends LXEffect {
+//   int fcount;
+//   int frames[][];
+//   int maxfbuf;
+//   int blendfactor;
+//   BlendFrames(LX lx) {
+//     super(lx);
+//     maxfbuf = 30;
+//     blendfactor=30;
+//     fcount=0;
+//     frames = new int[maxfbuf][];
+//     for(int i=0; i<maxfbuf; i++){
+//        frames[i] = new int[model.points.size()];       
+//     }
+//   }
+//   public void apply(int[] colors) {
+//     if(fcount<maxfbuf){
+//       for(int i=0; i<colors.length; i++){
+//         frames[(maxfbuf-1)-fcount][i]=colors[i];
+//       }
+//       fcount++;
+//       return;
+//     } else {
+//       for(int i=maxfbuf-1; i>0; i--){
+//         frames[i] = frames[i-1];
+//       }
+//       frames[0] = new int[model.points.size()];
       
-      for(int i=0; i<colors.length; i++){
-        int r,g,b;
-        r=g=b=0;
-        for(int j=0; j<blendfactor; j++){          
-          if(j==0) { frames[0][i] = colors[i]; }
-          r += ((frames[j][i] >> 16) & 0xFF);
-          g += ((frames[j][i] >> 8) & 0xFF);
-          b += ((frames[j][i] >> 0) & 0xFF);
-        }
-        r/=blendfactor;
-        g/=blendfactor;
-        b/=blendfactor;
-        colorMode(ARGB);
-        colors[i] = (0xFF << 24) | (r << 16) | (g << 8) | b;
-        colorMode(HSB);
-      }
+//       for(int i=0; i<colors.length; i++){
+//         int r,g,b;
+//         r=g=b=0;
+//         for(int j=0; j<blendfactor; j++){          
+//           if(j==0) { frames[0][i] = colors[i]; }
+//           r += ((frames[j][i] >> 16) & 0xFF);
+//           g += ((frames[j][i] >> 8) & 0xFF);
+//           b += ((frames[j][i] >> 0) & 0xFF);
+//         }
+//         r/=blendfactor;
+//         g/=blendfactor;
+//         b/=blendfactor;
+//         colorMode(ARGB);
+//         colors[i] = (0xFF << 24) | (r << 16) | (g << 8) | b;
+//         colorMode(HSB);
+//       }
             
-    }
-  }
-}
-
-
-import netP5.*;
-import oscP5.*;
-
-
-
-abstract class OSCPattern extends SCPattern {
-  public OSCPattern(GLucose glucose){super(glucose);}
-  public abstract void oscEvent(OscMessage msg);
-}
-
-class Ball {
-  public int lastSeen;
-  public float x,y;
-  public Ball(){
-    x=y=lastSeen=0;  
-  }
-}
-
-class OSC_Balls extends OSCPattern {
-  Ball[] balls;
-  public OSC_Balls(GLucose glucose){
-    super(glucose);
-    balls = new Ball[20];
-    for(int i=0; i<balls.length; i++) { balls[i] = new Ball(); }    
-  }
-  void oscEvent(OscMessage msg){
-    String pattern[] = split(msg.addrPattern(), "/");    
-    int ballnum = int(pattern[3]);
-    balls[ballnum].lastSeen=millis();
-    balls[ballnum].x = msg.get(0).floatValue();
-    balls[ballnum].y = msg.get(1).floatValue();    
-  }
+//     }
+//   }
+// }
+
+
+
+// abstract class OSCPattern extends SCPattern {
+//   public OSCPattern(LX lx){super(lx);}
+//   public abstract void oscEvent(OscMessage msg);
+// }
+
+// class Ball {
+//   public int lastSeen;
+//   public float x,y;
+//   public Ball(){
+//     x=y=lastSeen=0;  
+//   }
+// }
+
+// class OSC_Balls extends OSCPattern {
+//   Ball[] balls;
+//   public OSC_Balls(LX lx){
+//     super(lx);
+//     balls = new Ball[20];
+//     for(int i=0; i<balls.length; i++) { balls[i] = new Ball(); }    
+//   }
+//   void oscEvent(OscMessage msg){
+//     String pattern[] = split(msg.addrPattern(), "/");    
+//     int ballnum = int(pattern[3]);
+//     balls[ballnum].lastSeen=millis();
+//     balls[ballnum].x = msg.get(0).floatValue();
+//     balls[ballnum].y = msg.get(1).floatValue();    
+//   }
   
-  void run(double deltaMs){
-    for(LXPoint p: model.points){ colors[p.index]=0; }
-    for(int i=1; i<balls.length; i++){
-      if(millis() - balls[i].lastSeen < 1000) {
-        for(LXPoint p: model.points){
-          int x = int(balls[i].x * 255.0);
-          int y = int(balls[i].y * 127.0);
-          if(p.x < x+4 && p.x > x-4 && p.y < y+4 && p.y > y-4) { colors[p.index] = #FF0000; } 
-        }
-      }
-    }
-  }
-}
-
-import processing.serial.*;
-
-
-/*class ScreenScrape extends SCPattern {
-  PImage pret;
-  ScreenShot ss;
-  public ScreenScrape(GLucose glucose) {
-    super(glucose);
-    System.loadLibrary("ScreenShot");
-    pret = new PImage(8, 128, ARGB);
-    ss = new ScreenShot();
-  }
-  void run(double deltaMs){
-     int x=(1366/2)+516;
-     int y=768-516;
-     int w=8;
-     int h=128;
-     pret.pixels = ss.getScreenShotJNI2(x, y, w, h);
-     //for(int i=0; i<px.length; i++){ pret.pixels[i] = px[i]; }
-     //println(pret.get(10,10));
-     for(LXPoint p: model.points){
-       colors[p.index] = pret.get((int(p.x)/8)*8, 128-int(p.y));
-     }     
-  }
-}*/
+//   void run(double deltaMs){
+//     for(LXPoint p: model.points){ colors[p.index]=0; }
+//     for(int i=1; i<balls.length; i++){
+//       if(millis() - balls[i].lastSeen < 1000) {
+//         for(LXPoint p: model.points){
+//           int x = int(balls[i].x * 255.0);
+//           int y = int(balls[i].y * 127.0);
+//           if(p.x < x+4 && p.x > x-4 && p.y < y+4 && p.y > y-4) { colors[p.index] = #FF0000; } 
+//         }
+//       }
+//     }
+//   }
+// }
+
+// import processing.serial.*;
+
+
+// /*class ScreenScrape extends SCPattern {
+//   PImage pret;
+//   ScreenShot ss;
+//   public ScreenScrape(LX lx) {
+//     super(lx);
+//     System.loadLibrary("ScreenShot");
+//     pret = new PImage(8, 128, ARGB);
+//     ss = new ScreenShot();
+//   }
+//   void run(double deltaMs){
+//      int x=(1366/2)+516;
+//      int y=768-516;
+//      int w=8;
+//      int h=128;
+//      pret.pixels = ss.getScreenShotJNI2(x, y, w, h);
+//      //for(int i=0; i<px.length; i++){ pret.pixels[i] = px[i]; }
+//      //println(pret.get(10,10));
+//      for(LXPoint p: model.points){
+//        colors[p.index] = pret.get((int(p.x)/8)*8, 128-int(p.y));
+//      }     
+//   }
+// }*/
 
index 382cf975c8a36740b4f15079783f657a52e720f1..44478befa3c5c8c6173bc1fe864d39497a65af9e 100644 (file)
@@ -124,8 +124,8 @@ public class DPat extends SCPattern
                updateLights(); 
        }
 
-       DPat(GLucose glucose) {
-               super(glucose);
+       DPat(LX lx) {
+               super(lx);
 
                pSpark          =       addParam("Sprk",  0);
                pWave           =       addParam("Wave",  0);
@@ -287,7 +287,7 @@ class dLattice {
        dPixel getClosest(PVector p) {
                dVertex v = null; int pos=0; float d = 500;
 
-               for (Strip s : glucose.model.strips) {
+               for (Strip s : model.strips) {
                        float nd = pd2(s.points.get(0),p.x,p.y,p.z); if (nd < d) { v=v0(s); d=nd; pos=0; }
                        if (nd > 30) continue;
                        for (int k=0; k<=15; k++) {
@@ -300,13 +300,13 @@ class dLattice {
        dLattice() {
                lattice=this;
 
-               for (Strip s  : glucose.model.strips) {
+               for (Strip s  : model.strips) {
                        dVertex vrtx0 = new dVertex(s,s.points.get(0 )); s.obj1=vrtx0;
                        dVertex vrtx1 = new dVertex(s,s.points.get(15)); s.obj2=vrtx1;
                        vrtx0.setOpp(vrtx1); vrtx1.setOpp(vrtx0);
                }
 
-               for (Strip s1 : glucose.model.strips) { for (Strip s2 : glucose.model.strips) {
+               for (Strip s1 : model.strips) { for (Strip s2 : model.strips) {
                        if (s1.points.get(0).index < s2.points.get(0).index) continue;
                        int c=0;
                        if (sameSame(s1,s2))    {       v0(s1).same = v0(s2); v1(s1).same = v1(s2);
diff --git a/DebugUI.pde b/DebugUI.pde
deleted file mode 100644 (file)
index a36f688..0000000
+++ /dev/null
@@ -1,283 +0,0 @@
-/**
- *     DOUBLE BLACK DIAMOND        DOUBLE BLACK DIAMOND
- *
- *         //\\   //\\                 //\\   //\\  
- *        ///\\\ ///\\\               ///\\\ ///\\\
- *        \\\/// \\\///               \\\/// \\\///
- *         \\//   \\//                 \\//   \\//
- *
- *        EXPERTS ONLY!!              EXPERTS ONLY!!
- *
- * Overlay UI that indicates pattern control, etc. This will be moved
- * into the Processing library once it is stabilized and need not be
- * regularly modified.
- */
-
-class DebugUI {
-  
-  final ChannelMapping[] channelList;
-  final int debugX = 5;
-  final int debugY = 5;
-  final int debugXSpacing = 28;
-  final int debugYSpacing = 21;
-  final int[][] debugState;
-  final int[] indexState;
-    
-  final int CUBE_STATE_UNUSED = 0;
-  final int CUBE_STATE_USED = 1;
-  final int CUBE_STATE_DUPLICATED = 2;
-  
-  final int DEBUG_STATE_ANIM = 0;
-  final int DEBUG_STATE_WHITE = 1;
-  final int DEBUG_STATE_OFF = 2;
-  final int DEBUG_STATE_UNUSED = 3;  
-  
-  DebugUI(PandaMapping[] pandaMappings) {
-    int totalChannels = pandaMappings.length * PandaMapping.CHANNELS_PER_BOARD;
-    debugState = new int[totalChannels+1][ChannelMapping.CUBES_PER_CHANNEL+1];
-    indexState = new int[glucose.model.cubes.size()+1];
-    
-    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;
-      }
-    }
-    
-    for (int rawIndex = 0; rawIndex < glucose.model.cubes.size()+1; ++rawIndex) {
-      indexState[rawIndex] = CUBE_STATE_UNUSED;
-    }
-    for (ChannelMapping channel : channelList) {
-      for (int rawCubeIndex : channel.objectIndices) {
-        if (rawCubeIndex > 0)
-          ++indexState[rawCubeIndex];
-      }
-    }
-  }
-  
-  void draw() {
-    noStroke();
-    int xBase = debugX;
-    int yPos = debugY;
-    
-    textSize(10);
-    
-    fill(#000000);
-    rect(0, 0, debugX + 5*debugXSpacing, height);
-    
-    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], indexState[rawCubeIndex]);
-            ++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_STRUTS_AND_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]);
-    yPos += debugYSpacing * 2;
-   
-    noFill();
-    fill(#CCCCCC);
-    text("Unused Cubes",  xBase, yPos + 12);
-    yPos += debugYSpacing;
-    
-    int xIndex = 0;
-    for (int rawIndex = 1; rawIndex <= glucose.model.cubes.size(); ++rawIndex) {
-      if (indexState[rawIndex] == CUBE_STATE_UNUSED) {
-        drawNumBox(xBase + (xIndex * debugXSpacing), yPos, rawIndex, DEBUG_STATE_UNUSED);
-        ++xIndex;
-        if (xIndex > 4) {
-          xIndex = 0;
-          yPos += debugYSpacing + 2;
-        }
-      }
-    }
-  }
-
-  
-  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) {
-    drawNumBox(xPos, yPos, "" + label, state, CUBE_STATE_USED);
-  }
-
-  void drawNumBox(int xPos, int yPos, int label, int state, int cubeState) {
-    drawNumBox(xPos, yPos, "" + label, state, cubeState);
-  }
-  
-  void drawNumBox(int xPos, int yPos, String label, int state, int cubeState) {
-    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);
-        break;
-      case DEBUG_STATE_WHITE:
-        stroke(textColor);
-        fill(#e9e9e9);
-        textColor = #333333;
-        break;
-      case DEBUG_STATE_OFF:
-        stroke(textColor);
-        break;
-      case DEBUG_STATE_UNUSED:
-        stroke(textColor);
-        fill(#880000);
-        break;
-    }
-    
-    if (cubeState >= CUBE_STATE_DUPLICATED) {
-      stroke(textColor = #FF0000);
-    }
-
-    rect(xPos, yPos, 16, 16);     
-    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 (LXPoint 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 (Strip s : glucose.model.bassBox.boxStrips) {
-                for (LXPoint p : s.points) {
-                  colors[p.index] = debugColor;
-                }
-              }
-           }
-           break;
-
-         case ChannelMapping.MODE_STRUTS_AND_FLOOR:
-           state = debugState[channelIndex][1];
-           if (state != DEBUG_STATE_ANIM) {
-              color debugColor = (state == DEBUG_STATE_WHITE) ? white : off;
-              for (LXPoint p : glucose.model.boothFloor.points) {
-                colors[p.index] = debugColor;
-              }
-              for (Strip s : glucose.model.bassBox.struts) {
-                for (LXPoint p : s.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 (LXPoint 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;
-    }
-  }
-  
-  boolean mousePressed() {
-    int dx = (mouseX - debugX) / debugXSpacing;
-    int dy = (mouseY - debugY) / debugYSpacing;
-    if ((dy < 0) || (dy >= debugState.length)) {
-      return false;
-    }
-    if ((dx < 0) || (dx >= debugState[dy].length)) {
-      return false;
-    }
-    int newState = debugState[dy][dx] = (debugState[dy][dx] + 1) % 3;
-    if (dy == debugState.length-1) {
-      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;
-      }
-    }
-    return true;
-  }    
-}
-
index da4c78f3955fbb1831ce6fab4532c20989acf3c4..83a70be6eca6e5f05c3892797ecb22cfc4b6de20 100644 (file)
@@ -79,9 +79,9 @@ class GranimPattern extends SCPattern
 {
        HashMap<String,Graphic> displayList;
 
-       GranimPattern(GLucose glucose)
+       GranimPattern(LX lx)
        {
-               super(glucose);
+               super(lx);
                displayList = new HashMap<String,Graphic>();
        }
 
diff --git a/Grizzly.pde b/Grizzly.pde
new file mode 100644 (file)
index 0000000..5f46b96
--- /dev/null
@@ -0,0 +1,158 @@
+/**
+ *     DOUBLE BLACK DIAMOND        DOUBLE BLACK DIAMOND
+ *
+ *         //\\   //\\                 //\\   //\\  
+ *        ///\\\ ///\\\               ///\\\ ///\\\
+ *        \\\/// \\\///               \\\/// \\\///
+ *         \\//   \\//                 \\//   \\//H
+ *
+ *        EXPERTS ONLY!!              EXPERTS ONLY!!
+ *
+ * If you are an artist, you may ignore this file! It contains
+ * the code to drive grizzly board outputs.
+ */
+import java.net.*;
+GrizzlyOutput[] buildGrizzlies() throws SocketException, UnknownHostException {
+  return new GrizzlyOutput[] {
+    new GrizzlyOutput(lx, "192.168.88.100", 6, 5, 6, 7, 7, 8, 1, 2, 4, 3, 11, 10, 9, 9, 12, 13),
+    new GrizzlyOutput(lx, "192.168.88.101", 25, 23, 24, 43, 45, 44, 1, 1, 1, 1, 1, 41, 42, 21, 20, 22),
+    new GrizzlyOutput(lx, "192.168.88.104", 26, 28, 27, 19, 18, 17, 1, 1, 18, 19, 15, 16, 14, 29, 30, 31),
+    new GrizzlyOutput(lx, "192.168.88.105", 1, 1, 1, 39, 38, 40, 34, 35, 33, 32, 37, 37, 1, 1, 1, 1),
+  };
+}
+
+/**
+ * Grizzly Output, sends packets to one grizzly board with a fixed IP and a number
+ * of channels.
+ */
+class GrizzlyOutput extends LXDatagramOutput {
+
+  public final String ipAddress;
+  
+  private int frameNumber = 0;
+  
+  public GrizzlyOutput(LX lx, String ipAddress, int ... cubeIndices) throws UnknownHostException, SocketException {
+    super(lx);
+    this.ipAddress = ipAddress;
+    int channelNum = 0;
+    for (int rawCubeIndex : cubeIndices) {
+      if (rawCubeIndex > 0) {
+        Cube cube = model.getCubeByRawIndex(rawCubeIndex);
+        addDatagram(new GrizzlyDatagram(this, channelNum, cube).setAddress(ipAddress));
+      }
+      ++channelNum;
+    }
+    this.enabled.setValue(false);
+  }
+  
+  protected void beforeSend(int[] colors) {
+    ++frameNumber;
+  }
+  
+  public int getFrameNumber() {
+    return this.frameNumber;
+  }
+}
+
+/**
+ * Datagram to a Grizzlyboard. A simple fixed OSC packet.
+ */
+static class GrizzlyDatagram extends LXDatagram {
+  
+  private static byte[] oscString(String s) {
+    int len = s.length();
+    int padding = (4 - ((len + 1) % 4)) % 4;
+    byte[] bytes = new byte[len + 1 + padding];
+    System.arraycopy(s.getBytes(), 0, bytes, 0, len);
+    for (int i = len; i < bytes.length; ++i) {
+      bytes[i] = 0;
+    }
+    return bytes;
+  }
+  
+  private static int oscIntCopy(int i, byte[] buffer, int pos) {
+    buffer[pos] = (byte) ((i >> 24) & 0xff);
+    buffer[pos + 1] = (byte) ((i >> 16) & 0xff);
+    buffer[pos + 2] = (byte) ((i >> 8) & 0xff);
+    buffer[pos + 3] = (byte) (i & 0xff);
+    return 4;
+  }
+  
+  private final static int[] STRIP_ORDERING = new int[] { 9, 8, 11, 5, 4, 7, 6, 10, 14, 2, 1, 0, 3, 13, 12, 15 };
+  
+  private static int[] cubePointIndices(Cube cube) {
+    int[] pointIndices = new int[Cube.POINTS_PER_CUBE - 2];
+    int pi = 0;
+    for (int stripIndex : STRIP_ORDERING) {
+      Strip strip = cube.strips.get(stripIndex);
+      int stripLen = ((stripIndex == 9) || (stripIndex == 15)) ? 15 : 16;
+      for (int i = stripLen-1; i >= 0; --i) {
+        pointIndices[pi++] = strip.points.get(i).index;
+      }
+    }
+    return pointIndices;
+  }
+  
+  private final static byte[] OSC_ADDRESS = oscString("/shady/pointbuffer");
+  private final static byte[] OSC_TYPETAG = oscString(",iiiiibi");  
+
+  private final static int HEADER_LENGTH = OSC_ADDRESS.length + OSC_TYPETAG.length + 24;
+  private final static int FOOTER_LENGTH = 4;
+
+  private final static int OSC_PORT = 779;
+
+  private GrizzlyOutput output;
+  
+  private int[] pointIndices;
+
+  private final int frameNumberPos;
+  
+  private final int dataPos;
+  
+  public GrizzlyDatagram(GrizzlyOutput output, int channelNum, Cube cube) {
+    this(output, channelNum, cubePointIndices(cube));
+  }
+  
+  public GrizzlyDatagram(GrizzlyOutput output, int channelNum, int[] pointIndices) {
+    super(HEADER_LENGTH + 4*pointIndices.length + FOOTER_LENGTH);
+    setPort(OSC_PORT);
+    
+    this.output = output;
+    this.pointIndices = pointIndices;
+    int dataLength = 4*pointIndices.length;
+    
+    int pos = 0;
+
+    // OSC address
+    System.arraycopy(OSC_ADDRESS, 0, this.buffer, pos, OSC_ADDRESS.length);
+    pos += OSC_ADDRESS.length;
+
+    // OSC typetag
+    System.arraycopy(OSC_TYPETAG, 0, this.buffer, pos, OSC_TYPETAG.length);
+    pos += OSC_TYPETAG.length;
+    this.frameNumberPos = pos;
+    pos += oscIntCopy(0, this.buffer, pos); // placeholder for frame number
+    pos += oscIntCopy(0xDEADBEEF, this.buffer, pos);
+    pos += oscIntCopy(channelNum, this.buffer, pos);
+    pos += oscIntCopy(0xFEEDBEEF, this.buffer, pos);
+    pos += oscIntCopy(dataLength, this.buffer, pos);
+    pos += oscIntCopy(dataLength, this.buffer, pos);
+    this.dataPos = pos;
+    
+    // end header
+    oscIntCopy(0xBEFFFFEB, this.buffer, this.buffer.length - 4);
+  }
+  
+  void onSend(int[] colors) {
+    oscIntCopy(this.output.getFrameNumber(), this.buffer, frameNumberPos);
+    int dataIndex = this.dataPos;
+    for (int index : this.pointIndices) {
+      color c = (index >= 0) ? colors[index] : 0;
+      this.buffer[dataIndex] = (byte) 0; // unused, alpha
+      this.buffer[dataIndex + 1] = (byte) ((c >> 16) & 0xff); // r
+      this.buffer[dataIndex + 2] = (byte) ((c >> 8) & 0xff); // g
+      this.buffer[dataIndex + 3] = (byte) (c & 0xff); // b
+      dataIndex += 4;
+    }
+  }
+}
index a1b8baf03f6ea1ca1cfda7833ec6021098b6c22b..b593f3ef07b9c4aa7db088430348d3da9c653ae7 100644 (file)
  * for general animation work.
  */
 
-import glucose.*;
-import glucose.model.*;
 import heronarts.lx.*;
 import heronarts.lx.effect.*;
+import heronarts.lx.model.*;
 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.*;
-import javax.media.opengl.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
-final int VIEWPORT_WIDTH = 900;
-final int VIEWPORT_HEIGHT = 700;
+static final int VIEWPORT_WIDTH = 900;
+static final int VIEWPORT_HEIGHT = 700;
+
+static final int LEFT_DECK = 0;
+static final int RIGHT_DECK = 1;
 
 // The trailer is measured from the outside of the black metal (but not including the higher welded part on the front)
-final float TRAILER_WIDTH = 240;
-final float TRAILER_DEPTH = 97;
-final float TRAILER_HEIGHT = 33;
+static final float TRAILER_WIDTH = 192;
+static final float TRAILER_DEPTH = 192;
+static final float TRAILER_HEIGHT = 33;
 
 int targetFramerate = 60;
 int startMillis, lastMillis;
 
 // Core engine variables
-GLucose glucose;
 LX lx;
+Model model;
 LXPattern[] patterns;
+LXTransition[] transitions;
 Effects effects;
+LXEffect[] effectsArr;
+DiscreteParameter selectedEffect;
 MappingTool mappingTool;
-PandaDriver[] pandaBoards;
+GrizzlyOutput[] grizzlies;
 PresetManager presetManager;
 MidiEngine midiEngine;
 
 // Display configuration mode
 boolean mappingMode = false;
 boolean debugMode = false;
-DebugUI debugUI;
-boolean uiOn = true;
 boolean simulationOn = true;
 boolean diagnosticsOn = false;
 LXPattern restoreToPattern = null;
@@ -62,7 +70,6 @@ PImage logo;
 float[] hsb = new float[3];
 
 // Handles to UI objects
-UIContext[] overlays;
 UIPatternDeck uiPatternA;
 UICrossfader uiCrossfader;
 UIMidi uiMidi;
@@ -70,30 +77,27 @@ UIMapping uiMapping;
 UIDebugText uiDebugText;
 UISpeed uiSpeed;
 
-// Camera variables
-float eyeR, eyeA, eyeX, eyeY, eyeZ, midX, midY, midZ;
-
 /**
  * Engine construction and initialization.
  */
 
-LXTransition _transition(GLucose glucose) {
-  return new DissolveTransition(glucose.lx).setDuration(1000);
+LXTransition _transition(LX lx) {
+  return new DissolveTransition(lx).setDuration(1000);
 }
 
-LXPattern[] _leftPatterns(GLucose glucose) {
-  LXPattern[] patterns = patterns(glucose);
+LXPattern[] _leftPatterns(LX lx) {
+  LXPattern[] patterns = patterns(lx);
   for (LXPattern p : patterns) {
-    p.setTransition(_transition(glucose));
+    p.setTransition(_transition(lx));
   }
   return patterns;
 }
 
-LXPattern[] _rightPatterns(GLucose glucose) {
-  LXPattern[] patterns = _leftPatterns(glucose);
+LXPattern[] _rightPatterns(LX lx) {
+  LXPattern[] patterns = _leftPatterns(lx);
   LXPattern[] rightPatterns = new LXPattern[patterns.length+1];
   int i = 0;
-  rightPatterns[i++] = new BlankPattern(glucose).setTransition(_transition(glucose));
+  rightPatterns[i++] = new BlankPattern(lx).setTransition(_transition(lx));
   for (LXPattern p : patterns) {
     rightPatterns[i++] = p;
   }
@@ -111,7 +115,11 @@ LXEffect[] _effectsArray(Effects effects) {
     } catch (IllegalAccessException iax) {}
   }
   return effectList.toArray(new LXEffect[]{});
-} 
+}
+
+LXEffect getSelectedEffect() {
+  return effectsArr[selectedEffect.getValuei()];
+}
 
 void logTime(String evt) {
   int now = millis();
@@ -129,20 +137,29 @@ void setup() {
   // hint(ENABLE_OPENGL_4X_SMOOTH); // no discernable improvement?
   logTime("Created viewport");
 
-  // Create the GLucose engine to run the cubes
-  glucose = new GLucose(this, buildModel());
-  lx = glucose.lx;
+  // Create the model
+  model = buildModel();
+  logTime("Built Model");
+  
+  // LX engine
+  lx = new LX(this, model);
   lx.enableKeyboardTempo();
-  logTime("Built GLucose engine");
+  logTime("Built LX engine");
     
   // Set the patterns
   LXEngine engine = lx.engine;
-  engine.setPatterns(patterns = _leftPatterns(glucose));
-  engine.addDeck(_rightPatterns(glucose));
+  engine.setPatterns(patterns = _leftPatterns(lx));
+  engine.addDeck(_rightPatterns(lx));
   logTime("Built patterns");
-  glucose.setTransitions(transitions(glucose));
+
+  // Transitions
+  transitions = transitions(lx);
+  lx.engine.getDeck(RIGHT_DECK).setFaderTransition(transitions[0]);
   logTime("Built transitions");
-  glucose.lx.addEffects(_effectsArray(effects = new Effects()));
+  
+  // Effects
+  lx.addEffects(effectsArr = _effectsArray(effects = new Effects()));
+  selectedEffect = new DiscreteParameter("EFFECT", effectsArr.length);
   logTime("Built effects");
 
   // Preset manager
@@ -154,93 +171,160 @@ void setup() {
   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 tool
+  mappingTool = new MappingTool(lx);
+  logTime("Built Mapping Tool");
+  
   // Build overlay UI
-  debugUI = new DebugUI(pandaMappings);
-  overlays = new UIContext[] {
-    uiPatternA = new UIPatternDeck(lx.engine.getDeck(GLucose.LEFT_DECK), "PATTERN A", 4, 4, 140, 324),
+  UILayer[] layers = new UILayer[] {
+    // Camera layer
+    new UICameraLayer(lx.ui)
+      .setCenter(model.cx, model.cy, model.cz)
+      .setRadius(290).addComponent(new UICubesLayer()),
+    
+    // Left controls
+    uiPatternA = new UIPatternDeck(lx.ui, lx.engine.getDeck(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),
     uiSpeed = new UISpeed(4, 624, 140, 50),
         
-    new UIPatternDeck(lx.engine.getDeck(GLucose.RIGHT_DECK), "PATTERN B", width-144, 4, 140, 324),
+    // Right controls
+    new UIPatternDeck(lx.ui, lx.engine.getDeck(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");
 }
 
+public SCPattern getPattern() {
+  return (SCPattern) lx.getPattern();
+}      
+
+/**
+ * Subclass of LXPattern specific to sugar cubes. These patterns
+ * get access to the state and geometry, and have some
+ * little helpers for interacting with the model.
+ */
+public static abstract class SCPattern extends LXPattern {
+               
+  protected SCPattern(LX lx) {
+    super(lx);
+  }
+       
+  /**
+   * Reset this pattern to its default state.
+   */
+  public final void reset() {
+    for (LXParameter parameter : getParameters()) {
+      parameter.reset();
+    }
+    onReset();
+  }
+       
+  /**
+   * Subclasses may override to add additional reset functionality.
+   */
+  protected /*abstract*/ void onReset() {}
+       
+  /**
+   * Invoked by the engine when a grid controller button press occurs
+   * 
+   * @param row Row index on the gird
+   * @param col Column index on the grid
+   * @return True if the event was consumed, false otherwise
+   */
+  public boolean gridPressed(int row, int col) {
+    return false;
+  }
+       
+  /**
+   * Invoked by the engine when a grid controller button release occurs
+   * 
+   * @param row Row index on the gird
+   * @param col Column index on the grid
+   * @return True if the event was consumed, false otherwise
+   */
+  public boolean gridReleased(int row, int col) {
+    return false;
+  }
+       
+  /**
+   * Invoked by engine when this pattern is focused an a midi note is received.  
+   * 
+   * @param note
+   * @return True if the pattern has consumed this note, false if the top-level
+   *         may handle it
+   */
+  public boolean noteOn(rwmidi.Note note) {
+    return false;
+  }
+       
+  /**
+   * Invoked by engine when this pattern is focused an a midi note off is received.  
+   * 
+   * @param note
+   * @return True if the pattern has consumed this note, false if the top-level
+   *         may handle it
+   */
+  public boolean noteOff(rwmidi.Note note) {
+    return false;
+  }
+       
+  /**
+   * Invoked by engine when this pattern is focused an a controller is received  
+   * 
+   * @param note
+   * @return True if the pattern has consumed this controller, false if the top-level
+   *         may handle it
+   */
+  public boolean controllerChange(rwmidi.Controller controller) {
+    return false;
+  }
+}
+
+long simulationNanos = 0;
+
 /**
  * Core render loop and drawing functionality.
  */
 void draw() {
   long drawStart = System.nanoTime();
   
-  // Draws the simulation and the 2D UI overlay
+  // Set background
   background(40);
-
-  color[] simulationColors;
-  color[] sendColors;
-  simulationColors = sendColors = 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();
-  }
-  if (debugMode) {
-    debugUI.maskColors(simulationColors);
-    debugUI.maskColors(sendColors);
-  }
-
-  long simulationStart = System.nanoTime();
-  if (simulationOn) {
-    drawSimulation(simulationColors);
-  }
-  long simulationNanos = System.nanoTime() - simulationStart;
-  
-  // 2D Overlay UI
-  long uiStart = System.nanoTime();
-  drawUI();
-  long uiNanos = System.nanoTime() - uiStart;
   
+  // Send colors
+  color[] sendColors = lx.getColors();  
   long gammaStart = System.nanoTime();
   // Gamma correction here. Apply a cubic to the brightness
   // for better representation of dynamic range
@@ -250,21 +334,20 @@ void draw() {
     sendColors[i] = lx.hsb(360.*hsb[0], 100.*hsb[1], 100.*(b*b*b));
   }
   long gammaNanos = System.nanoTime() - gammaStart;
-  
-  long sendStart = System.nanoTime();
-  for (PandaDriver p : pandaBoards) {
-    p.send(sendColors);
-  }
-  long sendNanos = System.nanoTime() - sendStart;
-  
+
+  // Always draw FPS meter
+  drawFPS();
+
+  // TODO(mcslee): fix
   long drawNanos = System.nanoTime() - drawStart;
-  
+  long uiNanos = 0;
+
   if (diagnosticsOn) {
-    drawDiagnostics(drawNanos, simulationNanos, uiNanos, gammaNanos, sendNanos);
-  }
+    drawDiagnostics(drawNanos, simulationNanos, uiNanos, gammaNanos);
+  }  
 }
 
-void drawDiagnostics(long drawNanos, long simulationNanos, long uiNanos, long gammaNanos, long sendNanos) {
+void drawDiagnostics(long drawNanos, long simulationNanos, long uiNanos, long gammaNanos) {
   float ws = 4 / 1000000.;
   int thirtyfps = 1000000000 / 30;
   int sixtyfps = 1000000000 / 60;
@@ -277,7 +360,7 @@ void drawDiagnostics(long drawNanos, long simulationNanos, long uiNanos, long ga
   noStroke();
   int xp = x;
   float hv = 0;
-  for (long val : new long[] {lx.timer.drawNanos, simulationNanos, uiNanos, gammaNanos, sendNanos }) {
+  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;
@@ -321,190 +404,12 @@ void drawDiagnostics(long drawNanos, long simulationNanos, long uiNanos, long ga
   }
 }
 
-void drawSimulation(color[] simulationColors) {
-  camera(
-    eyeX, eyeY, eyeZ,
-    midX, midY, midZ,
-    0, -1, 0
-  );
-
-  translate(0, 40, 0);
-
-  noStroke();
-  fill(#141414);
-  drawBox(0, -TRAILER_HEIGHT, 0, 0, 0, 0, TRAILER_WIDTH, TRAILER_HEIGHT, TRAILER_DEPTH, TRAILER_HEIGHT/2.);
-  fill(#070707);
-  stroke(#222222);
-  beginShape();
-  vertex(0, 0, 0);
-  vertex(TRAILER_WIDTH, 0, 0);
-  vertex(TRAILER_WIDTH, 0, TRAILER_DEPTH);
-  vertex(0, 0, TRAILER_DEPTH);
-  endShape();
-
-  // Draw the logo on the front of platform  
-  pushMatrix();
-  translate(0, 0, -1);
-  float s = .07;
-  scale(s, -s, s);
-  image(logo, TRAILER_WIDTH/2/s-logo.width/2, TRAILER_HEIGHT/2/s-logo.height/2-2/s);
-  popMatrix();
-  
-  noStroke();
-  if (glucose.model.bassBox.exists) {
-    drawBassBox(glucose.model.bassBox, false);
-  }
-  for (Speaker speaker : glucose.model.speakers) {
-    drawSpeaker(speaker);
-  }
-  for (Cube c : glucose.model.cubes) {
-    drawCube(c);
-  }
-
-  noFill();
-  strokeWeight(2);
-  beginShape(POINTS);
-  for (LXPoint p : glucose.model.points) {
-    stroke(simulationColors[p.index]);
-    vertex(p.x, p.y, p.z);
-  }
-  endShape();
-}
-
-void drawBassBox(BassBox b, boolean hasSub) {
-  
-  float in = .15;
-  
-  if (hasSub) {
-    noStroke();
-    fill(#191919);
-    pushMatrix();
-    translate(b.x + BassBox.EDGE_WIDTH/2., b.y + BassBox.EDGE_HEIGHT/2, b.z + BassBox.EDGE_DEPTH/2.);
-    box(BassBox.EDGE_WIDTH-20*in, BassBox.EDGE_HEIGHT-20*in, BassBox.EDGE_DEPTH-20*in);
-    popMatrix();
-  }
-
-  noStroke();
-  fill(#393939);
-  drawBox(b.x+in, b.y+in, b.z+in, 0, 0, 0, BassBox.EDGE_WIDTH-in*2, BassBox.EDGE_HEIGHT-in*2, BassBox.EDGE_DEPTH-in*2, Cube.CHANNEL_WIDTH-in);
-
-  pushMatrix();
-  translate(b.x+(Cube.CHANNEL_WIDTH-in)/2., b.y + BassBox.EDGE_HEIGHT-in, b.z + BassBox.EDGE_DEPTH/2.);
-  float lastOffset = 0;
-  for (float offset : BoothFloor.STRIP_OFFSETS) {
-    translate(offset - lastOffset, 0, 0);
-    box(Cube.CHANNEL_WIDTH-in, 0, BassBox.EDGE_DEPTH - 2*in);
-    lastOffset = offset;
-  }
-  popMatrix();
-
-  pushMatrix();
-  translate(b.x + (Cube.CHANNEL_WIDTH-in)/2., b.y + BassBox.EDGE_HEIGHT/2., b.z + in);
-  for (int j = 0; j < 2; ++j) {
-    pushMatrix();
-    for (int i = 0; i < BassBox.NUM_FRONT_STRUTS; ++i) {
-      translate(BassBox.FRONT_STRUT_SPACING, 0, 0);
-      box(Cube.CHANNEL_WIDTH-in, BassBox.EDGE_HEIGHT - in*2, 0);
-    }
-    popMatrix();
-    translate(0, 0, BassBox.EDGE_DEPTH - 2*in);
-  }
-  popMatrix();
-  
-  pushMatrix();
-  translate(b.x + in, b.y + BassBox.EDGE_HEIGHT/2., b.z + BassBox.SIDE_STRUT_SPACING + (Cube.CHANNEL_WIDTH-in)/2.);
-  box(0, BassBox.EDGE_HEIGHT - in*2, Cube.CHANNEL_WIDTH-in);
-  translate(BassBox.EDGE_WIDTH-2*in, 0, 0);
-  box(0, BassBox.EDGE_HEIGHT - in*2, Cube.CHANNEL_WIDTH-in);
-  popMatrix();
-  
-}
-
-void drawCube(Cube c) {
-  float in = .15;
-  noStroke();
-  fill(#393939);  
-  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);
-}
-
-void drawSpeaker(Speaker s) {
-  float in = .15;
-  
-  noStroke();
-  fill(#191919);
-  pushMatrix();
-  translate(s.x, s.y, s.z);
-  rotate(s.ry / 180. * PI, 0, -1, 0);
-  translate(Speaker.EDGE_WIDTH/2., Speaker.EDGE_HEIGHT/2., Speaker.EDGE_DEPTH/2.);
-  box(Speaker.EDGE_WIDTH-20*in, Speaker.EDGE_HEIGHT-20*in, Speaker.EDGE_DEPTH-20*in);
-  translate(0, Speaker.EDGE_HEIGHT/2. + Speaker.EDGE_HEIGHT*.8/2, 0);
-
-  fill(#222222);
-  box(Speaker.EDGE_WIDTH*.6, Speaker.EDGE_HEIGHT*.8, Speaker.EDGE_DEPTH*.75);
-  popMatrix();
-  
-  noStroke();
-  fill(#393939);  
-  drawBox(s.x+in, s.y+in, s.z+in, 0, s.ry, 0, Speaker.EDGE_WIDTH-in*2, Speaker.EDGE_HEIGHT-in*2, Speaker.EDGE_DEPTH-in*2, Cube.CHANNEL_WIDTH-in);
-}
-
-void drawBox(float x, float y, float z, float rx, float ry, float rz, float xd, float yd, float zd, float sw) {
-  pushMatrix();
-  translate(x, y, z);
-  rotate(rx / 180. * PI, -1, 0, 0);
-  rotate(ry / 180. * PI, 0, -1, 0);
-  rotate(rz / 180. * PI, 0, 0, -1);
-  for (int i = 0; i < 4; ++i) {
-    float wid = (i % 2 == 0) ? xd : zd;
-    
-    beginShape();
-    vertex(0, 0);
-    vertex(wid, 0);
-    vertex(wid, yd);
-    vertex(wid - sw, yd);
-    vertex(wid - sw, sw);
-    vertex(0, sw);
-    endShape();
-    beginShape();
-    vertex(0, sw);
-    vertex(0, yd);
-    vertex(wid - sw, yd);
-    vertex(wid - sw, yd - sw);
-    vertex(sw, yd - sw);
-    vertex(sw, sw);
-    endShape();
-
-    translate(wid, 0, 0);
-    rotate(HALF_PI, 0, -1, 0);
-  }
-  popMatrix();
-}
-
-
-
-void drawUI() {
-  camera();
-  PGraphicsOpenGL gl = (PGraphicsOpenGL) g;  
-
-  //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();
-  }
 }
 
 
@@ -593,9 +498,10 @@ 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 'q':
@@ -608,64 +514,6 @@ void keyPressed() {
         simulationOn = !simulationOn;
       }
       break;
-    case 'u':
-      if (!midiEngine.isQwertyEnabled()) {
-        uiOn = !uiOn;
-      }
-      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);
-  }
-}
diff --git a/JR.pde b/JR.pde
index b1d8a437ce929293d43479ee1de8e615549462f6..07ddf386c9d990f300bc702d7a20cae892c33a44 100644 (file)
--- a/JR.pde
+++ b/JR.pde
@@ -23,8 +23,8 @@ class Gimbal extends SCPattern {
   private final BasicParameter bP = new BasicParameter("b", 0);
   private final BasicParameter gP = new BasicParameter("g", 0);
 
-  Gimbal(GLucose glucose) {
-    super(glucose);
+  Gimbal(LX lx) {
+    super(lx);
     projection = new LXProjection(model);
     addParameter(beatsPerRevolutionParam);
     addParameter(hueDeltaParam);
@@ -207,8 +207,8 @@ class Zebra extends SCPattern {
   _P size;
   */
 
-  Zebra(GLucose glucose) {
-    super(glucose);
+  Zebra(LX lx) {
+    super(lx);
     projection = new LXProjection(model);
 
     addModulator(angleM).trigger();
index 4299543b63119b222062060b6c4b9cd5f4651367..3b69815f92a4cbc6bb5472be00a134d8c3b92faf 100644 (file)
@@ -21,8 +21,8 @@ class Swim extends SCPattern {
 
   final BasicParameter hueScale = new BasicParameter("HUE", 0.3);
 
-  public Swim(GLucose glucose) {
-    super(glucose);
+  public Swim(LX lx) {
+    super(lx);
     projection = new LXProjection(model);
     addParameter(hueScale);
     addParameter(crazyParam);
@@ -108,8 +108,8 @@ class Balance extends SCPattern {
   private final float centerX, centerY, centerZ, modelHeight, modelWidth, modelDepth;
   SinLFO heightMod = new SinLFO(0.8, 1.9, 17298);
 
-  public Balance(GLucose glucose) {
-    super(glucose);
+  public Balance(LX lx) {
+    super(lx);
 
     projection = new LXProjection(model);
 
index dc5922f6d4c51df660bfdbf38817eb686f9d65ab..fe18092e129a0bee2450c01cfb75ab3d68d40274 100644 (file)
@@ -43,8 +43,8 @@ class JackieSquares extends SCPattern {
   private List<FaceFlash> flashes;
   private int faceNum = 0;
   
-  public JackieSquares(GLucose glucose) {
-    super(glucose);
+  public JackieSquares(LX lx) {
+    super(lx);
     addParameter(rateParameter);
     addParameter(attackParameter);
     addParameter(decayParameter);
@@ -132,8 +132,8 @@ class JackieLines extends SCPattern {
   private List<StripFlash> flashes;
   private int stripNum = 0;
   
-  public JackieLines(GLucose glucose) {
-    super(glucose);
+  public JackieLines(LX lx) {
+    super(lx);
     addParameter(rateParameter);
     addParameter(attackParameter);
     addParameter(decayParameter);
@@ -222,8 +222,8 @@ class JackieDots extends SCPattern {
   private List<PointFlash> flashes;
   private int pointNum = 0;
   
-  public JackieDots(GLucose glucose) {
-    super(glucose);
+  public JackieDots(LX lx) {
+    super(lx);
     addParameter(rateParameter);
     addParameter(attackParameter);
     addParameter(decayParameter);
index fc4bac0040c9d92e08add0066f6975140662eb94..a81901617938ddd9c8ff0e16736f5d2b65333586 100644 (file)
@@ -42,8 +42,8 @@ class L8onLife extends SCPattern {
   // Hold the new lives
   private List<Boolean> new_lives;
   
-  public L8onLife(GLucose glucose) {
-     super(glucose);  
+  public L8onLife(LX lx) {
+     super(lx);  
      
      //Print debug info about the cubes.
      //outputCubeInfo();
@@ -310,8 +310,8 @@ class L8onAutomata extends SCPattern {
   // Hold the new lives
   private List<Boolean> new_states;
 
-  public L8onAutomata(GLucose glucose) {
-     super(glucose);
+  public L8onAutomata(LX lx) {
+     super(lx);
 
      //Print debug info about the cubes.
      //outputCubeInfo();
@@ -552,8 +552,8 @@ class L8onStripLife extends SCPattern {
   // Hold the new lives
   private List<Boolean> new_lives;
 
-  public L8onStripLife(GLucose glucose) {
-     super(glucose);
+  public L8onStripLife(LX lx) {
+     super(lx);
 
      //Print debug info about the strips.
      //outputStripInfo();
index 2716494663ca33abb33be0908f86f618b22e06b1..5a198f0e608df954c68058678e480fafcff32998 100644 (file)
--- a/MIDI.pde
+++ b/MIDI.pde
@@ -115,7 +115,7 @@ public interface SCMidiInputListener {
   public void onEnabled(SCMidiInput controller, boolean enabled);
 }
 
-public abstract class SCMidiInput extends AbstractScrollItem {
+public abstract class SCMidiInput extends UIScrollList.AbstractItem {
 
   protected boolean enabled = false;
   private final String name;
@@ -445,7 +445,7 @@ public class APC40MidiInput extends GenericDeviceMidiInput {
 
     // Crossfader
     case 15:
-      lx.engine.getDeck(GLucose.RIGHT_DECK).getFader().setNormalized(value);
+      lx.engine.getDeck(RIGHT_DECK).getFader().setNormalized(value);
       return true;
       
     // Cue level
@@ -478,7 +478,8 @@ public class APC40MidiInput extends GenericDeviceMidiInput {
     
     if (number >= 20 && number <= 23) {
       int effectIndex = number - 20;
-      List<LXParameter> parameters = glucose.getSelectedEffect().getParameters();
+      // TODO(mclsee): fix selected effect
+      List<LXParameter> parameters = getSelectedEffect().getParameters();
       if (effectIndex < parameters.size()) {
         setNormalized(parameters.get(effectIndex), value);
         return true;
@@ -537,7 +538,7 @@ public class APC40MidiInput extends GenericDeviceMidiInput {
 
     case 91: // play
       if (shiftOn) {
-        midiEngine.setFocusedDeck(GLucose.LEFT_DECK);
+        midiEngine.setFocusedDeck(LEFT_DECK);
       } else {
         uiCrossfader.setDisplayMode("A");
       }
@@ -549,7 +550,7 @@ public class APC40MidiInput extends GenericDeviceMidiInput {
       
     case 93: // rec
       if (shiftOn) {
-        midiEngine.setFocusedDeck(GLucose.RIGHT_DECK);
+        midiEngine.setFocusedDeck(RIGHT_DECK);
       } else {
         uiCrossfader.setDisplayMode("B");
       }
@@ -557,7 +558,7 @@ public class APC40MidiInput extends GenericDeviceMidiInput {
 
     case 94: // up bank
       if (shiftOn) {
-        glucose.incrementSelectedEffectBy(-1);
+        selectedEffect.setValue(selectedEffect.getValuei() - 1);
       } else {
         getTargetDeck().goPrev();
       }
@@ -565,7 +566,7 @@ public class APC40MidiInput extends GenericDeviceMidiInput {
       
     case 95: // down bank
       if (shiftOn) {
-        glucose.incrementSelectedEffectBy(1);
+        selectedEffect.setValue(selectedEffect.getValuei() + 1);
       } else {
         getTargetDeck().goNext();
       }
@@ -588,7 +589,7 @@ public class APC40MidiInput extends GenericDeviceMidiInput {
       return true;
 
     case 62: // Detail View / red 5
-      releaseEffect = glucose.getSelectedEffect(); 
+      releaseEffect = getSelectedEffect(); 
       if (releaseEffect.isMomentary()) {
         releaseEffect.enable();
       } else {
@@ -597,7 +598,7 @@ public class APC40MidiInput extends GenericDeviceMidiInput {
       return true;
 
     case 63: // rec quantize / red 6
-      glucose.getSelectedEffect().disable();
+      getSelectedEffect().disable();
       return true;
     }
 
@@ -689,11 +690,11 @@ class KorgNanoKontrolMidiInput extends GenericDeviceMidiInput {
       switch (number) {
       
       case 58: // Left track
-        midiEngine.setFocusedDeck(GLucose.LEFT_DECK);
+        midiEngine.setFocusedDeck(LEFT_DECK);
         return true;
       
       case 59: // Right track
-        midiEngine.setFocusedDeck(GLucose.RIGHT_DECK);
+        midiEngine.setFocusedDeck(RIGHT_DECK);
         return true;
       
       case 43: // Left chevron
@@ -737,8 +738,8 @@ class APC40MidiOutput implements LXParameterListener, GridOutput {
         }
       });
     }
-    glucose.addEffectListener(new GLucose.EffectListener() {
-      public void effectSelected(LXEffect effect) {
+    selectedEffect.addListener(new LXParameterListener() {
+      public void onParameterChanged(LXParameter parameter) {
         resetEffectParameters();
       }
     });
@@ -842,7 +843,7 @@ class APC40MidiOutput implements LXParameterListener, GridOutput {
   }
   
   private void resetEffectParameters() {
-    LXEffect newEffect = glucose.getSelectedEffect();
+    LXEffect newEffect = getSelectedEffect();
     if (newEffect == focusedEffect) {
       return;
     }
index d1c51b2e4d3b1509493cfbb35fbae7064c6dc381..8798fb59fea91797853017ed978d5ad191538e71 100644 (file)
  * when physical changes or tuning is being done to the structure.
  */
 
-import java.util.Arrays;
+static final float SPACING = 27;
+static final float RISER = 13.5;
+static final float FLOOR = 0;
 
-final int MaxCubeHeight = 6;
-final int NumBackTowers = 16;
+/**
+ * Definitions of tower positions. This is all that should need
+ * to be modified. Distances are measured from the left-most cube.
+ * The first value is the offset moving NE (towards back-right).
+ * The second value is the offset moving NW (negative comes forward-right).
+ */
+static final float[][] TOWER_CONFIG = new float[][] {
+  new float[] { 0, 0, RISER, 4 },
+  new float[] { 25, -10, RISER, 4 },
+  new float[] { 50, -22.5, FLOOR, 5 },
+  new float[] { 17.25, -35.5, FLOOR, 6 },
+  new float[] { 43.25, -51.5, RISER, 6 },
+  new float[] { 69.25, -56, FLOOR, 6 },
+  new float[] { 12.75, -62.5, RISER, 4 },
+  new float[] { 38.75, -78.5, FLOOR, 5 },
+  new float[] { 65.75, -83, RISER, 5 },  
+
+};
 
 public Model buildModel() {
 
-  // Shorthand helpers for specifying wiring more quickly
-  final Cube.Wiring WFL = Cube.Wiring.FRONT_LEFT;
-  final Cube.Wiring WFR = Cube.Wiring.FRONT_RIGHT;
-  final Cube.Wiring WRL = Cube.Wiring.REAR_LEFT;
-  final Cube.Wiring WRR = Cube.Wiring.REAR_RIGHT;
-  
-  // Utility value if you need the height of a cube shorthand
-  final float CH = Cube.EDGE_HEIGHT;
-  final float CW = Cube.EDGE_WIDTH ;
-  
-  // Positions for the bass box
-  final float BBY = BassBox.EDGE_HEIGHT + BoothFloor.PLEXI_WIDTH;
-  final float BBX = 56;
-  final float BBZ = 2;
-
-  // The model is represented as an array of towers. The cubes in the tower
-  // are represenented relatively. Each tower has an x, y, z reference position,
-  // which is typically the base cube's bottom left corner.
-  //
-  // Following that is an array of floats. A 2-d array contains an x-offset
-  // and a z-offset from the previous reference position. Typically the first cube
-  // will just be {0, 0}. Each successive cube uses the position of the previous
-  // cube as its reference.
-  //
-  // A 3-d array contains an x-offset, a z-offset, and a rotation about the
-  // y-axis.
-  //
-  // The cubes automatically increment their y-position by Cube.EDGE_HEIGHT.
-
-  // To-Do:  (Mark Slee, Alex Green, or Ben Morrow):   The Cube # is determined by the order in this list.
-  // "raw object index" is serialized by running through towermapping and then individual cube mapping below.
-  //  We can do better than this.  The raw object index should be obvious from the code-- looking through the
-  //  rendered simulation and counting through cubes in mapping mode is grossly inefficient. 
-
-  TowerMapping[] towerCubes = new TowerMapping[] {};
-  
-  // Single cubes can be constructed directly here if you need them
-  Cube[] singleCubes = new Cube[] {
-    // new Cube(15, int( Cube.EDGE_HEIGHT), 39, 0, 10, 0,  WRL),     // Back left channel behind speaker
-     //new Cube(x, y, z, rx, ry, rz, wiring),
-   //new Cube(0,0,0,0,225,0, WRR),
-  };
-
-  // The bass box!
-  // BassBox bassBox = BassBox.unlitBassBox(BBX, 0, BBZ); // frame exists, no lights
-     BassBox bassBox = BassBox.noBassBox(); // no bass box at all
-  // BassBox bassBox = new BassBox(BBX, 0, BBZ); // bass box with lights
-  // The speakers!
-  List<Speaker> speakers = Arrays.asList(new Speaker[] {
-     // Each speaker parameter is x, y, z, rotation, the left speaker comes first
-     // new Speaker(TRAILER_WIDTH - Speaker.EDGE_WIDTH + 8, 6, 3, -15)
-  });
-
-
-  ////////////////////////////////////////////////////////////////////////
-  // dan's proposed lattice
-        ArrayList<StaggeredTower> scubes = new ArrayList<StaggeredTower>();
-        //if (NumBackTowers != 25) exit();
-        for (int i=0; i<NumBackTowers/2; i++) scubes.add(new StaggeredTower(
-                  (i+1)*CW,                                                                 // x
-                  (i % 2 == 0) ? 0 : CH * 2./3.                ,   // y
-                 - ((i % 2 == 0) ? 11 : 0) + 80          ,   // z
-                 -45, (i % 2 == 0) ? MaxCubeHeight : MaxCubeHeight) );         // num cubes
-        
-//        for (int i=0; i<NumBackTowers/2; i++) scubes.add(new StaggeredTower(
-//                  (i+1)*CW,                                                                 // x
-//                  (i % 2 == 0) ? 0 : CH * 2./3.                ,   // y
-//                 - ((i % 2 == 0) ? 0 : 11) + 80 - pow(CH*CH + CW*CW, .5),   // z
-//                 225, (i % 2 == 0) ? MaxCubeHeight : MaxCubeHeight-1) ); 
-
-      // for (int i=0; i<2 ; i++) scubes.add(new StaggeredTower(
-      //             (i+1)*CW,                                                                 // x
-      //                0             ,   // y
-      //            - 0 + 97 - 2*pow(CH*CH + CW*CW, .5),   // z
-      //            225,  MaxCubeHeight  ) ); 
-        
-        ArrayList<Cube> dcubes = new ArrayList<Cube>();
-        // for (int i=1; i<6; i++) {
-        //         if (i>1) dcubes.add(new Cube(-6+CW*4/3*i             , 0, 0, 0, 0, 0, WRR));        
-        //                          dcubes.add(new Cube(-6+CW*4/3*i+CW*2/3., CH*.5, 0, 0, 0, 0, WRR));        
-        // }
-
-float current_x_position = 0;
-// scubes.add(new StaggeredTower(//tower 1
-//       current_x_position,               // x
-//        15   ,   // y
-//        0  ,   // z
-//      45, 6, new Cube.Wiring[] { WFL, WRR, WFL, WRR, WFL, WRR}) );
-// current_x_position += 25.25;
-// scubes.add(new StaggeredTower(// tower 2
-//       current_x_position,               // x
-//        0  ,   // y
-//        -10.5   ,   // z
-//      45, 6, new Cube.Wiring[] { WFR, WFL, WRR, WRR, WFL, WRR}) );
-// current_x_position += 25.25;
-// scubes.add(new StaggeredTower(//tower 3
-//       current_x_position,               // x
-//        15   ,   // y
-//        0,   // z
-//      45, 6, new Cube.Wiring[] { WRR, WFL, WRR, WRR, WFL, WRR}) );
-// current_x_position += 25.25;
-// scubes.add(new StaggeredTower(//tower 4
-//     current_x_position,               // x
-//        0,   // y
-//        -10.5  ,   // z
-//      45, 6, new Cube.Wiring[] { WFL, WRR, WFL, WRR, WFL, WRR}) );
-// current_x_position += 28;
-// scubes.add(new StaggeredTower(//tower 5
-//       current_x_position,               // x
-//        15   ,   // y
-//        -4.5 ,   // z
-//      45, 6, new Cube.Wiring[] { WRR, WFL, WRR, WFL, WRR, WFL}) );
-// current_x_position += 28;
-// scubes.add(new StaggeredTower(//tower 6
-//       current_x_position,               // x
-//        0 ,   // y
-//        -10.5,   // z
-//      45, 6, new Cube.Wiring[] { WFL, WRR, WFL, WRR, WFL, WRR}) );
-// current_x_position += 25.25;
-// scubes.add(new StaggeredTower(// tower 7
-//       current_x_position,               // x
-//        15   ,   // y
-//       0,   // z
-//      45, 6, new Cube.Wiring[] { WRR, WFL, WRR, WFL, WRR, WFL}) );
-// current_x_position += 25.25;     
-// scubes.add(new StaggeredTower(//tower 8
-//       current_x_position,               // x
-//        0  ,   // y
-//        -10.5 ,   // z
-//      45, 6, new Cube.Wiring[] { WFL, WRR, WFL, WRR, WFL, WRR}) );
-// current_x_position += 25.25;
-// scubes.add(new StaggeredTower(//tower 9
-//       current_x_position,               // x
-//        15   ,   // y
-//        0,   // z
-//      45, 6, new Cube.Wiring[] { WFL, WRR, WFL, WRR, WFL, WRR}) );
-// current_x_position += 25.25;
-
-// //TOWERS ON DANCE FLOOR
-// scubes.add(new StaggeredTower(//tower 10
-//       83.75+39+43-124.5,   // x
-//       0,   // y
-//        -47.5-43,   // z
-//      45,  4, new Cube.Wiring[]{ WRR, WFL, WFL, WRR})  ); 
-// scubes.add(new StaggeredTower(//tower 11
-//       83.75,   // x
-//        0,   // y
-//        -47.5,   // z
-//      45,  4, new Cube.Wiring[]{ WFL, WRR, WRR, WFL})  );  
-// scubes.add(new StaggeredTower(//tower 12
-//       83.75+39,   // x
-//        0,   // y
-//        -47.5,   // z
-//      45,  4, new Cube.Wiring[]{ WRR, WFL, WFL, WRR})  ); 
-// scubes.add(new StaggeredTower(//tower 13
-//        83.75+39+43,   // x
-//        0,   // y
-//        -47.5-43,   // z
-//      45,  4, new Cube.Wiring[]{ WFL, WRR, WFL, WRR})  ); 
-
-// scubes.add(new StaggeredTower(// Single cube on top of tower 4
-//       42,               // x
-//        112   ,   // y
-//          72,   // z
-//      -10,  1, new Cube.Wiring[]{ WRL})  );  
-
-
-
-
-
-
-
-  //////////////////////////////////////////////////////////////////////
-  //      BENEATH HERE SHOULD NOT REQUIRE ANY MODIFICATION!!!!        //
-  //////////////////////////////////////////////////////////////////////
-
-  // These guts just convert the shorthand mappings into usable objects
-  ArrayList<Tower> towerList = new ArrayList<Tower>();
-  ArrayList<Cube> tower;
+  List<Tower> towers = new ArrayList<Tower>();
   Cube[] cubes = new Cube[200];
-  int cubeIndex = 1;  
-  float px, pz, ny;
-  for (TowerMapping tm : towerCubes) {
-    px = tm.x;
-    ny = tm.y;
-    pz = tm.z;
-    tower = new ArrayList<Cube>();
-    for (CubeMapping cm : tm.cubeMappings) {
-      tower.add(cubes[cubeIndex++] = new Cube(px = px + cm.dx, ny, pz = pz + cm.dz, 0, cm.ry, 0, cm.wiring));
-      ny += Cube.EDGE_HEIGHT;
+  int cubeIndex = 1;
+
+  float rt2 = sqrt(2);
+  float x, y, z, xd, zd, num;
+  for (float[] tc : TOWER_CONFIG) {
+    x = -tc[1];
+    z = tc[0]; 
+    y = tc[2];
+    num = tc[3];
+    if (z < x) {
+      zd = -(x-z)/rt2;
+      xd = z*rt2 - zd;
+    } else {
+      zd = (z-x)/rt2;
+      xd = z*rt2 - zd;
     }
-    towerList.add(new Tower(tower));
-  }
-
-  
-  for (Cube cube : singleCubes) {
-    cubes[cubeIndex++] = cube;
-  }
-  for (Cube cube : dcubes) {
-    cubes[cubeIndex++] = cube;
-  }
-  for (StaggeredTower st : scubes) {
-    tower = new ArrayList<Cube>();
-    for (int i=0; i < st.n; i++) {
-      Cube.Wiring w = (i < st.wiring.length) ? st.wiring[i] : WRR;
-      tower.add(cubes[cubeIndex++] = new Cube(st.x, st.y + CH* 4/3.*i, st.z, 0, st.r, 0, w));
-    }
-    towerList.add(new Tower(tower));
-  }   
-
-  return new Model(towerList, cubes, bassBox, speakers);
-}
-
-/**
- * This function maps the panda boards. We have an array of them, each has
- * an IP address and a list of channels.
- */
-public PandaMapping[] buildPandaList() {
-  final int LEFT_SPEAKER = 0;
-  final int RIGHT_SPEAKER = 1;
-  
-  // 8 channels map to:  3, 4, 7, 8, 13, 14, 15, 16.
-  return new PandaMapping[] {
-    new PandaMapping(
-      "10.200.1.28", new ChannelMapping[] {
-        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 37, 38, 39 }),
-        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] {  }),
-        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 43, 44, 45 }),
-        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 46, 47, 48 }),
-        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] {  }), // new front thing
-        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] {  }), // new back thing
-        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 13, 14, 15 }), // new back thing
-    }),
-    new PandaMapping(
-      "10.200.1.29", new ChannelMapping[] {
-        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 19, 20, 21 }),
-        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] {  }),
-        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 1, 2, 3 }),
-        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 4, 5, 6 }),
-        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 7, 8, 9 }),
-
-        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 10, 11, 12 }),
-        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 16, 17, 18 }),
-//        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 34, 35, 36}),
-//        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { }),
-//        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 19, 20, 21}),
-//        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 22, 23, 24}), 
-//        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 25, 26, 27}),
-//        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 28, 29, 30}),
-//        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 31, 32, 33}),
-//        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { }),
-    }),    
-    new PandaMapping(
-      "10.200.1.30", new ChannelMapping[] {
-        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 40, 41, 42 }),
-        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { }),
-        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 22, 23, 24 }),
-        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 25, 26, 27 }),
-        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 28, 29, 30 }),
-        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 31, 32, 33 }),
-        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 34, 35, 36 }),
-//        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 1,1,1}), // 30 J3 *
-//        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 1,1,1}),  // 30 J4 //ORIG *
-//        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 37, 38, 39}),                // 30 J7 *
-//        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 40, 41, 42}),  // 30 J8 *
-//        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 43, 44, 45}),                // 30 J13 (not working)
-//        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 46, 47, 48}),                // 30 J14 (unplugged)
-//        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 49, 50, 51}),                // 30 J15 (unplugged)
-//        new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 52, 53, 54}), // 30 J16
-   }),    
-//     new PandaMapping(
-//       "10.200.1.31", new ChannelMapping[] {
-//         new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 65, 66}),       // J3 
-//         new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 1,1}),       // J4
-//         new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 55, 56}), // 30 J7 
-//         new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 57, 58}), //  J8 
-//         new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 59, 60}),           // J13 
-//         new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 61, 62}),                // 30 J14 
-//         new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 63, 64}),                //  J15
-//         new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 1,1}),              //  J16
-//     }),
-
-     // new PandaMapping(
-     //   "10.200.1.32", new ChannelMapping[] {
-     //     new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { }),       // J3 
-     //     new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { }),       // J4
-     //     new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 67, 68}), // 30 J7 
-     //     new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { 69, 70}), //  J8 
-     //     new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { }),           // J13 
-     //     new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { }),                // 30 J14 
-     //     new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { }),                //  J15
-     //     new ChannelMapping(ChannelMapping.MODE_CUBES, new int[] { }),              //  J16
-     // }),
-  };
-}
-
-class TowerMapping {
-  public final float x, y, z;
-  public final CubeMapping[] cubeMappings;
-  
-  TowerMapping(float x, float y, float z, CubeMapping[] cubeMappings) {
-    this.x = x;
-    this.y = y;
-    this.z = z;
-    this.cubeMappings = cubeMappings;
-  }
-}
-
-class CubeMapping {
-  public final float dx, dz, ry;
-  public final Cube.Wiring wiring;
-  
-  CubeMapping(float dx, float dz, Cube.Wiring wiring) {
-    this(dx, dz, 0., wiring);
-  }
-  CubeMapping(float dx, float dz, float ry) {
-    this(dz, dz, ry, Cube.Wiring.FRONT_LEFT);
-  }
-  
-  CubeMapping(float dx, float dz, float ry, Cube.Wiring wiring) {
-    this.dx = dx;
-    this.dz = dz;
-    this.ry = ry;
-    this.wiring = wiring;
-  }
-}
-
-class StaggeredTower {
-  public final float x, y, z, r;
-  public final int n;
-  public final Cube.Wiring[] wiring;
-  StaggeredTower(float _x, float _y, float _z, float _r, int _n) { this(_x, _y, _z, _r, _n, new Cube.Wiring[]{}); }
-  StaggeredTower(float _x, float _y, float _z, float _r, int _n, Cube.Wiring[] _wiring) { x=_x; y=_y; z=_z; r=_r; n=_n; wiring=_wiring;}
-}
-
-/**
- * Each panda board has an IP address and a fixed number of channels. The channels
- * each have a fixed number of pixels on them. Whether or not that many physical
- * pixels are connected to the channel, we still send it that much data.
- */
-class PandaMapping {
-  
-  // How many channels are on the panda board
-  public final static int CHANNELS_PER_BOARD = 8;
-  
-  // How many total pixels on the whole board
-  public final static int PIXELS_PER_BOARD = ChannelMapping.PIXELS_PER_CHANNEL * CHANNELS_PER_BOARD;
-  
-  final String ip;
-  final ChannelMapping[] channelList = new ChannelMapping[CHANNELS_PER_BOARD];
-  
-  PandaMapping(String ip, ChannelMapping[] rawChannelList) {
-    this.ip = ip;
-    
-    // Ensure our array is the right length and has all valid items in it
-    for (int i = 0; i < channelList.length; ++i) {
-      channelList[i] = (i < rawChannelList.length) ? rawChannelList[i] : new ChannelMapping();
-      if (channelList[i] == null) {
-        channelList[i] = new ChannelMapping();
-      }
+    List<Cube> tower = new ArrayList<Cube>();
+    for (int n = 0; n < num; ++n) {
+      Cube cube = new Cube(xd + 24, y, zd + 84, 0, -45, 0);
+      tower.add(cube);
+      cubes[cubeIndex++] = cube;
+      y += SPACING;
     }
+    towers.add(new Tower(tower));
   }
-}
-
-/**
- * Each channel on a pandaboard can be mapped in a number of modes. The typical is
- * to a series of connected cubes, but we also have special mappings for the bass box,
- * the speaker enclosures, and the DJ booth floor.
- *
- * This class is just the mapping meta-data. It sanitizes the input to make sure
- * that the cubes and objects being referenced actually exist in the model.
- *
- * The logic for how to encode the pixels is contained in the PandaDriver.
- */
-class ChannelMapping {
-
-  // How many cubes per channel xc_PB is configured for
-  public final static int CUBES_PER_CHANNEL = 4;  
 
-  // How many total pixels on each channel
-  public final static int PIXELS_PER_CHANNEL = Cube.POINTS_PER_CUBE * CUBES_PER_CHANNEL;
-  
-  public static final int MODE_NULL = 0;
-  public static final int MODE_CUBES = 1;
-  public static final int MODE_BASS = 2;
-  public static final int MODE_SPEAKER = 3;
-  public static final int MODE_STRUTS_AND_FLOOR = 4;
-  public static final int MODE_INVALID = 5;
-  
-  public static final int NO_OBJECT = -1;
-  
-  final int mode;
-  final int[] objectIndices = new int[CUBES_PER_CHANNEL];
-  
-  ChannelMapping() {
-    this(MODE_NULL);
-  }
-  
-  ChannelMapping(int mode) {
-    this(mode, new int[]{});
-  }
-  
-  ChannelMapping(int mode, int rawObjectIndex) {
-    this(mode, new int[]{ rawObjectIndex });
-  }
-  
-  ChannelMapping(int mode, int[] rawObjectIndices) {
-    if (mode < 0 || mode >= MODE_INVALID) {
-      throw new RuntimeException("Invalid channel mapping mode: " + mode);
-    }
-    if (mode == MODE_SPEAKER) {
-      if (rawObjectIndices.length != 1) {
-        throw new RuntimeException("Speaker channel mapping mode must specify one speaker index");
-      }
-      int speakerIndex = rawObjectIndices[0];
-      if (speakerIndex < 0 || speakerIndex >= glucose.model.speakers.size()) {
-        throw new RuntimeException("Invalid speaker channel mapping: " + speakerIndex);
-      }
-    } else if ((mode == MODE_STRUTS_AND_FLOOR) || (mode == MODE_BASS) || (mode == MODE_NULL)) {
-      if (rawObjectIndices.length > 0) {
-        throw new RuntimeException("Bass/floor/null mappings cannot specify object indices");
-      }
-    } else if (mode == MODE_CUBES) {
-      for (int rawCubeIndex : rawObjectIndices) {
-        if (glucose.model.getCubeByRawIndex(rawCubeIndex) == null) {
-          throw new RuntimeException("Non-existing cube specified in cube mapping: " + rawCubeIndex);
-        }
-      }
-    }
-    
-    this.mode = mode;
-    for (int i = 0; i < objectIndices.length; ++i) {
-      objectIndices[i] = (i < rawObjectIndices.length) ? rawObjectIndices[i] : NO_OBJECT;
-    }
-  }
+  return new Model(towers, cubes);
 }
index 0976d57eb25a2a18d56362b43aa7e077bee306d5..fea4a43d18a668070981be8d4c57fa745bbd75c4 100644 (file)
@@ -7,15 +7,15 @@ class Cathedrals extends SCPattern {
   private final BasicParameter sat = new BasicParameter("SAT", 0.5);
   private GraphicEQ eq;
   
-  Cathedrals(GLucose glucose) {
-    super(glucose);
+  Cathedrals(LX lx) {
+    super(lx);
     addParameter(xpos);
     addParameter(wid);
     addParameter(arms);
     addParameter(sat);
   }
  
-  protected void onActive() {
+  void onActive() {
     if (eq == null) {
       eq = new GraphicEQ(lx, 16);
       eq.slope.setValue(0.7);
@@ -82,8 +82,8 @@ class MidiMusic extends SCPattern {
   
   private final BasicParameter wave = new BasicParameter("WAVE", 0);
   
-  MidiMusic(GLucose glucose) {
-    super(glucose);
+  MidiMusic(LX lx) {
+    super(lx);
     addParameter(lightSize);
     addParameter(wave);
     addModulator(sparkle).setValue(1);
@@ -287,8 +287,8 @@ class Pulley extends SCPattern {
   private BasicParameter sz = new BasicParameter("SIZE", 0.5);
   private BasicParameter beatAmount = new BasicParameter("BEAT", 0);
   
-  Pulley(GLucose glucose) {
-    super(glucose);
+  Pulley(LX lx) {
+    super(lx);
     for (int i = 0; i < NUM_DIVISIONS; ++i) {
       addModulator(gravity[i] = new Accelerator(0, 0, 0));
       addModulator(delays[i] = new Click(0));
@@ -393,8 +393,8 @@ class ViolinWave extends SCPattern {
   
   LinearEnvelope dbValue = new LinearEnvelope(0, 0, 10);
 
-  ViolinWave(GLucose glucose) {
-    super(glucose);
+  ViolinWave(LX lx) {
+    super(lx);
     addParameter(level);
     addParameter(edge);
     addParameter(range);
@@ -566,8 +566,8 @@ class BouncyBalls extends SCPattern {
   final BasicParameter flr = new BasicParameter("FLR", 0);
   final BasicParameter blobSize = new BasicParameter("SIZE", 0.5);
   
-  BouncyBalls(GLucose glucose) {
-    super(glucose);
+  BouncyBalls(LX lx) {
+    super(lx);
     for (int i = 0; i < balls.length; ++i) {
       balls[i] = new BouncyBall(i);
     }
@@ -601,8 +601,8 @@ class SpaceTime extends SCPattern {
   BasicParameter sizeParameter = new BasicParameter("SIZE", 0.5);
 
 
-  public SpaceTime(GLucose glucose) {
-    super(glucose);
+  public SpaceTime(LX lx) {
+    super(lx);
     
     addModulator(pos).trigger();
     addModulator(rate).trigger();
@@ -653,8 +653,8 @@ class Swarm extends SCPattern {
   SinLFO fY = new SinLFO(model.yMin, model.yMax, 11000);
   SinLFO hOffX = new SinLFO(model.xMin, model.xMax, 13000);
 
-  public Swarm(GLucose glucose) {
-    super(glucose);
+  public Swarm(LX lx) {
+    super(lx);
     
     addModulator(offset).trigger();
     addModulator(rate).trigger();
@@ -695,12 +695,12 @@ class Swarm extends SCPattern {
   }
 }
 
-class SwipeTransition extends SCTransition {
+class SwipeTransition extends LXTransition {
   
   final BasicParameter bleed = new BasicParameter("WIDTH", 0.5);
   
-  SwipeTransition(GLucose glucose) {
-    super(glucose);
+  SwipeTransition(LX lx) {
+    super(lx);
     setDuration(5000);
     addParameter(bleed);
   }
@@ -721,96 +721,18 @@ class SwipeTransition extends SCTransition {
   }
 }
 
-abstract class BlendTransition extends SCTransition {
-  
-  final int blendType;
-  
-  BlendTransition(GLucose glucose, int blendType) {
-    super(glucose);
-    this.blendType = blendType;
-  }
-
-  void computeBlend(int[] c1, int[] c2, double progress) {
-    if (progress < 0.5) {
-      for (int i = 0; i < c1.length; ++i) {
-        colors[i] = lerpColor(
-          c1[i],
-          blendColor(c1[i], c2[i], blendType),
-          (float) (2.*progress),
-          RGB);
-      }
-    } else {
-      for (int i = 0; i < c1.length; ++i) {
-        colors[i] = lerpColor(
-          c2[i],
-          blendColor(c1[i], c2[i], blendType),
-          (float) (2.*(1. - progress)),
-          RGB);
-      }
-    }
-  }
-}
-
-class MultiplyTransition extends BlendTransition {
-  MultiplyTransition(GLucose glucose) {
-    super(glucose, MULTIPLY);
-  }
-}
-
-class ScreenTransition extends BlendTransition {
-  ScreenTransition(GLucose glucose) {
-    super(glucose, SCREEN);
-  }
-}
-
-class BurnTransition extends BlendTransition {
-  BurnTransition(GLucose glucose) {
-    super(glucose, BURN);
-  }
-}
-
-class DodgeTransition extends BlendTransition {
-  DodgeTransition(GLucose glucose) {
-    super(glucose, DODGE);
-  }
-}
-
-class OverlayTransition extends BlendTransition {
-  OverlayTransition(GLucose glucose) {
-    super(glucose, OVERLAY);
-  }
-}
-
-class AddTransition extends BlendTransition {
-  AddTransition(GLucose glucose) {
-    super(glucose, ADD);
-  }
-}
-
-class SubtractTransition extends BlendTransition {
-  SubtractTransition(GLucose glucose) {
-    super(glucose, SUBTRACT);
-  }
-}
-
-class SoftLightTransition extends BlendTransition {
-  SoftLightTransition(GLucose glucose) {
-    super(glucose, SOFT_LIGHT);
-  }
-}
-
 class BassPod extends SCPattern {
 
   private GraphicEQ eq = null;
   
   private final BasicParameter clr = new BasicParameter("CLR", 0.5);
   
-  public BassPod(GLucose glucose) {
-    super(glucose);
+  public BassPod(LX lx) {
+    super(lx);
     addParameter(clr);
   }
   
-  protected void onActive() {
+  void onActive() {
     if (eq == null) {
       eq = new GraphicEQ(lx, 16);
       eq.range.setValue(0.4);
@@ -858,11 +780,11 @@ class CubeEQ extends SCPattern {
   private final BasicParameter clr = new BasicParameter("CLR", 0.5);
   private final BasicParameter blockiness = new BasicParameter("BLK", 0.5);
 
-  public CubeEQ(GLucose glucose) {
-    super(glucose);
+  public CubeEQ(LX lx) {
+    super(lx);
   }
 
-  protected void onActive() {
+  void onActive() {
     if (eq == null) {
       eq = new GraphicEQ(lx, 16);
       addParameter(eq.level);
@@ -909,7 +831,7 @@ class CubeEQ extends SCPattern {
   }
 }
 
-class BoomEffect extends SCEffect {
+class BoomEffect extends LXEffect {
 
   final BasicParameter falloff = new BasicParameter("WIDTH", 0.5);
   final BasicParameter speed = new BasicParameter("SPD", 0.5);
@@ -946,8 +868,8 @@ class BoomEffect extends SCEffect {
     }
   }
 
-  BoomEffect(GLucose glucose) {
-    super(glucose, true);
+  BoomEffect(LX lx) {
+    super(lx, true);
     addParameter(falloff);
     addParameter(speed);
     addParameter(bright);
@@ -989,8 +911,8 @@ public class PianoKeyPattern extends SCPattern {
   final BasicParameter release = new BasicParameter("REL", 0.5);
   final BasicParameter level = new BasicParameter("AMB", 0.6);
   
-  PianoKeyPattern(GLucose glucose) {
-    super(glucose);
+  PianoKeyPattern(LX lx) {
+    super(lx);
         
     addParameter(attack);
     addParameter(release);
@@ -1064,8 +986,8 @@ class CrossSections extends SCPattern {
   final BasicParameter zl = new BasicParameter("ZLEV", 0.5);
 
   
-  CrossSections(GLucose glucose) {
-    super(glucose);
+  CrossSections(LX lx) {
+    super(lx);
     addModulator(x).trigger();
     addModulator(y).trigger();
     addModulator(z).trigger();
@@ -1142,8 +1064,8 @@ class Blinders extends SCPattern {
   final SinLFO s;
   final TriangleLFO hs;
 
-  public Blinders(GLucose glucose) {
-    super(glucose);
+  public Blinders(LX lx) {
+    super(lx);
     m = new SinLFO[12];
     for (int i = 0; i < m.length; ++i) {  
       addModulator(m[i] = new SinLFO(0.5, 120, (120000. / (3+i)))).trigger();
@@ -1181,8 +1103,8 @@ class Psychedelia extends SCPattern {
   TriangleLFO h = new TriangleLFO(0, 240, 19000);
   SinLFO c = new SinLFO(-.2, .8, 31000);
 
-  Psychedelia(GLucose glucose) {
-    super(glucose);
+  Psychedelia(LX lx) {
+    super(lx);
     addModulator(m).trigger();
     addModulator(s).trigger();
     addModulator(h).trigger();
@@ -1236,8 +1158,8 @@ class AskewPlanes extends SCPattern {
   final Plane[] planes;
   final int NUM_PLANES = 3;
   
-  AskewPlanes(GLucose glucose) {
-    super(glucose);
+  AskewPlanes(LX lx) {
+    super(lx);
     planes = new Plane[NUM_PLANES];
     for (int i = 0; i < planes.length; ++i) {
       planes[i] = new Plane(i);
@@ -1281,8 +1203,8 @@ class ShiftingPlane extends SCPattern {
   final SinLFO c = new SinLFO(-1.4, 1.4, 5700);
   final SinLFO d = new SinLFO(-10, 10, 9500);
 
-  ShiftingPlane(GLucose glucose) {
-    super(glucose);
+  ShiftingPlane(LX lx) {
+    super(lx);
     addModulator(a).trigger();
     addModulator(b).trigger();
     addModulator(c).trigger();
@@ -1319,8 +1241,8 @@ class Traktor extends SCPattern {
   private int index = 0;
   private GraphicEQ eq = null;
 
-  public Traktor(GLucose glucose) {
-    super(glucose);
+  public Traktor(LX lx) {
+    super(lx);
     for (int i = 0; i < FRAME_WIDTH; ++i) {
       bass[i] = 0;
       treble[i] = 0;
@@ -1382,7 +1304,7 @@ class Traktor extends SCPattern {
   }
 }
 
-class ColorFuckerEffect extends SCEffect {
+class ColorFuckerEffect extends LXEffect {
   
   final BasicParameter level = new BasicParameter("BRT", 1);
   final BasicParameter desat = new BasicParameter("DSAT", 0);
@@ -1395,8 +1317,8 @@ class ColorFuckerEffect extends SCEffect {
   
   float[] hsb = new float[3];
   
-  ColorFuckerEffect(GLucose glucose) {
-    super(glucose);
+  ColorFuckerEffect(LX lx) {
+    super(lx);
     addParameter(level);
     addParameter(desat);
     addParameter(sharp);
@@ -1407,7 +1329,7 @@ class ColorFuckerEffect extends SCEffect {
   }
   
   public void apply(int[] colors) {
-    if (!enabled) {
+    if (!isEnabled()) {
       return;
     }
     float bMod = level.getValuef();
@@ -1451,15 +1373,15 @@ class ColorFuckerEffect extends SCEffect {
   }
 }
 
-class QuantizeEffect extends SCEffect {
+class QuantizeEffect extends LXEffect {
   
   color[] quantizedFrame;
   float lastQuant;
   final BasicParameter amount = new BasicParameter("AMT", 0);
   
-  QuantizeEffect(GLucose glucose) {
-    super(glucose);
-    quantizedFrame = new color[glucose.lx.total];
+  QuantizeEffect(LX lx) {
+    super(lx);
+    quantizedFrame = new color[lx.total];
     lastQuant = 0;
   } 
   
@@ -1482,14 +1404,14 @@ class QuantizeEffect extends SCEffect {
   }
 }
 
-class BlurEffect extends SCEffect {
+class BlurEffect extends LXEffect {
   
   final BasicParameter amount = new BasicParameter("AMT", 0);
   final int[] frame;
   final LinearEnvelope env = new LinearEnvelope(0, 1, 100);
   
-  BlurEffect(GLucose glucose) {
-    super(glucose);
+  BlurEffect(LX lx) {
+    super(lx);
     addParameter(amount);
     addModulator(env);
     frame = new int[lx.total];
diff --git a/Model.pde b/Model.pde
new file mode 100644 (file)
index 0000000..3376246
--- /dev/null
+++ b/Model.pde
@@ -0,0 +1,365 @@
+/**
+ *     DOUBLE BLACK DIAMOND        DOUBLE BLACK DIAMOND
+ *
+ *         //\\   //\\                 //\\   //\\  
+ *        ///\\\ ///\\\               ///\\\ ///\\\
+ *        \\\/// \\\///               \\\/// \\\///
+ *         \\//   \\//                 \\//   \\//
+ *
+ *        EXPERTS ONLY!!              EXPERTS ONLY!!
+ *
+ * Contains the model definitions for the cube structures.
+ */
+
+/**
+ * Top-level model of the entire sculpture. This contains a list of
+ * every cube on the sculpture, which forms a hierarchy of faces, strips
+ * and points.
+ */
+public static class Model extends LXModel {
+
+  public final List<Tower> towers;
+  public final List<Cube> cubes;
+  public final List<Face> faces;
+  public final List<Strip> strips;
+
+  private final Cube[] _cubes;
+
+  public Model(List<Tower> towerList, Cube[] cubeArr) {
+    super(new Fixture(cubeArr));
+    Fixture fixture = (Fixture) this.fixtures.get(0);
+
+    _cubes = cubeArr;
+
+    // Make unmodifiable accessors to the model data
+    List<Cube> cubeList = new ArrayList<Cube>();
+    List<Face> faceList = new ArrayList<Face>();
+    List<Strip> stripList = new ArrayList<Strip>();
+    for (Cube cube : _cubes) {
+      if (cube != null) {
+        cubeList.add(cube);
+        for (Face face : cube.faces) {
+          faceList.add(face);
+          for (Strip strip : face.strips) {
+            stripList.add(strip);
+          }
+        }
+      }
+    }
+
+    this.towers = Collections.unmodifiableList(towerList);
+    this.cubes = Collections.unmodifiableList(cubeList);
+    this.faces = Collections.unmodifiableList(faceList);
+    this.strips = Collections.unmodifiableList(stripList);
+  }
+
+  private static class Fixture extends LXAbstractFixture {
+
+    private Fixture(Cube[] cubeArr) {
+      for (Cube cube : cubeArr) {
+        if (cube != null) {
+          for (LXPoint point : cube.points) {
+            this.points.add(point);
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * TODO(mcslee): figure out better solution
+   * 
+   * @param index
+   * @return
+   */
+  public Cube getCubeByRawIndex(int index) {
+    return _cubes[index];
+  }
+}
+
+/**
+ * Model of a set of cubes stacked in a tower
+ */
+public static class Tower extends LXModel {
+  /**
+   * Immutable list of cubes
+   */
+  public final List<Cube> cubes;
+
+  /**
+   * Immutable list of faces
+   */
+  public final List<Face> faces;
+
+  /**
+        * Immutable list of strips
+        */
+  public final List<Strip> strips;
+
+  /**
+   * Constructs a tower model from these cubes
+   * 
+   * @param cubes Array of cubes
+   */
+  public Tower(List<Cube> cubes) {
+    super(cubes.toArray(new Cube[] {}));
+
+    List<Cube> cubeList = new ArrayList<Cube>();
+    List<Face> faceList = new ArrayList<Face>();
+    List<Strip> stripList = new ArrayList<Strip>();
+
+    for (Cube cube : cubes) {
+      cubeList.add(cube);
+      for (Face face : cube.faces) {
+        faceList.add(face);
+        for (Strip strip : face.strips) {
+          stripList.add(strip);
+        }
+      }
+    }
+    this.cubes = Collections.unmodifiableList(cubeList);
+    this.faces = Collections.unmodifiableList(faceList);
+    this.strips = Collections.unmodifiableList(stripList);
+  }
+}
+
+/**
+ * Model of a single cube, which has an orientation and position on the
+ * car. The position is specified in x,y,z coordinates with rotation. The
+ * x axis is left->right, y is bottom->top, and z is front->back.
+ * 
+ * A cube's x,y,z position is specified as the left, bottom, front corner.
+ * 
+ * Dimensions are all specified in real-world inches.
+ */
+public static class Cube extends LXModel {
+
+  public final static int FACES_PER_CUBE = 4;  
+  public static final int POINTS_PER_STRIP = 16;
+
+  public final static int STRIPS_PER_CUBE = FACES_PER_CUBE*Face.STRIPS_PER_FACE;
+  public final static int POINTS_PER_CUBE = STRIPS_PER_CUBE*POINTS_PER_STRIP;
+  public final static int POINTS_PER_FACE = Face.STRIPS_PER_FACE*POINTS_PER_STRIP;
+
+  public final static float EDGE_HEIGHT = 21.75f;
+  public final static float EDGE_WIDTH = 24.625f;
+  public final static float CHANNEL_WIDTH = 1.5f;
+
+  public final static Face.Metrics FACE_METRICS = new Face.Metrics(
+    new Strip.Metrics(EDGE_WIDTH, POINTS_PER_STRIP), 
+    new Strip.Metrics(EDGE_HEIGHT, POINTS_PER_STRIP)
+  );
+
+  /**
+   * Immutable list of all cube faces
+   */
+  public final List<Face> faces;
+
+  /**
+   * Immutable list of all strips
+   */
+  public final List<Strip> strips;
+
+  /**
+   * Front left corner x coordinate 
+   */
+  public final float x;
+
+  /**
+   * Front left corner y coordinate 
+   */
+  public final float y;
+
+  /**
+   * Front left corner z coordinate 
+   */
+  public final float z;
+
+  /**
+   * Rotation about the x-axis 
+   */
+  public final float rx;
+
+  /**
+   * Rotation about the y-axis 
+   */
+  public final float ry;
+
+  /**
+   * Rotation about the z-axis 
+   */
+  public final float rz;
+
+  public Cube(double x, double y, double z, double rx, double ry, double rz) {
+    this((float) x, (float) y, (float) z, (float) rx, (float) ry, (float) rz);
+  }
+
+  public Cube(float x, float y, float z, float rx, float ry, float rz) {
+    super(new Fixture(x, y, z, rx, ry, rz));
+    Fixture fixture = (Fixture) this.fixtures.get(0);
+
+    while (rx < 0) rx += 360;
+    while (ry < 0) ry += 360;
+    while (rz < 0) rz += 360;
+    rx = rx % 360;
+    ry = ry % 360;
+    rz = rz % 360;
+
+    this.x = x; 
+    this.y = y;
+    this.z = z;
+    this.rx = rx;
+    this.ry = ry;
+    this.rz = rz;
+
+    this.faces = Collections.unmodifiableList(fixture.faces);
+    this.strips = Collections.unmodifiableList(fixture.strips);
+  }
+
+  private static class Fixture extends LXAbstractFixture {
+
+    private final List<Face> faces = new ArrayList<Face>();
+    private final List<Strip> strips = new ArrayList<Strip>();
+
+    private Fixture(float x, float y, float z, float rx, float ry, float rz) {
+      LXTransform t = new LXTransform();
+      t.translate(x, y, z);
+      t.rotateX(rx * PI / 180.);
+      t.rotateY(ry * PI / 180.);
+      t.rotateZ(rz * PI / 180.);               
+
+      for (int i = 0; i < FACES_PER_CUBE; i++) {
+        Face face = new Face(FACE_METRICS, (ry + 90*i) % 360, t);
+        this.faces.add(face);
+        for (Strip s : face.strips) {
+          this.strips.add(s);
+        }
+        for (LXPoint p : face.points) {
+          this.points.add(p);
+        }
+        t.translate(EDGE_WIDTH, 0, 0);
+        t.rotateY(HALF_PI);
+      }
+    }
+  }
+}
+
+/**
+ * A face is a component of a cube. It is comprised of four strips forming
+ * the lights on this side of a cube. A whole cube is formed by four faces.
+ */
+public static class Face extends LXModel {
+
+  public final static int STRIPS_PER_FACE = 4;
+
+  public static class Metrics {
+    final Strip.Metrics horizontal;
+    final Strip.Metrics vertical;
+
+    public Metrics(Strip.Metrics horizontal, Strip.Metrics vertical) {
+      this.horizontal = horizontal;
+      this.vertical = vertical;
+    }
+  }
+
+  /**
+   * Immutable list of strips
+   */
+  public final List<Strip> strips;
+
+  /**
+   * Rotation of the face about the y-axis
+   */
+  public final float ry;
+
+  Face(Metrics metrics, float ry, LXTransform transform) {
+    super(new Fixture(metrics, ry, transform));
+    Fixture fixture = (Fixture) this.fixtures.get(0);
+    this.ry = ry;
+    this.strips = Collections.unmodifiableList(fixture.strips);
+  }
+
+  private static class Fixture extends LXAbstractFixture {
+
+    private final List<Strip> strips = new ArrayList<Strip>();
+
+    private Fixture(Metrics metrics, float ry, LXTransform transform) {
+      transform.push();
+      transform.translate(0, metrics.vertical.length, 0);
+      for (int i = 0; i < STRIPS_PER_FACE; i++) {
+        boolean isHorizontal = (i % 2 == 0);
+        Strip.Metrics stripMetrics = isHorizontal ? metrics.horizontal : metrics.vertical;
+        Strip strip = new Strip(stripMetrics, ry, transform, isHorizontal);
+        this.strips.add(strip);
+        transform.translate(isHorizontal ? metrics.horizontal.length : metrics.vertical.length, 0, 0);
+        transform.rotateZ(HALF_PI);
+        for (LXPoint p : strip.points) {
+          this.points.add(p);
+        }
+      }
+      transform.pop();
+    }
+  }
+}
+
+/**
+ * A strip is a linear run of points along a single edge of one cube.
+ */
+public static class Strip extends LXModel {
+
+  public static final float POINT_SPACING = 18.625f / 15.f;
+
+  public static class Metrics {
+
+    public final float length;
+    public final int numPoints;
+
+    public Metrics(float length, int numPoints) {
+      this.length = length;
+      this.numPoints = numPoints;
+    }
+  }
+
+  public final Metrics metrics;
+
+  /**
+   * Whether this is a horizontal strip
+   */
+  public final boolean isHorizontal;
+
+  /**
+   * Rotation about the y axis
+   */
+  public final float ry;
+
+  public Object obj1 = null, obj2 = null;
+
+  Strip(Metrics metrics, float ry, List<LXPoint> points, boolean isHorizontal) {
+    super(points);
+    this.isHorizontal = isHorizontal;
+    this.metrics = metrics;            
+    this.ry = ry;
+  }
+
+  Strip(Metrics metrics, float ry, LXTransform transform, boolean isHorizontal) {
+    super(new Fixture(metrics, ry, transform));
+    this.metrics = metrics;
+    this.isHorizontal = isHorizontal;
+    this.ry = ry;
+  }
+
+  private static class Fixture extends LXAbstractFixture {
+    private Fixture(Metrics metrics, float ry, LXTransform transform) {
+      float offset = (metrics.length - (metrics.numPoints - 1) * POINT_SPACING) / 2.f;
+      transform.push();
+      transform.translate(offset, -Cube.CHANNEL_WIDTH/2.f, 0);
+      for (int i = 0; i < metrics.numPoints; i++) {
+        LXPoint point = new LXPoint(transform.x(), transform.y(), transform.z());
+        this.points.add(point);
+        transform.translate(POINT_SPACING, 0, 0);
+      }
+      transform.pop();
+    }
+  }
+}
+
diff --git a/PandaDriver.pde b/PandaDriver.pde
deleted file mode 100644 (file)
index 5d8ad24..0000000
+++ /dev/null
@@ -1,359 +0,0 @@
-import netP5.*;
-import oscP5.*;
-
-/**
- *     DOUBLE BLACK DIAMOND        DOUBLE BLACK DIAMOND
- *
- *         //\\   //\\                 //\\   //\\  
- *        ///\\\ ///\\\               ///\\\ ///\\\
- *        \\\/// \\\///               \\\/// \\\///
- *         \\//   \\//                 \\//   \\//
- *
- *        EXPERTS ONLY!!              EXPERTS ONLY!!
- *
- * This class implements the output function to the Panda Boards. It
- * will be moved into GLucose once stabilized.
- */
-public static class PandaDriver {
-  
-  interface Listener {
-    public void onToggle(boolean enabled);
-  }
-  
-  private Listener listener = null;
-  
-  // IP address
-  public final String ip;
-  
-  // Address to send to
-  private final NetAddress address;
-  
-  // Whether board output is enabled
-  private boolean enabled = false;
-  
-  // OSC message
-  private final OscMessage message;
-
-  // List of point indices that get sent to this board
-  private final int[] points;
-    
-  // Packet data
-  private final byte[] packet = new byte[4*352]; // magic number, our UDP packet size
-
-  private static final int NO_POINT = -1;
-
-  ////////////////////////////////////////////////////////////////
-  //
-  // READ THIS RIGHT NOW BEFORE YOU MODIFY THE BELOW!!!!!!!!!!!!!
-  // READ THIS RIGHT NOW BEFORE YOU MODIFY THE BELOW!!!!!!!!!!!!!
-  // READ THIS RIGHT NOW BEFORE YOU MODIFY THE BELOW!!!!!!!!!!!!!
-  //
-  // The mappings below indicate the physical order of strips
-  // connected to a pandaboard channel. The strip numbers are a
-  // reflection of how the model is built.
-  //
-  // For ANYTHING in the model which is a rectangular prism,
-  // which means Cubes, the BassBox, and each Speaker, the
-  // strips are numbered incrementally by face. The first
-  // face is always the FRONT, which you are looking at.
-  // The next face is the RIGHT, then the BACK, then the LEFT.
-  //
-  // For every face, the strips are ordered numerically moving
-  // clockwise from the the TOP LEFT.
-  //
-  // So, for a cube:
-  //
-  //  Strip 0: front face, top strip, left to right
-  //  Strip 1: front face, right strip, top to bottom
-  //  Strip 2: front face, bottom strip, right to left
-  //  Strip 3: front face, left strip, bottom to top
-  //
-  //  Strip 4: right face, top strip, left to right
-  //  ... and so on
-  //  Strip 14: left face, bottom strip, right to left
-  //  Strip 15: left face, left strip, bottom to top
-  //
-  ////////////////////////////////////////////////////////////////
-  
-  private final static int FORWARD = -1;
-  private final static int BACKWARD = -2;
-
-  /**
-   * These constant arrays indicate the order in which the strips of a cube
-   * are wired. There are four different options, depending on which bottom
-   * corner of the cube the data wire comes in.
-   */
-  private final static int[][] CUBE_STRIP_ORDERINGS = new int[][] {
-//    {  2,  1,  0,  3, 13, 12, 15, 14,  4,  7,  6,  5, 11, 10,  9,  8 }, // FRONT_LEFT
-//    {  6,  5,  4,  7,  1,  0,  3,  2,  8, 11, 10,  9, 15, 14, 13, 12 }, // FRONT_RIGHT
-//    { 14, 13, 12, 15,  9,  8, 11, 10,  0,  3,  2,  1,  7,  6,  5,  4 }, // REAR_LEFT
-//    { 10,  9,  8, 11,  5,  4,  7,  6, 12, 15, 14, 13,  3,  2,  1,  0 }, // REAR_RIGHT
-
-
-    {  2,  1,  0,  3, 13, 12, 15, 14,  4,  7,  6,  5, 11, 10,  9,  8 }, // FRONT_LEFT
-    {  6,  5,  4,  7,  1,  0,  3,  2,  8, 11, 10,  9, 15, 14, 13, 12 }, // FRONT_RIGHT
-    { 14, 13, 12, 15,  9,  8, 11, 10,  0,  3,  2,  1,  7,  6,  5,  4 }, // REAR_LEFT
-    {  9,  8, 11,  5,  4,  7,  6, 10, 14,  2,  1,  0,  3, 13, 12, 15 }, // REAR_RIGHT
-
-  };
-  
-  private final static int[][] BASS_STRIP_ORDERING = {
-    // front face, counterclockwise from bottom front left
-    {2, BACKWARD /* if this strip has extra pixels, you can add them here */ /*, 4 */ }, 
-    {1, BACKWARD /* if this strip is short some pixels, substract them here */ /*, -3 */ },
-    {0, BACKWARD },
-    {3, BACKWARD },
-    
-    // left face, counterclockwise from bottom front left
-    {13, BACKWARD },
-    {12, BACKWARD },
-    {15, BACKWARD },
-    {14, BACKWARD },
-
-    // back face, counterclockwise from bottom rear left
-    {9, BACKWARD },
-    {8, BACKWARD },
-    {11, BACKWARD },
-    {10, BACKWARD },
-
-    // right face, counterclockwise from bottom rear right
-    {5, BACKWARD },
-    {4, BACKWARD },
-    {7, BACKWARD },
-    {6, BACKWARD },
-  };
-
-  private final static int[][] STRUT_STRIP_ORDERING = {
-    {6, BACKWARD},
-    {5, FORWARD},
-    {4, BACKWARD},
-    {3, FORWARD},
-    {2, BACKWARD},
-    {1, FORWARD},
-    {0, BACKWARD},
-    {7, FORWARD},    
-  };
-  
-  private final static int[][] FLOOR_STRIP_ORDERING = {
-    {0, FORWARD},
-    {1, FORWARD},
-    {2, FORWARD},
-    {3, BACKWARD},
-  };
-  
-  // The speakers are currently configured to be wired the same
-  // as cubes with Wiring.FRONT_LEFT. If this needs to be changed,
-  // remove this null assignment and change the below to have mappings
-  // for the LEFT and RIGHT speaker
-  private final static int[][][] SPEAKER_STRIP_ORDERING = {
-    // Left speaker
-    { 
-      // Front face, counter-clockwise from bottom left
-      {2, BACKWARD },
-      {1, BACKWARD },
-      {0, BACKWARD },
-      {3, BACKWARD },
-    },
-    // Right speaker
-    {
-      // Front face, counter-clockwise from bottom left
-      {2, BACKWARD },
-      {1, BACKWARD },
-      {0, BACKWARD },
-      {3, BACKWARD },
-    }
-  };
-
-  public PandaDriver(String ip) {
-    this.ip = ip;
-    
-    // Initialize our OSC output stuff
-    address = new NetAddress(ip, 9001);
-    message = new OscMessage("/shady/pointbuffer");
-    
-    // Build the array of points, initialize all to nothing
-    points = new int[PandaMapping.PIXELS_PER_BOARD];
-    for (int i = 0; i < points.length; ++i) {
-      points[i] = NO_POINT;
-    }
-  }
-    
-  public PandaDriver(String ip, Model model, PandaMapping pm) {
-    this(ip);
-    
-    // Ok, we are initialized, time to build the array if points in order to
-    // send out. We start at the head of our point buffer, and work our way
-    // down. This is the order in which points will be sent down the wire.
-    int ci = -1;
-    
-    // Iterate through all our channels
-    for (ChannelMapping channel : pm.channelList) {
-      ++ci;
-      int pi = ci * ChannelMapping.PIXELS_PER_CHANNEL;
-      
-      switch (channel.mode) {
-
-        case ChannelMapping.MODE_CUBES:
-          // We have a list of cubes per channel
-          for (int rawCubeIndex : channel.objectIndices) {
-            if (rawCubeIndex < 0) {
-              // No cube here, skip ahead in the buffer
-              pi += Cube.POINTS_PER_CUBE;
-            } else {
-              // The cube exists, check which way it is wired to
-              // figure out the order of strips.
-              Cube cube = model.getCubeByRawIndex(rawCubeIndex);
-              int stripOrderIndex = 0;
-              switch (cube.wiring) {
-                case FRONT_LEFT: stripOrderIndex = 0; break;
-                case FRONT_RIGHT: stripOrderIndex = 1; break;
-                case REAR_LEFT: stripOrderIndex = 2; break;
-                case REAR_RIGHT: stripOrderIndex = 3; break;
-              }
-              
-              // Iterate through all the strips on the cube and add the points
-              for (int stripIndex : CUBE_STRIP_ORDERINGS[stripOrderIndex]) {
-                // We go backwards here... in the model strips go clockwise, but
-                // the physical wires are run counter-clockwise
-                pi = mapStrip(cube.strips.get(stripIndex), BACKWARD, points, pi);
-              }
-            }
-          }
-          break;
-          
-        case ChannelMapping.MODE_BASS:
-          for (int[] config : BASS_STRIP_ORDERING) {
-            pi = mapStrip(model.bassBox.strips.get(config[0]), config[1], points, pi);
-            if (config.length >= 3) pi += config[2];            
-          }
-          break;
-          
-        case ChannelMapping.MODE_STRUTS_AND_FLOOR:
-          for (int[] config : STRUT_STRIP_ORDERING) {
-            pi = mapStrip(model.bassBox.struts.get(config[0]), config[1], points, pi);
-            if (config.length >= 3) pi += config[2];
-          }     
-          for (int[] config : FLOOR_STRIP_ORDERING) {
-            pi = mapStrip(model.boothFloor.strips.get(config[0]), config[1], points, pi);
-            if (config.length >= 3) pi += config[2];
-          }
-          break;
-          
-        case ChannelMapping.MODE_SPEAKER:
-          int [][] speakerStripOrdering;
-          if (SPEAKER_STRIP_ORDERING == null) {
-            // Copy the cube strip ordering
-            int[] frontLeftCubeWiring = CUBE_STRIP_ORDERINGS[0];
-            speakerStripOrdering = new int[frontLeftCubeWiring.length][];
-            for (int i = 0; i < frontLeftCubeWiring.length; ++i) {
-              speakerStripOrdering[i] = new int[] { frontLeftCubeWiring[0], BACKWARD }; 
-            }
-          } else {
-            speakerStripOrdering = SPEAKER_STRIP_ORDERING[channel.objectIndices[0]];
-          }
-          for (int[] config : speakerStripOrdering) {
-            Speaker speaker = model.speakers.get(channel.objectIndices[0]);
-            pi = mapStrip(speaker.strips.get(config[0]), config[1], points, pi);
-            if (config.length >= 3) pi += config[2];            
-          }
-          break;
-          
-        case ChannelMapping.MODE_NULL:
-          // No problem, nothing on this channel!
-          break;
-          
-        default:
-          throw new RuntimeException("Invalid/unhandled channel mapping mode: " + channel.mode);
-      }
-
-    }
-  }
-  
-  private int mapStrip(Strip s, int direction, int[] points, int pi) {
-    if (direction == FORWARD) {
-      for (LXPoint p : s.points) {
-        points[pi++] = p.index;
-      }
-    } else if (direction == BACKWARD) {
-      for (int i = s.points.size()-1; i >= 0; --i) {
-        points[pi++] = s.points.get(i).index;
-      }
-    } else {
-      throw new RuntimeException("Unidentified strip mapping direction: " + direction);
-    }
-    return pi;
-  }
-
-  public PandaDriver setListener(Listener listener) {
-    this.listener = listener;
-    return this;
-  }
-
-  public void setEnabled(boolean enabled) {
-    if (this.enabled != enabled) {
-      this.enabled = enabled;
-      println("PandaBoard/" + ip + ": " + (enabled ? "ON" : "OFF"));
-      if (listener != null) {
-        listener.onToggle(enabled);
-      }
-    }
-  }
-  
-  public boolean isEnabled() {
-    return this.enabled;
-  }
-
-  public void disable() {
-    setEnabled(false);
-  }
-  
-  public void enable() {
-    setEnabled(true);
-  }
-
-  public void toggle() {
-    setEnabled(!enabled);
-  }
-
-  public final void send(int[] colors) {
-    if (!enabled) {
-      return;
-    }
-    int len = 0;
-    int packetNum = 0;
-    for (int index : points) {
-      int c = (index < 0) ? 0 : colors[index];
-      byte r = (byte) ((c >> 16) & 0xFF);
-      byte g = (byte) ((c >> 8) & 0xFF);
-      byte b = (byte) ((c) & 0xFF);
-      packet[len++] = 0; // alpha channel, unused but makes for 4-byte alignment
-      packet[len++] = r;
-      packet[len++] = g;
-      packet[len++] = b;
-
-      // Flush once packet is full buffer size
-      if (len >= packet.length) {
-        sendPacket(packetNum++);
-        len = 0;
-      }
-    }
-
-    // Flush any remaining data
-    if (len > 0) {
-      sendPacket(packetNum++);
-    }
-  }
-  
-
-  private void sendPacket(int packetNum) {
-    message.clearArguments();
-    message.add(packetNum);
-    message.add(packet.length);
-    message.add(packet);
-    try {
-      OscP5.flush(message, address);
-    } catch (Exception x) {
-      x.printStackTrace();
-    }
-  }
-}
index 350615dbdbb614016f99dfda9ba7b9619a54f2da..00ed073c46506c1f3012938381efc3f89892c676 100644 (file)
@@ -1,13 +1,13 @@
 abstract class SamPattern extends SCPattern {
-  public SamPattern(GLucose glucose) {
-    super(glucose);
+  public SamPattern(LX lx) {
+    super(lx);
     setEligible(false);
   }
 }
 
 class JazzRainbow extends SamPattern {
-  public JazzRainbow(GLucose glucose) {
-    super(glucose);
+  public JazzRainbow(LX lx) {
+    super(lx);
   }
 
   
index 83b97cf31bf356149d9bb9bd42d49a5292326294..cda8fed4358c5b18302cdce3c6394179456a11c4 100644 (file)
@@ -183,8 +183,8 @@ class HelixPattern extends SCPattern {
   private static final float tMin = -200;
   private static final float tMax = 200;
 
-  public HelixPattern(GLucose glucose) {
-    super(glucose);
+  public HelixPattern(LX lx) {
+    super(lx);
 
     addParameter(helix1On);
     addParameter(helix2On);
index fbaccc38fd5f0915d5d8aab72df047b69f8401a4..0afeefecc75bb85893e0dbee8f3ca367dd9178cb 100644 (file)
  *
  * Welcome to the Sugar Cubes! This Processing sketch is a fun place to build
  * animations, effects, and interactions for the platform. Most of the icky
- * code guts are embedded in the GLucose library extension. If you're an
- * artist, you shouldn't need to worry about any of that.
+ * code guts are embedded in the HeronLX library, or files prefixed with
+ * an underscore. If you're an artist, you shouldn't need to worry about that.
  *
  * Below, you will find definitions of the Patterns, Effects, and Interactions.
  * If you're an artist, create a new tab in the Processing environment with
  * your name. Implement your classes there, and add them to the list below.
  */ 
-LXPattern[] patterns(GLucose glucose) {
+
+LXPattern[] patterns(LX lx) {
   return new LXPattern[] {        
 
-    new SineSphere(glucose),
-    //new CubeCurl(glucose), 
+    new SineSphere(lx),
+    //new CubeCurl(lx), 
      
     // Slee
-    // new Cathedrals(glucose),
-     new Swarm(glucose),
-    new MidiMusic(glucose),
-    new Pulley(glucose),
+    // new Cathedrals(lx),
+    new Swarm(lx),
+    new MidiMusic(lx),
+    new Pulley(lx),
     
-    new ViolinWave(glucose),
-    new BouncyBalls(glucose),
-    new SpaceTime(glucose),
-    new ShiftingPlane(glucose),
-    new AskewPlanes(glucose),
-    new Blinders(glucose),
-    new CrossSections(glucose),
-    new Psychedelia(glucose),
+    new ViolinWave(lx),
+    new BouncyBalls(lx),
+    new SpaceTime(lx),
+    new ShiftingPlane(lx),
+    new AskewPlanes(lx),
+    new Blinders(lx),
+    new CrossSections(lx),
+    new Psychedelia(lx),
 
-    new MultipleCubes(glucose),
+    new MultipleCubes(lx),
     
-    new Traktor(glucose).setEligible(false),
-    new BassPod(glucose).setEligible(false),
-    new CubeEQ(glucose).setEligible(false),
-    new PianoKeyPattern(glucose).setEligible(false),
+    new Traktor(lx).setEligible(false),
+    new BassPod(lx).setEligible(false),
+    new CubeEQ(lx).setEligible(false),
+    new PianoKeyPattern(lx).setEligible(false),
 
-       // AntonK
-       new AKPong(glucose),
+    // AntonK
+    new AKPong(lx),
 
     // DanH
-    new Noise(glucose),
-    new Play (glucose),
-    new Pong (glucose),
-    new Worms(glucose),
+    new Noise(lx),
+    new Play (lx),
+    new Pong (lx),
+    new Worms(lx),
 
     // JR
-    new Gimbal(glucose),
+    new Gimbal(lx),
     
     // Alex G
      
-     // Tim
-    new TimMetronome(glucose),
-    new TimPlanes(glucose),
-    new TimPinwheels(glucose),
-    new TimRaindrops(glucose),
-    new TimCubes(glucose),
-    // new TimTrace(glucose),
-    new TimSpheres(glucose),
+    // Tim
+    new TimMetronome(lx),
+    new TimPlanes(lx),
+    new TimPinwheels(lx),
+    new TimRaindrops(lx),
+    new TimCubes(lx),
+    // new TimTrace(lx),
+    new TimSpheres(lx),
 
     // Jackie
-    new JackieSquares(glucose),
-    new JackieLines(glucose),
-    new JackieDots(glucose),
+    new JackieSquares(lx),
+    new JackieLines(lx),
+    new JackieDots(lx),
 
     // L8on
-    new L8onAutomata(glucose),
-    new L8onLife(glucose),
-    new L8onStripLife(glucose),
+    new L8onAutomata(lx),
+    new L8onLife(lx),
+    new L8onStripLife(lx),
 
     // Vincent
-    new VSTowers(glucose),
+    new VSTowers(lx),
     
     // Toby
-    new GlitchPlasma(glucose),
-    new FireEffect(glucose).setEligible(false),
-    new StripBounce(glucose),
-    new SoundRain(glucose).setEligible(false),
-    new SoundSpikes(glucose).setEligible(false),
-    new FaceSync(glucose),
+    new GlitchPlasma(lx),
+    new FireEffect(lx).setEligible(false),
+    new StripBounce(lx),
+    new SoundRain(lx).setEligible(false),
+    new SoundSpikes(lx).setEligible(false),
+    new FaceSync(lx),
 
     // Jack
-    new Swim(glucose),
-    new Balance(glucose),
-    
-
+    new Swim(lx),
+    new Balance(lx),
     
     // Ben
-    // new Sandbox(glucose),
-    new TowerParams(glucose),
-    new DriveableCrossSections(glucose),
-    new GranimTestPattern2(glucose),
+    // new Sandbox(lx),
+    new TowerParams(lx),
+    new DriveableCrossSections(lx),
+    new GranimTestPattern2(lx),
     
     // Shaheen
-    //new HelixPattern(glucose).setEligible(false),
+    // new HelixPattern(lx).setEligible(false),
     
     // Sam
-    new JazzRainbow(glucose),
+    new JazzRainbow(lx),
     
     // Arjun
-    new TelevisionStatic(glucose),
-    new AbstractPainting(glucose),
-    new Spirality(glucose),
+    new TelevisionStatic(lx),
+    new AbstractPainting(lx),
+    new Spirality(lx),
 
     // Basic test patterns for reference, not art    
-    new TestCubePattern(glucose),
-    new TestTowerPattern(glucose),
-    new TestProjectionPattern(glucose),
-    new TestStripPattern(glucose),
-    new TestBassMapping(glucose),
-    new TestFloorMapping(glucose),
-    new TestSpeakerMapping(glucose),    
-    // new TestHuePattern(glucose),
-    // new TestXPattern(glucose),
-    // new TestYPattern(glucose),
-    // new TestZPattern(glucose),
+    new TestCubePattern(lx),
+    new TestTowerPattern(lx),
+    new TestProjectionPattern(lx),
+    new TestStripPattern(lx),
+    // new TestHuePattern(lx),
+    // new TestXPattern(lx),
+    // new TestYPattern(lx),
+    // new TestZPattern(lx),
 
   };
 }
 
-LXTransition[] transitions(GLucose glucose) {
+LXTransition[] transitions(LX lx) {
   return new LXTransition[] {
     new DissolveTransition(lx),
-    new AddTransition(glucose),
-    new MultiplyTransition(glucose),
-    new OverlayTransition(glucose),
-    new DodgeTransition(glucose),
-    new SwipeTransition(glucose),
+    new AddTransition(lx),
+    new MultiplyTransition(lx),
+    new OverlayTransition(lx),
+    new DodgeTransition(lx),
+    new SwipeTransition(lx),
     new FadeTransition(lx),
-//  new SubtractTransition(glucose),   // similar to multiply - dh
-//  new BurnTransition(glucose),               // similar to multiply - dh
-//  new ScreenTransition(glucose),             // same as add -dh
-//  new SoftLightTransition(glucose),  // same as overlay -dh
   };
 }
 
 // Handles to globally triggerable effects 
 class Effects {
-  //FlashEffect flash = new FlashEffect(lx);
-  BoomEffect boom = new BoomEffect(glucose);
-  BlurEffect blur = new BlurEffect(glucose);
-  QuantizeEffect quantize = new QuantizeEffect(glucose);
-  ColorFuckerEffect colorFucker = new ColorFuckerEffect(glucose);
+  FlashEffect flash = new FlashEffect(lx);
+  BoomEffect boom = new BoomEffect(lx);
+  BlurEffect blur = new BlurEffect(lx);
+  QuantizeEffect quantize = new QuantizeEffect(lx);
+  ColorFuckerEffect colorFucker = new ColorFuckerEffect(lx);
   
   Effects() {
     blur.enable();
diff --git a/SugarCubes.pde.orig b/SugarCubes.pde.orig
deleted file mode 100644 (file)
index e989980..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-/**
- *           +-+-+-+-+-+               +-+-+-+-+-+
- *          /         /|               |\         \
- *         /         / +               + \         \
- *        +-+-+-+-+-+  |   +-+-+-+-+   |  +-+-+-+-+-+
- *        |         |  +  /         \  +  |         |
- *        +   THE   + /  /           \  \ +  CUBES  +
- *        |         |/  +-+-+-+-+-+-+-+  \|         |
- *        +-+-+-+-+-+   |             |   +-+-+-+-+-+
- *                      +             +
- *                      |    SUGAR    |
- *                      +             +
- *                      |             |
- *                      +-+-+-+-+-+-+-+
- *
- * Welcome to the Sugar Cubes! This Processing sketch is a fun place to build
- * animations, effects, and interactions for the platform. Most of the icky
- * code guts are embedded in the GLucose library extension. If you're an
- * artist, you shouldn't need to worry about any of that.
- *
- * Below, you will find definitions of the Patterns, Effects, and Interactions.
- * If you're an artist, create a new tab in the Processing environment with
- * your name. Implement your classes there, and add them to the list below.
- */ 
-
-LXPattern[] patterns(GLucose glucose) {
-  return new LXPattern[] {
-
-<<<<<<< HEAD
-    new SineSphere(glucose),
-    new CubeCurl(glucose),
-=======
->>>>>>> b8bb27489db7dc687bf150576e9d9439f1fa17a6
-    // Slee
-    new Cathedrals(glucose),
-    new MidiMusic(glucose),
-    new Pulley(glucose),
-    new Swarm(glucose),
-    new ViolinWave(glucose),
-    new BouncyBalls(glucose),
-    new SpaceTime(glucose),
-    new ShiftingPlane(glucose),
-    new AskewPlanes(glucose),
-    new Blinders(glucose),
-    new CrossSections(glucose),
-    new Psychedelia(glucose),
-    
-    new Traktor(glucose).setEligible(false),
-    new BassPod(glucose).setEligible(false),
-    new CubeEQ(glucose).setEligible(false),
-    new PianoKeyPattern(glucose).setEligible(false),
-
-    // DanH
-    new Noise(glucose),
-    new Play (glucose),
-    new Pong (glucose),
-    new Worms(glucose),
-
-    // Alex G
-     
-
-    // Shaheen
-    new HelixPattern(glucose).setEligible(false),
-    
-    // Toby
-    new GlitchPlasma(glucose),
-    new FireEffect(glucose).setEligible(false),
-    new StripBounce(glucose),
-    new SoundRain(glucose).setEligible(false),
-    new SoundSpikes(glucose).setEligible(false),
-    new FaceSync(glucose),
-
-    // Jack
-    new Swim(glucose),
-    new Balance(glucose),
-
-    // Tim
-    new TimPlanes(glucose),
-    new TimPinwheels(glucose),
-    new TimRaindrops(glucose),
-    new TimCubes(glucose),
-    // new TimTrace(glucose),
-    new TimSpheres(glucose),
-
-    // Ben
-    // new Sandbox(glucose),
-    new TowerParams(glucose),
-    new DriveableCrossSections(glucose),
-    new GranimTestPattern2(glucose),
-    
-    //JR
-    new Gimbal(glucose),
-    
-    // Sam
-    new JazzRainbow(glucose),
-    
-    // Arjun
-    new TelevisionStatic(glucose),
-    new AbstractPainting(glucose),
-    new Spirality(glucose),
-
-    // Basic test patterns for reference, not art    
-    new TestCubePattern(glucose),
-    new TestTowerPattern(glucose),
-    new TestProjectionPattern(glucose),
-    new TestStripPattern(glucose),
-    new TestBassMapping(glucose),
-    new TestFloorMapping(glucose),
-    new TestSpeakerMapping(glucose),    
-    // new TestHuePattern(glucose),
-    // new TestXPattern(glucose),
-    // new TestYPattern(glucose),
-    // new TestZPattern(glucose),
-
-  };
-}
-
-LXTransition[] transitions(GLucose glucose) {
-  return new LXTransition[] {
-    new DissolveTransition(lx),
-    new AddTransition(glucose),
-    new MultiplyTransition(glucose),
-    new OverlayTransition(glucose),
-    new DodgeTransition(glucose),
-    new SwipeTransition(glucose),
-    new FadeTransition(lx),
-//  new SubtractTransition(glucose),   // similar to multiply - dh
-//  new BurnTransition(glucose),               // similar to multiply - dh
-//  new ScreenTransition(glucose),             // same as add -dh
-//  new SoftLightTransition(glucose),  // same as overlay -dh
-  };
-}
-
-// Handles to globally triggerable effects 
-class Effects {
-  FlashEffect flash = new FlashEffect(lx);
-  BoomEffect boom = new BoomEffect(glucose);
-  BlurEffect blur = new BlurEffect(glucose);
-  QuantizeEffect quantize = new QuantizeEffect(glucose);
-  ColorFuckerEffect colorFucker = new ColorFuckerEffect(glucose);
-  
-  Effects() {
-    blur.enable();
-    quantize.enable();
-    colorFucker.enable();
-  }
-}
-
index 6a662f248fb5dfe4f1152eff98f0f35e9a6a6ee0..728683ec45dea70eec6ee5e03f4f4f3635449514 100644 (file)
@@ -1,6 +1,6 @@
 class BlankPattern extends SCPattern {
-  BlankPattern(GLucose glucose) {
-    super(glucose);
+  BlankPattern(LX lx) {
+    super(lx);
   }
   
   public void run(double deltaMs) {
@@ -9,87 +9,18 @@ class BlankPattern extends SCPattern {
 }
 
 abstract class TestPattern extends SCPattern {
-  public TestPattern(GLucose glucose) {
-    super(glucose);
+  public TestPattern(LX lx) {
+    super(lx);
     setEligible(false);
   }
 }
 
-class TestSpeakerMapping extends TestPattern {
-  TestSpeakerMapping(GLucose glucose) {
-    super(glucose);
-  }
-  
-  public void run(double deltaMs) {
-    int h = 0;
-    for (Speaker speaker : model.speakers) {
-      for (Strip strip : speaker.strips) {
-        float b = 100;
-        for (LXPoint p : strip.points) {
-          colors[p.index] = lx.hsb(h % 360, 100, b);
-          b = max(0, b - 10);
-        }
-        h += 70;
-      }
-    }
-  }
-
-}
-
-class TestBassMapping extends TestPattern {
-  TestBassMapping(GLucose glucose) {
-    super(glucose);
-  }
-  
-  public void run(double deltaMs) {
-    int[] strips = { 2, 1, 0, 3, 13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6 };
-    int h = 0;
-    for (int si : strips) {
-      float b = 100;
-      for (LXPoint p : model.bassBox.strips.get(si).points) {
-        colors[p.index] = lx.hsb(h % 360, 100, b);
-        b = max(0, b - 10);
-      }
-      h += 70;
-    }
-  }
-}
-
-class TestFloorMapping extends TestPattern {
-  TestFloorMapping(GLucose glucose) {
-    super(glucose);
-  }
-
-  public void run(double deltaMs) {
-    int[] strutIndices = {6, 5, 4, 3, 2, 1, 0, 7};
-    int h = 0;
-    for (int si : strutIndices) {
-      float b = 100;
-      for (LXPoint p : model.bassBox.struts.get(si).points) {
-        colors[p.index] = lx.hsb(h % 360, 100, b);
-        b = max(0, b - 10);
-      }
-      h += 50;
-    }
-    int[] floorIndices = {0, 1, 2, 3};
-    h = 0;
-    for (int fi : floorIndices) {
-      float b = 100;
-      for (LXPoint p : model.boothFloor.strips.get(fi).points) {
-        colors[p.index] = lx.hsb(h, 100, b);
-        b = max(0, b - 3);
-      }
-      h += 90;
-    }
-  }
-}
-
 class TestStripPattern extends TestPattern {
   
   SinLFO d = new SinLFO(4, 40, 4000);
   
-  public TestStripPattern(GLucose glucose) {
-    super(glucose);
+  public TestStripPattern(LX lx) {
+    super(lx);
     addModulator(d).trigger();
   }
   
@@ -111,8 +42,8 @@ class TestStripPattern extends TestPattern {
  * All pixels are full-on the same color.
  */
 class TestHuePattern extends TestPattern {
-  public TestHuePattern(GLucose glucose) {
-    super(glucose);
+  public TestHuePattern(LX lx) {
+    super(lx);
   }
   
   public void run(double deltaMs) {
@@ -129,8 +60,8 @@ class TestHuePattern extends TestPattern {
  */
 class TestXPattern extends TestPattern {
   private final SinLFO xPos = new SinLFO(0, model.xMax, 4000);
-  public TestXPattern(GLucose glucose) {
-    super(glucose);
+  public TestXPattern(LX lx) {
+    super(lx);
     addModulator(xPos).trigger();
   }
   public void run(double deltaMs) {
@@ -151,8 +82,8 @@ class TestXPattern extends TestPattern {
  */
 class TestYPattern extends TestPattern {
   private final SinLFO yPos = new SinLFO(0, model.yMax, 4000);
-  public TestYPattern(GLucose glucose) {
-    super(glucose);
+  public TestYPattern(LX lx) {
+    super(lx);
     addModulator(yPos).trigger();
   }
   public void run(double deltaMs) {
@@ -169,8 +100,8 @@ class TestYPattern extends TestPattern {
  */
 class TestZPattern extends TestPattern {
   private final SinLFO zPos = new SinLFO(0, model.zMax, 4000);
-  public TestZPattern(GLucose glucose) {
-    super(glucose);
+  public TestZPattern(LX lx) {
+    super(lx);
     addModulator(zPos).trigger();
   }
   public void run(double deltaMs) {
@@ -188,8 +119,8 @@ class TestZPattern extends TestPattern {
 class TestTowerPattern extends TestPattern {
   private final SawLFO towerIndex = new SawLFO(0, model.towers.size(), 1000*model.towers.size());
   
-  public TestTowerPattern(GLucose glucose) {
-    super(glucose);
+  public TestTowerPattern(LX lx) {
+    super(lx);
     addModulator(towerIndex).trigger();
   }
 
@@ -233,8 +164,8 @@ class TestProjectionPattern extends TestPattern {
   private final SawLFO angle = new SawLFO(0, TWO_PI, 9000);
   private final SinLFO yPos = new SinLFO(-20, 40, 5000);
   
-  public TestProjectionPattern(GLucose glucose) {
-    super(glucose);
+  public TestProjectionPattern(LX lx) {
+    super(lx);
     projection = new LXProjection(model);
     addModulator(angle).trigger();
     addModulator(yPos).trigger();
@@ -273,8 +204,8 @@ class TestCubePattern extends TestPattern {
   
   private SawLFO index = new SawLFO(0, Cube.POINTS_PER_CUBE, Cube.POINTS_PER_CUBE*60);
   
-  TestCubePattern(GLucose glucose) {
-    super(glucose);
+  TestCubePattern(LX lx) {
+    super(lx);
     addModulator(index).start();
   }
   
@@ -314,15 +245,11 @@ class MappingTool extends TestPattern {
   public boolean channelModeBlue = false;
   
   private final int numChannels;
-  
-  private final PandaMapping[] pandaMappings;
-  private PandaMapping activePanda;
-  private ChannelMapping activeChannel;
-  
-  MappingTool(GLucose glucose, PandaMapping[] pandaMappings) {
-    super(glucose);
-    this.pandaMappings = pandaMappings;
-    numChannels = pandaMappings.length * PandaMapping.CHANNELS_PER_BOARD;
+    
+  MappingTool(LX lx) {
+    super(lx);
+    // TODO(mcslee): port channels to grizzly
+    numChannels = 1;
     setChannel();
   }
 
@@ -331,21 +258,12 @@ class MappingTool extends TestPattern {
   }
   
   private void setChannel() {
-    activePanda = pandaMappings[channelIndex / PandaMapping.CHANNELS_PER_BOARD];
-    activeChannel = activePanda.channelList[channelIndex % PandaMapping.CHANNELS_PER_BOARD];
+    // TODO(mcslee): port to grizzly
   }
   
   private int indexOfCubeInChannel(Cube c) {
-    if (activeChannel.mode == ChannelMapping.MODE_CUBES) {
-      int i = 1;
-      for (int index : activeChannel.objectIndices) {
-        if ((index >= 0) && (c == model.getCubeByRawIndex(index))) {
-          return i;
-        }
-        ++i;
-      }
-    }
-    return 0;
+    // TODO(mcslee): port to grizzly
+    return -1;
   }
   
   private void printInfo() {
@@ -440,7 +358,9 @@ class MappingTool extends TestPattern {
   }
   
   public void setChannel(int index) {
-    channelIndex = index % numChannels;
+    if (numChannels > 0) {
+      channelIndex = index % numChannels;
+    }
     setChannel();
   }
 
index 3fcd5b160353986498ff01793cd8cf64c5d05bf9..2ca73d7475ce77a39fb4a330d9eb70aa753682bb 100644 (file)
@@ -16,8 +16,8 @@ class TimSpheres extends SCPattern {
   
   private final Sphere[] spheres;
   
-  public TimSpheres(GLucose glucose) {
-    super(glucose);
+  public TimSpheres(LX lx) {
+    super(lx);
     addParameter(hueParameter);
     addParameter(periodParameter);
     addModulator(lfo).trigger();
@@ -236,8 +236,8 @@ class TimRaindrops extends SCPattern {
   private float msPerRaindrop = 40;
   private List<Raindrop> raindrops;
   
-  public TimRaindrops(GLucose glucose) {
-    super(glucose);
+  public TimRaindrops(LX lx) {
+    super(lx);
     raindrops = new LinkedList<Raindrop>();
   }
   
@@ -320,8 +320,8 @@ class TimCubes extends SCPattern {
   private float leftoverMs = 0;
   private List<CubeFlash> flashes;
   
-  public TimCubes(GLucose glucose) {
-    super(glucose);
+  public TimCubes(LX lx) {
+    super(lx);
     addParameter(rateParameter);
     addParameter(attackParameter);
     addParameter(decayParameter);
@@ -397,8 +397,8 @@ class TimPlanes extends SCPattern {
     }
   }
       
-  TimPlanes(GLucose glucose) {
-    super(glucose);
+  TimPlanes(LX lx) {
+    super(lx);
     centerX = (model.xMin + model.xMax) / 2;
     centerY = (model.yMin + model.yMax) / 2;
     centerZ = (model.zMin + model.zMax) / 2;
@@ -560,8 +560,8 @@ class TimPinwheels extends SCPattern {
   private final List<Pinwheel> pinwheels;
   private final float[] values;
   
-  TimPinwheels(GLucose glucose) {
-    super(glucose);
+  TimPinwheels(LX lx) {
+    super(lx);
     
     addParameter(horizSpreadParameter);
 //    addParameter(vertSpreadParameter);
@@ -727,8 +727,8 @@ class TimTrace extends SCPattern {
   
   List<MovingPoint> movingPoints;
   
-  TimTrace(GLucose glucose) {
-    super(glucose);
+  TimTrace(LX lx) {
+    super(lx);
     
     extraMs = 0;
     
@@ -843,8 +843,8 @@ class TimMetronome extends SCPattern {
   private float[] values;
   private float[] hues;
   
-  TimMetronome(GLucose glucose) {
-    super(glucose);
+  TimMetronome(LX lx) {
+    super(lx);
     addParameter(clickyParameter);
     addParameter(derezParameter);
     addParameter(driftParameter);
index 8aaacb175ef7e7e67e0eb9ba0dd285ac3f14a28d..8769b101ef17b728d1281d169bef79eb6aff036a 100644 (file)
@@ -7,8 +7,8 @@ class GlitchPlasma extends SCPattern {
   BasicParameter speedParameter = new BasicParameter("SPEED", 0.1);
   BasicParameter glitchParameter = new BasicParameter("GLITCH", 0.0);
   
-  public GlitchPlasma(GLucose glucose) {
-    super(glucose);
+  public GlitchPlasma(LX lx) {
+    super(lx);
     addParameter(saturationParameter);
     addParameter(speedParameter);
     addParameter(glitchParameter);
@@ -49,8 +49,8 @@ class FireEffect extends SCPattern {
   private int ym;
   BasicParameter decayParameter = new BasicParameter("DECAY", 0.3);
   
-  public FireEffect(GLucose glucose) {
-    super(glucose);
+  public FireEffect(LX lx) {
+    super(lx);
     xm = int(model.xMax);
     ym = int(model.yMax);
     
@@ -97,8 +97,8 @@ class StripBounce extends SCPattern {
   SinLFO[] sat = new SinLFO[numOsc];
   float[] colorOffset = new float[numOsc];
   
-  public StripBounce(GLucose glucose) {
-    super(glucose);
+  public StripBounce(LX lx) {
+    super(lx);
     for (int i=0;i<numOsc;i++) {
       fX[i] = new SinLFO(0, model.xMax, random(2000,20000)); 
       fY[i] = new SinLFO(0, model.yMax, random(2000,20000)); 
@@ -142,8 +142,8 @@ class SoundRain extends SCPattern {
   SinLFO col1 = new SinLFO(0, model.xMax, 5000);
   BasicParameter gainParameter = new BasicParameter("GAIN", 0.5);
   
-  public SoundRain(GLucose glucose) {
-    super(glucose);
+  public SoundRain(LX lx) {
+    super(lx);
     addModulator(pos).trigger();
     addModulator(col1).trigger();
     addParameter(gainParameter);
@@ -154,7 +154,7 @@ class SoundRain extends SCPattern {
       gain = 50*parameter.getValuef();
     }
   }
-  protected void onActive() {
+  void onActive() {
     if (this.fft == null) {
       this.fft = new FFT(lx.audioInput().bufferSize(), lx.audioInput().sampleRate());
       this.fft.window(FFT.HAMMING);
@@ -201,8 +201,8 @@ class FaceSync extends SCPattern {
   SinLFO col1 = new SinLFO(0, model.xMax, 5000);
   SinLFO col2 = new SinLFO(0, model.xMax, 4000);
 
-  public FaceSync(GLucose glucose) {
-    super(glucose);
+  public FaceSync(LX lx) {
+    super(lx);
     addModulator(xosc).trigger();
     addModulator(zosc).trigger();
     zosc.setValue(0);
@@ -244,8 +244,8 @@ class SoundSpikes extends SCPattern {
   BasicParameter gainParameter = new BasicParameter("GAIN", 0.5);
   SawLFO pos = new SawLFO(0, model.xMax, 8000);
 
-  public SoundSpikes(GLucose glucose) {
-    super(glucose);
+  public SoundSpikes(LX lx) {
+    super(lx);
     addParameter(gainParameter);
     addModulator(pos).trigger();
   }
@@ -255,7 +255,7 @@ class SoundSpikes extends SCPattern {
       gain = 50*parameter.getValuef();
     }
   }
-  protected void onActive() {
+  void onActive() {
     if (this.fft == null) {
       this.fft = new FFT(lx.audioInput().bufferSize(), lx.audioInput().sampleRate());
       this.fft.window(FFT.HAMMING);
diff --git a/UIFramework.pde b/UIFramework.pde
deleted file mode 100644 (file)
index 8ecb7e9..0000000
+++ /dev/null
@@ -1,917 +0,0 @@
-/**
- *     DOUBLE BLACK DIAMOND        DOUBLE BLACK DIAMOND
- *
- *         //\\   //\\                 //\\   //\\  
- *        ///\\\ ///\\\               ///\\\ ///\\\
- *        \\\/// \\\///               \\\/// \\\///
- *         \\//   \\//                 \\//   \\//
- *
- *        EXPERTS ONLY!!              EXPERTS ONLY!!
- *
- * Little UI framework in progress to handle mouse events, layout,
- * redrawing, etc.
- */
-
-final color lightGreen = #669966;
-final color lightBlue = #666699;
-final color bgGray = #444444;
-final color defaultTextColor = #999999;
-final PFont defaultItemFont = createFont("Lucida Grande", 11);
-final PFont defaultTitleFont = createFont("Myriad Pro", 10);
-
-public abstract class UIObject {
-  
-  protected final static int DOUBLE_CLICK_THRESHOLD = 300;
-  
-  protected final List<UIObject> children = new ArrayList<UIObject>();  
-
-  protected boolean needsRedraw = true;
-  protected boolean childNeedsRedraw = true;
-  
-  protected float x=0, y=0, w=0, h=0;
-  
-  public UIContainer parent = null;
-  
-  protected boolean visible = true;
-  
-  public UIObject() {}
-  
-  public UIObject(float x, float y, float w, float h) {
-    this.x = x;
-    this.y = y;
-    this.w = w;
-    this.h = h;
-  }
-
-  public boolean isVisible() {
-    return visible;
-  }
-
-  public UIObject setVisible(boolean visible) {
-    if (visible != this.visible) {
-      this.visible = visible;
-      redraw();
-    }
-    return this;
-  }
-
-  public final UIObject setPosition(float x, float y) {
-    this.x = x;
-    this.y = y;
-    redraw();
-    return this;
-  }
-  
-  public final UIObject setSize(float w, float h) {
-    this.w = w;
-    this.h = h;
-    redraw();
-    return this;
-  }
-
-  public final UIObject addToContainer(UIContainer c) {
-    c.children.add(this);
-    this.parent = c;
-    return this;
-  }
-  
-  public final UIObject removeFromContainer(UIContainer c) {
-    c.children.remove(this);
-    this.parent = null;
-    return this;
-  }
-  
-  public final UIObject redraw() {
-    _redraw();
-    UIObject p = this.parent;
-    while (p != null) {
-      p.childNeedsRedraw = true;
-      p = p.parent;
-    }
-    return this;
-  }
-  
-  private final void _redraw() {
-    needsRedraw = true;
-    for (UIObject child : children) {
-      childNeedsRedraw = true;
-      child._redraw();
-    }    
-  }
-    
-  public final void draw(PGraphics pg) {
-    if (!visible) {
-      return;
-    }
-    if (needsRedraw) {
-      needsRedraw = false;
-      onDraw(pg);
-    }
-    if (childNeedsRedraw) {
-      childNeedsRedraw = false;
-      for (UIObject child : children) {
-        if (needsRedraw || child.needsRedraw || child.childNeedsRedraw) {
-          pg.pushMatrix();
-          pg.translate(child.x, child.y);
-          child.draw(pg);
-          pg.popMatrix();
-        }
-      }
-    }
-  }
-  
-  public final boolean contains(float x, float y) {
-    return
-      (x >= this.x && x < (this.x + this.w)) &&
-      (y >= this.y && y < (this.y + this.h));
-  }
-  
-  protected void onDraw(PGraphics pg) {}
-  protected void onMousePressed(float mx, float my) {}
-  protected void onMouseReleased(float mx, float my) {}
-  protected void onMouseDragged(float mx, float my, float dx, float dy) {}  
-  protected void onMouseWheel(float mx, float my, float dx) {}  
-}
-
-public class UIContainer extends UIObject {
-  
-  private UIObject focusedChild = null;
-  
-  public UIContainer() {}
-  
-  public UIContainer(float x, float y, float w, float h) {
-    super(x, y, w, h);
-  }
-  
-  public UIContainer(UIObject[] children) {
-    for (UIObject child : children) {
-      child.addToContainer(this);
-    }
-  }
-  
-  protected void onMousePressed(float mx, float my) {
-    for (int i = children.size() - 1; i >= 0; --i) {
-      UIObject child = children.get(i);
-      if (child.contains(mx, my)) {
-        child.onMousePressed(mx - child.x, my - child.y);
-        focusedChild = child;
-        break;
-      }
-    }
-  }
-    
-  protected void onMouseReleased(float mx, float my) {
-    if (focusedChild != null) {
-      focusedChild.onMouseReleased(mx - focusedChild.x, my - focusedChild.y);
-    }
-    focusedChild = null;
-  }
-  
-  protected void onMouseDragged(float mx, float my, float dx, float dy) {
-    if (focusedChild != null) {
-      focusedChild.onMouseDragged(mx - focusedChild.x, my - focusedChild.y, dx, dy);
-    }
-  }
-  
-  protected void onMouseWheel(float mx, float my, float delta) {
-    for (UIObject child : children) {
-      if (child.contains(mx, my)) {
-        child.onMouseWheel(mx - child.x, mx - child.y, delta);
-      }
-    }
-  }
-  
-}
-
-public class UIContext extends UIContainer {
-  
-  final public PGraphics pg;
-  
-  UIContext(float x, float y, float w, float h) {
-    super(x, y, w, h);
-    pg = createGraphics((int)w, (int)h, JAVA2D);
-    pg.smooth();
-  }
-  
-  public void draw() {
-    if (!visible) {
-      return;
-    }
-    if (needsRedraw || childNeedsRedraw) {
-      pg.beginDraw();
-      draw(pg);
-      pg.endDraw();
-    }
-    image(pg, x, y);
-  }
-  
-  private float px, py;
-  private boolean dragging = false;
-  
-  public boolean mousePressed(float mx, float my) {
-    if (!visible) {
-      return false;
-    }
-    if (contains(mx, my)) {
-      dragging = true;
-      px = mx;
-      py = my;
-      onMousePressed(mx - x, my - y);
-      return true;
-    }
-    return false;
-  }
-  
-  public boolean mouseReleased(float mx, float my) {
-    if (!visible) {
-      return false;
-    }
-    dragging = false;
-    onMouseReleased(mx - x, my - y);
-    return true;
-  }
-  
-  public boolean mouseDragged(float mx, float my) {
-    if (!visible) {
-      return false;
-    }
-    if (dragging) {
-      float dx = mx - px;
-      float dy = my - py;
-      onMouseDragged(mx - x, my - y, dx, dy);
-      px = mx;
-      py = my;
-      return true;
-    }
-    return false;
-  }
-  
-  public boolean mouseWheel(float mx, float my, float delta) {
-    if (!visible) {
-      return false;
-    }
-    if (contains(mx, my)) {
-      onMouseWheel(mx - x, my - y, delta);
-      return true;
-    }
-    return false;
-  }
-}
-
-public class UIWindow extends UIContext {
-  
-  protected final static int titleHeight = 24;
-  
-  public UIWindow(String label, float x, float y, float w, float h) {
-    super(x, y, w, h);
-    new UILabel(6, 8, w-6, titleHeight-8) {
-      protected void onMouseDragged(float mx, float my, float dx, float dy) {
-        parent.x = constrain(parent.x + dx, 0, width - w);
-        parent.y = constrain(parent.y + dy, 0, height - h);
-      }
-    }.setLabel(label).setFont(defaultTitleFont).addToContainer(this);
-  }
-
-  protected void onDraw(PGraphics pg) {
-    pg.noStroke();
-    pg.fill(#444444);
-    pg.stroke(#292929);
-    pg.rect(0, 0, w-1, h-1);
-  }
-}
-
-public class UILabel extends UIObject {
-  
-  private PFont font = defaultTitleFont;
-  private color fontColor = #CCCCCC;
-  private String label = "";
-    
-  public UILabel(float x, float y, float w, float h) {
-    super(x, y, w, h);
-  }
-  
-  protected void onDraw(PGraphics pg) {
-    pg.textAlign(LEFT, TOP);
-    pg.textFont(font);
-    pg.fill(fontColor);
-    pg.text(label, 0, 0);
-  }
-  
-  public UILabel setFont(PFont font) {
-    this.font = font;
-    redraw();
-    return this;
-  }
-  
-  public UILabel setFontColor(color fontColor) {
-    this.fontColor = fontColor;
-    redraw();
-    return this;
-  }
-  
-  public UILabel setLabel(String label) {
-    this.label = label;
-    redraw();
-    return this;
-  }
-}
-
-public class UICheckbox extends UIButton {
-  
-  private boolean firstDraw = true;
-  
-  public UICheckbox(float x, float y, float w, float h) {
-    super(x, y, w, h);
-    setMomentary(false);
-  }
-  
-  public void onDraw(PGraphics pg) {
-    pg.stroke(borderColor);
-    pg.fill(active ? activeColor : inactiveColor);
-    pg.rect(0, 0, h, h);
-    if (firstDraw) {
-      pg.fill(labelColor);
-      pg.textFont(defaultItemFont);
-      pg.textAlign(LEFT, CENTER);
-      pg.text(label, h + 4, h/2);
-      firstDraw = false;
-    }
-  }
-      
-}
-
-public class UIButton extends UIObject {
-
-  protected boolean active = false;
-  protected boolean isMomentary = false;
-  protected color borderColor = #666666;
-  protected color inactiveColor = #222222;
-  protected color activeColor = #669966;
-  protected color labelColor = #999999;
-  protected String label = "";
-   
-  public UIButton(float x, float y, float w, float h) {
-    super(x, y, w, h);
-  }
-  
-  public UIButton setMomentary(boolean momentary) {
-    isMomentary = momentary;
-    return this;
-  }
-  
-  protected void onDraw(PGraphics pg) {
-    pg.stroke(borderColor);
-    pg.fill(active ? activeColor : inactiveColor);
-    pg.rect(0, 0, w, h);
-    if (label != null && label.length() > 0) {
-      pg.fill(active ? #FFFFFF : labelColor);
-      pg.textFont(defaultItemFont);
-      pg.textAlign(CENTER);
-      pg.text(label, w/2, h-5);
-    }
-  }
-  
-  protected void onMousePressed(float mx, float my) {
-    if (isMomentary) {
-      setActive(true);
-    } else {
-      setActive(!active);
-    }
-  }
-  
-  protected void onMouseReleased(float mx, float my) {
-    if (isMomentary) {
-      setActive(false);
-    }
-  }
-  
-  public boolean isActive() {
-    return active;
-  }
-  
-  public UIButton setActive(boolean active) {
-    this.active = active;
-    onToggle(active);
-    redraw();
-    return this;
-  }
-  
-  public UIButton toggle() {
-    return setActive(!active);
-  }
-  
-  protected void onToggle(boolean active) {}
-  
-  public UIButton setBorderColor(color borderColor) {
-    if (this.borderColor != borderColor) {
-      this.borderColor = borderColor;
-      redraw();
-    }
-    return this;
-  }
-  
-  public UIButton setActiveColor(color activeColor) {
-    if (this.activeColor != activeColor) {
-      this.activeColor = activeColor;
-      if (active) {
-        redraw();
-      }
-    }
-    return this;
-  }
-  
-  public UIButton setInactiveColor(color inactiveColor) {
-    if (this.inactiveColor != inactiveColor) {
-      this.inactiveColor = inactiveColor;
-      if (!active) {
-        redraw();
-      }
-    }
-    return this;
-  }
-  
-  public UIButton setLabelColor(color labelColor) {
-    if (this.labelColor != labelColor) {
-      this.labelColor = labelColor;
-      redraw();
-    }
-    return this;
-  }
-
-  public UIButton setLabel(String label) {
-    if (!this.label.equals(label)) {
-      this.label = label;
-      redraw();
-    }
-    return this;
-  }
-  
-  public void onMousePressed() {
-    setActive(!active);
-  }
-}
-
-public class UIToggleSet extends UIObject {
-
-  private String[] options;
-  private int[] boundaries;
-  private String value;
-  
-  public UIToggleSet(float x, float y, float w, float h) {
-    super(x, y, w, h);
-  }
-  
-  public UIToggleSet setOptions(String[] options) {
-    this.options = options;
-    boundaries = new int[options.length];
-    int totalLength = 0;
-    for (String s : options) {
-      totalLength += s.length();
-    }
-    int lengthSoFar = 0;
-    for (int i = 0; i < options.length; ++i) {
-      lengthSoFar += options[i].length();
-      boundaries[i] = (int) (lengthSoFar * w / totalLength);
-    }
-    value = options[0];
-    redraw();
-    return this;
-  }
-  
-  public String getValue() {
-    return value;
-  }
-  
-  public UIToggleSet setValue(String option) {
-    value = option;
-    onToggle(value);
-    redraw();
-    return this;
-  }
-  
-  public void onDraw(PGraphics pg) {
-    pg.stroke(#666666);
-    pg.fill(#222222);
-    pg.rect(0, 0, w, h);
-    for (int b : boundaries) {
-      pg.line(b, 1, b, h-1);
-    }
-    pg.noStroke();
-    pg.textAlign(CENTER);
-    pg.textFont(defaultItemFont);
-    int leftBoundary = 0;
-    
-    for (int i = 0; i < options.length; ++i) {
-      boolean isActive = options[i] == value;
-      if (isActive) {
-        pg.fill(lightGreen);
-        pg.rect(leftBoundary + 1, 1, boundaries[i] - leftBoundary - 1, h-1);
-      }
-      pg.fill(isActive ? #FFFFFF : #999999);
-      pg.text(options[i], (leftBoundary + boundaries[i]) / 2., h-6);
-      leftBoundary = boundaries[i];
-    }
-  }
-  
-  public void onMousePressed(float mx, float my) {
-    for (int i = 0; i < boundaries.length; ++i) {
-      if (mx < boundaries[i]) {
-        setValue(options[i]);
-        break;
-      }
-    }
-  }
-  
-  protected void onToggle(String option) {}
-  
-}
-
-
-public abstract class UIParameterControl extends UIObject implements LXParameterListener {
-  protected LXParameter parameter = null;
-    
-  protected UIParameterControl(float x, float y, float w, float h) {
-    super(x, y, w, h);
-  }
-  
-  public void onParameterChanged(LXParameter parameter) {
-    redraw();
-  }
-  
-  protected float getNormalized() {
-    if (parameter != null) {
-      if (parameter instanceof BasicParameter) {
-        return ((BasicParameter)parameter).getNormalizedf();
-      }
-      return parameter.getValuef();
-    }
-    return 0;
-  }
-  
-  protected UIParameterControl setNormalized(float value) {
-    if (parameter != null) {
-      if (parameter instanceof BasicParameter) {
-        ((BasicParameter)parameter).setNormalized(value);
-      } else {
-        parameter.setValue(value);
-      }
-    }
-    return this;
-  }
-  
-  public UIParameterControl setParameter(LXParameter parameter) {
-    if (this.parameter != null) {
-      if (this.parameter instanceof LXListenableParameter) {
-        ((LXListenableParameter)this.parameter).removeListener(this);
-      }
-    }
-    this.parameter = parameter;
-    if (this.parameter != null) {
-      if (this.parameter instanceof LXListenableParameter) {
-        ((LXListenableParameter)this.parameter).addListener(this);
-      }
-    }
-    redraw();
-    return this;
-  }
-}
-
-public class UIParameterKnob extends UIParameterControl {
-  private int knobSize = 28;
-  private final float knobIndent = .4;  
-  private final int knobLabelHeight = 14;
-  private boolean showValue = false;
-    
-  public UIParameterKnob(float x, float y) {
-    this(x, y, 0, 0);
-    setSize(knobSize, knobSize + knobLabelHeight);
-  }
-  
-  public UIParameterKnob(float x, float y, float w, float h) {
-    super(x, y, w, h);
-  }
-
-  protected void onDraw(PGraphics pg) {    
-    float knobValue = getNormalized();
-    
-    pg.ellipseMode(CENTER);
-    pg.noStroke();
-
-    pg.fill(bgGray);
-    pg.rect(0, 0, knobSize, knobSize);
-
-    // Full outer dark ring
-    pg.fill(#222222);    
-    pg.arc(knobSize/2, knobSize/2, knobSize, knobSize, HALF_PI + knobIndent, HALF_PI + knobIndent + (TWO_PI-2*knobIndent));
-
-    // Light ring indicating value
-    pg.fill(lightGreen);
-    pg.arc(knobSize/2, knobSize/2, knobSize, knobSize, HALF_PI + knobIndent, HALF_PI + knobIndent + knobValue*(TWO_PI-2*knobIndent));
-    
-    // Center circle of knob
-    pg.fill(#333333);
-    pg.ellipse(knobSize/2, knobSize/2, knobSize/2, knobSize/2);
-
-    String knobLabel;
-    if (showValue) {
-      knobLabel = (parameter != null) ? ("" + parameter.getValue()) : null;
-    } else {
-      knobLabel = (parameter != null) ? parameter.getLabel() : null;
-    }
-    if (knobLabel == null) {
-      knobLabel = "-";
-    } else if (knobLabel.length() > 4) {
-      knobLabel = knobLabel.substring(0, 4);
-    }
-    pg.fill(#000000);
-    pg.rect(0, knobSize + 2, knobSize, knobLabelHeight - 2);
-    pg.fill(#999999);
-    pg.textAlign(CENTER);
-    pg.textFont(defaultTitleFont);
-    pg.text(knobLabel, knobSize/2, knobSize + knobLabelHeight - 2);
-  }
-  
-  private long lastMousePress = 0;
-  public void onMousePressed(float mx, float my) {
-    super.onMousePressed(mx, my);
-    long now = millis();
-    if (now - lastMousePress < DOUBLE_CLICK_THRESHOLD) {
-      parameter.reset();
-      lastMousePress = 0;
-    } else {
-      lastMousePress = now;
-    }
-    showValue = true;
-    redraw();    
-  }
-  
-  public void onMouseReleased(float mx, float my) {
-    showValue = false;
-    redraw();
-  }
-  
-  public void onMouseDragged(float mx, float my, float dx, float dy) {
-    float value = constrain(getNormalized() - dy / 100., 0, 1);
-    setNormalized(value);
-  }
-}
-
-public class UIParameterSlider extends UIParameterControl {
-  
-  private static final float handleWidth = 12;
-  
-  UIParameterSlider(float x, float y, float w, float h) {
-    super(x, y, w, h);
-  }
-  
-  protected void onDraw(PGraphics pg) {
-    pg.noStroke();
-    pg.fill(#333333);
-    pg.rect(0, 0, w, h);
-    pg.fill(#222222);
-    pg.rect(4, h/2-2, w-8, 4);
-    pg.fill(#666666);
-    pg.stroke(#222222);
-    pg.rect((int) (4 + parameter.getValuef() * (w-8-handleWidth)), 4, handleWidth, h-8);
-  }
-  
-  private boolean editing = false;
-  private long lastClick = 0;
-  private float doubleClickMode = 0;
-  private float doubleClickX = 0;
-  protected void onMousePressed(float mx, float my) {
-    long now = millis();
-    float handleLeft = 4 + getNormalized() * (w-8-handleWidth);
-    if (mx >= handleLeft && mx < handleLeft + handleWidth) {
-      editing = true;
-    } else {
-      if ((now - lastClick) < DOUBLE_CLICK_THRESHOLD && abs(mx - doubleClickX) < 3) {
-        setNormalized(doubleClickMode);  
-      }
-      doubleClickX = mx;
-      if (mx < w*.25) {
-        doubleClickMode = 0;
-      } else if (mx > w*.75) {
-        doubleClickMode = 1;
-      } else {
-        doubleClickMode = 0.5;
-      }
-    }
-    lastClick = now;
-  }
-  
-  protected void onMouseReleased(float mx, float my) {
-    editing = false;
-  }
-  
-  protected void onMouseDragged(float mx, float my, float dx, float dy) {
-    if (editing) {
-      setNormalized(constrain((mx - handleWidth/2. - 4) / (w-8-handleWidth), 0, 1));
-    }
-  }
-}
-
-public class UIScrollList extends UIObject {
-
-  private List<ScrollItem> items = new ArrayList<ScrollItem>();
-
-  private PFont itemFont = defaultItemFont;
-  private int itemHeight = 20;
-  private color selectedColor = lightGreen;
-  private color pendingColor = lightBlue;
-  private int scrollOffset = 0;
-  private int numVisibleItems = 0;
-
-  private boolean hasScroll;
-  private float scrollYStart;
-  private float scrollYHeight;
-  
-  public UIScrollList(float x, float y, float w, float h) {
-    super(x, y, w, h);
-  }
-    
-  protected void onDraw(PGraphics pg) {
-    int yp = 0;
-    boolean even = true;
-    for (int i = 0; i < numVisibleItems; ++i) {
-      if (i + scrollOffset >= items.size()) {
-        break;
-      }
-      ScrollItem item = items.get(i + scrollOffset);
-      color itemColor;
-      color labelColor = #FFFFFF;
-      if (item.isSelected()) {
-        itemColor = selectedColor;
-      } else if (item.isPending()) {
-        itemColor = pendingColor;
-      } else {
-        labelColor = #000000;
-        itemColor = #707070;
-      }
-      float factor = even ? .92 : 1.08;
-      itemColor = lx.scaleBrightness(itemColor, factor);
-      
-      pg.noStroke();
-      pg.fill(itemColor);
-      pg.rect(0, yp, w, itemHeight);
-      pg.fill(labelColor);
-      pg.textFont(itemFont);
-      pg.textAlign(LEFT, TOP);
-      pg.text(item.getLabel(), 6, yp+4);
-                  
-      yp += itemHeight;
-      even = !even;
-    }
-    if (hasScroll) {
-      pg.noStroke();
-      pg.fill(0x26ffffff);
-      pg.rect(w-12, 0, 12, h);
-      pg.fill(#333333);
-      pg.rect(w-12, scrollYStart, 12, scrollYHeight);
-    }
-    
-  }
-  
-  private boolean scrolling = false;
-  private ScrollItem pressedItem = null;
-  
-  public void onMousePressed(float mx, float my) {
-    pressedItem = null;
-    if (hasScroll && mx >= w-12) {
-      if (my >= scrollYStart && my < (scrollYStart + scrollYHeight)) {
-        scrolling = true;
-        dAccum = 0;
-      }
-    } else {
-      int index = (int) my / itemHeight;
-      if (scrollOffset + index < items.size()) {
-        pressedItem = items.get(scrollOffset + index);
-        pressedItem.onMousePressed();
-        redraw();
-      }
-    }
-  }
-  
-  public void onMouseReleased(float mx, float my) {
-    scrolling = false;
-    if (pressedItem != null) {
-      pressedItem.onMouseReleased();
-      redraw();
-    }    
-  }
-  
-  private float dAccum = 0;
-  public void onMouseDragged(float mx, float my, float dx, float dy) {
-    if (scrolling) {
-      dAccum += dy;
-      float scrollOne = h / items.size();
-      int offset = (int) (dAccum / scrollOne);
-      if (offset != 0) {
-        dAccum -= offset * scrollOne;
-        setScrollOffset(scrollOffset + offset);
-      }
-    }
-  }
-    
-  private float wAccum = 0;
-  public void onMouseWheel(float mx, float my, float delta) {
-    wAccum += delta;
-    int offset = (int) (wAccum / 5);
-    if (offset != 0) {
-      wAccum -= offset * 5;
-      setScrollOffset(scrollOffset + offset);
-    }
-  }
-  
-  public void setScrollOffset(int offset) {
-    scrollOffset = constrain(offset, 0, max(0, items.size() - numVisibleItems));
-    scrollYStart = round(scrollOffset * h / items.size());
-    scrollYHeight = round(numVisibleItems * h / items.size());
-    redraw();
-  }
-  
-  public UIScrollList setItems(List<ScrollItem> items) {
-    this.items = items;
-    numVisibleItems = (int) (h / itemHeight);
-    hasScroll = items.size() > numVisibleItems;
-    setScrollOffset(0);
-    redraw();
-    return this;
-  }
-}
-
-public interface ScrollItem {
-  public boolean isSelected();
-  public boolean isPending();
-  public String getLabel();
-  public void onMousePressed();
-  public void onMouseReleased();  
-}
-
-public abstract class AbstractScrollItem implements ScrollItem {
-  public boolean isPending() {
-    return false;
-  }
-  public void select() {}
-  public void onMousePressed() {}
-  public void onMouseReleased() {}
-}
-
-public class UIIntegerBox extends UIObject {
-  
-  private int minValue = 0;
-  private int maxValue = MAX_INT;
-  private int value = 0;
-  
-  UIIntegerBox(float x, float y, float w, float h) {
-    super(x, y, w, h);
-  }
-  
-  public UIIntegerBox setRange(int minValue, int maxValue) {
-    this.minValue = minValue;
-    this.maxValue = maxValue;
-    setValue(constrain(value, minValue, maxValue));
-    return this;
-  }
-  
-  protected void onDraw(PGraphics pg) {
-    pg.stroke(#666666);
-    pg.fill(#222222);
-    pg.rect(0, 0, w, h);
-    pg.textAlign(CENTER, CENTER);
-    pg.textFont(defaultItemFont);
-    pg.fill(#999999);
-    pg.text("" + value, w/2, h/2);
-  }
-  
-  protected void onValueChange(int value) {}
-  
-  float dAccum = 0;
-  protected void onMousePressed(float mx, float my) {
-    dAccum = 0;
-  }
-  
-  protected void onMouseDragged(float mx, float my, float dx, float dy) {
-    dAccum -= dy;
-    int offset = (int) (dAccum / 5);
-    dAccum = dAccum - (offset * 5);
-    setValue(value + offset);
-  }
-  
-  public int getValue() {
-    return value;
-  }
-  
-  public UIIntegerBox setValue(int value) {
-    if (this.value != value) {
-      int range = (maxValue - minValue + 1);
-      while (value < minValue) {
-        value += range;
-      }        
-      this.value = minValue + (value - minValue) % range;
-      this.onValueChange(this.value);
-      redraw();
-    }
-    return this;
-  }
-}
index 0ea8073ddb57d6701a6a0a1b55df6fc88c89bbe8..7750ab930c365a3322d635b6f82728483f0bca7c 100644 (file)
  *
  * Custom UI components using the framework.
  */
-class UIPatternDeck extends UIWindow {
-    
-  LXDeck deck;
-  
-  public UIPatternDeck(LXDeck deck, String label, float x, float y, float w, float h) {
-    super(label, x, y, w, h);
-    this.deck = deck;
-    int yp = titleHeight;
-        
-    List<ScrollItem> items = new ArrayList<ScrollItem>();
-    for (LXPattern p : deck.getPatterns()) {
-      items.add(new PatternScrollItem(p));
-    }    
-    final UIScrollList patternList = new UIScrollList(1, yp, w-2, 140).setItems(items);
-    patternList.addToContainer(this);
-    yp += patternList.h + 10;
-    
-    final UIParameterKnob[] parameterKnobs = new UIParameterKnob[12];
-    for (int ki = 0; ki < parameterKnobs.length; ++ki) {
-      parameterKnobs[ki] = new UIParameterKnob(5 + 34*(ki % 4), yp + (ki/4) * 48);
-      parameterKnobs[ki].addToContainer(this);
+import java.util.Arrays;
+class UICubesLayer extends UICameraComponent {
+  void onDraw(UI ui) {
+    color[] simulationColors = lx.getColors();
+    String displayMode = uiCrossfader.getDisplayMode();
+    if (displayMode == "A") {
+      simulationColors = lx.engine.getDeck(LEFT_DECK).getColors();
+    } else if (displayMode == "B") {
+      simulationColors = lx.engine.getDeck(RIGHT_DECK).getColors();
     }
+
+    long simulationStart = System.nanoTime();
+    if (simulationOn) {
+      drawSimulation(simulationColors);
+    }
+    simulationNanos = System.nanoTime() - simulationStart;
     
-    LXDeck.Listener lxListener = new LXDeck.AbstractListener() {
-      public void patternWillChange(LXDeck deck, LXPattern pattern, LXPattern nextPattern) {
-        patternList.redraw();
-      }
-      public void patternDidChange(LXDeck deck, LXPattern pattern) {
-        patternList.redraw();
-        int pi = 0;
-        for (LXParameter parameter : pattern.getParameters()) {
-          if (pi >= parameterKnobs.length) {
-            break;
-          }
-          parameterKnobs[pi++].setParameter(parameter);
-        }
-        while (pi < parameterKnobs.length) {
-          parameterKnobs[pi++].setParameter(null);
-        }
-      }
-    };
-    
-    deck.addListener(lxListener);
-    lxListener.patternDidChange(deck, deck.getActivePattern());
-    
+    camera();
+    PGraphicsOpenGL gl = (PGraphicsOpenGL) g;  
+    strokeWeight(1);
   }
   
-  class PatternScrollItem extends AbstractScrollItem {
-    
-    private LXPattern pattern;
-    private String label;
-    
-    PatternScrollItem(LXPattern pattern) {
-      this.pattern = pattern;
-      label = className(pattern, "Pattern");
-    }
-    
-    public String getLabel() {
-      return label;
-    }
-    
-    public boolean isSelected() {
-      return deck.getActivePattern() == pattern;
-    }
+  void drawSimulation(color[] simulationColors) {
+    translate(0, 30, 0);
+  
+    noStroke();
+    fill(#141414);
+    drawBox(0, -TRAILER_HEIGHT, 0, 0, 0, 0, TRAILER_WIDTH, TRAILER_HEIGHT, TRAILER_DEPTH, TRAILER_HEIGHT/2.);
+    fill(#070707);
+    stroke(#222222);
+    beginShape();
+    vertex(0, 0, 0);
+    vertex(TRAILER_WIDTH, 0, 0);
+    vertex(TRAILER_WIDTH, 0, TRAILER_DEPTH);
+    vertex(0, 0, TRAILER_DEPTH);
+    endShape();
+  
+    // Draw the logo on the front of platform  
+    pushMatrix();
+    translate(0, 0, -1);
+    float s = .07;
+    scale(s, -s, s);
+    image(logo, TRAILER_WIDTH/2/s-logo.width/2, TRAILER_HEIGHT/2/s-logo.height/2-2/s);
+    popMatrix();
     
-    public boolean isPending() {
-      return deck.getNextPattern() == pattern;
+    noStroke();
+    for (Cube c : model.cubes) {
+      drawCube(c);
     }
-    
-    public void onMousePressed() {
-      deck.goPattern(pattern);
+  
+    noFill();
+    strokeWeight(2);
+    beginShape(POINTS);
+    for (LXPoint p : model.points) {
+      stroke(simulationColors[p.index]);
+      vertex(p.x, p.y, p.z);
+    }
+    endShape();
+  }
+  
+  void drawCube(Cube c) {
+    float in = .15;
+    noStroke();
+    fill(#393939);  
+    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);
+  }
+  
+  void drawBox(float x, float y, float z, float rx, float ry, float rz, float xd, float yd, float zd, float sw) {
+    pushMatrix();
+    translate(x, y, z);
+    rotate(rx / 180. * PI, -1, 0, 0);
+    rotate(ry / 180. * PI, 0, -1, 0);
+    rotate(rz / 180. * PI, 0, 0, -1);
+    for (int i = 0; i < 4; ++i) {
+      float wid = (i % 2 == 0) ? xd : zd;
+      
+      beginShape();
+      vertex(0, 0);
+      vertex(wid, 0);
+      vertex(wid, yd);
+      vertex(wid - sw, yd);
+      vertex(wid - sw, sw);
+      vertex(0, sw);
+      endShape();
+      beginShape();
+      vertex(0, sw);
+      vertex(0, yd);
+      vertex(wid - sw, yd);
+      vertex(wid - sw, yd - sw);
+      vertex(sw, yd - sw);
+      vertex(sw, sw);
+      endShape();
+  
+      translate(wid, 0, 0);
+      rotate(HALF_PI, 0, -1, 0);
     }
+    popMatrix();
   }
 }
 
 class UIBlendMode extends UIWindow {
   public UIBlendMode(float x, float y, float w, float h) {
-    super("BLEND MODE", x, y, w, h);
-    List<ScrollItem> items = new ArrayList<ScrollItem>();
-    for (LXTransition t : glucose.getTransitions()) {
+    super(lx.ui, "BLEND MODE", x, y, w, h);
+    List<UIScrollList.Item> items = new ArrayList<UIScrollList.Item>();
+    for (LXTransition t : transitions) {
       items.add(new TransitionScrollItem(t));
     }
     final UIScrollList tList;
-    (tList = new UIScrollList(1, titleHeight, w-2, 60)).setItems(items).addToContainer(this);
+    (tList = new UIScrollList(1, UIWindow.TITLE_LABEL_HEIGHT, w-2, 60)).setItems(items).addToContainer(this);
 
-    lx.engine.getDeck(GLucose.RIGHT_DECK).addListener(new LXDeck.AbstractListener() {
+    lx.engine.getDeck(RIGHT_DECK).addListener(new LXDeck.AbstractListener() {
       public void faderTransitionDidChange(LXDeck deck, LXTransition transition) {
         tList.redraw();
       }
     });
   }
 
-  class TransitionScrollItem extends AbstractScrollItem {
+  class TransitionScrollItem extends UIScrollList.AbstractItem {
     private final LXTransition transition;
-    private String label;
+    private final String label;
     
     TransitionScrollItem(LXTransition transition) {
       this.transition = transition;
-      label = className(transition, "Transition");
+      this.label = className(transition, "Transition");
     }
     
     public String getLabel() {
@@ -117,7 +141,7 @@ class UIBlendMode extends UIWindow {
     }
     
     public boolean isSelected() {
-      return transition == glucose.getSelectedTransition();
+      return this.transition == lx.engine.getDeck(RIGHT_DECK).getFaderTransition();
     }
     
     public boolean isPending() {
@@ -125,7 +149,7 @@ class UIBlendMode extends UIWindow {
     }
     
     public void onMousePressed() {
-      glucose.setSelectedTransition(transition);
+      lx.engine.getDeck(RIGHT_DECK).setFaderTransition(this.transition);
     }
   }
 
@@ -136,10 +160,10 @@ class UICrossfader extends UIWindow {
   private final UIToggleSet displayMode;
   
   public UICrossfader(float x, float y, float w, float h) {
-    super("CROSSFADER", x, y, w, h);
+    super(lx.ui, "CROSSFADER", x, y, w, h);
 
-    new UIParameterSlider(4, titleHeight, w-9, 32).setParameter(lx.engine.getDeck(GLucose.RIGHT_DECK).getFader()).addToContainer(this);
-    (displayMode = new UIToggleSet(4, titleHeight + 36, w-9, 20)).setOptions(new String[] { "A", "COMP", "B" }).setValue("COMP").addToContainer(this);
+    new UISlider(4, UIWindow.TITLE_LABEL_HEIGHT, w-9, 32).setParameter(lx.engine.getDeck(RIGHT_DECK).getFader()).addToContainer(this);
+    (displayMode = new UIToggleSet(4, UIWindow.TITLE_LABEL_HEIGHT + 36, w-9, 20)).setOptions(new String[] { "A", "COMP", "B" }).setValue("COMP").addToContainer(this);
   }
   
   public UICrossfader setDisplayMode(String value) {
@@ -154,31 +178,34 @@ class UICrossfader extends UIWindow {
 
 class UIEffects extends UIWindow {
   UIEffects(float x, float y, float w, float h) {
-    super("FX", x, y, w, h);
+    super(lx.ui, "FX", x, y, w, h);
 
-    int yp = titleHeight;
-    List<ScrollItem> items = new ArrayList<ScrollItem>();
-    for (LXEffect fx : glucose.lx.getEffects()) {
-      items.add(new FXScrollItem(fx));
+    int yp = UIWindow.TITLE_LABEL_HEIGHT;
+    List<UIScrollList.Item> items = new ArrayList<UIScrollList.Item>();
+    int i = 0;
+    for (LXEffect fx : effectsArr) {
+      items.add(new FXScrollItem(fx, i++));
     }    
     final UIScrollList effectsList = new UIScrollList(1, yp, w-2, 60).setItems(items);
     effectsList.addToContainer(this);
-    yp += effectsList.h + 10;
+    yp += effectsList.getHeight() + 10;
     
-    final UIParameterKnob[] parameterKnobs = new UIParameterKnob[4];
+    final UIKnob[] parameterKnobs = new UIKnob[4];
     for (int ki = 0; ki < parameterKnobs.length; ++ki) {
-      parameterKnobs[ki] = new UIParameterKnob(5 + 34*(ki % 4), yp + (ki/4) * 48);
+      parameterKnobs[ki] = new UIKnob(5 + 34*(ki % 4), yp + (ki/4) * 48);
       parameterKnobs[ki].addToContainer(this);
     }
     
-    GLucose.EffectListener fxListener = new GLucose.EffectListener() {
-      public void effectSelected(LXEffect effect) {
+    LXParameterListener fxListener = new LXParameterListener() {
+      public void onParameterChanged(LXParameter parameter) {
         int i = 0;
-        for (LXParameter p : effect.getParameters()) {
+        for (LXParameter p : getSelectedEffect().getParameters()) {
           if (i >= parameterKnobs.length) {
             break;
           }
-          parameterKnobs[i++].setParameter(p);
+          if (p instanceof BasicParameter) {
+            parameterKnobs[i++].setParameter((BasicParameter) p);
+          }
         }
         while (i < parameterKnobs.length) {
           parameterKnobs[i++].setParameter(null);
@@ -186,19 +213,21 @@ class UIEffects extends UIWindow {
       }
     };
     
-    glucose.addEffectListener(fxListener);
-    fxListener.effectSelected(glucose.getSelectedEffect());
+    selectedEffect.addListener(fxListener);
+    fxListener.onParameterChanged(null);
 
   }
   
-  class FXScrollItem extends AbstractScrollItem {
+  class FXScrollItem extends UIScrollList.AbstractItem {
     
-    private LXEffect effect;
-    private String label;
+    private final LXEffect effect;
+    private final int index;
+    private final String label;
     
-    FXScrollItem(LXEffect effect) {
+    FXScrollItem(LXEffect effect, int index) {
       this.effect = effect;
-      label = className(effect, "Effect");
+      this.index = index;
+      this.label = className(effect, "Effect");
     }
     
     public String getLabel() {
@@ -206,7 +235,7 @@ class UIEffects extends UIWindow {
     }
     
     public boolean isSelected() {
-      return !effect.isEnabled() && (glucose.getSelectedEffect() == effect);
+      return !effect.isEnabled() && (effect == getSelectedEffect());
     }
     
     public boolean isPending() {
@@ -214,14 +243,14 @@ class UIEffects extends UIWindow {
     }
     
     public void onMousePressed() {
-      if (glucose.getSelectedEffect() == effect) {
+      if (effect == getSelectedEffect()) {
         if (effect.isMomentary()) {
           effect.enable();
         } else {
           effect.toggle();
         }
       } else {
-        glucose.setSelectedEffect(effect);
+        selectedEffect.setValue(index);
       }
     }
     
@@ -236,17 +265,17 @@ class UIEffects extends UIWindow {
 }
 
 class UIOutput extends UIWindow {
-  public UIOutput(float x, float y, float w, float h) {
-    super("OUTPUT", x, y, w, h);
-    float yp = titleHeight;
+  public UIOutput(GrizzlyOutput[] grizzlies, float x, float y, float w, float h) {
+    super(lx.ui, "OUTPUT", x, y, w, h);
+    float yp = UIWindow.TITLE_LABEL_HEIGHT;
     
-    final UIScrollList outputs = new UIScrollList(1, titleHeight, w-2, 80);
+    final UIScrollList outputs = new UIScrollList(1, UIWindow.TITLE_LABEL_HEIGHT, w-2, 80);
     
-    List<ScrollItem> items = new ArrayList<ScrollItem>();
-    for (final PandaDriver panda : pandaBoards) {
-      items.add(new PandaScrollItem(panda));
-      panda.setListener(new PandaDriver.Listener() {
-        public void onToggle(boolean active) {
+    List<UIScrollList.Item> items = new ArrayList<UIScrollList.Item>();
+    for (GrizzlyOutput grizzly : grizzlies) {
+      items.add(new GrizzlyScrollItem(grizzly));
+      grizzly.enabled.addListener(new LXParameterListener() {
+        public void onParameterChanged(LXParameter parameter) {
            outputs.redraw();
         }
       });
@@ -254,22 +283,23 @@ class UIOutput extends UIWindow {
     outputs.setItems(items).addToContainer(this);
   } 
  
-  class PandaScrollItem extends AbstractScrollItem {
-    final PandaDriver panda;
-    PandaScrollItem(PandaDriver panda) {
-      this.panda = panda;
+  class GrizzlyScrollItem extends UIScrollList.AbstractItem {
+    final GrizzlyOutput output;
+
+    GrizzlyScrollItem(GrizzlyOutput output) {
+      this.output = output;
     }
     
     public String getLabel() {
-      return panda.ip;
+      return output.ipAddress;
     }
     
     public boolean isSelected() {
-      return panda.isEnabled();
+      return output.enabled.isOn();
     }
     
     public void onMousePressed() {
-      panda.toggle();
+      output.enabled.setValue(!isSelected());
     }
   } 
 }
@@ -279,8 +309,8 @@ class UITempo extends UIWindow {
   private final UIButton tempoButton;
   
   UITempo(float x, float y, float w, float h) {
-    super("TEMPO", x, y, w, h);
-    tempoButton = new UIButton(4, titleHeight, w-10, 20) {
+    super(lx.ui, "TEMPO", x, y, w, h);
+    tempoButton = new UIButton(4, UIWindow.TITLE_LABEL_HEIGHT, w-10, 20) {
       protected void onToggle(boolean active) {
         if (active) {
           lx.tempo.tap();
@@ -288,17 +318,26 @@ class UITempo extends UIWindow {
       }
     }.setMomentary(true);
     tempoButton.addToContainer(this);
+    new UITempoBlipper(8, UIWindow.TITLE_LABEL_HEIGHT + 5, 12, 12).addToContainer(this);
   }
   
-  public void draw() {
-    tempoButton.setLabel("" + ((int)(lx.tempo.bpm() * 10)) / 10.);
-    super.draw();
+  class UITempoBlipper extends UIObject {
+    UITempoBlipper(float x, float y, float w, float h) {
+      super(x, y, w, h);
+    }
     
-    // Overlay tempo thing with openGL, redraw faster than button UI
-    fill(color(0, 0, 24 - 8*lx.tempo.rampf()));
-    noStroke();
-    rect(x + 8, y + titleHeight + 5, 12, 12);
+    void onDraw(UI ui, PGraphics pg) {
+      tempoButton.setLabel("" + ((int)(lx.tempo.bpm() * 10)) / 10.);
+    
+      // Overlay tempo thing with openGL, redraw faster than button UI
+      pg.fill(color(0, 0, 24 - 8*lx.tempo.rampf()));
+      pg.noStroke();
+      pg.rect(0, 0, width, height);
+      
+      redraw();
+    }
   }
+  
 }
 
 class UIMapping extends UIWindow {
@@ -318,10 +357,10 @@ class UIMapping extends UIWindow {
   private final UIIntegerBox stripBox;
   
   UIMapping(MappingTool tool, float x, float y, float w, float h) {
-    super("MAPPING", x, y, w, h);
+    super(lx.ui, "MAPPING", x, y, w, h);
     mappingTool = tool;
     
-    int yp = titleHeight;
+    int yp = UIWindow.TITLE_LABEL_HEIGHT;
     new UIToggleSet(4, yp, w-10, 20) {
       protected void onToggle(String value) {
         if (value == MAP_MODE_ALL) mappingTool.mappingMode = mappingTool.MAPPING_MODE_ALL;
@@ -345,12 +384,12 @@ class UIMapping extends UIWindow {
       protected void onValueChange(int value) {
         mappingTool.setCube(value-1);
       }
-    }).setRange(1, glucose.model.cubes.size()).addToContainer(this);
+    }).setRange(1, model.cubes.size()).addToContainer(this);
     yp += 24;
     
     yp += 10;
         
-    new UIScrollList(1, yp, w-2, 60).setItems(Arrays.asList(new ScrollItem[] {
+    new UIScrollList(1, yp, w-2, 60).setItems(Arrays.asList(new UIScrollList.Item[] {
       new ColorScrollItem(ColorScrollItem.COLOR_RED),
       new ColorScrollItem(ColorScrollItem.COLOR_GREEN),
       new ColorScrollItem(ColorScrollItem.COLOR_BLUE),
@@ -392,7 +431,7 @@ class UIMapping extends UIWindow {
     stripBox.setValue(value);
   }
   
-  class ColorScrollItem extends AbstractScrollItem {
+  class ColorScrollItem extends UIScrollList.AbstractItem {
     
     public static final int COLOR_RED = 1;
     public static final int COLOR_GREEN = 2;
@@ -438,7 +477,7 @@ class UIDebugText extends UIContext {
   private String line2 = "";
   
   UIDebugText(float x, float y, float w, float h) {
-    super(x, y, w, h);
+    super(lx.ui, x, y, w, h);
   }
 
   public UIDebugText setText(String line1) {
@@ -455,13 +494,13 @@ class UIDebugText extends UIContext {
     return this;
   }
   
-  protected void onDraw(PGraphics pg) {
-    super.onDraw(pg);
+  protected void onDraw(UI ui, PGraphics pg) {
+    super.onDraw(ui, pg);
     if (line1.length() + line2.length() > 0) {
       pg.noStroke();
       pg.fill(#444444);
-      pg.rect(0, 0, w, h);
-      pg.textFont(defaultItemFont);
+      pg.rect(0, 0, width, height);
+      pg.textFont(ui.getItemFont());
       pg.textSize(10);
       pg.textAlign(LEFT, TOP);
       pg.fill(#cccccc);
@@ -476,14 +515,14 @@ class UISpeed extends UIWindow {
   final BasicParameter speed;
   
   UISpeed(float x, float y, float w, float h) {
-    super("SPEED", x, y, w, h);
+    super(lx.ui, "SPEED", x, y, w, h);
     speed = new BasicParameter("SPEED", 0.5);
-    new UIParameterSlider(4, titleHeight, w-10, 20)
-    .setParameter(speed.addListener(new LXParameterListener() {
+    speed.addListener(new LXParameterListener() {
       public void onParameterChanged(LXParameter parameter) {
         lx.setSpeed(parameter.getValuef() * 2);
       }
-    })).addToContainer(this);
+    });
+    new UISlider(4, UIWindow.TITLE_LABEL_HEIGHT, w-10, 20).setParameter(speed).addToContainer(this);
   }
 }
 
@@ -493,15 +532,15 @@ class UIMidi extends UIWindow {
   private final UIButton logMode;
   
   UIMidi(final MidiEngine midiEngine, float x, float y, float w, float h) {
-    super("MIDI", x, y, w, h);
+    super(lx.ui, "MIDI", x, y, w, h);
 
     // Processing compiler doesn't seem to get that list of class objects also conform to interface
-    List<ScrollItem> scrollItems = new ArrayList<ScrollItem>();
+    List<UIScrollList.Item> scrollItems = new ArrayList<UIScrollList.Item>();
     for (SCMidiInput mc : midiEngine.getControllers()) {
       scrollItems.add(mc);
     }
     final UIScrollList scrollList;
-    (scrollList = new UIScrollList(1, titleHeight, w-2, 100)).setItems(scrollItems).addToContainer(this);
+    (scrollList = new UIScrollList(1, UIWindow.TITLE_LABEL_HEIGHT, w-2, 100)).setItems(scrollItems).addToContainer(this);
     (deckMode = new UIToggleSet(4, 130, 90, 20) {
       protected void onToggle(String value) {
         midiEngine.setFocusedDeck(value == "A" ? 0 : 1);
@@ -531,7 +570,7 @@ class UIMidi extends UIWindow {
   }
   
   public LXDeck getFocusedDeck() {
-    return lx.engine.getDeck(deckMode.getValue() == "A" ? GLucose.LEFT_DECK : GLucose.RIGHT_DECK);
+    return lx.engine.getDeck(deckMode.getValue() == "A" ? LEFT_DECK : RIGHT_DECK);
   }
 }
 
index 48a368e611e19e8f38ba2c89e0e32ca97c8ffe48..797651a5f20de588c417376de23793f6c49f6d52 100644 (file)
@@ -42,8 +42,8 @@ class VSTowers extends SCPattern {
     }
   }
 
-  public VSTowers(GLucose glucose) {
-    super(glucose);
+  public VSTowers(LX lx) {
+    super(lx);
     addParameter(saturationParameter);
     addParameter(attackParameter);
     addParameter(decayParameter);
diff --git a/build-tmp/source/SugarCubes.java b/build-tmp/source/SugarCubes.java
deleted file mode 100644 (file)
index edd72f4..0000000
+++ /dev/null
@@ -1,6279 +0,0 @@
-import processing.core.*; 
-import processing.data.*; 
-import processing.event.*; 
-import processing.opengl.*; 
-
-import netP5.*; 
-import oscP5.*; 
-import processing.serial.*; 
-import java.util.LinkedHashMap; 
-import toxi.geom.Vec3D; 
-import toxi.geom.Matrix4x4; 
-
-import heronarts.lx.font.*; 
-import heronarts.lx.transition.*; 
-import glucose.transform.*; 
-import netP5.*; 
-import heronarts.lx.pattern.*; 
-import glucose.pattern.*; 
-import heronarts.lx.model.*; 
-import toxi.geom.mesh2d.*; 
-import heronarts.lx.client.*; 
-import glucose.*; 
-import toxi.util.datatypes.*; 
-import toxi.math.waves.*; 
-import heronarts.lx.kinet.*; 
-import oscP5.*; 
-import toxi.geom.*; 
-import toxi.util.events.*; 
-import heronarts.lx.modulator.*; 
-import rwmidi.*; 
-import glucose.transition.*; 
-import glucose.effect.*; 
-import glucose.model.*; 
-import toxi.math.conversion.*; 
-import heronarts.lx.effect.*; 
-import heronarts.lx.control.*; 
-import glucose.control.*; 
-import toxi.math.noise.*; 
-import toxi.util.*; 
-import heronarts.lx.*; 
-import toxi.math.*; 
-import heronarts.lx.audio.*; 
-
-import java.util.HashMap; 
-import java.util.ArrayList; 
-import java.io.File; 
-import java.io.BufferedReader; 
-import java.io.PrintWriter; 
-import java.io.InputStream; 
-import java.io.OutputStream; 
-import java.io.IOException; 
-
-public class SugarCubes extends PApplet {
-
-/**
- *           +-+-+-+-+-+               +-+-+-+-+-+
- *          /         /|               |\         \
- *         /         / +               + \         \
- *        +-+-+-+-+-+  |   +-+-+-+-+   |  +-+-+-+-+-+
- *        |         |  +  /         \  +  |         |
- *        +   THE   + /  /           \  \ +  CUBES  +
- *        |         |/  +-+-+-+-+-+-+-+  \|         |
- *        +-+-+-+-+-+   |             |   +-+-+-+-+-+
- *                      +             +
- *                      |    SUGAR    |
- *                      +             +
- *                      |             |
- *                      +-+-+-+-+-+-+-+
- *
- * Welcome to the Sugar Cubes! This Processing sketch is a fun place to build
- * animations, effects, and interactions for the platform. Most of the icky
- * code guts are embedded in the GLucose library extension. If you're an
- * artist, you shouldn't need to worry about any of that.
- *
- * Below, you will find definitions of the Patterns, Effects, and Interactions.
- * If you're an artist, create a new tab in the Processing environment with
- * your name. Implement your classes there, and add them to the list below.
- */ 
-
-public LXPattern[] patterns(GLucose glucose) {
-  return new LXPattern[] {
-
-    
-    // Slee
-    new Cathedrals(glucose),
-    new MidiMusic(glucose),
-    new Pulley(glucose),
-    new Swarm(glucose),
-    new ViolinWave(glucose),
-    new BouncyBalls(glucose),
-    new SpaceTime(glucose),
-    new ShiftingPlane(glucose),
-    new AskewPlanes(glucose),
-    new Blinders(glucose),
-    new CrossSections(glucose),
-    new Psychedelia(glucose),
-    
-    new Traktor(glucose).setEligible(false),
-    new BassPod(glucose).setEligible(false),
-    new CubeEQ(glucose).setEligible(false),
-    new PianoKeyPattern(glucose).setEligible(false),
-
-    // DanH
-    new Noise(glucose),
-    new Play (glucose),
-    new Pong (glucose),
-    new Worms(glucose),
-
-    // Alex G
-     new SineSphere(glucose),
-//     new CubeCurl(glucose),
-
-    // Shaheen
-    new HelixPattern(glucose).setEligible(false),
-    
-    // Toby
-    new GlitchPlasma(glucose),
-    new FireEffect(glucose).setEligible(false),
-    new StripBounce(glucose),
-    new SoundRain(glucose).setEligible(false),
-    new SoundSpikes(glucose).setEligible(false),
-    new FaceSync(glucose),
-
-    // Jack
-    new Swim(glucose),
-    new Balance(glucose),
-
-    // Tim
-    new TimPlanes(glucose),
-    new TimPinwheels(glucose),
-    new TimRaindrops(glucose),
-    new TimCubes(glucose),
-    // new TimTrace(glucose),
-    new TimSpheres(glucose),
-
-    // Ben
-    // new Sandbox(glucose),
-    new TowerParams(glucose),
-    new DriveableCrossSections(glucose),
-    new GranimTestPattern2(glucose),
-    
-    //JR
-    new Gimbal(glucose),
-    
-    // Sam
-    new JazzRainbow(glucose),
-    
-    // Arjun
-    new TelevisionStatic(glucose),
-    new AbstractPainting(glucose),
-    new Spirality(glucose),
-
-    // Basic test patterns for reference, not art    
-    new TestCubePattern(glucose),
-    new TestTowerPattern(glucose),
-    new TestProjectionPattern(glucose),
-    new TestStripPattern(glucose),
-    new TestBassMapping(glucose),
-    new TestFloorMapping(glucose),
-    new TestSpeakerMapping(glucose),    
-    new TestPerformancePattern(glucose),
-    // new TestHuePattern(glucose),
-    // new TestXPattern(glucose),
-    // new TestYPattern(glucose),
-    // new TestZPattern(glucose),
-
-  };
-}
-
-public LXTransition[] transitions(GLucose glucose) {
-  return new LXTransition[] {
-    new DissolveTransition(lx),
-    new AddTransition(glucose),
-    new MultiplyTransition(glucose),
-    new OverlayTransition(glucose),
-    new DodgeTransition(glucose),
-    new SwipeTransition(glucose),
-    new FadeTransition(lx),
-//  new SubtractTransition(glucose),   // similar to multiply - dh
-//  new BurnTransition(glucose),               // similar to multiply - dh
-//  new ScreenTransition(glucose),             // same as add -dh
-//  new SoftLightTransition(glucose),  // same as overlay -dh
-  };
-}
-
-// Handles to globally triggerable effects 
-class Effects {
-  FlashEffect flash = new FlashEffect(lx);
-  BoomEffect boom = new BoomEffect(glucose);
-  BlurEffect blur = new BlurEffect(glucose);
-  QuantizeEffect quantize = new QuantizeEffect(glucose);
-  ColorFuckerEffect colorFucker = new ColorFuckerEffect(glucose);
-  
-  Effects() {
-    blur.enable();
-    quantize.enable();
-    colorFucker.enable();
-  }
-}
-
-class SineSphere extends SCPattern {
-  private SinLFO yrot = new SinLFO(0, TWO_PI, 2000);
-  public final Projection sinespin; 
- float modelrad = sqrt((model.xMax)*(model.xMax) + (model.yMax)*(model.yMax) + (model.zMax)*(model.zMax));
-  Pick Sshape; 
-
-  class Sphery {
-  float f1xcenter, f1ycenter, f1zcenter, f2xcenter , f2ycenter, f2zcenter; //second three are for an ellipse with two foci
-  private  SinLFO vibration; 
-  private  SinLFO surface;
-  private  SinLFO vx;
-  private SinLFO xbounce;
-  public SinLFO ybounce;
-  private SinLFO zbounce;
-  float vibration_min, vibration_max, vperiod;
-  public BasicParameter widthparameter;
-  public BasicParameter huespread;
-  public BasicParameter bouncerate;
-  public BasicParameter bounceamp;
-  
-  
-  public Sphery(float f1xcenter, float f1ycenter, float f1zcenter, float vibration_min, float vibration_max, float vperiod) 
-  {
-   this.f1xcenter = f1xcenter;
-   this.f1ycenter = f1ycenter;
-   this.f1zcenter = f1zcenter;
-   this.vibration_min = vibration_min;
-   this.vibration_max = vibration_max;
-   this.vperiod = vperiod;
-   addParameter(bounceamp = new BasicParameter("Amp", .5f));
-   addParameter(bouncerate = new BasicParameter("Rate", .5f));  //ybounce.modulateDurationBy(bouncerate);
-   addParameter(widthparameter = new BasicParameter("Width", .1f));
-   addParameter(huespread = new BasicParameter("Hue", .2f));
-   
-   addModulator( vx = new SinLFO(-4000, 10000, 100000)).trigger() ;
-   //addModulator(xbounce = new SinLFO(model.xMax/3, 2*model.yMax/3, 2000)).trigger(); 
-   addModulator(ybounce= new SinLFO(model.yMax/3, 2*model.yMax/3, 240000.f/lx.tempo.bpm())).trigger(); //ybounce.modulateDurationBy
-    
-   //addModulator(bounceamp); //ybounce.setMagnitude(bouncerate);
-   addModulator( vibration = new SinLFO(vibration_min , vibration_max, 240000.f/lx.tempo.bpm())).trigger(); //vibration.modulateDurationBy(vx);
-   
-  }
- public Sphery(float f1xcenter, float f1ycenter, float f1zcenter, float f2xcenter, float f2ycenter, float f2zcenter, 
-  float vibration_min, float vibration_max, float vperiod)  
- {
-    this.f1xcenter = f1xcenter;
-   this.f1ycenter = f1ycenter;
-   this.f1zcenter = f1zcenter;
-   this.f2xcenter = f2xcenter;
-   this.f2ycenter = f2ycenter;
-   this.f2zcenter = f2zcenter;
-   this.vibration_min = vibration_min;
-   this.vibration_max = vibration_max;
-   this.vperiod = vperiod;
-   //addModulator(xbounce = new SinLFO(model.xMax/3, 2*model.yMax/3, 2000)).trigger(); 
-   addModulator(ybounce).trigger(); 
-   addModulator( vibration = new SinLFO(vibration_min , vibration_max, lx.tempo.rampf())).trigger(); //vibration.modulateDurationBy(vx);
-   addParameter(widthparameter = new BasicParameter("Width", .1f));
-   addParameter(huespread = new BasicParameter("Hue", .2f));
-  
-}
-
-
-
-
-
-public float distfromcirclecenter(float px, float py, float pz, float f1x, float f1y, float f1z) 
-{
-   return dist(px, py, pz, f1x, f1y, f1z);
-    }
- //void updatespherey(deltaMs, )
- public int spheryvalue (float px, float py, float pz , float f1xc, float f1yc, float f1zc) 
- {
-//switch(sShpape.cur() ) {}  
-   return lx.hsb(constrain(huespread.getValuef()*5*px, 0, 360) , dist(px, py, pz, f1xc, f1yc, f1zc) , 
-    max(0, 100 - 100*widthparameter.getValuef()*abs(dist(px, py, pz, f1xcenter, ybounce.getValuef(), f1zcenter)
-      - vibration.getValuef() ) ) ); 
- }
- public int ellipsevalue(float px, float py, float pz , float f1xc, float f1yc, float f1zc, float f2xc, float f2yc, float f2zc)
-  {
-//switch(sShpape.cur() ) {}  
-   return lx.hsb(huespread.getValuef()*5*px, dist(model.xMax-px, model.yMax-py, model.zMax-pz, f1xc, f1yc, f1zc) , 
-    max(0, 100 - 100*widthparameter.getValuef() *
-      abs( (dist(px, py, pz, f1xc, ybounce.getValuef(), f1zc) + 
-        (dist(px, py , pz, f2xc, ybounce.getValuef(), f2zc) ) )/2  
-      - 1.2f*vibration.getValuef() ) ) ) ; 
-  }
-
-public void run(double deltaMs) {
-      float vv = vibration.getValuef();
-      float ybv = ybounce.getValuef();
-      
-    }
-  
-}  
-
-
-final Sphery[] spherys;
-  SineSphere(GLucose glucose) 
-  {
-    super(glucose);
-    sinespin = new Projection(model);
-    addModulator(yrot).trigger();
-    //Sshape = addPick("Shape", , 1);
-    spherys = new Sphery[] {
-      new Sphery(model.xMax/4, model.yMax/2, model.zMax/2, modelrad/16, modelrad/8, 3000),
-      new Sphery(.75f*model.xMax, model.yMax/2, model.zMax/2, modelrad/20, modelrad/10, 2000),
-      new Sphery(model.xMax/2, model.yMax/2, model.zMax/2,  modelrad/4, modelrad/8, 2300),
-    };
-  
-  }
-
-// public void onParameterChanged(LXParameter parameter)
-// {
-
-
-//     for (Sphery s : spherys) {
-//       if (s == null) continue;
-//       double bampv = s.bounceamp.getValue();
-//       double brv = s.bouncerate.getValue();
-//       double tempobounce = lx.tempo.bpm();
-//       if (parameter == s.bounceamp) 
-//       {
-//         s.ybounce.setRange(bampv*model.yMax/3 , bampv*2*model.yMax/3, brv);
-//       }
-//       else if ( parameter == s.bouncerate )   
-//       {
-//         s.ybounce.setDuration(120000./tempobounce);
-//       }
-//     }
-//   }
-
-     public void run( double deltaMs) {
-     float t = lx.tempo.rampf();
-     float bpm = lx.tempo.bpmf();
-     //spherys[1].run(deltaMs);
-     //spherys[2].run(deltaMs);
-     //spherys[3].run(deltaMs);]
-     sinespin.reset(model)
-
-     // Translate so the center of the car is the origin, offset by yPos
-      .translateCenter(model, 0, 0, 0)
-
-      // Rotate around the origin (now the center of the car) about an X-vector
-      .rotate(yrot.getValuef(), 0, 1, 0);
-
-
-
-     for (Point p: model.points){
-    int c = 0;
-    c = blendColor(c, spherys[1].spheryvalue(p.x, p.y, p.z, .75f*model.xMax, model.yMax/2, model.zMax/2), ADD);
-    c = blendColor(c, spherys[0].spheryvalue(p.x, p.y, p.z, model.xMax/4, model.yMax/4, model.zMax/2), ADD);
-    c = blendColor(c, spherys[2].spheryvalue(p.x, p.y, p.z, model.xMax/2, model.yMax/2, model.zMax/2),ADD);
-     
-      colors[p.index] = lx.hsb(lx.h(c), lx.s(c), lx.b(c));
-
-               }
-      
-
-
-  }
-  int spheremode = 0;
-  
-   // void keyPressed() {
-   //   spheremode++;
-   //     }
-
-  // color CalcPoint(PVector Px) 
-  // { 
-  //      // if (spheremode == 0 )
-              //{
-            
-             //}
-      //   else if (spheremode == 1)
-      // {
-
-      //   color c = 0;
-      //   c = blendColor(c, spherys[3].ellipsevalue(Px.x, Px.y, Px.z, model.xMax/4, model.yMax/4, model.zMax/4, 3*model.xMax/4, 3*model.yMax/4, 3*model.zMax/4),ADD);
-      //   return c; 
-      // }
-      // return lx.hsb(0,0,0);
-      //  // else if(spheremode ==2)
-       // { color c = 0;
-       //   return lx.hsb(CalcCone( (xyz by = new xyz(0,spherys[2].ybounce.getValuef(),0) ), Px, mid) );
-
-       // }
-
-  
-       //   } 
-        
-  }
-
-class CubeCurl extends SCPattern{
-float CH, CW, diag;
-ArrayList<PVector> cubeorigin = new ArrayList<PVector>();
-ArrayList<PVector> centerlist = new ArrayList<PVector>();
-private SinLFO curl = new SinLFO(0, Cube.EDGE_HEIGHT, 5000 ); 
-
-private SinLFO bg = new SinLFO(180, 220, 3000);
-
-CubeCurl(GLucose glucose){
-super(glucose);
-addModulator(curl).trigger();
-addModulator(bg).trigger();
- this.CH = Cube.EDGE_HEIGHT;
- this.CW = Cube.EDGE_WIDTH;
- this.diag = sqrt(CW*CW + CW*CW);
-
-
-ArrayList<PVector> centerlistrelative = new ArrayList<PVector>();
-for (int i = 0; i < model.cubes.size(); i++){
-  Cube a = model.cubes.get(i);
-  cubeorigin.add(new PVector(a.x, a.y, a.z));
-  centerlist.add(centerofcube(i));
-  
-} 
-
-}
-//there is definitely a better way of doing this!
-public PVector centerofcube(int i) { 
-Cube c = model.cubes.get(i);
-
-println(" cube #:  " + i + " c.x  "  +  c.x  + "  c.y   "  + c.y   + "  c.z  "  +   c.z  );
-PVector cubeangle = new PVector(c.rx, c.ry, c.rz);
-//println("raw x" + cubeangle.x + "raw y" + cubeangle.y + "raw z" + cubeangle.z);
-PVector cubecenter = new PVector(c.x + CW/2, c.y + CH/2, c.z + CW/2);
-println("cubecenter unrotated:  "  + cubecenter.x + "  "  +cubecenter.y + "  " +cubecenter.z );
-PVector centerrot = new PVector(cos(c.rx)*CW/2 - sin(c.rx)*CW/2, 0, cos(c.rz)*CW/2 + sin(c.rz)*CW/2);
- // nCos*(y-o.y) - nSin*(z-o.z) + o.y
-cubecenter = PVector.add(cubecenter, centerrot);
-println( "  cubecenter.x  " + cubecenter.x  + " cubecenter.y  " +  cubecenter.y + " cubecenter.z  "   +  cubecenter.z  + "   ");
-
-
-return cubecenter;
-}
-
-
-public void run(double deltaMs){
-for (int i =0; i < model.cubes.size(); i++)  {
-Cube c = model.cubes.get(i);
-float cfloor = c.y;
-
-// if (i%3 == 0){
-
-// for (Point p : c.points ){
-//  // colors[p.index]=color(0,0,0);
-//   //float dif = (p.y - c.y);
-//   //colors[p.index] = color( bg.getValuef() , 80 , dif < curl.getValuef() ? 80 : 0, ADD);
-//    }
-//  }
-
-// else if (i%3 == 1) {
-  
-//  for (Point p: c.points){
-//   colors[p.index]=color(0,0,0);
-//   float dif = (p.y - c.y);
-//   // colors[p.index] = 
-//   // color(bg.getValuef(),
-//   //   map(curl.getValuef(), 0, Cube.EDGE_HEIGHT, 20, 100), 
-//   //   100 - 10*abs(dif - curl.getValuef()), ADD );
-//      }
-//     }
-// else if (i%3 == 2){
- // centerlist[i].sub(cubeorigin(i);
-   for (Point p: c.points) {
-    PVector pv = new PVector(p.x, p.y, p.z);
-     colors[p.index] =color( constrain(4* pv.dist(centerlist.get(i)), 0, 360)  , 50, 100 );
-   // colors[p.index] =color(constrain(centerlist[i].x, 0, 360), constrain(centerlist[i].y, 0, 100),  );
-
-
-    }
-
-
-  //}
-
-   }
-  }
- }
-
- class HueTestHSB extends SCPattern{
-  BasicParameter HueT = new BasicParameter("Hue", .5f);
-  BasicParameter SatT = new BasicParameter("Sat", .5f);
-  BasicParameter BriT = new BasicParameter("Bright", .5f);
-
-HueTestHSB(GLucose glucose) {
-  super(glucose);
-  addParameter(HueT);
-  addParameter(SatT);
-  addParameter(BriT);
-}
-  public void run(double deltaMs){
-
-  for (Point p : model.points) {
-    int c = 0;
-    c = blendColor(c, lx.hsb(360*HueT.getValuef(), 100*SatT.getValuef(), 100*BriT.getValuef()), ADD);
-    colors[p.index]= c;
-  }
-   int now= millis();
-   if (now % 1000 <= 20)
-   {
-   println("Hue: " + 360*HueT.getValuef() + "Sat: " + 100*SatT.getValuef() + "Bright:  " + 100*BriT.getValuef());
-   }
-  }
-
- }
-
-class TelevisionStatic extends SCPattern {
-  BasicParameter brightParameter = new BasicParameter("BRIGHT", 1.0f);
-  BasicParameter saturationParameter = new BasicParameter("SAT", 1.0f);
-  BasicParameter hueParameter = new BasicParameter("HUE", 1.0f);
-  SinLFO direction = new SinLFO(0, 10, 3000);
-  
-  public TelevisionStatic(GLucose glucose) {
-    super(glucose);
-    addModulator(direction).trigger();
-    addParameter(brightParameter);
-    addParameter(saturationParameter);
-    addParameter(hueParameter);
-  }
-
- public void run(double deltaMs) {
-    boolean d = direction.getValuef() > 5.0f;
-    for (Point p : model.points) {             
-      colors[p.index] = lx.hsb((lx.getBaseHuef() + random(hueParameter.getValuef() * 360))%360, random(saturationParameter.getValuef() * 100), random(brightParameter.getValuef() * 100));
-    }
-  }
-}
-
-class AbstractPainting extends SCPattern {
-  
-  PImage img;
-  
-  SinLFO colorMod = new SinLFO(0, 360, 5000);
-  SinLFO brightMod = new SinLFO(0, model.zMax, 2000);
-    
-  public AbstractPainting(GLucose glucose) {
-    super(glucose);
-    addModulator(colorMod).trigger();
-    addModulator(brightMod).trigger();
-    
-    img = loadImage("abstract.jpg");
-    img.loadPixels();    
-  } 
-  public void run(double deltaMs) {    
-    for (Point p : model.points) {
-      int c = img.get((int)((p.x / model.xMax) * img.width), img.height - (int)((p.y / model.yMax) * img.height));
-      colors[p.index] = lx.hsb(hue(c) + colorMod.getValuef()%360, saturation(c), brightness(c) - ((p.z - brightMod.getValuef())/p.z));
-    }    
-  }       
-}
-
-class Spirality extends SCPattern {
-  final BasicParameter r = new BasicParameter("RADIUS", 0.5f);
-  
-  float angle = 0;
-  float rad = 0;
-  int direction = 1;
-  
-  Spirality(GLucose glucose) {
-    super(glucose);   
-    addParameter(r);
-    for (Point p : model.points) {  
-      colors[p.index] = lx.hsb(0, 0, 0);
-    }
-  }
-    
-  public void run(double deltaMs) {
-    angle += deltaMs * 0.007f;
-    rad += deltaMs * .025f * direction;
-    float x = model.xMax / 2 + cos(angle) * rad;
-    float y = model.yMax / 2 + sin(angle) * rad;
-    for (Point p : model.points) {    
-      float b = dist(x,y,p.x,p.y);
-      if (b < 90) {
-        colors[p.index] = blendColor(
-          colors[p.index],
-          lx.hsb(lx.getBaseHuef() + 25, 10, map(b, 0, 10, 100, 0)),
-          ADD);        
-        } else {
-      colors[p.index] = blendColor(
-        colors[p.index],
-        lx.hsb(25, 10, map(b, 0, 10, 0, 15)),
-        SUBTRACT); 
-      }
-    }
-    if (rad > model.xMax / 2 || rad <= .001f) {
-      direction *= -1;
-    }
-  }
-}
-
-
-
-
-/**
- * This is a reusable equalizer class that lets you get averaged
- * bands with dB scaling and smoothing.
- */
-public static class GraphicEQ {
-  
-  private final LX lx;
-  
-  public final BasicParameter level = new BasicParameter("LVL", 0.5f);
-  public final BasicParameter range = new BasicParameter("RNGE", 0.5f);
-  public final BasicParameter slope = new BasicParameter("SLOP", 0.5f);
-  public final BasicParameter attack = new BasicParameter("ATK", 0.5f);
-  public final BasicParameter release = new BasicParameter("REL", 0.5f);    
-
-  private final FFT fft;
-  private final int numBands;
-
-  private final LinearEnvelope[] bandVals;
-  
-  public final static int DEFAULT_NUM_BANDS = 16;
-
-  public GraphicEQ(LX lx) {
-    this(lx, DEFAULT_NUM_BANDS);
-  }
-  
-  /**
-   * Note that the number of bands is a suggestion. Due to the FFT implementation
-   * the actual number may be slightly different.
-   */
-  public GraphicEQ(LX lx, int num) {
-    this.lx = lx;
-    fft = new FFT(lx.audioInput().bufferSize(), lx.audioInput().sampleRate());
-    fft.window(FFT.HAMMING);
-    fft.logAverages(50, num/8);
-    numBands = this.fft.avgSize();
-    bandVals = new LinearEnvelope[numBands];
-    for (int i = 0; i < bandVals.length; ++i) {
-      (bandVals[i] = new LinearEnvelope(0, 0, 500)).trigger();
-    }
-  }
-  
-  static final float logTen = log(10);
-  public static float log10(float val) {
-    return log(val) / logTen;
-  }
-  
-  public float getLevel(int band) {
-    return bandVals[band].getValuef();
-  }
-  
-  public float getAverageLevel(int minBand, int numBands) {
-    float avg = 0;
-    for (int i = minBand; i < minBand + numBands; ++i) {
-      avg += bandVals[i].getValuef();
-    }
-    avg /= numBands;
-    return avg;
-  }
-  
-  public void run(double deltaMs) {
-    fft.forward(lx.audioInput().mix);
-    float zeroDBReference = pow(10, 100*(1-level.getValuef())/20.f);
-    float decibelRange = 12 + range.getValuef() * 60;
-    float decibelSlope = slope.getValuef() * 60.f / numBands;
-    for (int i = 0; i < numBands; ++i) {
-      float raw = fft.getAvg(i);
-      float decibels = 20*log10(raw / zeroDBReference);
-      float positiveDecibels = decibels + decibelRange;
-      positiveDecibels += i*decibelSlope;
-      float value = constrain(positiveDecibels / decibelRange, 0, 1);
-      
-      if (value > bandVals[i].getValuef()) {
-        bandVals[i].setRangeFromHereTo(value, attack.getValuef() * 20).trigger();
-      }
-    }
-    for (LinearEnvelope band : bandVals) {
-      band.run(deltaMs);
-      if (!band.isRunning() && band.getValuef() > 0) {
-        band.setRangeFromHereTo(0, release.getValuef() * 1600).trigger();
-      }
-    }    
-  }
-}
-
-
-class TowerParams extends SCPattern
-{
-       BasicParameter hueoff = new BasicParameter("Hueoff", 0.0f);
-       BasicParameter hueSpan = new BasicParameter("HueRange", 0.0f);
-       BasicParameter t1 = new BasicParameter("T1", 0.0f);
-       BasicParameter t2 = new BasicParameter("T2", 0.0f);
-       BasicParameter t3 = new BasicParameter("T3", 0.0f);
-       BasicParameter t4 = new BasicParameter("T4", 0.0f);
-       BasicParameter t5 = new BasicParameter("T5", 0.0f);
-       BasicParameter t6 = new BasicParameter("T6", 0.0f);
-       BasicParameter t7 = new BasicParameter("T7", 0.0f);
-       BasicParameter t8 = new BasicParameter("T8", 0.0f);
-       BasicParameter t9 = new BasicParameter("T9", 0.0f);
-       BasicParameter t10 = new BasicParameter("T10", 0.0f);
-       BasicParameter t11 = new BasicParameter("T11", 0.0f);
-       BasicParameter t12 = new BasicParameter("T12", 0.0f);
-       BasicParameter t13 = new BasicParameter("T13", 0.0f);
-       BasicParameter t14 = new BasicParameter("T14", 0.0f);
-       BasicParameter t15 = new BasicParameter("T15", 0.0f);
-       BasicParameter t16 = new BasicParameter("T16", 0.0f);
-
-       ArrayList<BasicParameter> towerParams;
-       int towerSize;
-       int colorSpan;
-       TowerParams(GLucose glucose) {
-               super(glucose);
-
-               towerParams = new ArrayList<BasicParameter>();
-               addParameter(hueoff);
-               addParameter(hueSpan);
-               towerParams.add(t1);
-               towerParams.add(t2);
-               towerParams.add(t3);
-               towerParams.add(t4);
-               towerParams.add(t5);
-               towerParams.add(t6);
-               towerParams.add(t7);
-               towerParams.add(t8);
-               towerParams.add(t9);
-               towerParams.add(t10);
-               towerParams.add(t11);
-               towerParams.add(t12);
-               towerParams.add(t13);
-               towerParams.add(t14);
-               towerParams.add(t15);
-               towerParams.add(t16);
-               for(BasicParameter p : towerParams)
-               {
-                       addParameter(p);
-               }
-               towerSize = model.towers.size();
-               colorSpan = 255 / towerSize;
-       }
-
-       public void run(double deltaMs)
-       {
-               clearALL();
-               Tower t;
-               for(int i=0; i<towerSize ;i++)
-               {       
-                       t= model.towers.get(i);
-                       for(Point p : t.points)
-                       {
-                               if(p.y<towerParams.get(i).getValuef()*200)
-                               {
-                                       colors[p.index]=lx.hsb(255 * hueoff.getValuef()+colorSpan * hueSpan.getValuef() * i, 255, 255);
-                               }
-                       }
-               }
-
-       }
-
-       public void clearALL()
-       {
-               for(Point p : model.points)
-               {
-                       colors[p.index] = 0;
-               }
-       }
-
-}
-class Sandbox extends SCPattern
-{
-       int c=0;
-       int prevC=0;
-       int huerange=255;
-       int pointrange= model.points.size();
-       int striprange= model.strips.size();
-       int facerange= model.faces.size();
-       int cuberange = model.cubes.size();
-       int towerrange = model.towers.size();
-       int counter=0;
-
-       Sandbox(GLucose glucose) {
-               super(glucose);
-               println("points "+pointrange);
-               println("strips "+striprange);
-               println("faces "+facerange);
-               println("cubes "+cuberange);
-               println("towers "+towerrange);
-       }
-       
-       public void run(double deltaMs) {
-               
-
-               if(counter % 10 ==0)
-               {
-                       doDraw(c,0);
-                       c = (c + 1) % towerrange;
-                       long col = lx.hsb(Math.round(Math.random()*255),255,255) ;
-                       doDraw(c,col);
-               }
-               counter++;
-
-       }
-
-       public void doDraw(int c,long col)
-       {
-                       Tower t= model.towers.get((int) c);
-                       for(Point p : t.points)
-                       {
-                               colors[p.index] = (int) col;
-                       }
-       }
-};
-
-class GranimTestPattern extends GranimPattern
-{
-       GranimTestPattern(GLucose glucose)
-       {
-               super(glucose);
-               addGraphic("myReds",new RedsGraphic(100));
-               int[] dots = {0,128,0,128,0,128,0,128,0,128,0,128};
-               addGraphic("myOtherColors",new ColorDotsGraphic(dots));
-
-               getGraphicByName("myOtherColors").position=100;
-       }
-       int counter=0;
-       public void run(double deltaMs) 
-       {
-               clearALL();
-               super.run(deltaMs);
-               
-               if(counter % 3 ==0)
-               {
-                       Graphic reds = getGraphicByName("myReds");
-                       Graphic others = getGraphicByName("myOtherColors");
-                       reds.position = reds.position + 1 % 19000;
-                       others.position = others.position + 10 % 19000;
-               }
-       }
-       public void clearALL()
-       {
-               for(int i = 0; i < colors.length; i++)
-               {
-                       colors[i] = 0;
-               }
-       }
-
-
-}
-
-class GranimTestPattern2 extends GranimPattern
-{
-       GranimTestPattern2(GLucose glucose)
-       {
-               super(glucose);
-               /*for(int i = 0;i < 100; i++)
-               {
-                       Graphic g = addGraphic("myReds_"+i,new RedsGraphic(Math.round(Math.random() * 100)));
-
-               }*/
-               Graphic g = addGraphic("myRandoms",new RandomsGranim(50));
-               g.position = 200;
-               
-       }
-       int counter=0;
-       float count=0;
-       public void run(double deltaMs) 
-       {
-               clearALL();
-               super.run(deltaMs);
-               Graphic randomsGraphic = getGraphicByName("myRandoms");
-               randomsGraphic.position = Math.round(sin(count)*1000)+5000;
-               count+= 0.005f;
-       }
-       public void clearALL()
-       {
-               for(Point p : model.points)
-               {
-                       colors[p.index] = 0;
-               }
-       }
-
-
-};
-
-class DriveableCrossSections extends CrossSections
-{
-       BasicParameter xd; 
-       BasicParameter yd;
-       BasicParameter zd;
-       BasicParameter mode; 
-
-       DriveableCrossSections(GLucose glucose) {
-               super(glucose); 
-       }
-
-       public void addParams()
-       {
-               mode = new BasicParameter("Mode", 0.0f);
-               xd = new BasicParameter("XD", 0.0f);
-               yd = new BasicParameter("YD", 0.0f);
-               zd = new BasicParameter("ZD", 0.0f);
-               addParameter(mode);
-               addParameter(xd);
-           addParameter(yd);
-           addParameter(zd);
-
-          super.addParams();
-       }
-
-       public void onParameterChanged(LXParameter p) {
-                       if(p == mode)
-                       {
-                               if(interactive())
-                               {
-                                       copyValuesToKnobs();
-                               }else{
-                                       copyKnobsToValues();
-                               }
-                       }
-       }
-
-       public void copyValuesToKnobs()
-       {
-               xd.setValue(x.getValue()/200);
-               yd.setValue(y.getValue()/115);
-               zd.setValue(z.getValue()/100);
-       }
-
-       public void copyKnobsToValues()
-       {
-               x.setValue(xd.getValue()*200);
-               y.setValue(yd.getValue()*115);
-               z.setValue(zd.getValue()*100);
-       }
-
-       public boolean interactive()
-       {
-               return Math.round(mode.getValuef())>0.5f;
-       }
-
-       public void updateXYZVals()
-       {
-               if(interactive())
-               {
-                       xv = xd.getValuef()*200;
-                   yv = yd.getValuef()*115;
-                   zv = zd.getValuef()*100;
-               }else{
-                       super.updateXYZVals();
-                       copyValuesToKnobs();
-               }
-       }
-
-}
-//----------------------------------------------------------------------------------------------------------------------------------
-public class Pong extends DPat {
-       SinLFO x,y,z,dx,dy,dz;
-       float cRad;     BasicParameter pSize;
-       Pick    pChoose;
-       PVector v = new PVector(), vMir =  new PVector();
-
-       Pong(GLucose glucose) {
-               super(glucose);
-               cRad = mMax.x/10;
-               addModulator(dx = new SinLFO(6000,  500, 30000  )).trigger();
-               addModulator(dy = new SinLFO(3000,  500, 22472  )).trigger();
-               addModulator(dz = new SinLFO(1000,  500, 18420  )).trigger();
-               addModulator(x  = new SinLFO(cRad, mMax.x - cRad, 0)).trigger();        x.modulateDurationBy(dx);
-               addModulator(y  = new SinLFO(cRad, mMax.y - cRad, 0)).trigger();        y.modulateDurationBy(dy);
-               addModulator(z  = new SinLFO(cRad, mMax.z - cRad, 0)).trigger();        z.modulateDurationBy(dz);
-           pSize       = addParam      ("Size"                 , 0.4f  );
-           pChoose = addPick   ("Animiation"   , 2, 2, new String[] {"Pong", "Ball", "Cone"}   );
-       }
-
-       public void     StartRun(double deltaMs)        { cRad = mMax.x*val(pSize)/6; }
-       public int      CalcPoint(PVector p)            {
-               v.set(x.getValuef(), y.getValuef(), z.getValuef());
-               v.z=0;p.z=0;// ignore z dimension
-               switch(pChoose.Cur()) {
-               case 0: vMir.set(mMax); vMir.sub(p);
-                               return lx.hsb(lxh(),100,c1c(1 - min(v.dist(p), v.dist(vMir))*.5f/cRad));                // balls
-               case 1: return lx.hsb(lxh(),100,c1c(1 - v.dist(p)*.5f/cRad));                                                   // ball
-               case 2: vMir.set(mMax.x/2,0,mMax.z/2);
-                               return lx.hsb(lxh(),100,c1c(1 - calcCone(p,v,vMir) * max(.02f,.45f-val(pSize))));       // spot
-               }
-               return lx.hsb(0,0,0);
-       }
-}
-//----------------------------------------------------------------------------------------------------------------------------------
-public class NDat {
-       float   xz, yz, zz, hue, speed, angle, den;
-       float   xoff,yoff,zoff;
-       float   sinAngle, cosAngle;
-       boolean isActive;
-       NDat              () { isActive=false; }
-       public boolean  Active() { return isActive; }
-       public void     set     (float _hue, float _xz, float _yz, float _zz, float _den, float _speed, float _angle) {
-               isActive = true;
-               hue=_hue; xz=_xz; yz=_yz; zz =_zz; den=_den; speed=_speed; angle=_angle;
-               xoff = random(100e3f); yoff = random(100e3f); zoff = random(100e3f);
-       }
-}
-
-public class Noise extends DPat
-{
-       int                             CurAnim, iSymm;
-       int                     XSym=1,YSym=2,RadSym=3;
-       float                   zTime , zTheta=0, zSin, zCos, rtime, ttime;
-       BasicParameter  pSpeed , pDensity, pSharp;
-       Pick                    pChoose, pSymm;
-       int                             _ND = 4;
-       NDat                    N[] = new NDat[_ND];
-
-       Noise(GLucose glucose) {
-               super(glucose);
-               pSpeed          = addParam("Fast"       , .55f);
-               pDensity        = addParam("Dens"        , .5f);
-               pSharp          = addParam("Shrp"        ,  0);
-               pSymm           = addPick("Symmetry" , 0, 3, new String[] {"None", "X", "Y", "Radial"}  );
-               pChoose         = addPick("Animation", 6, 7, new String[] {"Drip", "Cloud", "Rain", "Fire", "Machine", "Spark","VWave", "Wave"} );
-               for (int i=0; i<_ND; i++) N[i] = new NDat();
-       }
-
-       public void onActive() { zTime = random(500); zTheta=0; rtime = 0; ttime = 0; }
-
-       public void StartRun(double deltaMs) {
-               zTime   += deltaMs*(val(pSpeed)-.5f)*.002f      ;
-               zTheta  += deltaMs*(spin()-.5f)*.01f    ;
-               rtime   += deltaMs;
-               iSymm    = pSymm.Cur();
-               zSin    = sin(zTheta);
-               zCos    = cos(zTheta);
-
-               if (pChoose.Cur() != CurAnim) {
-                       CurAnim = pChoose.Cur(); ttime = rtime;
-                       pSpin           .reset();       zTheta          = 0;
-                       pDensity        .reset();       pSpeed          .reset();
-                       for (int i=0; i<_ND; i++) { N[i].isActive = false; }
-                       
-                       switch(CurAnim) {
-                       //                          hue xz yz zz den mph angle
-                       case 0: N[0].set(0  ,75 ,75 ,150,45 ,3  ,0  ); pSharp.setValue(1 ); break;      // drip
-                       case 1: N[0].set(0  ,100,100,200,45 ,3  ,180); pSharp.setValue(0 ); break;      // clouds
-                       case 2: N[0].set(0  ,2  ,400,2  ,20 ,3  ,0  ); pSharp.setValue(.5f); break;     // rain
-                       case 3: N[0].set(40 ,100,100,200,10 ,1  ,180); 
-                                       N[1].set(0  ,100,100,200,10 ,5  ,180); pSharp.setValue(0 ); break;      // fire 1
-                       case 4: N[0].set(0  ,40 ,40 ,40 ,15 ,2.5f,180);
-                                       N[1].set(20 ,40 ,40 ,40 ,15 ,4  ,0  );
-                                       N[2].set(40 ,40 ,40 ,40 ,15 ,2  ,90 );
-                                       N[3].set(60 ,40 ,40 ,40 ,15 ,3  ,-90); pSharp.setValue(.5f); break; // machine
-                       case 5: N[0].set(0  ,400,100,2  ,15 ,3  ,90 );
-                                       N[1].set(20 ,400,100,2  ,15 ,2.5f,0  );
-                                       N[2].set(40 ,100,100,2  ,15 ,2  ,180);
-                                       N[3].set(60 ,100,100,2  ,15 ,1.5f,270); pSharp.setValue(.5f); break; // spark
-                       }
-               }
-               
-               for (int i=0; i<_ND; i++) if (N[i].Active()) {
-                       N[i].sinAngle = sin(radians(N[i].angle));
-                       N[i].cosAngle = cos(radians(N[i].angle));
-               }
-       }
-
-       public int CalcPoint(PVector p) {
-               int c = 0;
-               rotateZ(p, mCtr, zSin, zCos);
-
-               if (CurAnim == 6 || CurAnim == 7) {
-                       setNorm(p);
-                       return lx.hsb(lxh(),100, 100 * (
-                                                       constrain(1-50*(1-val(pDensity))*abs(p.y-sin(zTime*10  + p.x*(300))*.5f - .5f),0,1) + 
-                       (CurAnim == 7 ? constrain(1-50*(1-val(pDensity))*abs(p.x-sin(zTime*10  + p.y*(300))*.5f - .5f),0,1) : 0))
-                       );
-               }                       
-
-               if (iSymm == XSym && p.x > mMax.x/2) p.x = mMax.x-p.x;
-               if (iSymm == YSym && p.y > mMax.y/2) p.y = mMax.y-p.y;
-
-               for (int i=0;i<_ND; i++) if (N[i].Active()) {
-                       NDat  n     = N[i];
-                       float zx    = zTime * n.speed * n.sinAngle,
-                                 zy    = zTime * n.speed * n.cosAngle;
-
-                       float b     = (iSymm==RadSym ? noise(zTime*n.speed+n.xoff-p.dist(mCtr)/n.xz)
-                                                                                : noise(p.x/n.xz+zx+n.xoff,p.y/n.yz+zy+n.yoff,p.z/n.zz+n.zoff))
-                                                       *1.8f;
-
-                       b +=    n.den/100 -.4f + val(pDensity) -1;
-                       c =     blendColor(c,lx.hsb(lxh()+n.hue,100,c1c(b)),ADD);
-               }
-               return c;
-       }
-}
-//----------------------------------------------------------------------------------------------------------------------------------
-public class Play extends DPat
-{
-       public class rAngle {
-               float   prvA, dstA, c;
-               float   prvR, dstR, r;          
-               float   _cos, _sin, x, y;
-               public float    fixAngle        (float a, float b) { return a<b ?
-                                                                               (abs(a-b) > abs(a+2*PI-b) ? a : a+2*PI) :
-                                                                               (abs(a-b) > abs(a-2*PI-b) ? a : a-2*PI) ; }
-               public float    getX(float r)   {       return mCtr.x + _cos*r; }
-               public float    getY(float r)   {       return mCtr.y + _sin*r; }
-               public void     move()                  {       c               = interp(t,prvA,dstA); 
-                                                                       r               = interp(t,prvR,dstR);
-                                                                       _cos    = cos(c);       _sin    = sin(c);
-                                      x                = getX(r);      y               = getY(r);              }               
-               public void     set()                   {       prvA    = dstA;         dstA    = random(2*PI);         prvA = fixAngle(prvA, dstA);
-                                                                       prvR    = dstR;         dstR    = random(mCtr.y);                                                                       }
-       }
-
-       BasicParameter  pAmp, pRadius, pBounce;
-       Pick                    pTimePattern, pTempoMult, pShape;
-
-       ArrayList<rWave> waves = new ArrayList<rWave>(10);
-
-       int             nBeats  =       0;
-       float   t,amp,rad,bnc,zTheta=0;
-
-       rAngle  a1              = new rAngle(), a2                      = new rAngle(),
-                       a3              = new rAngle(), a4                      = new rAngle();
-       PVector cPrev   = new PVector(), cRand          = new PVector(),
-                       cMid    = new PVector(), V                      = new PVector(),
-                       theta   = new PVector(), tSin           = new PVector(),
-                       tCos    = new PVector(), cMidNorm       = new PVector(),
-                       Pn              = new PVector();
-       float   LastBeat=3, LastMeasure=3;
-       int             curRandTempo = 1, curRandTPat = 1;
-
-       Play(GLucose glucose) {
-               super(glucose);
-           pRadius             = addParam("Rad"        , .1f   );
-               pBounce         = addParam("Bnc"        , .2f   );
-           pAmp                = addParam("Amp"        , .2f   );
-               pTempoMult      = addPick ("TMult"      , 5 , 5         , new String[] {"1x", "2x", "4x", "8x", "16x", "Rand"   }       );
-               pTimePattern= addPick ("TPat"   , 7 , 7         , new String[] {"Bounce", "Sin", "Roll", "Quant", "Accel", "Deccel", "Slide", "Rand"}   );
-               pShape          = addPick ("Shape"      , 7 , 15        , new String[] {"Line", "Tap", "V", "RandV",
-                                                                                                                                       "Pyramid", "Wings", "W2", "Clock",
-                                                                                                                                       "Triangle", "Quad", "Sphere", "Cone",
-                                                                                                                                       "Noise", "Wave", "?", "?"}                                              );
-       }
-
-       public class rWave {
-               float v0, a0, x0, t,damp,a;
-               boolean bDone=false;
-               final float len=8;
-               rWave(float _x0, float _a0, float _v0, float _damp) { x0=_x0*len; a0=_a0; v0=_v0; t=0; damp = _damp; }
-               public void move(double deltaMs) {
-                       t += deltaMs*.001f;
-                       if (t>4) bDone=true;
-               }
-               public float val(float _x) {
-                       _x*=len;
-                       float dist = t*v0 - abs(_x-x0);
-                       if (dist<0) { a=1; return 0; }
-                       a  = a0*exp(-dist*damp) * exp(-abs(_x-x0)/(.2f*len)); // * max(0,1-t/dur)
-                       return  -a*sin(dist);
-               }
-       }
-
-       public void onReset()  { zTheta=0; super.onReset(); }
-       public void onActive() { 
-               zTheta=0; 
-               while (lx.tempo.bpm() > 40) lx.tempo.setBpm(lx.tempo.bpm()/2);
-       }
-
-       int KeyPressed = -1;
-       public boolean noteOn(Note note) {
-               int row = note.getPitch(), col = note.getChannel();
-               if (row == 57) {KeyPressed = col; return true; }
-               return super.noteOn(note);
-       }
-
-       public void StartRun(double deltaMs) {
-               t       = lx.tempo.rampf();
-               amp = pAmp              .getValuef();
-               rad     = pRadius       .getValuef();
-               bnc     = pBounce       .getValuef();           
-               zTheta  += deltaMs*(val(pSpin)-.5f)*.01f;
-
-               theta   .set(val(pRotX)*PI*2, val(pRotY)*PI*2, val(pRotZ)*PI*2 + zTheta);
-               tSin    .set(sin(theta.x), sin(theta.y), sin(theta.z));
-               tCos    .set(cos(theta.x), cos(theta.y), cos(theta.z));
-
-               if (t<LastMeasure) {
-                       if (random(3) < 1) { curRandTempo = PApplet.parseInt(random(4)); if (curRandTempo == 3) curRandTempo = PApplet.parseInt(random(4));     }
-                       if (random(3) < 1) { curRandTPat  = pShape.Cur() > 6 ? 2+PApplet.parseInt(random(5)) : PApplet.parseInt(random(7));                                     }
-               } LastMeasure = t;
-                       
-               int nTempo = pTempoMult  .Cur(); if (nTempo == 5) nTempo = curRandTempo;
-               int nTPat  = pTimePattern.Cur(); if (nTPat  == 7) nTPat  = curRandTPat ;
-
-               switch (nTempo) {
-                       case 0:         t = t;                                                          break;
-                       case 1:         t = (t*2.f )%1.f;                                               break;
-                       case 2:         t = (t*4.f )%1.f;                                               break;
-                       case 3:         t = (t*8.f )%1.f;                                               break;
-                       case 4:         t = (t*16.f)%1.f;                                               break;
-               }
-
-               int i=0; while (i< waves.size()) {
-                       rWave w = waves.get(i);
-                       w.move(deltaMs); if (w.bDone) waves.remove(i); else i++;
-               }
-
-               if ((t<LastBeat && pShape.Cur()!=14) || KeyPressed>-1) {
-                       waves.add(new rWave(
-                                               KeyPressed>-1 ? map(KeyPressed,0,7,0,1) : random(1),            // location
-                                               bnc*10,                 // bounciness
-                                               7,                              // velocity
-                                               2*(1-amp)));    // dampiness
-                       KeyPressed=-1;
-                       if (waves.size() > 5) waves.remove(0);
-               }
-               
-               if (t<LastBeat) {
-                       cPrev.set(cRand); setRand(cRand);
-                       a1.set(); a2.set(); a3.set(); a4.set();
-               } LastBeat = t;
-
-               switch (nTPat) {
-                       case 0:         t = sin(PI*t);                                                  break;  // bounce
-                       case 1:         t = norm(sin(2*PI*(t+PI/2)),-1,1);              break;  // sin
-                       case 2:         t = t;                                                                  break;  // roll
-                       case 3:         t = constrain(PApplet.parseInt(t*8)/7.f,0,1);                   break;  // quant
-                       case 4:         t = t*t*t;                                                              break;  // accel
-                       case 5:         t = sin(PI*t*.5f);                                              break;  // deccel
-                       case 6:         t = .5f*(1-cos(PI*t));                                  break;  // slide
-               }
-               
-               cMid.set                (cPrev);        interpolate(t,cMid,cRand);
-               cMidNorm.set    (cMid);         setNorm(cMidNorm);
-               a1.move(); a2.move(); a3.move(); a4.move();
-       }
-
-       public int CalcPoint(PVector Px) {
-               if (theta.x != 0) rotateX(Px, mCtr, tSin.x, tCos.x);
-               if (theta.y != 0) rotateY(Px, mCtr, tSin.y, tCos.y);
-               if (theta.z != 0) rotateZ(Px, mCtr, tSin.z, tCos.z);
-               
-               Pn.set(Px); setNorm(Pn);
-
-               float mp        = min(Pn.x, Pn.z);
-               float yt        = map(t,0,1,.5f-bnc/2,.5f+bnc/2);
-               float r,d;
-
-               switch (pShape.Cur()) {
-               case 0:         V.set(Pn.x, yt                                                          , Pn.z);                                                        break;  // bouncing line
-               case 1:         V.set(Pn.x, map(cos(PI*t * Pn.x),-1,1,0,1)  , Pn.z);                                                    break;  // top tap
-               case 2:         V.set(Pn.x, bnc*map(Pn.x<.5f?Pn.x:1-Pn.x,0,.5f ,0,t-.5f)+.5f, Pn.z);                            break;  // V shape
-               case 3:         V.set(Pn.x, Pn.x < cMidNorm.x ? map(Pn.x,0,cMidNorm.x, .5f,yt) :
-                                                                                               map(Pn.x,cMidNorm.x,1, yt,.5f), Pn.z);                          break;  //  Random V shape
-
-               case 4:         V.set(Pn.x,     .5f*(Pn.x < cMidNorm.x ?        map(Pn.x,0,cMidNorm.x, .5f,yt) :
-                                                                                                               map(Pn.x,cMidNorm.x,1, yt,.5f)) +
-                                                       .5f*(Pn.z < cMidNorm.z ?        map(Pn.z,0,cMidNorm.z, .5f,yt) :
-                                                                                                               map(Pn.z,cMidNorm.z,1, yt,.5f)), Pn.z);                 break;  //  Random Pyramid shape
-                                                                                                       
-               case 5:         V.set(Pn.x, bnc*map((Pn.x-.5f)*(Pn.x-.5f),0,.25f,0,t-.5f)+.5f, Pn.z);                           break;  // wings
-               case 6:         V.set(Pn.x, bnc*map((mp  -.5f)*(mp  -.5f),0,.25f,0,t-.5f)+.5f, Pn.z);                           break;  // wings
-
-               case 7:         d = min(
-                                               distToSeg(Px.x, Px.y, a1.getX(70),a1.getY(70), mCtr.x, mCtr.y),
-                                               distToSeg(Px.x, Px.y, a2.getX(40),a2.getY(40), mCtr.x, mCtr.y));
-                                       d = constrain(30*(rad*40-d),0,100);
-                                       return lx.hsb(lxh(),100, d); // clock
-
-               case 8:         r = amp*200 * map(bnc,0,1,1,sin(PI*t));
-                                       d = min(
-                                               distToSeg(Px.x, Px.y, a1.getX(r),a1.getY(r), a2.getX(r),a2.getY(r)),
-                                               distToSeg(Px.x, Px.y, a2.getX(r),a2.getY(r), a3.getX(r),a3.getY(r)),
-                                               distToSeg(Px.x, Px.y, a3.getX(r),a3.getY(r), a1.getX(r),a1.getY(r))                             // triangle
-                                               );
-                                       d = constrain(30*(rad*40-d),0,100);
-                                       return lx.hsb(lxh(),100, d); // clock
-
-               case 9:         r = amp*200 * map(bnc,0,1,1,sin(PI*t));
-                                       d = min(
-                                               distToSeg(Px.x, Px.y, a1.getX(r),a1.getY(r), a2.getX(r),a2.getY(r)),
-                                               distToSeg(Px.x, Px.y, a2.getX(r),a2.getY(r), a3.getX(r),a3.getY(r)),
-                                               distToSeg(Px.x, Px.y, a3.getX(r),a3.getY(r), a4.getX(r),a4.getY(r)),
-                                               distToSeg(Px.x, Px.y, a4.getX(r),a4.getY(r), a1.getX(r),a1.getY(r))                             // quad
-                                       );
-                                       d = constrain(30*(rad*40-d),0,100);
-                                       return lx.hsb(lxh(),100, d); // clock
-
-               case 10:
-                                       r = map(bnc,0,1,a1.r,amp*200*sin(PI*t));
-                                       return lx.hsb(lxh(),100,c1c(.9f+2*rad - dist(Px.x,Px.y,a1.getX(r),a1.getY(r))*.03f) );          // sphere
-
-               case 11:
-                                       Px.z=mCtr.z; cMid.z=mCtr.z;
-                                       return lx.hsb(lxh(),100,c1c(1 - calcCone(Px,cMid,mCtr) * 0.02f > .5f?1:0));                             // cone
-
-               case 12:        return lx.hsb(lxh() + noise(Pn.x,Pn.y,Pn.z + (NoiseMove+50000)/1000.f)*200,
-                                               85,c1c(Pn.y < noise(Pn.x + NoiseMove/2000.f,Pn.z)*(1+amp)-amp/2.f-.1f ? 1 : 0));        // noise
-
-               case 13:        
-               case 14:        float y=0; for (rWave w : waves) y += .5f*w.val(Pn.x);  // wave
-                                       V.set(Pn.x, .7f+y, Pn.z);
-                                       break;
-
-               default:        return lx.hsb(0,0,0);
-               }
-
-               return lx.hsb(lxh(), 100, c1c(1 - V.dist(Pn)/rad));
-       }
-}
-//----------------------------------------------------------------------------------------------------------------------------------
-boolean dDebug = false;
-class dCursor {
-       dVertex vCur, vNext, vDest;
-       float   destSpeed;
-       int     posStop, pos,posNext;   // 0 - 65535
-       int     clr;
-
-       dCursor() {}
-
-       public boolean isDone   ()                                                                      { return pos==posStop;                                                                           }
-       public boolean atDest  ()                                                                       { return vCur.s==vDest.s || 
-                                                                                                                                xyDist(vCur.getPoint(0), vDest.getPoint(0)) < 12 || 
-                                                                                                                                xyDist(vCur.getPoint(0), vDest.getPoint(15))< 12;}
-       public void     setCur  (dVertex _v, int _p)                            { p2=null; vCur=_v; pos=_p; pickNext();                                          }
-       public void     setCur  (dPixel  _p)                                            { setCur(_p.v, _p.pos);                                                                          }
-       public void     setNext (dVertex _v, int _p, int _s)            { vNext = _v; posNext = _p<<12; posStop = _s<<12;                        }
-       public void     setDest (dVertex _v, float _speed)                      { vDest = _v; destSpeed = _speed;                                                        }
-       public void     onDone  ()                                                                      { setCur(vNext, posNext); pickNext();                                            }
-
-       float   minDist;
-       int     nTurns;
-       boolean bRandEval;
-
-       public void     evaluate(dVertex v, int p, int s) {
-               if (v == null) return; ++nTurns;
-               if (bRandEval) {
-                       if (random(nTurns) < 1) setNext(v,p,s); return; }
-               else {
-                       float d = xyDist(v.getPoint(15), vDest.getPoint(0));
-                       if (d <  minDist)                                       { minDist=d; setNext(v,p,s); }
-                       if (d == minDist && random(2)<1)        { minDist=d; setNext(v,p,s); }
-               }
-       }
-
-       public void     evalTurn(dTurn t) { 
-               if (t == null || t.pos0<<12 <= pos) return; 
-               evaluate(t.v    ,    t.pos1, t.pos0);
-               evaluate(t.v.opp, 16-t.pos1, t.pos0);
-       }
-
-       public void     pickNext()      {
-               bRandEval = random(.05f+destSpeed) < .05f; minDist=500; nTurns=0;
-               evaluate(vCur.c0, 0, 16);       evaluate(vCur.c1, 0, 16);
-               evaluate(vCur.c2, 0, 16);       evaluate(vCur.c3, 0, 16);
-               evalTurn(vCur.t0);                      evalTurn(vCur.t1);
-               evalTurn(vCur.t2);                      evalTurn(vCur.t3);
-       }
-
-       Point   p1, p2; int i2;
-
-       public int draw(int nAmount, SCPattern pat) {
-               int nFrom       = (pos    ) >> 12;
-               int     nMv     = min(nAmount, posStop-pos);
-               int     nTo     = min(15,(pos+nMv) >> 12);
-               dVertex v       = vCur;
-
-               if (dDebug) {   p1 = v.getPoint(nFrom); float d = (p2 == null ? 0 : pointDist(p1,p2)); if (d>5) { println("too wide! quitting: " + d); exit(); }}
-                                                               for (int i = nFrom; i <= nTo; i++) { pat.getColors()[v.ci          + v.dir*i     ] = clr; }
-               if (v.same != null)             for (int i = nFrom; i <= nTo; i++) { pat.getColors()[v.same.ci + v.same.dir*i] = clr; }
-
-               if (dDebug) {   p2 = v.getPoint(nTo); i2 = nTo; }
-
-               pos += nMv; return nAmount - nMv;
-                       }       
-}
-
-//----------------------------------------------------------------------------------------------------------------------------------
-class Worms extends SCPattern {
-       float   StripsPerSec    = 10;
-       float   TrailTime               = 3000;
-       int     numCursors              = 50;
-       ArrayList<dCursor> cur  = new ArrayList<dCursor>(30);
-
-       private GraphicEQ eq = null;
-
-       private BasicParameter pBeat      = new BasicParameter("BEAT",  0);
-       private BasicParameter pSpeed     = new BasicParameter("FAST", .2f);
-       private BasicParameter pBlur      = new BasicParameter("BLUR", .3f);
-       private BasicParameter pWorms     = new BasicParameter("WRMS", .3f);
-       private BasicParameter pConfusion = new BasicParameter("CONF", .1f);
-       private BasicParameter pEQ        = new BasicParameter("EQ"  ,  0);
-       private BasicParameter pSpawn     = new BasicParameter("DIR" ,  0);
-       private BasicParameter pColor     = new BasicParameter("CLR" ,  .1f);
-
-       float   zMidLat = 82.f;
-       float   nConfusion;
-       private final Click moveChase = new Click(1000);
-
-       PVector middle;
-       public int      AnimNum() { return floor(pSpawn.getValuef()*(4-.01f));  }
-       public float   randX() { return random(model.xMax-model.xMin)+model.xMin; }
-       public float   randY() { return random(model.yMax-model.yMin)+model.yMin; }
-       public PVector  randEdge() { 
-               return random(2) < 1 ?  new PVector(random(2)<1 ? model.xMin:model.xMax, randY(), zMidLat)      :
-                                                               new PVector(randX(), random(2)<1 ? model.yMin:model.yMax, zMidLat)      ;
-       }
-
-       Worms(GLucose glucose) {
-               super(glucose); 
-           addModulator(moveChase).start();
-           addParameter(pBeat);    addParameter(pSpeed);
-           addParameter(pBlur);    addParameter(pWorms);
-           addParameter(pEQ);      addParameter(pConfusion);
-               addParameter(pSpawn);   addParameter(pColor);
-
-           middle = new PVector(1.5f*model.cx, 1.5f*model.cy, 71);
-               if (lattice == null) lattice = new dLattice();
-               for (int i=0; i<numCursors; i++) { dCursor c = new dCursor(); reset(c); cur.add(c); }
-               onParameterChanged(pEQ); setNewDest();
-       }
-
-       public void onParameterChanged(LXParameter parameter) {
-               super.onParameterChanged(parameter);
-               nConfusion = 1-pConfusion.getValuef();
-               for (int i=0; i<numCursors; i++) {
-                       if (parameter==pSpawn) reset(cur.get(i));
-                       cur.get(i).destSpeed = nConfusion;
-               }
-       }
-
-       public float getClr() { return lx.getBaseHuef() + random(pColor.getValuef()*300); }
-       public void reset(dCursor c) {
-               switch(AnimNum()) {
-                       case 0: c.clr = lx.hsb(getClr(),100,100);                       // middle to edges
-                                       c.setDest(lattice.getClosest(randEdge()).v, nConfusion);
-                                       c.setCur (lattice.getClosest(middle));
-                                       break;
-
-                       case 1: c.clr = lx.hsb(getClr(),100,100);                               // top to bottom
-                                       float xLin = randX();
-                                       c.setDest(lattice.getClosest(new PVector(xLin, 0         , zMidLat)).v, nConfusion);
-                                       c.setCur (lattice.getClosest(new PVector(xLin, model.yMax, zMidLat)));
-                                       break;
-
-                       case 2: c.clr = lx.hsb(getClr(),100,100); break;                // chase a point around
-
-                       case 3: boolean bLeft = random(2)<1;
-                                       c.clr = lx.hsb(getClr()+random(120),100,100);                           // sideways
-                                       float yLin = randX();
-                                       c.setDest(lattice.getClosest(new PVector(bLeft ? 0 : model.xMax,yLin,zMidLat)).v, nConfusion);
-                                       c.setCur (lattice.getClosest(new PVector(bLeft ? model.xMax : 0,yLin,zMidLat)));
-                                       break;
-               }
-               if (pBlur.getValuef() == 1 && random(2)<1) c.clr = lx.hsb(0,0,0);
-       }
-
-       public void setNewDest() {
-               if (AnimNum() != 2) return;
-               PVector dest = new PVector(randX(), randY(), zMidLat);
-               for (int i=0; i<numCursors; i++) {
-                       cur.get(i).setDest(lattice.getClosest(dest).v, nConfusion);
-                       cur.get(i).clr = lx.hsb(getClr()+75,100,100);   // chase a point around
-               }
-       }
-
-       public void run(double deltaMs) { 
-               if (deltaMs > 100) return;
-           if (moveChase.click()) setNewDest();
-
-           float fBass=0, fTreble=0;
-           if (pEQ.getValuef()>0) {            // EQ
-                   eq.run(deltaMs);
-                   fBass       = eq.getAverageLevel(0, 4);
-                   fTreble = eq.getAverageLevel(eq.numBands-7, 7);
-               }
-
-               if (pBlur.getValuef() < 1) {    // trails
-                       for (int i=0,s=model.points.size(); i<s; i++) {
-                               int c = colors[i]; float b = lx.b(c); 
-                               if (b>0) colors[i] = lx.hsb(lx.h(c), lx.s(c), constrain((float)(b-100*deltaMs/(pBlur.getValuef()*TrailTime)),0,100));
-                       }
-               }
-
-               int nWorms = floor(pWorms.getValuef() * numCursors * 
-                                        map(pEQ.getValuef(),0,1,1,constrain(2*fTreble,0,1)));
-
-               for (int i=0; i<nWorms; i++) {
-                       dCursor c = cur.get(i);
-                       int nLeft = floor((float)deltaMs*.001f*StripsPerSec * 65536 * (5*pSpeed.getValuef()));
-                       nLeft *= (1 - lx.tempo.rampf()*pBeat.getValuef());
-                       while(nLeft > 0) { 
-                               nLeft = c.draw(nLeft,this); if (!c.isDone()) continue;
-                               c.onDone(); if (c.atDest()) reset(c);
-                       }
-               }
-       }
-
-
-       public void onActive() { if (eq == null) {
-               eq = new GraphicEQ(lx, 16);             eq.slope.setValue(0.6f);
-               eq.level.setValue(0.65f);               eq.range.setValue(0.35f);
-               eq.release.setValue(0.4f);
-       }}
-}
-//----------------------------------------------------------------------------------------------------------------------------------
-class GenericController {
-    GenericController(){}
-    public void RotateKnob(int type, int num, float val){
-      LXParameter p = null;
-      if(type==0) {
-        p = glucose.patternKnobs.get(num);
-        if(p!=null) { p.setValue(val); }
-      }
-      if(type==1) {
-        p = glucose.transitionKnobs.get(num);
-        if(p!=null) { p.setValue(val); }
-      }
-      if(type==2) {
-        p = glucose.effectKnobs.get(num);
-        if(p!=null) { p.setValue(val); }
-      }
-    }
-}
-
-class MidiController extends GenericController {
-  MidiController() {
-     super();
-  }  
-}
-//PApplet xparent;  // be sure to set
-
-
-
-OscP5 listener;
-// Setup OSC
-//listener = new OscP5(this,7022);
-
-//boolean[] noteState = new boolean[16];
-//
-//void controllerChangeReceived(rwmidi.Controller cc) {
-//  if (debugMode) {
-//    println("CC: " + cc.toString());
-//  }
-//  if(cc.getCC()==1){
-//    for(int i=0; i<16; i++){
-//      if(noteState[i] && i<8)  { LXParameter p = glucose.patternKnobs.get(i); p.setValue(cc.getValue()/127.0); }
-//      else if(noteState[i] && i<12) { LXParameter p = glucose.transitionKnobs.get(i-8); p.setValue(cc.getValue()/127.0); }
-//      else if(noteState[i] && i<16) { LXParameter p = glucose.effectKnobs.get(i-12); p.setValue(cc.getValue()/127.0); }
-//    }
-//  }
-//}
-//
-//void noteOnReceived(Note note) {
-//  if (debugMode) {
-//    println("Note On: " + note.toString());
-//  }
-//  int pitch = note.getPitch();
-//  if(pitch>=36 && pitch <36+16){
-//    noteState[pitch-36]=true;
-//  }
-//}
-//
-//void noteOffReceived(Note note) {
-//  if (debugMode) {
-//    println("Note Off: " + note.toString());
-//  }
-//  int pitch = note.getPitch();
-//  if(pitch>=36 && pitch <36+16){
-//    noteState[pitch-36]=false;
-//  }
-//}
-//
-//void oscEvent(OscMessage theOscMessage) {
-//  println(theOscMessage);
-//  LXPattern currentPattern = lx.getPattern();
-//  if (currentPattern instanceof OSCPattern) {
-//    ((OSCPattern)currentPattern).oscEvent(theOscMessage);
-//  }
-//}
-//
-
-
-class ObjectMuckerEffect extends SCEffect {
-  ObjectMuckerEffect(GLucose glucose) {
-    super(glucose);
-  }
-  public void apply(int[] colors){
-    /*for(Strip s: model.strips){
-      for(int i=0; i<s.points.size(); i++){
-         int index = s.points.get(i).index;
-         color c = colors[index];
-         colors[index] = lx.hsb((i*22.5), saturation(c), brightness(c));
-      }
-    }*/
-  }
-}
-
-class BlendFrames extends SCEffect {
-  int fcount;
-  int frames[][];
-  int maxfbuf;
-  int blendfactor;
-  BlendFrames(GLucose glucose) {
-    super(glucose);
-    maxfbuf = 30;
-    blendfactor=30;
-    fcount=0;
-    frames = new int[maxfbuf][];
-    for(int i=0; i<maxfbuf; i++){
-       frames[i] = new int[model.points.size()];       
-    }
-  }
-  public void apply(int[] colors) {
-    if(fcount<maxfbuf){
-      for(int i=0; i<colors.length; i++){
-        frames[(maxfbuf-1)-fcount][i]=colors[i];
-      }
-      fcount++;
-      return;
-    } else {
-      for(int i=maxfbuf-1; i>0; i--){
-        frames[i] = frames[i-1];
-      }
-      frames[0] = new int[model.points.size()];
-      
-      for(int i=0; i<colors.length; i++){
-        int r,g,b;
-        r=g=b=0;
-        for(int j=0; j<blendfactor; j++){          
-          if(j==0) { frames[0][i] = colors[i]; }
-          r += ((frames[j][i] >> 16) & 0xFF);
-          g += ((frames[j][i] >> 8) & 0xFF);
-          b += ((frames[j][i] >> 0) & 0xFF);
-        }
-        r/=blendfactor;
-        g/=blendfactor;
-        b/=blendfactor;
-        colorMode(ARGB);
-        colors[i] = (0xFF << 24) | (r << 16) | (g << 8) | b;
-        colorMode(HSB);
-      }
-            
-    }
-  }
-}
-
-
-
-
-
-
-
-abstract class OSCPattern extends SCPattern {
-  public OSCPattern(GLucose glucose){super(glucose);}
-  public abstract void oscEvent(OscMessage msg);
-}
-
-class Ball {
-  public int lastSeen;
-  public float x,y;
-  public Ball(){
-    x=y=lastSeen=0;  
-  }
-}
-
-class OSC_Balls extends OSCPattern {
-  Ball[] balls;
-  public OSC_Balls(GLucose glucose){
-    super(glucose);
-    balls = new Ball[20];
-    for(int i=0; i<balls.length; i++) { balls[i] = new Ball(); }    
-  }
-  public void oscEvent(OscMessage msg){
-    String pattern[] = split(msg.addrPattern(), "/");    
-    int ballnum = PApplet.parseInt(pattern[3]);
-    balls[ballnum].lastSeen=millis();
-    balls[ballnum].x = msg.get(0).floatValue();
-    balls[ballnum].y = msg.get(1).floatValue();    
-  }
-  
-  public void run(double deltaMs){
-    for(Point p: model.points){ colors[p.index]=0; }
-    for(int i=1; i<balls.length; i++){
-      if(millis() - balls[i].lastSeen < 1000) {
-        for(Point p: model.points){
-          int x = PApplet.parseInt(balls[i].x * 255.0f);
-          int y = PApplet.parseInt(balls[i].y * 127.0f);
-          if(p.x < x+4 && p.x > x-4 && p.y < y+4 && p.y > y-4) { colors[p.index] = 0xffFF0000; } 
-        }
-      }
-    }
-  }
-}
-
-
-
-
-/*class ScreenScrape extends SCPattern {
-  PImage pret;
-  ScreenShot ss;
-  public ScreenScrape(GLucose glucose) {
-    super(glucose);
-    System.loadLibrary("ScreenShot");
-    pret = new PImage(8, 128, ARGB);
-    ss = new ScreenShot();
-  }
-  void run(double deltaMs){
-     int x=(1366/2)+516;
-     int y=768-516;
-     int w=8;
-     int h=128;
-     pret.pixels = ss.getScreenShotJNI2(x, y, w, h);
-     //for(int i=0; i<px.length; i++){ pret.pixels[i] = px[i]; }
-     //println(pret.get(10,10));
-     for(Point p: model.points){
-       colors[p.index] = pret.get((int(p.x)/8)*8, 128-int(p.y));
-     }     
-  }
-}*/
-
-//----------------------------------------------------------------------------------------------------------------------------------
-int                    NumApcRows=4, NumApcCols=8;
-
-public boolean btwn    (int            a,int    b,int          c)              { return a >= b && a <= c;      }
-public boolean btwn    (double         a,double b,double       c)              { return a >= b && a <= c;      }
-public float   interp  (float a, float b, float c) { return (1-a)*b + a*c; }
-public float   randctr (float a) { return random(a) - a*.5f; }
-public float   min             (float a, float b, float c, float d) { return min(min(a,b),min(c,d));   }
-public float   pointDist(Point p1, Point p2) { return dist(p1.x,p1.y,p1.z,p2.x,p2.y,p2.z);     }
-public float   xyDist   (Point p1, Point p2) { return dist(p1.x,p1.y,p2.x,p2.y);                               }
-public float   distToSeg(float x, float y, float x1, float y1, float x2, float y2) {
-       float A                         = x - x1, B = y - y1, C = x2 - x1, D = y2 - y1;
-       float dot                       = A * C + B * D, len_sq = C * C + D * D;
-       float xx, yy,param      = dot / len_sq;
-       
-       if (param < 0 || (x1 == x2 && y1 == y2)) {      xx = x1; yy = y1; }
-       else if (param > 1) {                                           xx = x2; yy = y2; }
-       else {                                                                          xx = x1 + param * C;
-                                                                                               yy = y1 + param * D; }
-       float dx = x - xx, dy = y - yy;
-       return sqrt(dx * dx + dy * dy);
-}
-
-public class Pick {
-       int     NumPicks, Default       ,       
-                       CurRow  , CurCol        ,
-                       StartRow, EndRow        ;
-       String  tag             , Desc[]        ;
-
-       Pick    (String label, int _Def, int _Num,      int nStart, String d[]) {
-               NumPicks        = _Num;         Default = _Def; 
-               StartRow        = nStart;       EndRow  = StartRow + floor((NumPicks-1) / NumApcCols);
-               tag                     = label;        Desc    = d;
-               reset();
-       }
-
-       public int              Cur()                   { return (CurRow-StartRow)*NumApcCols + CurCol;                                 }
-       public String   CurDesc()               { return Desc[Cur()]; }
-       public void     reset()                 { CurCol = Default % NumApcCols; CurRow = StartRow + Default / NumApcCols; }
-
-       public boolean set(int r, int c)        {
-               if (!btwn(r,StartRow,EndRow) || !btwn(c,0,NumApcCols-1) ||
-                       !btwn((r-StartRow)*NumApcCols + c,0,NumPicks-1))        return false;
-               CurRow=r; CurCol=c;                                                                     return true;
-       }
-}
-
-public class DBool {
-       boolean def, b;
-       String  tag;
-       int             row, col;
-       public void     reset() { b = def; }
-       public boolean set      (int r, int c, boolean val) { if (r != row || c != col) return false; b = val; return true; }
-       DBool(String _tag, boolean _def, int _row, int _col) {
-               def = _def; b = _def; tag = _tag; row = _row; col = _col;
-       }
-}
-//----------------------------------------------------------------------------------------------------------------------------------
-public class DPat extends SCPattern
-{
-       ArrayList<Pick>   picks  = new ArrayList<Pick>  ();
-       ArrayList<DBool>  bools  = new ArrayList<DBool> ();
-
-       PVector         mMax, mCtr, mHalf;
-
-       MidiOutput  APCOut;
-       int                     nMaxRow         = 53;
-       float           LastJog = -1;
-       float[]         xWaveNz, yWaveNz;
-       int             nPoint  , nPoints;
-       PVector         xyzJog = new PVector(), modmin;
-
-       float                   NoiseMove       = random(10000);
-       BasicParameter  pSpark, pWave, pRotX, pRotY, pRotZ, pSpin, pTransX, pTransY;
-       DBool                   pXsym, pYsym, pRsym, pXdup, pXtrip, pJog, pGrey;
-
-       public float            lxh             ()                                                                      { return lx.getBaseHuef();                                                                                      }
-       public int                      c1c              (float a)                                                      { return round(100*constrain(a,0,1));                                                           }
-       public float            interpWv(float i, float[] vals)                         { return interp(i-floor(i), vals[floor(i)], vals[ceil(i)]);             }
-       public void             setNorm (PVector vec)                                           { vec.set(vec.x/mMax.x, vec.y/mMax.y, vec.z/mMax.z);                            }
-       public void             setRand (PVector vec)                                           { vec.set(random(mMax.x), random(mMax.y), random(mMax.z));                      }
-       public void             setVec  (PVector vec, Point p)                          { vec.set(p.x, p.y, p.z);                                                                                       }
-       public void             interpolate(float i, PVector a, PVector b)      { a.set(interp(i,a.x,b.x), interp(i,a.y,b.y), interp(i,a.z,b.z));       }
-       public void             StartRun(double deltaMs)                                        { }
-       public float            val             (BasicParameter p)                                      { return p.getValuef();                                                                                         }
-       public int              CalcPoint(PVector p)                                            { return lx.hsb(0,0,0);                                                                                         }
-       public int              blend3(int c1, int c2, int c3)          { return blendColor(c1,blendColor(c2,c3,ADD),ADD);                                      }
-
-       public void     rotateZ (PVector p, PVector o, float nSin, float nCos) { p.set(    nCos*(p.x-o.x) - nSin*(p.y-o.y) + o.x    , nSin*(p.x-o.x) + nCos*(p.y-o.y) + o.y,p.z); }
-       public void     rotateX (PVector p, PVector o, float nSin, float nCos) { p.set(p.x,nCos*(p.y-o.y) - nSin*(p.z-o.z) + o.y    , nSin*(p.y-o.y) + nCos*(p.z-o.z) + o.z    ); }
-       public void     rotateY (PVector p, PVector o, float nSin, float nCos) { p.set(    nSin*(p.z-o.z) + nCos*(p.x-o.x) + o.x,p.y, nCos*(p.z-o.z) - nSin*(p.x-o.x) + o.z    ); }
-
-       public BasicParameter   addParam(String label, double value)    { BasicParameter p = new BasicParameter(label, value); addParameter(p); return p; }
-
-       PVector         vT1 = new PVector(), vT2 = new PVector();
-       public float            calcCone (PVector v1, PVector v2, PVector c)    {       vT1.set(v1); vT2.set(v2); vT1.sub(c); vT2.sub(c);
-                                                                                                                                       return degrees(PVector.angleBetween(vT1,vT2)); }
-
-       public Pick             addPick(String name, int def, int _max, String[] desc) {
-               Pick P          = new Pick(name, def, _max+1, nMaxRow, desc); 
-               nMaxRow         = P.EndRow + 1;
-               picks.add(P);
-               return P;
-       }
-
-    public boolean     noteOff(Note note) {
-               int row = note.getPitch(), col = note.getChannel();
-               for (int i=0; i<bools.size(); i++) if (bools.get(i).set(row, col, false)) { presetManager.dirty(this); return true; }
-               updateLights(); return false;
-       }
-
-    public boolean     noteOn(Note note) {
-               int row = note.getPitch(), col = note.getChannel();
-               for (int i=0; i<picks.size(); i++) if (picks.get(i).set(row, col))                      { presetManager.dirty(this); return true; }
-               for (int i=0; i<bools.size(); i++) if (bools.get(i).set(row, col, true))        { presetManager.dirty(this); return true; }
-               println("row: " + row + "  col:   " + col); return false;
-       }
-
-       public void             onInactive()                    { uiDebugText.setText(""); }
-       public void             onReset()                               {
-               for (int i=0; i<bools .size(); i++) bools.get(i).reset();
-               for (int i=0; i<picks .size(); i++) picks.get(i).reset();
-               presetManager.dirty(this); 
-               updateLights(); 
-       }
-
-       DPat(GLucose glucose) {
-               super(glucose);
-
-               pSpark          =       addParam("Sprk",  0);
-               pWave           =       addParam("Wave",  0);
-               pTransX         =       addParam("TrnX", .5f);
-               pTransY         =       addParam("TrnY", .5f);
-               pRotX           =       addParam("RotX", .5f);
-               pRotY           =       addParam("RotY", .5f);
-               pRotZ           =       addParam("RotZ", .5f);
-               pSpin           =       addParam("Spin", .5f);
-
-               nPoints         =       model.points.size();
-               pXsym           =       new DBool("X-SYM", false, 48, 0);       bools.add(pXsym );
-               pYsym           =       new DBool("Y-SYM", false, 48, 1);       bools.add(pYsym );
-               pRsym           =       new DBool("R-SYM", false, 48, 2);       bools.add(pRsym );
-               pXdup           =       new DBool("X-DUP", false, 48, 3);       bools.add(pXdup );
-               pJog            =       new DBool("JOG"  , false, 48, 4);       bools.add(pJog  );
-               pGrey           =       new DBool("GREY" , false, 48, 5);       bools.add(pGrey );
-
-               modmin          =       new PVector(model.xMin, model.yMin, model.zMin);
-               mMax            =       new PVector(model.xMax, model.yMax, model.zMax); mMax.sub(modmin);
-               mCtr            =       new PVector(); mCtr.set(mMax); mCtr.mult(.5f);
-               mHalf           =       new PVector(.5f,.5f,.5f);
-               xWaveNz         =       new float[ceil(mMax.y)+1];
-               yWaveNz         =       new float[ceil(mMax.x)+1];
-
-               //println (model.xMin + " " + model.yMin + " " +  model.zMin);
-               //println (model.xMax + " " + model.yMax + " " +  model.zMax);
-         //for (MidiOutputDevice o: RWMidi.getOutputDevices()) { if (o.toString().contains("APC")) { APCOut = o.createOutput(); break;}}
-       }
-
-       public float spin() {
-         float raw = val(pSpin);
-         if (raw <= 0.45f) {
-           return raw + 0.05f;
-         } else if (raw >= 0.55f) {
-           return raw - 0.05f;
-    }
-    return 0.5f;
-       }
-       
-       public void setAPCOutput(MidiOutput output) {
-         APCOut = output;
-       }
-
-       public void updateLights() { if (APCOut == null) return;
-           for (int i = 0; i < NumApcRows; ++i) 
-               for (int j = 0; j < 8; ++j)             APCOut.sendNoteOn(j, 53+i,  0);
-               for (int i=0; i<picks .size(); i++)     APCOut.sendNoteOn(picks.get(i).CurCol, picks.get(i).CurRow, 3);
-               for (int i=0; i<bools .size(); i++)     if (bools.get(i).b)     APCOut.sendNoteOn       (bools.get(i).col, bools.get(i).row, 1);
-                                                                                               else                                    APCOut.sendNoteOff      (bools.get(i).col, bools.get(i).row, 0);
-       }
-
-       public void run(double deltaMs)
-       {
-               if (deltaMs > 100) return;
-
-               if (this == midiEngine.getFocusedDeck().getActivePattern()) {
-                       String Text1="", Text2="";
-                       for (int i=0; i<bools.size(); i++) if (bools.get(i).b) Text1 += " " + bools.get(i).tag       + "   ";
-                       for (int i=0; i<picks.size(); i++) Text1 += picks.get(i).tag + ": " + picks.get(i).CurDesc() + "   ";
-                       uiDebugText.setText(Text1, Text2);
-               }
-
-               NoiseMove       += deltaMs; NoiseMove = NoiseMove % 1e7f;
-               StartRun                (deltaMs);
-               PVector P               = new PVector(), tP = new PVector(), pSave = new PVector();
-               PVector pTrans  = new PVector(val(pTransX)*200-100, val(pTransY)*100-50,0);
-               nPoint  = 0;
-
-               if (pJog.b) {
-                       float tRamp     = (lx.tempo.rampf() % .25f);
-                       if (tRamp < LastJog) xyzJog.set(randctr(mMax.x*.2f), randctr(mMax.y*.2f), randctr(mMax.z*.2f));
-                       LastJog = tRamp; 
-               }
-
-               // precalculate this stuff
-               float wvAmp = val(pWave), sprk = val(pSpark);
-               if (wvAmp > 0) {
-                       for (int i=0; i<ceil(mMax.x)+1; i++)
-                               yWaveNz[i] = wvAmp * (noise(i/(mMax.x*.3f)-(2e3f+NoiseMove)/1500.f) - .5f) * (mMax.y/2.f);
-
-                       for (int i=0; i<ceil(mMax.y)+1; i++)
-                               xWaveNz[i] = wvAmp * (noise(i/(mMax.y*.3f)-(1e3f+NoiseMove)/1500.f) - .5f) * (mMax.x/2.f);
-               }
-
-               for (Point p : model.points) { nPoint++;
-                       setVec(P,p);
-                       P.sub(modmin);
-                       P.sub(pTrans);
-                       if (sprk  > 0) {P.y += sprk*randctr(50); P.x += sprk*randctr(50); P.z += sprk*randctr(50); }
-                       if (wvAmp > 0)  P.y += interpWv(p.x-modmin.x, yWaveNz);
-                       if (wvAmp > 0)  P.x += interpWv(p.y-modmin.y, xWaveNz);
-                       if (pJog.b)             P.add(xyzJog);
-
-
-                       int cNew, cOld = colors[p.index];
-                                                       { tP.set(P);                                                                    cNew = CalcPoint(tP);                                                   }
-                       if (pXsym.b)    { tP.set(mMax.x-P.x,P.y,P.z);                                   cNew = blendColor(cNew, CalcPoint(tP), ADD);    }
-                       if (pYsym.b)    { tP.set(P.x,mMax.y-P.y,P.z);                                   cNew = blendColor(cNew, CalcPoint(tP), ADD);    }
-                       if (pRsym.b)    { tP.set(mMax.x-P.x,mMax.y-P.y,mMax.z-P.z);             cNew = blendColor(cNew, CalcPoint(tP), ADD);    }
-                       if (pXdup.b)    { tP.set((P.x+mMax.x*.5f)%mMax.x,P.y,P.z);              cNew = blendColor(cNew, CalcPoint(tP), ADD);    }
-                       if (pGrey.b)    { cNew = lx.hsb(0, 0, lx.b(cNew)); }
-                       colors[p.index] = cNew;
-               }
-       }
-}
-//----------------------------------------------------------------------------------------------------------------------------------
-class dTurn { 
-       dVertex v; 
-       int pos0, pos1;
-       dTurn(int _pos0, dVertex _v, int _pos1) { v = _v; pos0 = _pos0; pos1 = _pos1; }
-}
-
-class dVertex {
-       dVertex c0, c1, c2, c3,         // connections on the cube
-                       opp, same;                      // opp - same strip, opp direction
-                                                               // same - same strut, diff strip, dir
-       dTurn   t0, t1, t2, t3;
-       Strip   s;
-       int     dir, ci;                // dir -- 1 or -1.
-                                                       // ci  -- color index
-
-       dVertex(Strip _s, Point _p)  { s = _s; ci  = _p.index; }
-       public Point    getPoint(int i)          { return s.points.get(dir>0 ? i : 15-i);  }
-       public void     setOpp(dVertex _opp) { opp = _opp; dir = (ci < opp.ci ? 1 : -1); }
-}
-//----------------------------------------------------------------------------------------------------------------------------------
-class dPixel   { dVertex v; int pos; dPixel(dVertex _v, int _pos) { v=_v; pos=_pos; } }
-class dLattice {
-       public void     addTurn  (dVertex v0, int pos0, dVertex v1, int pos1) { dTurn t = new dTurn(pos0, v1, pos1); 
-                                                                                                                                       if (v0.t0 == null) { v0.t0=t; return; }
-                                                                                                                                       if (v0.t1 == null) { v0.t1=t; return; }
-                                                                                                                                       if (v0.t2 == null) { v0.t2=t; return; }
-                                                                                                                                       if (v0.t3 == null) { v0.t3=t; return; }
-                                                                                                                               }
-       public float   dist2     (Strip s1, int pos1, Strip s2, int pos2)       {       return pointDist(s1.points.get(pos1), s2.points.get(pos2)); }
-       public float   pd2       (Point p1, float x, float y, float z)          {       return dist(p1.x,p1.y,p1.z,x,y,z); }
-       public boolean sameSame (Strip s1, Strip s2)                                            {       return max(dist2(s1, 0, s2, 0), dist2(s1,15, s2,15)) < 5 ;      }       // same strut, same direction
-       public boolean sameOpp  (Strip s1, Strip s2)                                            {       return max(dist2(s1, 0, s2,15), dist2(s1,15, s2,0 )) < 5 ;      }       // same strut, opp direction
-       public boolean sameBar  (Strip s1, Strip s2)                                            {       return sameSame(s1,s2) || sameOpp(s1,s2);                                       }       // 2 strips on same strut
-
-
-       public void     addJoint (dVertex v1, dVertex v2) {
-               // should probably replace parallel but further with the new one
-               if (v1.c0 != null && sameBar(v2.s, v1.c0.s)) return;
-               if (v1.c1 != null && sameBar(v2.s, v1.c1.s)) return;
-               if (v1.c2 != null && sameBar(v2.s, v1.c2.s)) return;
-               if (v1.c3 != null && sameBar(v2.s, v1.c3.s)) return;
-
-               if              (v1.c0 == null) v1.c0 = v2; 
-               else if (v1.c1 == null) v1.c1 = v2; 
-               else if (v1.c2 == null) v1.c2 = v2; 
-               else if (v1.c3 == null) v1.c3 = v2;
-       }
-
-       public dVertex v0(Strip s) { return (dVertex)s.obj1; }
-       public dVertex v1(Strip s) { return (dVertex)s.obj2; }
-
-       public dPixel getClosest(PVector p) {
-               dVertex v = null; int pos=0; float d = 500;
-
-               for (Strip s : glucose.model.strips) {
-                       float nd = pd2(s.points.get(0),p.x,p.y,p.z); if (nd < d) { v=v0(s); d=nd; pos=0; }
-                       if (nd > 30) continue;
-                       for (int k=0; k<=15; k++) {
-                               nd = pd2(s.points.get(k),p.x,p.y,p.z); if (nd < d) { v =v0(s); d=nd; pos=k; }
-                       }
-               }
-               return random(2) < 1 ? new dPixel(v,pos) : new dPixel(v.opp,15-pos);
-       }
-
-       dLattice() {
-               lattice=this;
-
-               for (Strip s  : glucose.model.strips) {
-                       dVertex vrtx0 = new dVertex(s,s.points.get(0 )); s.obj1=vrtx0;
-                       dVertex vrtx1 = new dVertex(s,s.points.get(15)); s.obj2=vrtx1;
-                       vrtx0.setOpp(vrtx1); vrtx1.setOpp(vrtx0);
-               }
-
-               for (Strip s1 : glucose.model.strips) { for (Strip s2 : glucose.model.strips) {
-                       if (s1.points.get(0).index < s2.points.get(0).index) continue;
-                       int c=0;
-                       if (sameSame(s1,s2))    {       v0(s1).same = v0(s2); v1(s1).same = v1(s2);
-                                                                               v0(s2).same = v0(s1); v1(s2).same = v1(s1); continue; } // parallel
-                       if (sameOpp (s1,s2))    {       v0(s1).same = v1(s2); v1(s1).same = v0(s2);
-                                                                               v0(s2).same = v1(s1); v1(s2).same = v0(s1); continue; } // parallel
-                       if (dist2(s1, 0, s2, 0) < 5) { c++; addJoint(v1(s1), v0(s2)); addJoint(v1(s2), v0(s1)); }
-                       if (dist2(s1, 0, s2,15) < 5) { c++; addJoint(v1(s1), v1(s2)); addJoint(v0(s2), v0(s1)); }
-                       if (dist2(s1,15, s2, 0) < 5) { c++; addJoint(v0(s1), v0(s2)); addJoint(v1(s2), v1(s1)); }
-                       if (dist2(s1,15, s2,15) < 5) { c++; addJoint(v0(s1), v1(s2)); addJoint(v0(s2), v1(s1)); }
-                       if (c>0) continue;
-
-                       // Are they touching at all?
-                       int pos1=0, pos2=0; float d = 100;
-
-                       while (pos1 < 15 || pos2 < 15) {
-                               float oldD = d;
-                               if (pos1<15) { float d2 = dist2(s1, pos1+1, s2, pos2+0); if (d2 < d) { d=d2; pos1++; } }
-                               if (pos2<15) { float d2 = dist2(s1, pos1+0, s2, pos2+1); if (d2 < d) { d=d2; pos2++; } }
-                               if (d > 50  || oldD == d) break ;
-                       }
-
-                       if (d>5) continue;
-                       addTurn(v0(s1), pos1, v0(s2), pos2); addTurn(v1(s1), 15-pos1, v0(s2), pos2); 
-                       addTurn(v0(s2), pos2, v0(s1), pos1); addTurn(v1(s2), 15-pos2, v0(s1), pos1);
-               }}
-       }
-}
-
-dLattice lattice;
-//----------------------------------------------------------------------------------------------------------------------------------
-
-class Graphic
-{
-       public boolean changed = false;
-       public int position  = 0;
-       public ArrayList<Integer> graphicBuffer;
-       Graphic()
-       {       
-               graphicBuffer = new ArrayList<Integer>();
-       }
-       public int width()
-       {
-               return graphicBuffer.size();
-       }
-
-       
-};
-class Granim extends Graphic
-{
-       HashMap<String,Graphic> displayList;
-       
-       Granim()
-       {
-               displayList = new HashMap<String,Graphic>();
-       }
-       public Graphic addGraphic(String name, Graphic g)
-       {
-               while(width()< g.position+1)
-               {
-                               graphicBuffer.add(lx.hsb(0,0,0));
-               }
-               drawAll();
-               displayList.put(name , g);
-               changed =true;
-               return g;
-       }
-
-       public Graphic getGraphicByName(String name)
-       {
-               return displayList.get(name);
-       }
-
-       public void update()
-       {
-               
-               for(Graphic g : displayList.values())
-               {
-                       if(g instanceof Granim)
-                       {
-                               ((Granim) g).update();
-                               
-                       }
-                       changed = changed || g.changed;
-                       if(changed)
-                       {
-                               while(width()< g.position + g.width())
-                               {
-                                       graphicBuffer.add(lx.hsb(0,0,0));
-                               }
-                               if(g.changed)
-                               {
-                                       drawOne(g);
-                                       g.changed =false;
-                               }
-                       }
-               }
-               changed = false;
-
-       }
-       public void drawOne(Graphic g)
-       {
-               graphicBuffer.addAll(g.position,g.graphicBuffer);
-       }
-       public void drawAll()
-       {
-       }
-};
-class GranimPattern extends SCPattern
-{
-       HashMap<String,Graphic> displayList;
-
-       GranimPattern(GLucose glucose)
-       {
-               super(glucose);
-               displayList = new HashMap<String,Graphic>();
-       }
-
-       public Graphic addGraphic(String name, Graphic g)
-       {
-               displayList.put(name,g);
-               return g;
-       }
-
-       public Graphic getGraphicByName(String name)
-       {
-               return displayList.get(name);
-       }
-
-       public void run(double deltaMs) 
-       {
-               drawToPointList();
-       }
-       private Integer[] gbuffer;
-       public void drawToPointList()
-       {
-               for(Graphic g : displayList.values())
-               {
-                       if(g instanceof Granim)
-                       {
-                               ((Granim) g).update();
-                       }
-                       List<Point> drawList = model.points.subList(Math.min(g.position,colors.length-1), Math.min(g.position + g.width(),colors.length-1));
-                       //println("drawlistsize "+drawList.size());
-                       
-                       gbuffer = g.graphicBuffer.toArray(new Integer[0]);
-                       
-                       for (int i=0; i < drawList.size(); i++)
-                       {
-                               colors[drawList.get(i).index] = gbuffer[i];
-                       }
-                       g.changed = false;
-               }
-       }
-
-};
-
-class RedsGraphic extends Graphic
-{
-       RedsGraphic()
-       {
-               super();
-               drawit(10);
-       }
-       RedsGraphic(int len)
-       {
-               super();
-               drawit(len);
-               
-       }
-       public void drawit(int len)
-       {
-               for(int i = 0; i < len ;i++)
-               {
-                       graphicBuffer.add(lx.hsb(0,255,255));
-               }
-       }
-};
-
-class RedsGranim extends Granim
-{
-       RedsGranim()
-       {
-               super();
-               addGraphic("myreds", new RedsGraphic(10));
-       }
-       RedsGranim(int len)
-       {
-               super();
-               addGraphic("myreds", new RedsGraphic(len));
-       }
-       public float count = 0.0f;
-       public void update()
-       {
-               Graphic g=getGraphicByName("myreds");
-               g.position = Math.round(sin(count)*20)+100;
-               count+= 0.1f;
-               if(count>Math.PI*2)
-               {
-                       count=0;
-               }
-               super.update();
-       }
-       
-};
-
-class RandomsGranim extends Granim
-{
-       private int _len =0 ;
-       RandomsGranim()
-       {
-               super();
-               _len =100;
-               addGraphic("myrandoms", makeGraphic(_len));
-       }
-       RandomsGranim(int len)
-       {
-               super();
-               _len=len;
-               addGraphic("myrandoms", makeGraphic(len));
-       }
-       int colorLid=0;
-       public Graphic makeGraphic(int len)
-       {
-
-               int[] colors= new int[len]; 
-               for(int i =0;i<len;i++)
-               {
-                       colors[i]=(int) Math.round(Math.random()*80)+colorLid;
-                       
-               }
-               colorLid+=4;
-               return new ColorDotsGraphic(colors);
-       }
-       private int count =1;
-       private int instanceCount =0;
-       public void update()
-       {
-               
-               if(instanceCount<90 && count % 20==0)
-               {
-                       instanceCount++;
-                       Graphic h=addGraphic("myrandoms_"+instanceCount, makeGraphic(_len));
-                       h.position = instanceCount*(_len+100);
-                       //println("one more " + instanceCount+" at "+h.position);
-                       count=0;
-                       changed = true;
-               }
-               count++;
-               super.update();
-       }
-       
-};
-
-
-class ColorDotsGraphic extends Graphic
-{
-       ColorDotsGraphic(int[] colorSequence)
-       {
-               super();
-               for (int colorVal : colorSequence)
-               {
-                       graphicBuffer.add(lx.hsb(colorVal, 255, 255));
-               }
-               changed = true;
-       }
-};
-int BLACK = 0xff000000;
-
-class Gimbal extends SCPattern {
-
-  private final boolean DEBUG_MANUAL_ABG = false;
-  private final int MAXIMUM_BEATS_PER_REVOLUTION = 100;
-  
-  private boolean first_run = true;
-  private final Projection projection;
-  private final BasicParameter beatsPerRevolutionParam = new BasicParameter("SLOW", 20.f/MAXIMUM_BEATS_PER_REVOLUTION);
-  private final BasicParameter hueDeltaParam = new BasicParameter("HUED", 60.f/360);
-  private final BasicParameter fadeFromCoreParam = new BasicParameter("FADE", 1);
-  private final BasicParameter girthParam = new BasicParameter("GRTH", .18f);
-  private final BasicParameter ringExtendParam = new BasicParameter("XTND", 1);
-  private final BasicParameter relativeSpeedParam = new BasicParameter("RLSP", .83f);
-  private final BasicParameter sizeParam = new BasicParameter("SIZE", .9f);
-
-  private final BasicParameter aP = new BasicParameter("a", 0);
-  private final BasicParameter bP = new BasicParameter("b", 0);
-  private final BasicParameter gP = new BasicParameter("g", 0);
-
-  Gimbal(GLucose glucose) {
-    super(glucose);
-    projection = new Projection(model);
-    addParameter(beatsPerRevolutionParam);
-    addParameter(hueDeltaParam);
-    addParameter(fadeFromCoreParam);
-    addParameter(girthParam);
-    addParameter(ringExtendParam);
-    addParameter(relativeSpeedParam);
-    addParameter(sizeParam);
-    
-    if (DEBUG_MANUAL_ABG) {
-      addParameter(aP);
-      addParameter(bP);
-      addParameter(gP);
-    }
-  }
-
-  float a = 0, b = 0, g = 0;
-
-  public void run(double deltaMs) {
-
-    if (DEBUG_MANUAL_ABG) {
-      a = aP.getValuef() * (2 * PI); 
-      b = bP.getValuef() * (2 * PI);
-      g = gP.getValuef() * (2 * PI);
-    } else {
-      float relativeSpeed = relativeSpeedParam.getValuef();
-      float time = millis() / 1000.f;
-      
-      int beatsPerRevolution = (int) (beatsPerRevolutionParam.getValuef() * MAXIMUM_BEATS_PER_REVOLUTION) + 1;
-      float radiansPerMs = 2 * PI             // radians / revolution
-                         / beatsPerRevolution // beats / revolution
-                         * lx.tempo.bpmf()    // BPM beats / min
-                         / 60                 // sec / min
-                         / 1000;              // ms / sec
-      
-      a += deltaMs * radiansPerMs * pow(relativeSpeed, 0);
-      b += deltaMs * radiansPerMs * pow(relativeSpeed, 1);
-      g += deltaMs * radiansPerMs * pow(relativeSpeed, 2);
-      a %= 2 * PI;
-      b %= 2 * PI;
-      g %= 2 * PI;
-    }
-
-    float hue = lx.getBaseHuef();
-    float hue_delta = hueDeltaParam.getValuef() * 360;
-    
-    float radius1 = model.xMax / 2 * sizeParam.getValuef();
-    float radius2 = ((model.xMax + model.yMax) / 2) / 2 * sizeParam.getValuef();
-    float radius3 = model.yMax / 2 * sizeParam.getValuef();
-    float girth = model.xMax * girthParam.getValuef();
-    Ring ring1 = new Ring((hue + hue_delta * 0) % 360, radius1, girth);
-    Ring ring2 = new Ring((hue + hue_delta * 1) % 360, radius2, girth);
-    Ring ring3 = new Ring((hue + hue_delta * 2) % 360, radius3, girth);
-
-    projection.reset(model)
-      // Translate so the center of the car is the origin
-      .translateCenter(model, 0, 0, 0);
-
-    for (Coord c : projection) {
-      //if (first_run) println(c.x + "," + c.y + "," + c.z);
-
-      rotate3d(c, a, 0, 0);
-      rotate3d(c, PI/4, PI/4, PI/4);
-      int color1 = ring1.colorFor(c);
-
-      rotate3d(c, 0, b, 0);
-      int color2 = ring2.colorFor(c);
-
-      rotate3d(c, 0, 0, g);
-      int color3 = ring3.colorFor(c);
-            
-      colors[c.index] = specialBlend(color1, color2, color3);      
-    }
-
-    first_run = false;
-  }
-
-  class Ring {
-
-    float hue;
-    float radius, girth;
-
-    public Ring(float hue, float radius, float girth) {
-      this.hue = hue;
-      this.radius = radius;
-      this.girth = girth;
-    }
-
-    public int colorFor(Coord c) {
-      float theta = atan2(c.y, c.x);
-      float nearest_circle_x = cos(theta) * radius;
-      float nearest_circle_y = sin(theta) * radius;
-      float nearest_circle_z = 0;
-
-      float distance_to_circle
-          = sqrt(pow(nearest_circle_x - c.x, 2)
-               + pow(nearest_circle_y - c.y, 2)
-               + pow(nearest_circle_z - c.z * ringExtendParam.getValuef(), 2));
-
-      float xy_distance = sqrt(c.x*c.x + c.y*c.y);
-      return lx.hsb(this.hue, 100, (1 - distance_to_circle / girth * fadeFromCoreParam.getValuef()) * 100);
-    }
-
-  }
-
-}
-
-
-
-
-
-
-class Zebra extends SCPattern {
-
-  private final Projection projection;
-  SinLFO angleM = new SinLFO(0, PI * 2, 30000);
-
-/*
-  SinLFO x, y, z, dx, dy, dz;
-  float cRad;
-  _P size;
-  */
-
-  Zebra(GLucose glucose) {
-    super(glucose);
-    projection = new Projection(model);
-
-    addModulator(angleM).trigger();
-  }
-
-  public int colorFor(Coord c) {
-    float hue = lx.getBaseHuef();
-
-
-
-
-/* SLIDE ALONG
-    c.x = c.x + millis() / 100.f;
-    */
-
-
-
-    int stripe_count = 12;
-    float stripe_width = model.xMax / (float)stripe_count;
-    if (Math.floor((c.x) / stripe_width) % 2 == 0) {
-      return lx.hsb(hue, 100, 100);
-    } else {
-      return lx.hsb((hue + 90) % 360, 100, 100);
-    }
-
-
-    /* OCTANTS
-
-    if ((isPositiveBit(c.x) + isPositiveBit(c.y) + isPositiveBit(c.z)) % 2 == 0) {
-      return lx.hsb(lx.getBaseHuef(), 100, 100);
-    } else {
-      return lx.hsb(0, 0, 0);
-    }
-    */
-  }
-
-  public int isPositiveBit(float f) {
-    return f > 0 ? 1 : 0;
-  }
-
-  public void run(double deltaMs) {
-    float a = (millis() / 1000.f) % (2 * PI);
-    float b = (millis() / 1200.f) % (2 * PI);
-    float g = (millis() / 1600.f) % (2 * PI);
-
-    projection.reset(model)
-      // Translate so the center of the car is the origin
-      .translateCenter(model, 0, 0, 0);
-
-    for (Coord c : projection) {
-//      rotate3d(c, a, b, g);
-      colors[c.index] = colorFor(c);
-    }
-
-    first_run = false;
-  }
-
-
-  // Utility!
-  boolean first_run = true;
-  private void log(String s) {
-    if (first_run) {
-      println(s);
-    }
-  }
-
-
-}
-
-public void rotate3d(Coord c, float a /* roll */, float b /* pitch */, float g /* yaw */) {
-  float cosa = cos(a);
-  float cosb = cos(b);
-  float cosg = cos(g);
-  float sina = sin(a);
-  float sinb = sin(b);
-  float sing = sin(g);
-
-  float a1 = cosa*cosb;
-  float a2 = cosa*sinb*sing - sina*cosg;
-  float a3 = cosa*sinb*cosg + sina*sing;
-  float b1 = sina*cosb;
-  float b2 = sina*sinb*sing + cosa*cosg;
-  float b3 = sina*sinb*cosg - cosa*sing;
-  float c1 = -sinb;
-  float c2 = cosb*sing;
-  float c3 = cosb*cosg;
-
-  float[] cArray = { c.x, c.y, c.z };
-  c.x = dotProduct(new float[] {a1, a2, a3}, cArray);
-  c.y = dotProduct(new float[] {b1, b2, b3}, cArray);
-  c.z = dotProduct(new float[] {c1, c2, c3}, cArray);
-}
-
-public float dotProduct(float[] a, float[] b) {
-  float ret = 0;
-  for (int i = 0 ; i < a.length; ++i) {
-    ret += a[i] * b[i];
-  }
-  return ret;
-}
-
-public int specialBlend(int c1, int c2, int c3) {
-  float h1 = hue(c1);
-  float h2 = hue(c2); 
-  float h3 = hue(c3);
-  
-  // force h1 < h2 < h3
-  while (h2 < h1) {
-    h2 += 360;
-  }
-  while (h3 < h2) {
-    h3 += 360;
-  }
-
-  float s1 = saturation(c1); 
-  float s2 = saturation(c2); 
-  float s3 = saturation(c3);
-  
-  float b1 = brightness(c1); 
-  float b2 = brightness(c2);
-  float b3 = brightness(c3);
-  float relative_b1 = b1 / (b1 + b2 + b3);
-  float relative_b2 = b2 / (b1 + b2 + b3);
-  float relative_b3 = b3 / (b1 + b2 + b3);
-  
-  return lx.hsb(
-    (h1 * relative_b1 + h2 * relative_b1 + h3 * relative_b3) % 360,
-     s1 * relative_b1 + s2 * relative_b2 + s3 * relative_b3,
-     max(max(b1, b2), b3)
-  );
-}
-
-/**
- * A Projection of sin wave in 3d space. 
- * It sort of looks like an animal swiming around in water.
- * Angle sliders are sort of a work in progress that allow yo to change the crazy ways it moves around.
- * Hue slider allows you to control how different the colors are along the wave. 
- *
- * This code copied heavily from Tim and Slee.
- */
-class Swim extends SCPattern {
-
-  // Projection stuff
-  private final Projection projection;
-  SawLFO rotation = new SawLFO(0, TWO_PI, 19000);
-  SinLFO yPos = new SinLFO(-25, 25, 12323);
-  final BasicParameter xAngle = new BasicParameter("XANG", 0.9f);
-  final BasicParameter yAngle = new BasicParameter("YANG", 0.3f);
-  final BasicParameter zAngle = new BasicParameter("ZANG", 0.3f);
-
-  final BasicParameter hueScale = new BasicParameter("HUE", 0.3f);
-
-  public Swim(GLucose glucose) {
-    super(glucose);
-    projection = new Projection(model);
-
-    addParameter(xAngle);
-    addParameter(yAngle);
-    addParameter(zAngle);
-    addParameter(hueScale);
-
-    addModulator(rotation).trigger();
-    addModulator(yPos).trigger();
-  }
-
-
-  int beat = 0;
-  float prevRamp = 0;
-  public void run(double deltaMs) {
-
-    // Sync to the beat
-    float ramp = (float)lx.tempo.ramp();
-    if (ramp < prevRamp) {
-      beat = (beat + 1) % 4;
-    }
-    prevRamp = ramp;
-    float phase = (beat+ramp) / 2.0f * 2 * PI;
-
-    float denominator = max(xAngle.getValuef() + yAngle.getValuef() + zAngle.getValuef(), 1);
-
-    projection.reset(model)
-      // Swim around the world
-      .rotate(rotation.getValuef(), xAngle.getValuef() / denominator, yAngle.getValuef() / denominator, zAngle.getValuef() / denominator)
-        .translateCenter(model, 0, 50 + yPos.getValuef(), 0);
-
-    float model_height =  model.yMax - model.yMin;
-    float model_width =  model.xMax - model.xMin;
-    for (Coord p : projection) {
-      float x_percentage = (p.x - model.xMin)/model_width;
-
-      // Multiply by 1.4 to shrink the size of the sin wave to be less than the height of the cubes.
-      float y_in_range = 1.4f * (2*p.y - model.yMax - model.yMin) / model_height;
-      float sin_x =  sin(phase + 2 * PI * x_percentage);       
-
-      // Color fade near the top of the sin wave
-      float v1 = sin_x > y_in_range  ? (100 + 100*(y_in_range - sin_x)) : 0;     
-
-      float hue_color = (lx.getBaseHuef() + hueScale.getValuef() * (abs(p.x-model.xMax/2.f)*.3f + abs(p.y-model.yMax/2)*.9f + abs(p.z - model.zMax/2.f))) % 360;
-      colors[p.index] = lx.hsb(hue_color, 70, v1);
-    }
-  }
-}
-
-/** 
- * The idea here is to do another sin wave pattern, but with less rotation and more of a breathing / heartbeat affect with spheres above / below the wave.
- * This is not done.
- */
-class Balance extends SCPattern {
-
-  final BasicParameter hueScale = new BasicParameter("Hue", 0.4f);
-
-  class Sphere {
-    float x, y, z;
-  }
-
-
-  // Projection stuff
-  private final Projection projection;
-
-  SinLFO sphere1Z = new SinLFO(0, 0, 15323);
-  SinLFO sphere2Z = new SinLFO(0, 0, 8323);
-  SinLFO rotationX = new SinLFO(-PI/32, PI/32, 9000);
-  SinLFO rotationY = new SinLFO(-PI/16, PI/16, 7000);
-  SinLFO rotationZ = new SinLFO(-PI/16, PI/16, 11000);
-  SawLFO phaseLFO = new SawLFO(0, 2 * PI, 5000 - 4500 * 0.5f);
-  final BasicParameter phaseParam = new BasicParameter("Spd", 0.5f);
-  final BasicParameter crazyParam = new BasicParameter("Crzy", 0.2f);
-
-
-  private final Sphere[] spheres;
-  private final float centerX, centerY, centerZ, modelHeight, modelWidth, modelDepth;
-  SinLFO heightMod = new SinLFO(0.8f, 1.9f, 17298);
-
-  public Balance(GLucose glucose) {
-    super(glucose);
-
-    projection = new Projection(model);
-
-    addParameter(hueScale);
-    addParameter(phaseParam);
-    addParameter(crazyParam);
-
-    spheres = new Sphere[2];
-    centerX = (model.xMax + model.xMin) / 2;
-    centerY = (model.yMax + model.yMin) / 2;
-    centerZ = (model.zMax + model.zMin) / 2;
-    modelHeight = model.yMax - model.yMin;
-    modelWidth = model.xMax - model.xMin;
-    modelDepth = model.zMax - model.zMin;
-
-    spheres[0] = new Sphere();
-    spheres[0].x = 1*modelWidth/2 + model.xMin;
-    spheres[0].y = centerY + 20;
-    spheres[0].z = centerZ;
-
-    spheres[1] = new Sphere();
-    spheres[1].x = model.xMin;
-    spheres[1].y = centerY - 20;
-    spheres[1].z = centerZ;
-
-    addModulator(rotationX).trigger();
-    addModulator(rotationY).trigger();
-    addModulator(rotationZ).trigger();
-
-
-    addModulator(sphere1Z).trigger();
-    addModulator(sphere2Z).trigger();
-    addModulator(phaseLFO).trigger();
-
-    addModulator(heightMod).trigger();
-  }
-
-  public void onParameterChanged(LXParameter parameter) {
-    if (parameter == phaseParam) {
-      phaseLFO.setDuration(5000 - 4500 * parameter.getValuef());
-    }
-  }
-
-  int beat = 0;
-  float prevRamp = 0;
-  public void run(double deltaMs) {
-
-    // Sync to the beat
-    float ramp = (float)lx.tempo.ramp();
-    if (ramp < prevRamp) {
-      beat = (beat + 1) % 4;
-    }
-    prevRamp = ramp;
-    float phase = phaseLFO.getValuef();
-
-    float crazy_factor = crazyParam.getValuef() / 0.2f;
-    projection.reset(model)
-      .rotate(rotationZ.getValuef() * crazy_factor,  0, 1, 0)
-        .rotate(rotationX.getValuef() * crazy_factor, 0, 0, 1)
-          .rotate(rotationY.getValuef() * crazy_factor, 0, 1, 0);
-
-    for (Coord p : projection) {
-      float x_percentage = (p.x - model.xMin)/modelWidth;
-
-      float y_in_range = heightMod.getValuef() * (2*p.y - model.yMax - model.yMin) / modelHeight;
-      float sin_x =  sin(PI / 2 + phase + 2 * PI * x_percentage);       
-
-      // Color fade near the top of the sin wave
-      float v1 = max(0, 100 * (1 - 4*abs(sin_x - y_in_range)));     
-
-      float hue_color = (lx.getBaseHuef() + hueScale.getValuef() * (abs(p.x-model.xMax/2.f) + abs(p.y-model.yMax/2)*.2f + abs(p.z - model.zMax/2.f)*.5f)) % 360;
-      int c = lx.hsb(hue_color, 80, v1);
-
-      // Now draw the spheres
-      for (Sphere s : spheres) {
-        float phase_x = (s.x - phase / (2 * PI) * modelWidth) % modelWidth;    
-        float x_dist = LXUtils.wrapdistf(p.x, phase_x, modelWidth);
-
-        float sphere_z = (s == spheres[0]) ? (s.z + sphere1Z.getValuef()) : (s.z - sphere2Z.getValuef()); 
-
-
-        float d = sqrt(pow(x_dist, 2) + pow(p.y - s.y, 2) + pow(p.z - sphere_z, 2));
-
-        float distance_from_beat =  (beat % 2 == 1) ? 1 - ramp : ramp;
-
-        min(ramp, 1-ramp);
-
-        float r = 40 - pow(distance_from_beat, 0.75f) * 20;
-
-        float distance_value = max(0, 1 - max(0, d - r) / 10);
-        float beat_value = 1.0f;
-
-        float value = min(beat_value, distance_value);
-
-        float sphere_color = (lx.getBaseHuef() - (1 - hueScale.getValuef()) * d/r * 45) % 360;
-
-        c = blendColor(c, lx.hsb((sphere_color + 270) % 360, 60, min(1, value) * 100), ADD);
-      }
-      colors[p.index] = c;
-    }
-  }
-}
-class Cathedrals extends SCPattern {
-  
-  private final BasicParameter xpos = new BasicParameter("XPOS", 0.5f);
-  private final BasicParameter wid = new BasicParameter("WID", 0.5f);
-  private final BasicParameter arms = new BasicParameter("ARMS", 0.5f);
-  private final BasicParameter sat = new BasicParameter("SAT", 0.5f);
-  private GraphicEQ eq;
-  
-  Cathedrals(GLucose glucose) {
-    super(glucose);
-    addParameter(xpos);
-    addParameter(wid);
-    addParameter(arms);
-    addParameter(sat);
-  }
-  protected void onActive() {
-    if (eq == null) {
-      eq = new GraphicEQ(lx, 16);
-      eq.slope.setValue(0.7f);
-      eq.range.setValue(0.4f);
-      eq.attack.setValue(0.4f);
-      eq.release.setValue(0.4f);
-      addParameter(eq.level);
-      addParameter(eq.range);
-      addParameter(eq.attack);
-      addParameter(eq.release);
-      addParameter(eq.slope);
-    }
-  }
-
-  public void run(double deltaMs) {
-    eq.run(deltaMs);
-    float bassLevel = eq.getAverageLevel(0, 4);
-    float trebleLevel = eq.getAverageLevel(8, 6);
-    
-    float falloff = 100 / (2 + 14*wid.getValuef());
-    float cx = model.xMin + (model.xMax-model.xMin) * xpos.getValuef();
-    float barm = 12 + 60*arms.getValuef()*max(0, 2*(bassLevel-0.1f));
-    float tarm = 12 + 60*arms.getValuef()*max(0, 2*(trebleLevel-0.1f));
-    
-    float arm = 0;
-    float middle = 0;
-    
-    float sf = 100.f / (70 - 69.9f*sat.getValuef());
-
-    for (Point p : model.points) {
-      float d = MAX_FLOAT;
-      if (p.y > model.cy) {
-        arm = tarm;
-        middle = model.yMax * 3/5.f;
-      } else {
-        arm = barm;
-        middle = model.yMax * 1/5.f;
-      }
-      if (abs(p.x - cx) < arm) {
-        d = min(abs(p.x - cx), abs(p.y - middle));
-      }
-      colors[p.index] = color(
-        (lx.getBaseHuef() + .2f*abs(p.y - model.cy)) % 360,
-        min(100, sf*dist(abs(p.x - cx), p.y, arm, middle)),
-        max(0, 120 - d*falloff));
-    }
-  } 
-}
-  
-class MidiMusic extends SCPattern {
-  
-  private final Stack<LXLayer> newLayers = new Stack<LXLayer>();
-  
-  private final Map<Integer, LightUp> lightMap = new HashMap<Integer, LightUp>();
-  private final List<LightUp> lights = new ArrayList<LightUp>();
-  private final BasicParameter lightSize = new BasicParameter("SIZE", 0.5f);
-
-  private final List<Sweep> sweeps = new ArrayList<Sweep>();
-
-  private final LinearEnvelope sparkle = new LinearEnvelope(0, 1, 500);
-  private boolean sparkleDirection = true;
-  private float sparkleBright = 100;
-  
-  private final BasicParameter wave = new BasicParameter("WAVE", 0);
-  
-  MidiMusic(GLucose glucose) {
-    super(glucose);
-    addParameter(lightSize);
-    addParameter(wave);
-    addModulator(sparkle).setValue(1);
-  }
-  
-  public void onReset() {
-    for (LightUp light : lights) {
-      light.noteOff(null);
-    }
-  }
-  
-  class Sweep extends LXLayer {
-    
-    final LinearEnvelope position = new LinearEnvelope(0, 1, 1000);
-    float bright = 100;
-    float falloff = 10;
-    
-    Sweep() {
-      addModulator(position);
-    }
-    
-    public void run(double deltaMs, int[] colors) {
-      if (!position.isRunning()) {
-        return;
-      }
-      float posf = position.getValuef();
-      for (Point p : model.points) {
-        colors[p.index] = blendColor(colors[p.index], color(
-          (lx.getBaseHuef() + .2f*abs(p.x - model.cx) + .2f*abs(p.y - model.cy)) % 360,
-          100,
-          max(0, bright - posf*100 - falloff*abs(p.y - posf*model.yMax))
-        ), ADD);
-      }
-    }
-  }
-  
-  class LightUp extends LXLayer {
-    
-    private final LinearEnvelope brt = new LinearEnvelope(0, 0, 0);
-    private final Accelerator yPos = new Accelerator(0, 0, 0);
-    private float xPos;
-    
-    LightUp() {
-      addModulator(brt);
-      addModulator(yPos);
-    }
-    
-    public boolean isAvailable() {
-      return brt.getValuef() <= 0;
-    }
-    
-    public void noteOn(Note note) {
-      xPos = lerp(0, model.xMax, constrain(0.5f + (note.getPitch() - 60) / 28.f, 0, 1));
-      yPos.setValue(lerp(20, model.yMax*.72f, note.getVelocity() / 127.f)).stop();
-      brt.setRangeFromHereTo(lerp(40, 100, note.getVelocity() / 127.f), 20).start();     
-    }
-
-    public void noteOff(Note note) {
-      yPos.setVelocity(0).setAcceleration(-380).start();
-      brt.setRangeFromHereTo(0, 1000).start();
-    }
-    
-    public void run(double deltaMs, int[] colors) {
-      float bVal = brt.getValuef();
-      if (bVal <= 0) {
-        return;
-      }
-      float yVal = yPos.getValuef();
-      for (Point p : model.points) {
-        float falloff = 6 - 5*lightSize.getValuef();
-        float b = max(0, bVal - falloff*dist(p.x, p.y, xPos, yVal));
-        if (b > 0) {
-          colors[p.index] = blendColor(colors[p.index], lx.hsb(
-            (lx.getBaseHuef() + .2f*abs(p.x - model.cx) + .2f*abs(p.y - model.cy)) % 360,
-            100,
-            b
-          ), ADD);
-        }
-      }
-    }
-  }
-  
-  private LightUp getLight() {
-    for (LightUp light : lights) {
-      if (light.isAvailable()) {
-        return light;
-      }
-    }
-    LightUp newLight = new LightUp();
-    lights.add(newLight);
-    synchronized(newLayers) {
-      newLayers.push(newLight);
-    }
-    return newLight;
-  }
-  
-  private Sweep getSweep() {
-    for (Sweep s : sweeps) {
-      if (!s.position.isRunning()) {
-        return s;
-      }
-    }
-    Sweep newSweep = new Sweep();
-    sweeps.add(newSweep);
-    synchronized(newLayers) {
-      newLayers.push(newSweep);
-    }
-    return newSweep;
-  }
-  
-  public synchronized boolean noteOn(Note note) {
-    if (note.getChannel() == 0) {
-      LightUp light = getLight();
-      lightMap.put(note.getPitch(), light);
-      light.noteOn(note);
-    } else if (note.getChannel() == 1) {
-    } else if (note.getChannel() == 9) {
-      if (note.getVelocity() > 0) {
-        switch (note.getPitch()) {
-          case 36:
-            Sweep s = getSweep();
-            s.bright = 50 + note.getVelocity() / 127.f * 50;
-            s.falloff = 20 - note.getVelocity() / 127.f * 17;
-            s.position.trigger();
-            break;
-          case 37:
-            sparkleBright = note.getVelocity() / 127.f * 100;
-            sparkleDirection = true;
-            sparkle.trigger();
-            break;
-          case 38:
-            sparkleBright = note.getVelocity() / 127.f * 100;
-            sparkleDirection = false;
-            sparkle.trigger();       
-            break;
-          case 39:
-            effects.boom.trigger();
-            break;
-          case 40:
-            effects.flash.trigger();
-            break;
-        }
-      }
-    }
-    return true;
-  }
-  
-  public synchronized boolean noteOff(Note note) {
-    if (note.getChannel() == 0) {
-      LightUp light = lightMap.get(note.getPitch());
-      if (light != null) {
-        light.noteOff(note);
-      }
-    }
-    return true;
-  }
-  
-  final float[] wval = new float[16];
-  float wavoff = 0;
-  
-  public synchronized void run(double deltaMs) {
-    wavoff += deltaMs * .001f;
-    for (int i = 0; i < wval.length; ++i) {
-      wval[i] = model.cy + 0.2f * model.yMax/2.f * sin(wavoff + i / 1.9f);
-    }
-    float sparklePos = (sparkleDirection ? sparkle.getValuef() : (1 - sparkle.getValuef())) * (Cube.POINTS_PER_STRIP)/2.f;
-    float maxBright = sparkleBright * (1 - sparkle.getValuef());
-    for (Strip s : model.strips) {
-      int i = 0;
-      for (Point p : s.points) {
-        int wavi = (int) constrain(p.x / model.xMax * wval.length, 0, wval.length-1);
-        float wavb = max(0, wave.getValuef()*100.f - 8.f*abs(p.y - wval[wavi]));
-        colors[p.index] = color(
-          (lx.getBaseHuef() + .2f*abs(p.x - model.cx) + .2f*abs(p.y - model.cy)) % 360,
-          100,
-          constrain(wavb + max(0, maxBright - 40.f*abs(sparklePos - abs(i - (Cube.POINTS_PER_STRIP-1)/2.f))), 0, 100)
-        );
-        ++i;
-      }
-    }
-        
-    if (!newLayers.isEmpty()) {
-      synchronized(newLayers) {
-        while (!newLayers.isEmpty()) {
-          addLayer(newLayers.pop());
-        }
-      }
-    }
-  }
-}
-
-class Pulley extends SCPattern {
-  
-  final int NUM_DIVISIONS = 16;
-  private final Accelerator[] gravity = new Accelerator[NUM_DIVISIONS];
-  private final Click[] delays = new Click[NUM_DIVISIONS];
-  
-  private final Click reset = new Click(9000);
-  private boolean isRising = false;
-  
-  private BasicParameter sz = new BasicParameter("SIZE", 0.5f);
-  private BasicParameter beatAmount = new BasicParameter("BEAT", 0);
-  
-  Pulley(GLucose glucose) {
-    super(glucose);
-    for (int i = 0; i < NUM_DIVISIONS; ++i) {
-      addModulator(gravity[i] = new Accelerator(0, 0, 0));
-      addModulator(delays[i] = new Click(0));
-    }
-    addModulator(reset).start();
-    addParameter(sz);
-    addParameter(beatAmount);
-    trigger();
-
-  }
-  
-  private void trigger() {
-    isRising = !isRising;
-    int i = 0;
-    for (Accelerator g : gravity) {
-      if (isRising) {
-        g.setSpeed(random(20, 33), 0).start();
-      } else {
-        g.setVelocity(0).setAcceleration(-420);
-        delays[i].setDuration(random(0, 500)).trigger();
-      }
-      ++i;
-    }
-  }
-  
-  public void run(double deltaMs) {
-    if (reset.click()) {
-      trigger();
-    }
-        
-    if (isRising) {
-      // Fucking A, had to comment this all out because of that bizarre
-      // Processing bug where some simple loop takes an absurd amount of
-      // time, must be some pre-processor bug
-//      for (Accelerator g : gravity) {
-//        if (g.getValuef() > model.yMax) {
-//          g.stop();
-//        } else if (g.getValuef() > model.yMax*.55) {
-//          if (g.getVelocityf() > 10) {
-//            g.setAcceleration(-16);
-//          } else {
-//            g.setAcceleration(0);
-//          }
-//        }
-//      }
-    } else {
-      int j = 0;
-      for (Click d : delays) {
-        if (d.click()) {
-          gravity[j].start();
-          d.stop();
-        }
-        ++j;
-      }
-      for (Accelerator g : gravity) {
-        if (g.getValuef() < 0) {
-          g.setValue(-g.getValuef());
-          g.setVelocity(-g.getVelocityf() * random(0.74f, 0.84f));
-        }
-      }
-    }
-
-    // A little silliness to test the grid API    
-    if (midiEngine != null && midiEngine.getFocusedPattern() == this) {
-           for (int i = 0; i < 5; ++i) {
-        for (int j = 0; j < 8; ++j) {
-          int gi = (int) constrain(j * NUM_DIVISIONS / 8, 0, NUM_DIVISIONS-1);
-          float b = 1 - 4.f*abs((6-i)/6.f - gravity[gi].getValuef() / model.yMax);
-          midiEngine.grid.setState(i, j, (b < 0) ? 0 : 3);
-        }
-      }
-    }
-    
-    float fPos = 1 - lx.tempo.rampf();
-    if (fPos < .2f) {
-      fPos = .2f + 4 * (.2f - fPos);
-    }
-    float falloff = 100.f / (3 + sz.getValuef() * 36 + fPos * beatAmount.getValuef()*48);
-    for (Point p : model.points) {
-      int gi = (int) constrain((p.x - model.xMin) * NUM_DIVISIONS / (model.xMax - model.xMin), 0, NUM_DIVISIONS-1);
-      colors[p.index] = lx.hsb(
-        (lx.getBaseHuef() + abs(p.x - model.cx)*.8f + p.y*.4f) % 360,
-        constrain(130 - p.y*.8f, 0, 100),
-        max(0, 100 - abs(p.y - gravity[gi].getValuef())*falloff)
-      );
-    }
-  }
-}
-
-class ViolinWave extends SCPattern {
-  
-  BasicParameter level = new BasicParameter("LVL", 0.45f);
-  BasicParameter range = new BasicParameter("RNG", 0.5f);
-  BasicParameter edge = new BasicParameter("EDG", 0.5f);
-  BasicParameter release = new BasicParameter("RLS", 0.5f);
-  BasicParameter speed = new BasicParameter("SPD", 0.5f);
-  BasicParameter amp = new BasicParameter("AMP", 0.25f);
-  BasicParameter period = new BasicParameter("WAVE", 0.5f);
-  BasicParameter pSize = new BasicParameter("PSIZE", 0.5f);
-  BasicParameter pSpeed = new BasicParameter("PSPD", 0.5f);
-  BasicParameter pDensity = new BasicParameter("PDENS", 0.25f);
-  
-  LinearEnvelope dbValue = new LinearEnvelope(0, 0, 10);
-
-  ViolinWave(GLucose glucose) {
-    super(glucose);
-    addParameter(level);
-    addParameter(edge);
-    addParameter(range);
-    addParameter(release);
-    addParameter(speed);
-    addParameter(amp);
-    addParameter(period);
-    addParameter(pSize);
-    addParameter(pSpeed);
-    addParameter(pDensity);
-
-    addModulator(dbValue);
-  }
-  
-  final List<Particle> particles = new ArrayList<Particle>();
-  
-  class Particle {
-    
-    LinearEnvelope x = new LinearEnvelope(0, 0, 0);
-    LinearEnvelope y = new LinearEnvelope(0, 0, 0);
-    
-    Particle() {
-      addModulator(x);
-      addModulator(y);
-    }
-    
-    public Particle trigger(boolean direction) {
-      float xInit = random(model.xMin, model.xMax);
-      float time = 3000 - 2500*pSpeed.getValuef();
-      x.setRange(xInit, xInit + random(-40, 40), time).trigger();
-      y.setRange(model.cy + 10, direction ? model.yMax + 50 : model.yMin - 50, time).trigger();
-      return this;
-    }
-    
-    public boolean isActive() {
-      return x.isRunning() || y.isRunning();
-    }
-    
-    public void run(double deltaMs) {
-      if (!isActive()) {
-        return;
-      }
-      
-      float pFalloff = (30 - 27*pSize.getValuef());
-      for (Point p : model.points) {
-        float b = 100 - pFalloff * (abs(p.x - x.getValuef()) + abs(p.y - y.getValuef()));
-        if (b > 0) {
-          colors[p.index] = blendColor(colors[p.index], lx.hsb(
-            lx.getBaseHuef(), 20, b
-          ), ADD);
-        }
-      }
-    }
-  }
-  
-  float[] centers = new float[30];
-  double accum = 0;
-  boolean rising = true;
-  
-  public void fireParticle(boolean direction) {
-    boolean gotOne = false;
-    for (Particle p : particles) {
-      if (!p.isActive()) {
-       p.trigger(direction);
-       return;
-      }
-    }
-    particles.add(new Particle().trigger(direction));
-  }
-  
-  public void run(double deltaMs) {
-    accum += deltaMs / (1000.f - 900.f*speed.getValuef());
-    for (int i = 0; i < centers.length; ++i) {
-      centers[i] = model.cy + 30*amp.getValuef()*sin((float) (accum + (i-centers.length/2.f)/(1.f + 9.f*period.getValuef())));
-    }
-    
-    float zeroDBReference = pow(10, (50 - 190*level.getValuef())/20.f);
-    float dB = 20*GraphicEQ.log10(lx.audioInput().mix.level() / zeroDBReference);
-    if (dB > dbValue.getValuef()) {
-      rising = true;
-      dbValue.setRangeFromHereTo(dB, 10).trigger();
-    } else {
-      if (rising) {
-        for (int j = 0; j < pDensity.getValuef()*3; ++j) {
-          fireParticle(true);
-          fireParticle(false);
-        }
-      }
-      rising = false;
-      dbValue.setRangeFromHereTo(max(dB, -96), 50 + 1000*release.getValuef()).trigger();
-    }
-    float edg = 1 + edge.getValuef() * 40;
-    float rng = (78 - 64 * range.getValuef()) / (model.yMax - model.cy);
-    float val = max(2, dbValue.getValuef());
-    
-    for (Point p : model.points) {
-      int ci = (int) lerp(0, centers.length-1, (p.x - model.xMin) / (model.xMax - model.xMin));
-      float rFactor = 1.0f -  0.9f * abs(p.x - model.cx) / (model.xMax - model.cx);
-      colors[p.index] = lx.hsb(
-        (lx.getBaseHuef() + abs(p.x - model.cx)) % 360,
-        min(100, 20 + 8*abs(p.y - centers[ci])),
-        constrain(edg*(val*rFactor - rng * abs(p.y-centers[ci])), 0, 100)
-      );
-    }
-    
-    for (Particle p : particles) {
-      p.run(deltaMs);
-    }
-  }
-}
-
-class BouncyBalls extends SCPattern {
-  
-  static final int NUM_BALLS = 6;
-  
-  class BouncyBall {
-       
-    Accelerator yPos;
-    TriangleLFO xPos = new TriangleLFO(0, model.xMax, random(8000, 19000));
-    float zPos;
-    
-    BouncyBall(int i) {
-      addModulator(xPos.setBasis(random(0, TWO_PI)).start());
-      addModulator(yPos = new Accelerator(0, 0, 0));
-      zPos = lerp(model.zMin, model.zMax, (i+2.f) / (NUM_BALLS + 4.f));
-    }
-    
-    public void bounce(float midiVel) {
-      float v = 100 + 8*midiVel;
-      yPos.setSpeed(v, getAccel(v, 60 / lx.tempo.bpmf())).start();
-    }
-    
-    public float getAccel(float v, float oneBeat) {
-      return -2*v / oneBeat;
-    }
-    
-    public void run(double deltaMs) {
-      float flrLevel = flr.getValuef() * model.xMax/2.f;
-      if (yPos.getValuef() < flrLevel) {
-        if (yPos.getVelocity() < -50) {
-          yPos.setValue(2*flrLevel-yPos.getValuef());
-          float v = -yPos.getVelocityf() * bounce.getValuef();
-          yPos.setSpeed(v, getAccel(v, 60 / lx.tempo.bpmf()));
-        } else {
-          yPos.setValue(flrLevel).stop();
-        }
-      }
-      float falloff = 130.f / (12 + blobSize.getValuef() * 36);
-      float xv = xPos.getValuef();
-      float yv = yPos.getValuef();
-      
-      for (Point p : model.points) {
-        float d = sqrt((p.x-xv)*(p.x-xv) + (p.y-yv)*(p.y-yv) + .1f*(p.z-zPos)*(p.z-zPos));
-        float b = constrain(130 - falloff*d, 0, 100);
-        if (b > 0) {
-          colors[p.index] = blendColor(colors[p.index], lx.hsb(
-            (lx.getBaseHuef() + p.y*.5f + abs(model.cx - p.x) * .5f) % 360,
-            max(0, 100 - .45f*(p.y - flrLevel)),
-            b
-          ), ADD);
-        }
-      }
-    }
-  }
-  
-  final BouncyBall[] balls = new BouncyBall[NUM_BALLS];
-  
-  final BasicParameter bounce = new BasicParameter("BNC", .8f);
-  final BasicParameter flr = new BasicParameter("FLR", 0);
-  final BasicParameter blobSize = new BasicParameter("SIZE", 0.5f);
-  
-  BouncyBalls(GLucose glucose) {
-    super(glucose);
-    for (int i = 0; i < balls.length; ++i) {
-      balls[i] = new BouncyBall(i);
-    }
-    addParameter(bounce);
-    addParameter(flr);
-    addParameter(blobSize);
-  }
-  
-  public void run(double deltaMs) {
-    setColors(0xff000000);
-    for (BouncyBall b : balls) {
-      b.run(deltaMs);
-    }
-  }
-  
-  public boolean noteOn(Note note) {
-    int pitch = (note.getPitch() + note.getChannel()) % NUM_BALLS;
-    balls[pitch].bounce(note.getVelocity());
-    return true;
-  }
-}
-
-class SpaceTime extends SCPattern {
-
-  SinLFO pos = new SinLFO(0, 1, 3000);
-  SinLFO rate = new SinLFO(1000, 9000, 13000);
-  SinLFO falloff = new SinLFO(10, 70, 5000);
-  float angle = 0;
-
-  BasicParameter rateParameter = new BasicParameter("RATE", 0.5f);
-  BasicParameter sizeParameter = new BasicParameter("SIZE", 0.5f);
-
-
-  public SpaceTime(GLucose glucose) {
-    super(glucose);
-    
-    addModulator(pos).trigger();
-    addModulator(rate).trigger();
-    addModulator(falloff).trigger();    
-    pos.modulateDurationBy(rate);
-    addParameter(rateParameter);
-    addParameter(sizeParameter);
-  }
-
-  public void onParameterChanged(LXParameter parameter) {
-    if (parameter == rateParameter) {
-      rate.stop().setValue(9000 - 8000*parameter.getValuef());
-    }  else if (parameter == sizeParameter) {
-      falloff.stop().setValue(70 - 60*parameter.getValuef());
-    }
-  }
-
-  public void run(double deltaMs) {    
-    angle += deltaMs * 0.0007f;
-    float sVal1 = model.strips.size() * (0.5f + 0.5f*sin(angle));
-    float sVal2 = model.strips.size() * (0.5f + 0.5f*cos(angle));
-
-    float pVal = pos.getValuef();
-    float fVal = falloff.getValuef();
-
-    int s = 0;
-    for (Strip strip : model.strips) {
-      int i = 0;
-      for (Point p : strip.points) {
-        colors[p.index] = lx.hsb(
-          (lx.getBaseHuef() + 360 - p.x*.2f + p.y * .3f) % 360, 
-          constrain(.4f * min(abs(s - sVal1), abs(s - sVal2)), 20, 100),
-          max(0, 100 - fVal*abs(i - pVal*(strip.metrics.numPoints - 1)))
-        );
-        ++i;
-      }
-      ++s;
-    }
-  }
-}
-
-class Swarm extends SCPattern {
-  
-  SawLFO offset = new SawLFO(0, 1, 1000);
-  SinLFO rate = new SinLFO(350, 1200, 63000);
-  SinLFO falloff = new SinLFO(15, 50, 17000);
-  SinLFO fX = new SinLFO(0, model.xMax, 19000);
-  SinLFO fY = new SinLFO(0, model.yMax, 11000);
-  SinLFO hOffX = new SinLFO(0, model.xMax, 13000);
-
-  public Swarm(GLucose glucose) {
-    super(glucose);
-    
-    addModulator(offset).trigger();
-    addModulator(rate).trigger();
-    addModulator(falloff).trigger();
-    addModulator(fX).trigger();
-    addModulator(fY).trigger();
-    addModulator(hOffX).trigger();
-    offset.modulateDurationBy(rate);
-  }
-
-  public float modDist(float v1, float v2, float mod) {
-    v1 = v1 % mod;
-    v2 = v2 % mod;
-    if (v2 > v1) {
-      return min(v2-v1, v1+mod-v2);
-    } 
-    else {
-      return min(v1-v2, v2+mod-v1);
-    }
-  }
-
-  public void run(double deltaMs) {
-    float s = 0;
-    for (Strip strip : model.strips  ) {
-      int i = 0;
-      for (Point p : strip.points) {
-        float fV = max(-1, 1 - dist(p.x/2.f, p.y, fX.getValuef()/2.f, fY.getValuef()) / 64.f);
-        colors[p.index] = lx.hsb(
-        (lx.getBaseHuef() + 0.3f * abs(p.x - hOffX.getValuef())) % 360, 
-        constrain(80 + 40 * fV, 0, 100), 
-        constrain(100 - (30 - fV * falloff.getValuef()) * modDist(i + (s*63)%61, offset.getValuef() * strip.metrics.numPoints, strip.metrics.numPoints), 0, 100)
-          );
-        ++i;
-      }
-      ++s;
-    }
-  }
-}
-
-class SwipeTransition extends SCTransition {
-  
-  final BasicParameter bleed = new BasicParameter("WIDTH", 0.5f);
-  
-  SwipeTransition(GLucose glucose) {
-    super(glucose);
-    setDuration(5000);
-    addParameter(bleed);
-  }
-
-  public void computeBlend(int[] c1, int[] c2, double progress) {
-    float bleedf = 10 + bleed.getValuef() * 200.f;
-    float xPos = (float) (-bleedf + progress * (model.xMax + bleedf));
-    for (Point p : model.points) {
-      float d = (p.x - xPos) / bleedf;
-      if (d < 0) {
-        colors[p.index] = c2[p.index];
-      } else if (d > 1) {
-        colors[p.index] = c1[p.index];
-      } else {
-        colors[p.index] = lerpColor(c2[p.index], c1[p.index], d, RGB);
-      }
-    }
-  }
-}
-
-abstract class BlendTransition extends SCTransition {
-  
-  final int blendType;
-  
-  BlendTransition(GLucose glucose, int blendType) {
-    super(glucose);
-    this.blendType = blendType;
-  }
-
-  public void computeBlend(int[] c1, int[] c2, double progress) {
-    if (progress < 0.5f) {
-      for (int i = 0; i < c1.length; ++i) {
-        colors[i] = lerpColor(
-          c1[i],
-          blendColor(c1[i], c2[i], blendType),
-          (float) (2.f*progress),
-          RGB);
-      }
-    } else {
-      for (int i = 0; i < c1.length; ++i) {
-        colors[i] = lerpColor(
-          c2[i],
-          blendColor(c1[i], c2[i], blendType),
-          (float) (2.f*(1.f - progress)),
-          RGB);
-      }
-    }
-  }
-}
-
-class MultiplyTransition extends BlendTransition {
-  MultiplyTransition(GLucose glucose) {
-    super(glucose, MULTIPLY);
-  }
-}
-
-class ScreenTransition extends BlendTransition {
-  ScreenTransition(GLucose glucose) {
-    super(glucose, SCREEN);
-  }
-}
-
-class BurnTransition extends BlendTransition {
-  BurnTransition(GLucose glucose) {
-    super(glucose, BURN);
-  }
-}
-
-class DodgeTransition extends BlendTransition {
-  DodgeTransition(GLucose glucose) {
-    super(glucose, DODGE);
-  }
-}
-
-class OverlayTransition extends BlendTransition {
-  OverlayTransition(GLucose glucose) {
-    super(glucose, OVERLAY);
-  }
-}
-
-class AddTransition extends BlendTransition {
-  AddTransition(GLucose glucose) {
-    super(glucose, ADD);
-  }
-}
-
-class SubtractTransition extends BlendTransition {
-  SubtractTransition(GLucose glucose) {
-    super(glucose, SUBTRACT);
-  }
-}
-
-class SoftLightTransition extends BlendTransition {
-  SoftLightTransition(GLucose glucose) {
-    super(glucose, SOFT_LIGHT);
-  }
-}
-
-class BassPod extends SCPattern {
-
-  private GraphicEQ eq = null;
-  
-  private final BasicParameter clr = new BasicParameter("CLR", 0.5f);
-  
-  public BassPod(GLucose glucose) {
-    super(glucose);
-    addParameter(clr);
-  }
-  
-  protected void onActive() {
-    if (eq == null) {
-      eq = new GraphicEQ(lx, 16);
-      eq.range.setValue(0.4f);
-      eq.level.setValue(0.4f);
-      eq.slope.setValue(0.6f);
-      addParameter(eq.level);
-      addParameter(eq.range);
-      addParameter(eq.attack);
-      addParameter(eq.release);
-      addParameter(eq.slope);
-    }
-  }
-
-  public void run(double deltaMs) {
-    eq.run(deltaMs);
-    
-    float bassLevel = eq.getAverageLevel(0, 5);
-    
-    float satBase = bassLevel*480*clr.getValuef();
-    
-    for (Point p : model.points) {
-      int avgIndex = (int) constrain(1 + abs(p.x-model.cx)/(model.cx)*(eq.numBands-5), 0, eq.numBands-5);
-      float value = 0;
-      for (int i = avgIndex; i < avgIndex + 5; ++i) {
-        value += eq.getLevel(i);
-      }
-      value /= 5.f;
-
-      float b = constrain(8 * (value*model.yMax - abs(p.y-model.yMax/2.f)), 0, 100);
-      colors[p.index] = lx.hsb(
-        (lx.getBaseHuef() + abs(p.y - model.cy) + abs(p.x - model.cx)) % 360,
-        constrain(satBase - .6f*dist(p.x, p.y, model.cx, model.cy), 0, 100),
-        b
-      );
-    }
-  }
-}
-
-
-class CubeEQ extends SCPattern {
-
-  private GraphicEQ eq = null;
-
-  private final BasicParameter edge = new BasicParameter("EDGE", 0.5f);
-  private final BasicParameter clr = new BasicParameter("CLR", 0.5f);
-  private final BasicParameter blockiness = new BasicParameter("BLK", 0.5f);
-
-  public CubeEQ(GLucose glucose) {
-    super(glucose);
-  }
-
-  protected void onActive() {
-    if (eq == null) {
-      eq = new GraphicEQ(lx, 16);
-      addParameter(eq.level);
-      addParameter(eq.range);
-      addParameter(eq.attack);
-      addParameter(eq.release);
-      addParameter(eq.slope);
-      addParameter(edge);
-      addParameter(clr);
-      addParameter(blockiness);
-    }
-  }
-
-  public void run(double deltaMs) {
-    eq.run(deltaMs);
-
-    float edgeConst = 2 + 30*edge.getValuef();
-    float clrConst = 1.1f + clr.getValuef();
-
-    for (Point p : model.points) {
-      float avgIndex = constrain(2 + p.x / model.xMax * (eq.numBands-4), 0, eq.numBands-4);
-      int avgFloor = (int) avgIndex;
-
-      float leftVal = eq.getLevel(avgFloor);
-      float rightVal = eq.getLevel(avgFloor+1);
-      float smoothValue = lerp(leftVal, rightVal, avgIndex-avgFloor);
-      
-      float chunkyValue = (
-        eq.getLevel(avgFloor/4*4) +
-        eq.getLevel(avgFloor/4*4 + 1) +
-        eq.getLevel(avgFloor/4*4 + 2) +
-        eq.getLevel(avgFloor/4*4 + 3)
-      ) / 4.f; 
-      
-      float value = lerp(smoothValue, chunkyValue, blockiness.getValuef());
-
-      float b = constrain(edgeConst * (value*model.yMax - p.y), 0, 100);
-      colors[p.index] = lx.hsb(
-        (480 + lx.getBaseHuef() - min(clrConst*p.y, 120)) % 360, 
-        100, 
-        b
-      );
-    }
-  }
-}
-
-class BoomEffect extends SCEffect {
-
-  final BasicParameter falloff = new BasicParameter("WIDTH", 0.5f);
-  final BasicParameter speed = new BasicParameter("SPD", 0.5f);
-  final BasicParameter bright = new BasicParameter("BRT", 1.0f);
-  final BasicParameter sat = new BasicParameter("SAT", 0.2f);
-  List<Layer> layers = new ArrayList<Layer>();
-  final float maxr = sqrt(model.xMax*model.xMax + model.yMax*model.yMax + model.zMax*model.zMax) + 10;
-
-  class Layer {
-    LinearEnvelope boom = new LinearEnvelope(-40, 500, 1300);
-
-    Layer() {
-      addModulator(boom);
-      trigger();
-    }
-
-    public void trigger() {
-      float falloffv = falloffv();
-      boom.setRange(-100 / falloffv, maxr + 100/falloffv, 4000 - speed.getValuef() * 3300);
-      boom.trigger();
-    }
-
-    public void apply(int[] colors) {
-      float brightv = 100 * bright.getValuef();
-      float falloffv = falloffv();
-      float satv = sat.getValuef() * 100;
-      float huev = lx.getBaseHuef();
-      for (Point p : model.points) {
-        colors[p.index] = blendColor(
-        colors[p.index], 
-        lx.hsb(huev, satv, constrain(brightv - falloffv*abs(boom.getValuef() - dist(p.x, 2*p.y, 3*p.z, model.xMax/2, model.yMax, model.zMax*1.5f)), 0, 100)), 
-        ADD);
-      }
-    }
-  }
-
-  BoomEffect(GLucose glucose) {
-    super(glucose, true);
-    addParameter(falloff);
-    addParameter(speed);
-    addParameter(bright);
-    addParameter(sat);
-  }
-
-  public void onEnable() {
-    for (Layer l : layers) {
-      if (!l.boom.isRunning()) {
-        l.trigger();
-        return;
-      }
-    }
-    layers.add(new Layer());
-  }
-
-  private float falloffv() {
-    return 20 - 19 * falloff.getValuef();
-  }
-
-  public void onTrigger() {
-    onEnable();
-  }
-
-  public void apply(int[] colors) {
-    for (Layer l : layers) {
-      if (l.boom.isRunning()) {
-        l.apply(colors);
-      }
-    }
-  }
-}
-
-public class PianoKeyPattern extends SCPattern {
-  
-  final LinearEnvelope[] cubeBrt;
-  final SinLFO base[];  
-  final BasicParameter attack = new BasicParameter("ATK", 0.1f);
-  final BasicParameter release = new BasicParameter("REL", 0.5f);
-  final BasicParameter level = new BasicParameter("AMB", 0.6f);
-  
-  PianoKeyPattern(GLucose glucose) {
-    super(glucose);
-        
-    addParameter(attack);
-    addParameter(release);
-    addParameter(level);
-    cubeBrt = new LinearEnvelope[model.cubes.size() / 4];
-    for (int i = 0; i < cubeBrt.length; ++i) {
-      addModulator(cubeBrt[i] = new LinearEnvelope(0, 0, 100));
-    }
-    base = new SinLFO[model.cubes.size() / 12];
-    for (int i = 0; i < base.length; ++i) {
-      addModulator(base[i] = new SinLFO(0, 1, 7000 + 1000*i)).trigger();
-    }
-  }
-  
-  private float getAttackTime() {
-    return 15 + attack.getValuef()*attack.getValuef() * 2000;
-  }
-  
-  private float getReleaseTime() {
-    return 15 + release.getValuef() * 3000;
-  }
-  
-  private LinearEnvelope getEnvelope(int index) {
-    return cubeBrt[index % cubeBrt.length];
-  }
-  
-  private SinLFO getBase(int index) {
-    return base[index % base.length];
-  }
-    
-  public boolean noteOn(Note note) {
-    LinearEnvelope env = getEnvelope(note.getPitch());
-    env.setEndVal(min(1, env.getValuef() + (note.getVelocity() / 127.f)), getAttackTime()).start();
-    return true;
-  }
-  
-  public boolean noteOff(Note note) {
-    getEnvelope(note.getPitch()).setEndVal(0, getReleaseTime()).start();
-    return true;
-  }
-  
-  public void run(double deltaMs) {
-    int i = 0;
-    float huef = lx.getBaseHuef();
-    float levelf = level.getValuef();
-    for (Cube c : model.cubes) {
-      float v = max(getBase(i).getValuef() * levelf/4.f, getEnvelope(i++).getValuef());
-      setColor(c, lx.hsb(
-        (huef + 20*v + abs(c.cx-model.xMax/2.f)*.3f + c.cy) % 360,
-        min(100, 120*v),
-        100*v
-      ));
-    }
-  }
-}
-
-class CrossSections extends SCPattern {
-  
-  final SinLFO x = new SinLFO(0, model.xMax, 5000);
-  final SinLFO y = new SinLFO(0, model.yMax, 6000);
-  final SinLFO z = new SinLFO(0, model.zMax, 7000);
-  
-  final BasicParameter xw = new BasicParameter("XWID", 0.3f);
-  final BasicParameter yw = new BasicParameter("YWID", 0.3f);
-  final BasicParameter zw = new BasicParameter("ZWID", 0.3f);  
-  final BasicParameter xr = new BasicParameter("XRAT", 0.7f);
-  final BasicParameter yr = new BasicParameter("YRAT", 0.6f);
-  final BasicParameter zr = new BasicParameter("ZRAT", 0.5f);
-  final BasicParameter xl = new BasicParameter("XLEV", 1);
-  final BasicParameter yl = new BasicParameter("YLEV", 1);
-  final BasicParameter zl = new BasicParameter("ZLEV", 0.5f);
-
-  
-  CrossSections(GLucose glucose) {
-    super(glucose);
-    addModulator(x).trigger();
-    addModulator(y).trigger();
-    addModulator(z).trigger();
-    addParams();
-  }
-  
-  protected void addParams() {
-    addParameter(xr);
-    addParameter(yr);
-    addParameter(zr);    
-    addParameter(xw);
-    addParameter(xl);
-    addParameter(yl);
-    addParameter(zl);
-    addParameter(yw);    
-    addParameter(zw);
-  }
-  
-  public void onParameterChanged(LXParameter p) {
-    if (p == xr) {
-      x.setDuration(10000 - 8800*p.getValuef());
-    } else if (p == yr) {
-      y.setDuration(10000 - 9000*p.getValuef());
-    } else if (p == zr) {
-      z.setDuration(10000 - 9000*p.getValuef());
-    }
-  }
-  
-  float xv, yv, zv;
-  
-  protected void updateXYZVals() {
-    xv = x.getValuef();
-    yv = y.getValuef();
-    zv = z.getValuef();    
-  }
-
-  public void run(double deltaMs) {
-    updateXYZVals();
-    
-    float xlv = 100*xl.getValuef();
-    float ylv = 100*yl.getValuef();
-    float zlv = 100*zl.getValuef();
-    
-    float xwv = 100.f / (10 + 40*xw.getValuef());
-    float ywv = 100.f / (10 + 40*yw.getValuef());
-    float zwv = 100.f / (10 + 40*zw.getValuef());
-    
-    for (Point p : model.points) {
-      int c = 0;
-      c = blendColor(c, lx.hsb(
-      (lx.getBaseHuef() + p.x/10 + p.y/3) % 360, 
-      constrain(140 - 1.1f*abs(p.x - model.xMax/2.f), 0, 100), 
-      max(0, xlv - xwv*abs(p.x - xv))
-        ), ADD);
-      c = blendColor(c, lx.hsb(
-      (lx.getBaseHuef() + 80 + p.y/10) % 360, 
-      constrain(140 - 2.2f*abs(p.y - model.yMax/2.f), 0, 100), 
-      max(0, ylv - ywv*abs(p.y - yv))
-        ), ADD); 
-      c = blendColor(c, lx.hsb(
-      (lx.getBaseHuef() + 160 + p.z / 10 + p.y/2) % 360, 
-      constrain(140 - 2.2f*abs(p.z - model.zMax/2.f), 0, 100), 
-      max(0, zlv - zwv*abs(p.z - zv))
-        ), ADD); 
-      colors[p.index] = c;
-    }
-  }
-}
-
-class Blinders extends SCPattern {
-    
-  final SinLFO[] m;
-  final TriangleLFO r;
-  final SinLFO s;
-  final TriangleLFO hs;
-
-  public Blinders(GLucose glucose) {
-    super(glucose);
-    m = new SinLFO[12];
-    for (int i = 0; i < m.length; ++i) {  
-      addModulator(m[i] = new SinLFO(0.5f, 120, (120000.f / (3+i)))).trigger();
-    }
-    addModulator(r = new TriangleLFO(9000, 15000, 29000)).trigger();
-    addModulator(s = new SinLFO(-20, 275, 11000)).trigger();
-    addModulator(hs = new TriangleLFO(0.1f, 0.5f, 15000)).trigger();
-    s.modulateDurationBy(r);
-  }
-
-  public void run(double deltaMs) {
-    float hv = lx.getBaseHuef();
-    int si = 0;
-    for (Strip strip : model.strips) {
-      int i = 0;
-      float mv = m[si % m.length].getValuef();
-      for (Point p : strip.points) {
-        colors[p.index] = lx.hsb(
-          (hv + p.z + p.y*hs.getValuef()) % 360, 
-          min(100, abs(p.x - s.getValuef())/2.f), 
-          max(0, 100 - mv/2.f - mv * abs(i - (strip.metrics.length-1)/2.f))
-        );
-        ++i;
-      }
-      ++si;
-    }
-  }
-}
-
-class Psychedelia extends SCPattern {
-  
-  final int NUM = 3;
-  SinLFO m = new SinLFO(-0.5f, NUM-0.5f, 9000);
-  SinLFO s = new SinLFO(-20, 147, 11000);
-  TriangleLFO h = new TriangleLFO(0, 240, 19000);
-  SinLFO c = new SinLFO(-.2f, .8f, 31000);
-
-  Psychedelia(GLucose glucose) {
-    super(glucose);
-    addModulator(m).trigger();
-    addModulator(s).trigger();
-    addModulator(h).trigger();
-    addModulator(c).trigger();
-  }
-
-  public void run(double deltaMs) {
-    float huev = h.getValuef();
-    float cv = c.getValuef();
-    float sv = s.getValuef();
-    float mv = m.getValuef();
-    int i = 0;
-    for (Strip strip : model.strips) {
-      for (Point p : strip.points) {
-        colors[p.index] = lx.hsb(
-          (huev + i*constrain(cv, 0, 2) + p.z/2.f + p.x/4.f) % 360, 
-          min(100, abs(p.y-sv)), 
-          max(0, 100 - 50*abs((i%NUM) - mv))
-        );
-      }
-      ++i;
-    }
-  }
-}
-
-class AskewPlanes extends SCPattern {
-  
-  class Plane {
-    private final SinLFO a;
-    private final SinLFO b;
-    private final SinLFO c;
-    float av = 1;
-    float bv = 1;
-    float cv = 1;
-    float denom = 0.1f;
-    
-    Plane(int i) {
-      addModulator(a = new SinLFO(-1, 1, 4000 + 1029*i)).trigger();
-      addModulator(b = new SinLFO(-1, 1, 11000 - 1104*i)).trigger();
-      addModulator(c = new SinLFO(-50, 50, 4000 + 1000*i * ((i % 2 == 0) ? 1 : -1))).trigger();      
-    }
-    
-    public void run(double deltaMs) {
-      av = a.getValuef();
-      bv = b.getValuef();
-      cv = c.getValuef();
-      denom = sqrt(av*av + bv*bv);
-    }
-  }
-    
-  final Plane[] planes;
-  final int NUM_PLANES = 3;
-  
-  AskewPlanes(GLucose glucose) {
-    super(glucose);
-    planes = new Plane[NUM_PLANES];
-    for (int i = 0; i < planes.length; ++i) {
-      planes[i] = new Plane(i);
-    }
-  }
-  
-  public void run(double deltaMs) {
-    float huev = lx.getBaseHuef();
-    
-    // This is super fucking bizarre. But if this is a for loop, the framerate
-    // tanks to like 30FPS, instead of 60. Call them manually and it works fine.
-    // Doesn't make ANY sense... there must be some weird side effect going on
-    // with the Processing internals perhaps?
-//    for (Plane plane : planes) {
-//      plane.run(deltaMs);
-//    }
-    planes[0].run(deltaMs);
-    planes[1].run(deltaMs);
-    planes[2].run(deltaMs);    
-    
-    for (Point p : model.points) {
-      float d = MAX_FLOAT;
-      for (Plane plane : planes) {
-        if (plane.denom != 0) {
-          d = min(d, abs(plane.av*(p.x-model.cx) + plane.bv*(p.y-model.cy) + plane.cv) / plane.denom);
-        }
-      }
-      colors[p.index] = lx.hsb(
-        (huev + abs(p.x-model.cx)*.3f + p.y*.8f) % 360,
-        max(0, 100 - .8f*abs(p.x - model.cx)),
-        constrain(140 - 10.f*d, 0, 100)
-      );
-    }
-  }
-}
-
-class ShiftingPlane extends SCPattern {
-
-  final SinLFO a = new SinLFO(-.2f, .2f, 5300);
-  final SinLFO b = new SinLFO(1, -1, 13300);
-  final SinLFO c = new SinLFO(-1.4f, 1.4f, 5700);
-  final SinLFO d = new SinLFO(-10, 10, 9500);
-
-  ShiftingPlane(GLucose glucose) {
-    super(glucose);
-    addModulator(a).trigger();
-    addModulator(b).trigger();
-    addModulator(c).trigger();
-    addModulator(d).trigger();    
-  }
-  
-  public void run(double deltaMs) {
-    float hv = lx.getBaseHuef();
-    float av = a.getValuef();
-    float bv = b.getValuef();
-    float cv = c.getValuef();
-    float dv = d.getValuef();    
-    float denom = sqrt(av*av + bv*bv + cv*cv);
-    for (Point p : model.points) {
-      float d = abs(av*(p.x-model.cx) + bv*(p.y-model.cy) + cv*(p.z-model.cz) + dv) / denom;
-      colors[p.index] = lx.hsb(
-        (hv + abs(p.x-model.cx)*.6f + abs(p.y-model.cy)*.9f + abs(p.z - model.cz)) % 360,
-        constrain(110 - d*6, 0, 100),
-        constrain(130 - 7*d, 0, 100)
-      );
-    }
-  }
-}
-
-class Traktor extends SCPattern {
-
-  final int FRAME_WIDTH = 60;
-  
-  final BasicParameter speed = new BasicParameter("SPD", 0.5f);
-  
-  private float[] bass = new float[FRAME_WIDTH];
-  private float[] treble = new float[FRAME_WIDTH];
-    
-  private int index = 0;
-  private GraphicEQ eq = null;
-
-  public Traktor(GLucose glucose) {
-    super(glucose);
-    for (int i = 0; i < FRAME_WIDTH; ++i) {
-      bass[i] = 0;
-      treble[i] = 0;
-    }
-    addParameter(speed);
-  }
-
-  public void onActive() {
-    if (eq == null) {
-      eq = new GraphicEQ(lx, 16);
-      eq.slope.setValue(0.6f);
-      eq.level.setValue(0.65f);
-      eq.range.setValue(0.35f);
-      eq.release.setValue(0.4f);
-      addParameter(eq.level);
-      addParameter(eq.range);
-      addParameter(eq.attack);
-      addParameter(eq.release);
-      addParameter(eq.slope);
-    }
-  }
-
-  int counter = 0;
-  
-  public void run(double deltaMs) {
-    eq.run(deltaMs);
-    
-    int stepThresh = (int) (40 - 39*speed.getValuef());
-    counter += deltaMs;
-    if (counter < stepThresh) {
-      return;
-    }
-    counter = counter % stepThresh;
-
-    index = (index + 1) % FRAME_WIDTH;
-    
-    float rawBass = eq.getAverageLevel(0, 4);
-    float rawTreble = eq.getAverageLevel(eq.numBands-7, 7);
-    
-    bass[index] = rawBass * rawBass * rawBass * rawBass;
-    treble[index] = rawTreble * rawTreble;
-
-    for (Point p : model.points) {
-      int i = (int) constrain((model.xMax - p.x) / model.xMax * FRAME_WIDTH, 0, FRAME_WIDTH-1);
-      int pos = (index + FRAME_WIDTH - i) % FRAME_WIDTH;
-      
-      colors[p.index] = lx.hsb(
-        (360 + lx.getBaseHuef() + .8f*abs(p.x-model.cx)) % 360,
-        100,
-        constrain(9 * (bass[pos]*model.cy - abs(p.y - model.cy + 5)), 0, 100)
-      );
-      colors[p.index] = blendColor(colors[p.index], lx.hsb(
-        (400 + lx.getBaseHuef() + .5f*abs(p.x-model.cx)) % 360,
-        60,
-        constrain(5 * (treble[pos]*.6f*model.cy - abs(p.y - model.cy)), 0, 100)
-
-      ), ADD);
-    }
-  }
-}
-
-class ColorFuckerEffect extends SCEffect {
-  
-  final BasicParameter level = new BasicParameter("BRT", 1);
-  final BasicParameter desat = new BasicParameter("DSAT", 0);
-  final BasicParameter hueShift = new BasicParameter("HSHFT", 0);
-  final BasicParameter sharp = new BasicParameter("SHARP", 0);
-  final BasicParameter soft = new BasicParameter("SOFT", 0);
-  final BasicParameter mono = new BasicParameter("MONO", 0);
-  final BasicParameter invert = new BasicParameter("INVERT", 0);
-
-  
-  float[] hsb = new float[3];
-  
-  ColorFuckerEffect(GLucose glucose) {
-    super(glucose);
-    addParameter(level);
-    addParameter(desat);
-    addParameter(sharp);
-    addParameter(hueShift);
-    addParameter(soft);
-    addParameter(mono);
-    addParameter(invert);
-  }
-  
-  public void apply(int[] colors) {
-    if (!enabled) {
-      return;
-    }
-    float bMod = level.getValuef();
-    float sMod = 1 - desat.getValuef();
-    float hMod = hueShift.getValuef();
-    float fSharp = 1/(1.0001f-sharp.getValuef());
-    float fSoft = soft.getValuef();
-    boolean mon = mono.getValuef() > 0.5f;
-    boolean ivt = invert.getValuef() > 0.5f;
-    if (bMod < 1 || sMod < 1 || hMod > 0 || fSharp > 0 || ivt || mon || fSoft > 0) {
-      for (int i = 0; i < colors.length; ++i) {
-        lx.RGBtoHSB(colors[i], hsb);
-        if (mon) {
-          hsb[0] = lx.getBaseHuef() / 360.f;
-        }
-        if (ivt) {
-          hsb[2] = 1 - hsb[2];
-        }
-        if (fSharp > 0) {
-          hsb[2] = hsb[2] < .5f ? pow(hsb[2],fSharp) : 1-pow(1-hsb[2],fSharp);
-        }
-        if (fSoft > 0) {
-          if (hsb[2] > 0.5f) {
-            hsb[2] = lerp(hsb[2], 0.5f + 2 * (hsb[2]-0.5f)*(hsb[2]-0.5f), fSoft);
-          } else {
-            hsb[2] = lerp(hsb[2], 0.5f * sqrt(2*hsb[2]), fSoft);
-          }
-        }
-        colors[i] = lx.hsb(
-          (360.f * hsb[0] + hMod*360.f) % 360,
-          100.f * hsb[1] * sMod,
-          100.f * hsb[2] * bMod
-        );
-      }
-    }
-  }
-}
-
-class QuantizeEffect extends SCEffect {
-  
-  int[] quantizedFrame;
-  float lastQuant;
-  final BasicParameter amount = new BasicParameter("AMT", 0);
-  
-  QuantizeEffect(GLucose glucose) {
-    super(glucose);
-    quantizedFrame = new int[glucose.lx.total];
-    lastQuant = 0;
-  } 
-  
-  public void apply(int[] colors) {
-    float fQuant = amount.getValuef();
-    if (fQuant > 0) {
-      float tRamp = (lx.tempo.rampf() % (1.f/pow(2,floor((1-fQuant) * 4))));
-      float f = lastQuant;
-      lastQuant = tRamp;
-      if (tRamp > f) {
-        for (int i = 0; i < colors.length; ++i) {
-          colors[i] = quantizedFrame[i];
-        }
-        return;
-      }
-    }
-    for (int i = 0; i < colors.length; ++i) {
-      quantizedFrame[i] = colors[i];
-    }
-  }
-}
-
-class BlurEffect extends SCEffect {
-  
-  final LXParameter amount = new BasicParameter("AMT", 0);
-  final int[] frame;
-  final LinearEnvelope env = new LinearEnvelope(0, 1, 100);
-  
-  BlurEffect(GLucose glucose) {
-    super(glucose);
-    addParameter(amount);
-    addModulator(env);
-    frame = new int[lx.total];
-    for (int i = 0; i < frame.length; ++i) {
-      frame[i] = 0xff000000;
-    }
-  }
-  
-  public void onEnable() {
-    env.setRangeFromHereTo(1, 400).start();
-    for (int i = 0; i < frame.length; ++i) {
-      frame[i] = 0xff000000;
-    }
-  }
-  
-  public void onDisable() {
-    env.setRangeFromHereTo(0, 1000).start();
-  }
-  
-  public void apply(int[] colors) {
-    float amt = env.getValuef() * amount.getValuef();
-    if (amt > 0) {    
-      amt = (1 - amt);
-      amt = 1 - (amt*amt*amt);
-      for (int i = 0; i < colors.length; ++i) {
-        // frame[i] = colors[i] = blendColor(colors[i], lerpColor(#000000, frame[i], amt, RGB), SCREEN);
-        frame[i] = colors[i] = lerpColor(colors[i], blendColor(colors[i], frame[i], SCREEN), amt, RGB);
-      }
-    }
-      
-  }  
-}
-abstract class SamPattern extends SCPattern {
-  public SamPattern(GLucose glucose) {
-    super(glucose);
-    setEligible(false);
-  }
-}
-
-class JazzRainbow extends SamPattern {
-  public JazzRainbow(GLucose glucose) {
-    super(glucose);
-  }
-
-  
-  public void run(double deltaMs) {
-    // Access the core master hue via this method call
-    float hv = lx.getBaseHuef();
-    for (int i = 0; i < colors.length*5; i=i+27) {
-      float a = hv%250;
-      if (i%2 == 0) {
-        for (int b = 0; b < 70; b++) {
-         colors[(i+b)%colors.length] = lx.hsb(a+i%250, 100, b*a%100);
-        }
-      }
-    }
-  } 
-}
-
-
-
-class HelixPattern extends SCPattern {
-
-  // Stores a line in point + vector form
-  private class Line {
-    private final PVector origin;
-    private final PVector vector;
-
-    Line(PVector pt, PVector v) {
-      origin = pt;
-      vector = v.get();
-      vector.normalize();
-    }
-
-    public PVector getPoint() {
-      return origin;
-    }
-
-    public PVector getVector() {
-      return vector;
-    }
-
-    public PVector getPointAt(final float t) {
-      return PVector.add(origin, PVector.mult(vector, t));
-    }
-
-    public boolean isColinear(final PVector pt) {
-      PVector projected = projectPoint(pt);
-      return projected.x==pt.x && projected.y==pt.y && projected.z==pt.z;
-    }
-
-    public float getTValue(final PVector pt) {
-      PVector subtraction = PVector.sub(pt, origin);
-      return subtraction.dot(vector);
-    }
-
-    public PVector projectPoint(final PVector pt) {
-      return getPointAt(getTValue(pt));
-    }
-
-    public PVector rotatePoint(final PVector p, final float t) {
-      final PVector o = origin;
-      final PVector v = vector;
-      
-      final float cost = cos(t);
-      final float sint = sin(t);
-
-      float x = (o.x*(v.y*v.y + v.z*v.z) - v.x*(o.y*v.y + o.z*v.z - v.x*p.x - v.y*p.y - v.z*p.z))*(1 - cost) + p.x*cost + (-o.z*v.y + o.y*v.z - v.z*p.y + v.y*p.z)*sint;
-      float y = (o.y*(v.x*v.x + v.z*v.z) - v.y*(o.x*v.x + o.z*v.z - v.x*p.x - v.y*p.y - v.z*p.z))*(1 - cost) + p.y*cost + (o.z*v.x - o.x*v.z + v.z*p.x - v.x*p.z)*sint;
-      float z = (o.z*(v.x*v.x + v.y*v.y) - v.z*(o.x*v.x + o.y*v.y - v.x*p.x - v.y*p.y - v.z*p.z))*(1 - cost) + p.z*cost + (-o.y*v.x + o.x*v.y - v.y*p.x + v.x*p.y)*sint;
-      return new PVector(x, y, z);
-    }
-  }
-
-  private class Helix {
-    private final Line axis;
-    private final float period; // period of coil
-    private final float rotationPeriod; // animation period
-    private final float radius; // radius of coil
-    private final float girth; // girth of coil
-    private final PVector referencePoint;
-    private float phase;
-    private PVector phaseNormal;
-
-    Helix(Line axis, float period, float radius, float girth, float phase, float rotationPeriod) {
-      this.axis = axis;
-      this.period = period;
-      this.radius = radius;
-      this.girth = girth;
-      this.phase = phase;
-      this.rotationPeriod = rotationPeriod;
-
-      // Generate a normal that will rotate to
-      // produce the helical shape.
-      PVector pt = new PVector(0, 1, 0);
-      if (this.axis.isColinear(pt)) {
-        pt = new PVector(0, 0, 1);
-        if (this.axis.isColinear(pt)) {
-          pt = new PVector(0, 1, 1);
-        }
-      }
-
-      this.referencePoint = pt;
-
-      // The normal is calculated by the cross product of the axis
-      // and a random point that is not colinear with it.
-      phaseNormal = axis.getVector().cross(referencePoint);
-      phaseNormal.normalize();
-      phaseNormal.mult(radius);
-    }
-
-    public Line getAxis() {
-      return axis;
-    }
-    
-    public PVector getPhaseNormal() {
-      return phaseNormal;
-    }
-    
-    public float getPhase() {
-      return phase;
-    }
-
-    public void step(double deltaMs) {
-      // Rotate
-      if (rotationPeriod != 0) {
-        this.phase = (phase + ((float)deltaMs / (float)rotationPeriod) * TWO_PI);
-      }
-    }
-
-    public PVector pointOnToroidalAxis(float t) {
-      PVector p = axis.getPointAt(t);
-      PVector middle = PVector.add(p, phaseNormal);
-      return axis.rotatePoint(middle, (t / period) * TWO_PI + phase);
-    }
-    
-    private float myDist(PVector p1, PVector p2) {
-      final float x = p2.x-p1.x;
-      final float y = p2.y-p1.y;
-      final float z = p2.z-p1.z;
-      return sqrt(x*x + y*y + z*z);
-    }
-
-    public int colorOfPoint(final PVector p) {
-      final float t = axis.getTValue(p);
-      final PVector axisPoint = axis.getPointAt(t);
-
-      // For performance reasons, cut out points that are outside of
-      // the tube where the toroidal coil lives.
-      if (abs(myDist(p, axisPoint) - radius) > girth*.5f) {
-        return lx.hsb(0,0,0);
-      }
-
-      // Find the appropriate point for the current rotation
-      // of the helix.
-      PVector toroidPoint = axisPoint;
-      toroidPoint.add(phaseNormal);
-      toroidPoint = axis.rotatePoint(toroidPoint, (t / period) * TWO_PI + phase);
-
-      // The rotated point represents the middle of the girth of
-      // the helix.  Figure out if the current point is inside that
-      // region.
-      float d = myDist(p, toroidPoint);
-
-      // Soften edges by fading brightness.
-      float b = constrain(100*(1 - ((d-.5f*girth)/(girth*.5f))), 0, 100);
-      return lx.hsb((lx.getBaseHuef() + (360*(phase / TWO_PI)))%360, 80, b);
-    }
-  }
-  
-  private class BasePairInfo {
-    Line line;
-    float colorPhase1;
-    float colorPhase2;
-    
-    BasePairInfo(Line line, float colorPhase1, float colorPhase2) {
-      this.line = line;
-      this.colorPhase1 = colorPhase1;
-      this.colorPhase2 = colorPhase2;
-    }
-  }
-
-  private final Helix h1;
-  private final Helix h2;
-  private final BasePairInfo[] basePairs;
-
-  private final BasicParameter helix1On = new BasicParameter("H1ON", 1);
-  private final BasicParameter helix2On = new BasicParameter("H2ON", 1);
-  private final BasicParameter basePairsOn = new BasicParameter("BPON", 1);
-
-  private static final float helixCoilPeriod = 100;
-  private static final float helixCoilRadius = 50;
-  private static final float helixCoilGirth = 30;
-  private static final float helixCoilRotationPeriod = 5000;
-
-  private static final float spokePeriod = 40;
-  private static final float spokeGirth = 20;
-  private static final float spokePhase = 10;
-  private static final float spokeRadius = helixCoilRadius - helixCoilGirth*.5f;
-  
-  private static final float tMin = -200;
-  private static final float tMax = 200;
-
-  public HelixPattern(GLucose glucose) {
-    super(glucose);
-
-    addParameter(helix1On);
-    addParameter(helix2On);
-    addParameter(basePairsOn);
-
-    PVector origin = new PVector(100, 50, 55);
-    PVector axis = new PVector(1,0,0);
-
-    h1 = new Helix(
-      new Line(origin, axis),
-      helixCoilPeriod,
-      helixCoilRadius,
-      helixCoilGirth,
-      0,
-      helixCoilRotationPeriod);
-    h2 = new Helix(
-      new Line(origin, axis),
-      helixCoilPeriod,
-      helixCoilRadius,
-      helixCoilGirth,
-      PI,
-      helixCoilRotationPeriod);
-      
-    basePairs = new BasePairInfo[(int)floor((tMax - tMin)/spokePeriod)];
-  }
-
-  private void calculateSpokes() {
-    float colorPhase = PI/6;
-    for (float t = tMin + spokePhase; t < tMax; t += spokePeriod) {
-      int spokeIndex = (int)floor((t - tMin)/spokePeriod);
-      PVector h1point = h1.pointOnToroidalAxis(t);
-      PVector spokeCenter = h1.getAxis().getPointAt(t);
-      PVector spokeVector = PVector.sub(h1point, spokeCenter);
-      Line spokeLine = new Line(spokeCenter, spokeVector);
-      basePairs[spokeIndex] = new BasePairInfo(spokeLine, colorPhase * spokeIndex, colorPhase * (spokeIndex + 1));
-    }
-  }
-  
-  private int calculateSpokeColor(final PVector pt) {
-    // Find the closest spoke's t-value and calculate its
-    // axis.  Until everything animates in the model reference
-    // frame, this has to be calculated at every step because
-    // the helices rotate.
-    Line axis = h1.getAxis();
-    float t = axis.getTValue(pt) + spokePhase;
-    int spokeIndex = (int)floor((t - tMin + spokePeriod/2) / spokePeriod);
-    if (spokeIndex < 0 || spokeIndex >= basePairs.length) {
-      return lx.hsb(0,0,0);
-    }
-    BasePairInfo basePair = basePairs[spokeIndex];
-    Line spokeLine = basePair.line;
-    PVector pointOnSpoke = spokeLine.projectPoint(pt);
-    float d = PVector.dist(pt, pointOnSpoke);
-    float b = (PVector.dist(pointOnSpoke, spokeLine.getPoint()) < spokeRadius) ? constrain(100*(1 - ((d-.5f*spokeGirth)/(spokeGirth*.5f))), 0, 100) : 0.f;
-    float phase = spokeLine.getTValue(pointOnSpoke) < 0 ? basePair.colorPhase1 : basePair.colorPhase2;
-    return lx.hsb((lx.getBaseHuef() + (360*(phase / TWO_PI)))%360, 80.f, b);
-  }
-
-  public void run(double deltaMs) {
-    boolean h1on = helix1On.getValue() > 0.5f;
-    boolean h2on = helix2On.getValue() > 0.5f;
-    boolean spokesOn = (float)basePairsOn.getValue() > 0.5f;
-
-    h1.step(deltaMs);
-    h2.step(deltaMs);
-    calculateSpokes();
-
-    for (Point p : model.points) {
-      PVector pt = new PVector(p.x,p.y,p.z);
-      int h1c = h1.colorOfPoint(pt);
-      int h2c = h2.colorOfPoint(pt);
-      int spokeColor = calculateSpokeColor(pt);
-
-      if (!h1on) {
-        h1c = lx.hsb(0,0,0);
-      }
-
-      if (!h2on) {
-        h2c = lx.hsb(0,0,0);
-      }
-
-      if (!spokesOn) {
-        spokeColor = lx.hsb(0,0,0);
-      }
-
-      // The helices are positioned to not overlap.  If that changes,
-      // a better blending formula is probably needed.
-      colors[p.index] = blendColor(blendColor(h1c, h2c, ADD), spokeColor, ADD);
-    }
-  }
-}
-
-class BlankPattern extends SCPattern {
-  BlankPattern(GLucose glucose) {
-    super(glucose);
-  }
-  
-  public void run(double deltaMs) {
-    setColors(0xff000000);
-  }
-}
-
-abstract class TestPattern extends SCPattern {
-  public TestPattern(GLucose glucose) {
-    super(glucose);
-    setEligible(false);
-  }
-}
-
-class TestSpeakerMapping extends TestPattern {
-  TestSpeakerMapping(GLucose glucose) {
-    super(glucose);
-  }
-  
-  public void run(double deltaMs) {
-    int h = 0;
-    for (Speaker speaker : model.speakers) {
-      for (Strip strip : speaker.strips) {
-        float b = 100;
-        for (Point p : strip.points) {
-          colors[p.index] = lx.hsb(h % 360, 100, b);
-          b = max(0, b - 10);
-        }
-        h += 70;
-      }
-    }
-  }
-
-}
-
-class TestBassMapping extends TestPattern {
-  TestBassMapping(GLucose glucose) {
-    super(glucose);
-  }
-  
-  public void run(double deltaMs) {
-    int[] strips = { 2, 1, 0, 3, 13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6 };
-    int h = 0;
-    for (int si : strips) {
-      float b = 100;
-      for (Point p : model.bassBox.strips.get(si).points) {
-        colors[p.index] = lx.hsb(h % 360, 100, b);
-        b = max(0, b - 10);
-      }
-      h += 70;
-    }
-  }
-}
-
-class TestFloorMapping extends TestPattern {
-  TestFloorMapping(GLucose glucose) {
-    super(glucose);
-  }
-
-  public void run(double deltaMs) {
-    int[] strutIndices = {6, 5, 4, 3, 2, 1, 0, 7};
-    int h = 0;
-    for (int si : strutIndices) {
-      float b = 100;
-      for (Point p : model.bassBox.struts.get(si).points) {
-        colors[p.index] = lx.hsb(h % 360, 100, b);
-        b = max(0, b - 10);
-      }
-      h += 50;
-    }
-    int[] floorIndices = {0, 1, 2, 3};
-    h = 0;
-    for (int fi : floorIndices) {
-      float b = 100;
-      for (Point p : model.boothFloor.strips.get(fi).points) {
-        colors[p.index] = lx.hsb(h, 100, b);
-        b = max(0, b - 3);
-      }
-      h += 90;
-    }
-  }
-}
-
-class TestPerformancePattern extends TestPattern {
-  
-  final BasicParameter ops = new BasicParameter("OPS", 0);
-  final BasicParameter iter = new BasicParameter("ITER", 0);
-  
-  TestPerformancePattern(GLucose glucose) {
-    super(glucose);
-    addParameter(ops);
-    addParameter(iter);
-  }
-  
-  public void run(double deltaMs) {
-    float x = 1;
-    for (int j = 0; j < ops.getValuef() * 400000; ++j) {
-      x *= random(0, 1);
-    }
-
-    if (iter.getValuef() < 0.25f) {
-      for (Point p : model.points) {
-        colors[p.index] = lx.hsb(
-          (p.x*.1f + p.y*.1f) % 360,
-          100,
-          100
-        );
-      }
-    } else if (iter.getValuef() < 0.5f) {
-      for (int i = 0; i < colors.length; ++i) {
-        colors[i] = lx.hsb(
-          (90 + model.px[i]*.1f + model.py[i]*.1f) % 360,
-          100,
-          100
-        );
-      }
-    } else if (iter.getValuef() < 0.75f) {
-      for (int i = 0; i < colors.length; ++i) {
-        colors[i] = lx.hsb(
-          (180 + model.p[3*i]*.1f + model.p[3*i+1]*.1f) % 360,
-          100,
-          100
-        );
-      }
-    } else {
-      for (int i = 0; i < colors.length; ++i) {
-        colors[i] = lx.hsb(
-          (270 + model.x(i)*.1f + model.y(i)*.1f) % 360,
-          100,
-          100
-        );
-      }
-    }
-  }
-}
-
-class TestStripPattern extends TestPattern {
-  
-  SinLFO d = new SinLFO(4, 40, 4000);
-  
-  public TestStripPattern(GLucose glucose) {
-    super(glucose);
-    addModulator(d).trigger();
-  }
-  
-  public void run(double deltaMs) {
-    for (Strip s : model.strips) {
-      for (Point p : s.points) {
-        colors[p.index] = lx.hsb(
-          lx.getBaseHuef(),
-          100,
-          max(0, 100 - d.getValuef()*dist(p.x, p.y, s.cx, s.cy))
-        );
-      }
-    }
-  }
-}
-
-/**
- * Simplest demonstration of using the rotating master hue.
- * All pixels are full-on the same color.
- */
-class TestHuePattern extends TestPattern {
-  public TestHuePattern(GLucose glucose) {
-    super(glucose);
-  }
-  
-  public void run(double deltaMs) {
-    // Access the core master hue via this method call
-    float hv = lx.getBaseHuef();
-    for (int i = 0; i < colors.length; ++i) {
-      colors[i] = lx.hsb(hv, 100, 100);
-    }
-  } 
-}
-
-/**
- * Test of a wave moving across the X axis.
- */
-class TestXPattern extends TestPattern {
-  private final SinLFO xPos = new SinLFO(0, model.xMax, 4000);
-  public TestXPattern(GLucose glucose) {
-    super(glucose);
-    addModulator(xPos).trigger();
-  }
-  public void run(double deltaMs) {
-    float hv = lx.getBaseHuef();
-    for (Point p : model.points) {
-      // This is a common technique for modulating brightness.
-      // You can use abs() to determine the distance between two
-      // values. The further away this point is from an exact
-      // point, the more we decrease its brightness
-      float bv = max(0, 100 - abs(p.x - xPos.getValuef()));
-      colors[p.index] = lx.hsb(hv, 100, bv);
-    }
-  }
-}
-
-/**
- * Test of a wave on the Y axis.
- */
-class TestYPattern extends TestPattern {
-  private final SinLFO yPos = new SinLFO(0, model.yMax, 4000);
-  public TestYPattern(GLucose glucose) {
-    super(glucose);
-    addModulator(yPos).trigger();
-  }
-  public void run(double deltaMs) {
-    float hv = lx.getBaseHuef();
-    for (Point p : model.points) {
-      float bv = max(0, 100 - abs(p.y - yPos.getValuef()));
-      colors[p.index] = lx.hsb(hv, 100, bv);
-    }
-  }
-}
-
-/**
- * Test of a wave on the Z axis.
- */
-class TestZPattern extends TestPattern {
-  private final SinLFO zPos = new SinLFO(0, model.zMax, 4000);
-  public TestZPattern(GLucose glucose) {
-    super(glucose);
-    addModulator(zPos).trigger();
-  }
-  public void run(double deltaMs) {
-    float hv = lx.getBaseHuef();
-    for (Point p : model.points) {
-      float bv = max(0, 100 - abs(p.z - zPos.getValuef()));
-      colors[p.index] = lx.hsb(hv, 100, bv);
-    }
-  }
-}
-
-/**
- * This shows how to iterate over towers, enumerated in the model.
- */
-class TestTowerPattern extends TestPattern {
-  private final SawLFO towerIndex = new SawLFO(0, model.towers.size(), 1000*model.towers.size());
-  
-  public TestTowerPattern(GLucose glucose) {
-    super(glucose);
-    addModulator(towerIndex).trigger();
-  }
-
-  public void run(double deltaMs) {
-    int ti = 0;
-    for (Tower t : model.towers) {
-      for (Point p : t.points) {
-        colors[p.index] = lx.hsb(
-          lx.getBaseHuef(),
-          100,
-          max(0, 100 - 80*LXUtils.wrapdistf(ti, towerIndex.getValuef(), model.towers.size()))
-        );
-      }
-      ++ti;
-    }
-  }
-  
-}
-
-/**
- * This is a demonstration of how to use the projection library. A projection
- * creates a mutation of the coordinates of all the points in the model, creating
- * virtual x,y,z coordinates. In effect, this is like virtually rotating the entire
- * art car. However, since in reality the car does not move, the result is that
- * it appears that the object we are drawing on the car is actually moving.
- *
- * Keep in mind that what we are creating a projection of is the view coordinates.
- * Depending on your intuition, some operations may feel backwards. For instance,
- * if you translate the view to the right, it will make it seem that the object
- * you are drawing has moved to the left. If you scale the view up 2x, objects
- * drawn with the same absolute values will seem to be half the size.
- *
- * If this feels counterintuitive at first, don't worry. Just remember that you
- * are moving the pixels, not the structure. We're dealing with a finite set
- * of sparse, non-uniformly spaced pixels. Mutating the structure would move
- * things to a space where there are no pixels in 99% of the cases.
- */
-class TestProjectionPattern extends TestPattern {
-  
-  private final Projection projection;
-  private final SawLFO angle = new SawLFO(0, TWO_PI, 9000);
-  private final SinLFO yPos = new SinLFO(-20, 40, 5000);
-  
-  public TestProjectionPattern(GLucose glucose) {
-    super(glucose);
-    projection = new Projection(model);
-    addModulator(angle).trigger();
-    addModulator(yPos).trigger();
-  }
-  
-  public void run(double deltaMs) {
-    // For the same reasons described above, it may logically feel to you that
-    // some of these operations are in reverse order. Again, just keep in mind that
-    // the car itself is what's moving, not the object
-    projection.reset(model)
-    
-      // Translate so the center of the car is the origin, offset by yPos
-      .translateCenter(model, 0, yPos.getValuef(), 0)
-
-      // Rotate around the origin (now the center of the car) about an X-vector
-      .rotate(angle.getValuef(), 1, 0, 0)
-
-      // Scale up the Y axis (objects will look smaller in that access)
-      .scale(1, 1.5f, 1);
-
-    float hv = lx.getBaseHuef();
-    for (Coord c : projection) {
-      float d = sqrt(c.x*c.x + c.y*c.y + c.z*c.z); // distance from origin
-      // d = abs(d-60) + max(0, abs(c.z) - 20); // life saver / ring thing
-      d = max(0, abs(c.y) - 10 + .1f*abs(c.z) + .02f*abs(c.x)); // plane / spear thing
-      colors[c.index] = lx.hsb(
-        (hv + .6f*abs(c.x) + abs(c.z)) % 360,
-        100,
-        constrain(140 - 40*d, 0, 100)
-      );
-    }
-  } 
-}
-
-class TestCubePattern extends TestPattern {
-  
-  private SawLFO index = new SawLFO(0, Cube.POINTS_PER_CUBE, Cube.POINTS_PER_CUBE*60);
-  
-  TestCubePattern(GLucose glucose) {
-    super(glucose);
-    addModulator(index).start();
-  }
-  
-  public void run(double deltaMs) {
-    for (Cube c : model.cubes) {
-      int i = 0;
-      for (Point p : c.points) {
-        colors[p.index] = lx.hsb(
-          lx.getBaseHuef(),
-          100,
-          max(0, 100 - 80.f*abs(i - index.getValuef()))
-        );
-        ++i;
-      }
-    }
-  }
-}
-
-class MappingTool extends TestPattern {
-    
-  private int cubeIndex = 0;
-  private int stripIndex = 0;
-  private int channelIndex = 0;
-
-  public final int MAPPING_MODE_ALL = 0;
-  public final int MAPPING_MODE_CHANNEL = 1;
-  public final int MAPPING_MODE_SINGLE_CUBE = 2;
-  public int mappingMode = MAPPING_MODE_ALL;
-
-  public final int CUBE_MODE_ALL = 0;
-  public final int CUBE_MODE_SINGLE_STRIP = 1;
-  public final int CUBE_MODE_STRIP_PATTERN = 2;
-  public int cubeMode = CUBE_MODE_ALL;
-
-  public boolean channelModeRed = true;
-  public boolean channelModeGreen = false;
-  public boolean channelModeBlue = false;
-  
-  private final int numChannels;
-  
-  private final PandaMapping[] pandaMappings;
-  private PandaMapping activePanda;
-  private ChannelMapping activeChannel;
-  
-  MappingTool(GLucose glucose, PandaMapping[] pandaMappings) {
-    super(glucose);
-    this.pandaMappings = pandaMappings;
-    numChannels = pandaMappings.length * PandaMapping.CHANNELS_PER_BOARD;
-    setChannel();
-  }
-
-  public int numChannels() {
-    return numChannels;
-  }
-  
-  private void setChannel() {
-    activePanda = pandaMappings[channelIndex / PandaMapping.CHANNELS_PER_BOARD];
-    activeChannel = activePanda.channelList[channelIndex % PandaMapping.CHANNELS_PER_BOARD];
-  }
-  
-  private int indexOfCubeInChannel(Cube c) {
-    if (activeChannel.mode == ChannelMapping.MODE_CUBES) {
-      int i = 1;
-      for (int index : activeChannel.objectIndices) {
-        if ((index >= 0) && (c == model.getCubeByRawIndex(index))) {
-          return i;
-        }
-        ++i;
-      }
-    }
-    return 0;
-  }
-  
-  private void printInfo() {
-    println("Cube:" + cubeIndex + " Strip:" + (stripIndex+1));
-  }
-  
-  public void cube(int delta) {
-    int len = model.cubes.size();
-    cubeIndex = (len + cubeIndex + delta) % len;
-    printInfo();
-  }
-  
-  public void strip(int delta) {
-    int len = Cube.STRIPS_PER_CUBE;
-    stripIndex = (len + stripIndex + delta) % len;
-    printInfo();
-  }
-  
-  public void run(double deltaMs) {
-    int off = 0xff000000;
-    int c = off;
-    int r = 0xffFF0000;
-    int g = 0xff00FF00;
-    int b = 0xff0000FF;
-    if (channelModeRed) c |= r;
-    if (channelModeGreen) c |= g;
-    if (channelModeBlue) c |= b;
-    
-    int ci = 0;
-    for (Cube cube : model.cubes) {
-      boolean cubeOn = false;
-      int indexOfCubeInChannel = indexOfCubeInChannel(cube);
-      switch (mappingMode) {
-        case MAPPING_MODE_ALL: cubeOn = true; break;
-        case MAPPING_MODE_SINGLE_CUBE: cubeOn = (cubeIndex == ci); break;
-        case MAPPING_MODE_CHANNEL: cubeOn = (indexOfCubeInChannel > 0); break;
-      }
-      if (cubeOn) {
-        if (mappingMode == MAPPING_MODE_CHANNEL) {
-          int cc = off;
-          switch (indexOfCubeInChannel) {
-            case 1: cc = r; break;
-            case 2: cc = r|g; break;
-            case 3: cc = g; break;
-            case 4: cc = b; break;
-            case 5: cc = r|b; break;
-          }
-          setColor(cube, cc);
-        } else if (cubeMode == CUBE_MODE_STRIP_PATTERN) {
-          int si = 0;
-          int sc = off;
-          for (Strip strip : cube.strips) {
-            int faceI = si / Face.STRIPS_PER_FACE;
-            switch (faceI) {
-              case 0: sc = r; break;
-              case 1: sc = g; break;
-              case 2: sc = b; break;
-              case 3: sc = r|g|b; break;
-            }
-            if (si % Face.STRIPS_PER_FACE == 2) {
-              sc = r|g;
-            }
-            setColor(strip, sc);
-            ++si;
-          }
-        } else if (cubeMode == CUBE_MODE_SINGLE_STRIP) {
-          setColor(cube, off);
-          setColor(cube.strips.get(stripIndex), c);
-        } else {
-          setColor(cube, c);
-        }
-      } else {
-        setColor(cube, off);
-      }
-      ++ci;
-    }
-  }
-  
-  public void setCube(int index) {
-    cubeIndex = index % model.cubes.size();
-  }
-  
-  public void incCube() {
-    cubeIndex = (cubeIndex + 1) % model.cubes.size();
-  }
-  
-  public void decCube() {
-    --cubeIndex;
-    if (cubeIndex < 0) {
-      cubeIndex += model.cubes.size();
-    }
-  }
-  
-  public void setChannel(int index) {
-    channelIndex = index % numChannels;
-    setChannel();
-  }
-
-  public void incChannel() {
-    channelIndex = (channelIndex + 1) % numChannels;
-    setChannel();
-  }
-  
-  public void decChannel() {
-    channelIndex = (channelIndex + numChannels - 1) % numChannels;
-    setChannel();    
-  }
-  
-  public void setStrip(int index) {
-    stripIndex = index % Cube.STRIPS_PER_CUBE;
-  }
-  
-  public void incStrip() {
-    stripIndex = (stripIndex + 1) % Cube.STRIPS_PER_CUBE;
-  }
-  
-  public void decStrip() {
-    stripIndex = (stripIndex + Cube.STRIPS_PER_CUBE - 1) % Cube.STRIPS_PER_CUBE;
-  }
-  
-  public void keyPressed(UIMapping uiMapping) {
-    switch (keyCode) {
-      case UP: if (mappingMode == MAPPING_MODE_CHANNEL) incChannel(); else incCube(); break;
-      case DOWN: if (mappingMode == MAPPING_MODE_CHANNEL) decChannel(); else decCube(); break;
-      case LEFT: decStrip(); break;
-      case RIGHT: incStrip(); break;
-    }
-    switch (key) {
-      case 'r': channelModeRed = !channelModeRed; break;
-      case 'g': channelModeGreen = !channelModeGreen; break;
-      case 'b': channelModeBlue = !channelModeBlue; break;
-    }
-    uiMapping.setChannelID(channelIndex+1);
-    uiMapping.setCubeID(cubeIndex+1);
-    uiMapping.setStripID(stripIndex+1);
-    uiMapping.redraw();
-  }
-
-}
-/**
- * Not very flushed out, but kind of fun nonetheless.
- */
-class TimSpheres extends SCPattern {
-  private BasicParameter hueParameter = new BasicParameter("RAD", 1.0f);
-  private final SawLFO lfo = new SawLFO(0, 1, 10000);
-  private final SinLFO sinLfo = new SinLFO(0, 1, 4000);
-  private final float centerX, centerY, centerZ;
-  
-  class Sphere {
-    float x, y, z;
-    float radius;
-    float hue;
-  }
-  
-  private final Sphere[] spheres;
-  
-  public TimSpheres(GLucose glucose) {
-    super(glucose);
-    addParameter(hueParameter);
-    addModulator(lfo).trigger();
-    addModulator(sinLfo).trigger();
-    centerX = (model.xMax + model.xMin) / 2;
-    centerY = (model.yMax + model.yMin) / 2;
-    centerZ = (model.zMax + model.zMin) / 2;
-    
-    spheres = new Sphere[2];
-    
-    spheres[0] = new Sphere();
-    spheres[0].x = model.xMin;
-    spheres[0].y = centerY;
-    spheres[0].z = centerZ;
-    spheres[0].hue = 0;
-    spheres[0].radius = 50;
-    
-    spheres[1] = new Sphere();
-    spheres[1].x = model.xMax;
-    spheres[1].y = centerY;
-    spheres[1].z = centerZ;
-    spheres[1].hue = 0.33f;
-    spheres[1].radius = 50;
-  }
-  
-  public void run(double deltaMs) {
-    // Access the core master hue via this method call
-    float hv = hueParameter.getValuef();
-    float lfoValue = lfo.getValuef();
-    float sinLfoValue = sinLfo.getValuef();
-    
-    spheres[0].x = model.xMin + sinLfoValue * model.xMax;
-    spheres[1].x = model.xMax - sinLfoValue * model.xMax;
-    
-    spheres[0].radius = 100 * hueParameter.getValuef();
-    spheres[1].radius = 100 * hueParameter.getValuef();
-    
-    for (Point p : model.points) {
-      float value = 0;
-
-      int c = lx.hsb(0, 0, 0);      
-      for (Sphere s : spheres) {
-        float d = sqrt(pow(p.x - s.x, 2) + pow(p.y - s.y, 2) + pow(p.z - s.z, 2));
-        float r = (s.radius); // * (sinLfoValue + 0.5));
-        value = max(0, 1 - max(0, d - r) / 10);
-        
-        c = blendColor(c, lx.hsb(((s.hue + lfoValue) % 1) * 360, 100, min(1, value) * 100), ADD);
-      }
-      
-      colors[p.index] = c;
-    }
-  } 
-}
-
-class Vector2 {
-  float x, y;
-  
-  Vector2() {
-    this(0, 0);
-  }
-  
-  Vector2(float x, float y) {
-    this.x = x;
-    this.y = y;
-  }
-  
-  public float distanceTo(float x, float y) {
-    return sqrt(pow(x - this.x, 2) + pow(y - this.y, 2));
-  }
-  
-  public float distanceTo(Vector2 v) {
-    return distanceTo(v.x, v.y);
-  }
-  
-  public Vector2 plus(float x, float y) {
-    return new Vector2(this.x + x, this.y + y);
-  }
-  
-  public Vector2 plus(Vector2 v) {
-    return plus(v.x, v.y);
-  }
-    
-  public Vector2 minus(Vector2 v) {
-    return plus(-1 * v.x, -1 * v.y);
-  }
-}
-
-class Vector3 {
-  float x, y, z;
-  
-  Vector3() {
-    this(0, 0, 0);
-  }
-  
-  Vector3(float x, float y, float z) {
-    this.x = x;
-    this.y = y;
-    this.z = z;
-  }
-  
-  public float distanceTo(float x, float y, float z) {
-    return sqrt(pow(x - this.x, 2) + pow(y - this.y, 2) + pow(z - this.z, 2));
-  }
-  
-  public float distanceTo(Vector3 v) {
-    return distanceTo(v.x, v.y, v.z);
-  }
-  
-  public float distanceTo(Point p) {
-    return distanceTo(p.x, p.y, p.z);
-  }
-  
-  public void add(Vector3 other, float multiplier) {
-    this.add(other.x * multiplier, other.y * multiplier, other.z * multiplier);
-  }  
-    
-  public void add(float x, float y, float z) {
-    this.x += x;
-    this.y += y;
-    this.z += z;
-  }
-  
-  public void divide(float factor) {
-    this.x /= factor;
-    this.y /= factor;
-    this.z /= factor;
-  }
-}
-
-class Rotation {
-  private float a, b, c, d, e, f, g, h, i;
-  
-  Rotation(float yaw, float pitch, float roll) {
-    float cosYaw = cos(yaw);
-    float sinYaw = sin(yaw);
-    float cosPitch = cos(pitch);
-    float sinPitch = sin(pitch);
-    float cosRoll = cos(roll);
-    float sinRoll = sin(roll);
-    
-    a = cosYaw * cosPitch;
-    b = cosYaw * sinPitch * sinRoll - sinYaw * cosRoll;
-    c = cosYaw * sinPitch * cosRoll + sinYaw * sinRoll;
-    d = sinYaw * cosPitch;
-    e = sinYaw * sinPitch * sinRoll + cosYaw * cosRoll;
-    f = sinYaw * sinPitch * cosRoll - cosYaw * sinRoll;
-    g = -1 * sinPitch;
-    h = cosPitch * sinRoll;
-    i = cosPitch * cosRoll;
-  }
-  
-  public Vector3 rotated(Vector3 v) {
-    return new Vector3(
-      rotatedX(v),
-      rotatedY(v),
-      rotatedZ(v));
-
-  }
-  
-  public float rotatedX(Vector3 v) {
-    return a * v.x + b * v.y + c * v.z;
-  }
-  
-  public float rotatedY(Vector3 v) {
-    return d * v.x + e * v.y + f * v.z;
-  }
-  
-  public float rotatedZ(Vector3 v) {
-    return g * v.x + h * v.y + i * v.z;
-  }
-}
-
-/**
- * Very literal rain effect.  Not that great as-is but some tweaking could make it nice.
- * A couple ideas:
- *   - changing hue and direction of "rain" could make a nice fire effect
- *   - knobs to change frequency and size of rain drops
- *   - sync somehow to tempo but maybe less frequently than every beat?
- */
-class TimRaindrops extends SCPattern {
-  public Vector3 randomVector3() {
-    return new Vector3(
-        random(model.xMax - model.xMin) + model.xMin,
-        random(model.yMax - model.yMin) + model.yMin,
-        random(model.zMax - model.zMin) + model.zMin);
-  }
-
-  class Raindrop {
-    Vector3 p;
-    Vector3 v;
-    float radius;
-    float hue;
-    
-    Raindrop() {
-      this.radius = 30;
-      this.p = new Vector3(
-              random(model.xMax - model.xMin) + model.xMin,
-              model.yMax + this.radius,
-              random(model.zMax - model.zMin) + model.zMin);
-      float velMagnitude = 120;
-      this.v = new Vector3(
-          0,
-          -3 * model.yMax,
-          0);
-      this.hue = random(40) + 200;
-    }
-    
-    // returns TRUE when this should die
-    public boolean age(double ms) {
-      p.add(v, (float) (ms / 1000.0f));
-      return this.p.y < (0 - this.radius);
-    }
-  }
-  
-  private float leftoverMs = 0;
-  private float msPerRaindrop = 40;
-  private List<Raindrop> raindrops;
-  
-  public TimRaindrops(GLucose glucose) {
-    super(glucose);
-    raindrops = new LinkedList<Raindrop>();
-  }
-  
-  public void run(double deltaMs) {
-    leftoverMs += deltaMs;
-    while (leftoverMs > msPerRaindrop) {
-      leftoverMs -= msPerRaindrop;
-      raindrops.add(new Raindrop());
-    }
-    
-    for (Point p : model.points) {
-      int c = 
-        blendColor(
-          lx.hsb(210, 20, (float)Math.max(0, 1 - Math.pow((model.yMax - p.y) / 10, 2)) * 50),
-          lx.hsb(220, 60, (float)Math.max(0, 1 - Math.pow((p.y - model.yMin) / 10, 2)) * 100),
-          ADD);
-      for (Raindrop raindrop : raindrops) {
-        if (p.x >= (raindrop.p.x - raindrop.radius) && p.x <= (raindrop.p.x + raindrop.radius) &&
-            p.y >= (raindrop.p.y - raindrop.radius) && p.y <= (raindrop.p.y + raindrop.radius)) {
-          float d = raindrop.p.distanceTo(p) / raindrop.radius;
-  //      float value = (float)Math.max(0, 1 - Math.pow(Math.min(0, d - raindrop.radius) / 5, 2)); 
-          if (d < 1) {
-            c = blendColor(c, lx.hsb(raindrop.hue, 80, (float)Math.pow(1 - d, 0.01f) * 100), ADD);
-          }
-        }
-      }
-      colors[p.index] = c;
-    }
-    
-    Iterator<Raindrop> i = raindrops.iterator();
-    while (i.hasNext()) {
-      Raindrop raindrop = i.next();
-      boolean dead = raindrop.age(deltaMs);
-      if (dead) {
-        i.remove();
-      }
-    }
-  } 
-}
-
-
-class TimCubes extends SCPattern {
-  private BasicParameter rateParameter = new BasicParameter("RATE", 0.125f);
-  private BasicParameter attackParameter = new BasicParameter("ATTK", 0.5f);
-  private BasicParameter decayParameter = new BasicParameter("DECAY", 0.5f);
-  private BasicParameter hueParameter = new BasicParameter("HUE", 0.5f);
-  private BasicParameter hueVarianceParameter = new BasicParameter("H.V.", 0.25f);
-  private BasicParameter saturationParameter = new BasicParameter("SAT", 0.5f);
-  
-  class CubeFlash {
-    Cube c;
-    float value;
-    float hue;
-    boolean hasPeaked;
-    
-    CubeFlash() {
-      c = model.cubes.get(floor(random(model.cubes.size())));
-      hue = random(1);
-      boolean infiniteAttack = (attackParameter.getValuef() > 0.999f);
-      hasPeaked = infiniteAttack;
-      value = (infiniteAttack ? 1 : 0);
-    }
-    
-    // returns TRUE if this should die
-    public boolean age(double ms) {
-      if (!hasPeaked) {
-        value = value + (float) (ms / 1000.0f * ((attackParameter.getValuef() + 0.01f) * 5));
-        if (value >= 1.0f) {
-          value = 1.0f;
-          hasPeaked = true;
-        }
-        return false;
-      } else {
-        value = value - (float) (ms / 1000.0f * ((decayParameter.getValuef() + 0.01f) * 10));
-        return value <= 0;
-      }
-    }
-  }
-  
-  private float leftoverMs = 0;
-  private List<CubeFlash> flashes;
-  
-  public TimCubes(GLucose glucose) {
-    super(glucose);
-    addParameter(rateParameter);
-    addParameter(attackParameter);
-    addParameter(decayParameter);
-    addParameter(hueParameter);
-    addParameter(hueVarianceParameter);
-    addParameter(saturationParameter);
-    flashes = new LinkedList<CubeFlash>();
-  }
-  
-  public void run(double deltaMs) {
-    leftoverMs += deltaMs;
-    float msPerFlash = 1000 / ((rateParameter.getValuef() + .01f) * 100);
-    while (leftoverMs > msPerFlash) {
-      leftoverMs -= msPerFlash;
-      flashes.add(new CubeFlash());
-    }
-    
-    for (Point p : model.points) {
-      colors[p.index] = 0;
-    }
-    
-    for (CubeFlash flash : flashes) {
-      float hue = (hueParameter.getValuef() + (hueVarianceParameter.getValuef() * flash.hue)) % 1.0f;
-      int c = lx.hsb(hue * 360, saturationParameter.getValuef() * 100, (flash.value) * 100);
-      for (Point p : flash.c.points) {
-        colors[p.index] = c;
-      }
-    }
-    
-    Iterator<CubeFlash> i = flashes.iterator();
-    while (i.hasNext()) {
-      CubeFlash flash = i.next();
-      boolean dead = flash.age(deltaMs);
-      if (dead) {
-        i.remove();
-      }
-    }
-  } 
-}
-
-/**
- * This one is the best but you need to play with all the knobs.  It's synced to
- * the tempo, with the WSpd knob letting you pick 4 discrete multipliers for
- * the tempo.
- *
- * Basically it's just 3 planes all rotating to the beat, but also rotated relative
- * to one another.  The intersection of the planes and the cubes over time makes
- * for a nice abstract effect.
- */
-class TimPlanes extends SCPattern {
-  private BasicParameter wobbleParameter = new BasicParameter("Wob", 0.166f);
-  private BasicParameter wobbleSpreadParameter = new BasicParameter("WSpr", 0.25f);
-  private BasicParameter wobbleSpeedParameter = new BasicParameter("WSpd", 0.375f);
-  private BasicParameter wobbleOffsetParameter = new BasicParameter("WOff", 0);
-  private BasicParameter derezParameter = new BasicParameter("Drez", 0.5f);
-  private BasicParameter thicknessParameter = new BasicParameter("Thick", 0.4f);
-  private BasicParameter ySpreadParameter = new BasicParameter("ySpr", 0.2f);
-  private BasicParameter hueParameter = new BasicParameter("Hue", 0.75f);
-  private BasicParameter hueSpreadParameter = new BasicParameter("HSpr", 0.68f);
-
-  final float centerX, centerY, centerZ;
-  float phase;
-  
-  class Plane {
-    Vector3 center;
-    Rotation rotation;
-    float hue;
-    
-    Plane(Vector3 center, Rotation rotation, float hue) {
-      this.center = center;
-      this.rotation = rotation;
-      this.hue = hue;
-    }
-  }
-      
-  TimPlanes(GLucose glucose) {
-    super(glucose);
-    centerX = (model.xMin + model.xMax) / 2;
-    centerY = (model.yMin + model.yMax) / 2;
-    centerZ = (model.zMin + model.zMax) / 2;
-    phase = 0;
-    addParameter(wobbleParameter);
-    addParameter(wobbleSpreadParameter);
-    addParameter(wobbleSpeedParameter);
-//    addParameter(wobbleOffsetParameter);
-    addParameter(derezParameter);
-    addParameter(thicknessParameter);
-    addParameter(ySpreadParameter);
-    addParameter(hueParameter);
-    addParameter(hueSpreadParameter);
-  }
-  
-  int beat = 0;
-  float prevRamp = 0;
-  float[] wobbleSpeeds = { 1.0f/8, 1.0f/4, 1.0f/2, 1.0f };
-  
-  public void run(double deltaMs) {
-    float ramp = (float)lx.tempo.ramp();
-    if (ramp < prevRamp) {
-      beat = (beat + 1) % 32;
-    }
-    prevRamp = ramp;
-    
-    float wobbleSpeed = wobbleSpeeds[floor(wobbleSpeedParameter.getValuef() * wobbleSpeeds.length * 0.9999f)];
-
-    phase = (((beat + ramp) * wobbleSpeed + wobbleOffsetParameter.getValuef()) % 1) * 2 * PI;
-    
-    float ySpread = ySpreadParameter.getValuef() * 50;
-    float wobble = wobbleParameter.getValuef() * PI;
-    float wobbleSpread = wobbleSpreadParameter.getValuef() * PI;
-    float hue = hueParameter.getValuef() * 360;
-    float hueSpread = (hueSpreadParameter.getValuef() - 0.5f) * 360;
-
-    float saturation = 10 + 60.0f * pow(ramp, 0.25f);
-    
-    float derez = derezParameter.getValuef();
-    
-    Plane[] planes = {
-      new Plane(
-        new Vector3(centerX, centerY + ySpread, centerZ),
-        new Rotation(wobble - wobbleSpread, phase, 0),
-        (hue + 360 - hueSpread) % 360),
-      new Plane(
-        new Vector3(centerX, centerY, centerZ),
-        new Rotation(wobble, phase, 0),
-        hue),
-      new Plane(
-        new Vector3(centerX, centerY - ySpread, centerZ),
-        new Rotation(wobble + wobbleSpread, phase, 0),
-        (hue + 360 + hueSpread) % 360)
-    };
-
-    float thickness = (thicknessParameter.getValuef() * 25 + 1);
-    
-    Vector3 normalizedPoint = new Vector3();
-
-    for (Point p : model.points) {
-      if (random(1.0f) < derez) {
-        continue;
-      }
-      
-      int c = 0;
-      
-      for (Plane plane : planes) {
-        normalizedPoint.x = p.x - plane.center.x;
-        normalizedPoint.y = p.y - plane.center.y;
-        normalizedPoint.z = p.z - plane.center.z;
-        
-        float v = plane.rotation.rotatedY(normalizedPoint);
-        float d = abs(v);
-        
-        final int planeColor;
-        if (d <= thickness) {
-          planeColor = lx.hsb(plane.hue, saturation, 100);
-        } else if (d <= thickness * 2) {    
-          float value = 1 - ((d - thickness) / thickness);
-          planeColor = lx.hsb(plane.hue, saturation, value * 100);
-        } else {
-          planeColor = 0;
-        }
-
-        if (planeColor != 0) {
-          if (c == 0) {
-            c = planeColor; 
-          } else {
-            c = blendColor(c, planeColor, ADD);
-          }
-        }
-      }
-
-      colors[p.index] = c;
-    }
-  }
-}
-
-/**
- * Two spinning wheels, basically XORed together, with a color palette that should
- * be pretty easy to switch around.  Timed to the beat; also introduces "clickiness"
- * which makes the movement non-linear throughout a given beat, giving it a nice
- * dance feel.  I'm not 100% sure that it's actually going to look like it's _on_
- * the beat, but that should be easy enough to adjust.
- *
- * It's particularly nice to turn down the clickiness and turn up derez during
- * slow/beatless parts of the music and then revert them at the drop :)  But maybe
- * I shouldn't be listening to so much shitty dubstep while making these...
- */
-class TimPinwheels extends SCPattern { 
-  private BasicParameter horizSpreadParameter = new BasicParameter("HSpr", 0.75f);
-  private BasicParameter vertSpreadParameter = new BasicParameter("VSpr", 0.5f);
-  private BasicParameter vertOffsetParameter = new BasicParameter("VOff", 1.0f);
-  private BasicParameter zSlopeParameter = new BasicParameter("ZSlp", 0.6f);
-  private BasicParameter sharpnessParameter = new BasicParameter("Shrp", 0.25f);
-  private BasicParameter derezParameter = new BasicParameter("Drez", 0.25f);
-  private BasicParameter clickinessParameter = new BasicParameter("Clic", 0.5f);
-  private BasicParameter hueParameter = new BasicParameter("Hue", 0.667f);
-  private BasicParameter hueSpreadParameter = new BasicParameter("HSpd", 0.667f);
-
-  float phase = 0;
-  private final int NUM_BLADES = 12;
-  
-  class Pinwheel {
-    Vector2 center;
-    int numBlades;
-    float realPhase;
-    float phase;
-    float speed;
-    
-    Pinwheel(float xCenter, float yCenter, int numBlades, float speed) {
-      this.center = new Vector2(xCenter, yCenter);
-      this.numBlades = numBlades;
-      this.speed = speed;
-    }
-    
-    public void age(float numBeats) {
-      int numSteps = numBlades;
-      
-      realPhase = (realPhase + numBeats / numSteps) % 2.0f;
-      
-      float phaseStep = floor(realPhase * numSteps);
-      float phaseRamp = (realPhase * numSteps) % 1.0f;
-      phase = (phaseStep + pow(phaseRamp, (clickinessParameter.getValuef() * 10) + 1)) / (numSteps * 2);
-//      phase = (phase + deltaMs / 1000.0 * speed) % 1.0;      
-    }
-    
-    public boolean isOnBlade(float x, float y) {
-      x = x - center.x;
-      y = y - center.y;
-      
-      float normalizedAngle = (atan2(x, y) / (2 * PI) + 1 + phase) % 1;
-      float v = (normalizedAngle * 4 * numBlades);
-      int blade_num = floor((v + 2) / 4);
-      return (blade_num % 2) == 0;
-    }
-  }
-  
-  private final List<Pinwheel> pinwheels;
-  private final float[] values;
-  
-  TimPinwheels(GLucose glucose) {
-    super(glucose);
-    
-    addParameter(horizSpreadParameter);
-//    addParameter(vertSpreadParameter);
-    addParameter(vertOffsetParameter);
-    addParameter(zSlopeParameter);
-    addParameter(sharpnessParameter);
-    addParameter(derezParameter);
-    addParameter(clickinessParameter);
-    addParameter(hueParameter);
-    addParameter(hueSpreadParameter);
-    
-    pinwheels = new ArrayList();
-    pinwheels.add(new Pinwheel(0, 0, NUM_BLADES, 0.1f));
-    pinwheels.add(new Pinwheel(0, 0, NUM_BLADES, -0.1f));
-    
-    this.updateHorizSpread();
-    this.updateVertPositions();
-    
-    values = new float[model.points.size()];
-  }
-  
-  public void onParameterChanged(LXParameter parameter) {
-    if (parameter == horizSpreadParameter) {
-      updateHorizSpread();
-    } else if (parameter == vertSpreadParameter || parameter == vertOffsetParameter) {
-      updateVertPositions();
-    }
-  }
-  
-  private void updateHorizSpread() {
-    float xDist = model.xMax - model.xMin;
-    float xCenter = (model.xMin + model.xMax) / 2;
-    
-    float spread = horizSpreadParameter.getValuef() - 0.5f;
-    pinwheels.get(0).center.x = xCenter - xDist * spread;
-    pinwheels.get(1).center.x = xCenter + xDist * spread; 
-  }
-  
-  private void updateVertPositions() {
-    float yDist = model.yMax - model.yMin;
-    float yCenter = model.yMin + yDist * vertOffsetParameter.getValuef();
-
-    float spread = vertSpreadParameter.getValuef() - 0.5f;
-    pinwheels.get(0).center.y = yCenter - yDist * spread;
-    pinwheels.get(1).center.y = yCenter + yDist * spread;     
-  }
-  
-  private float prevRamp = 0;
-  
-  public void run(double deltaMs) {
-    float ramp = lx.tempo.rampf();
-    float numBeats = (1 + ramp - prevRamp) % 1;
-    prevRamp = ramp;
-    
-    float hue = hueParameter.getValuef() * 360;
-    // 0 -> -180
-    // 0.5 -> 0
-    // 1 -> 180
-    float hueSpread = (hueSpreadParameter.getValuef() - 0.5f) * 360;
-    
-    float fadeAmount = (float) (deltaMs / 1000.0f) * pow(sharpnessParameter.getValuef() * 10, 1);
-    
-    for (Pinwheel pw : pinwheels) {
-      pw.age(numBeats);
-    }
-    
-    float derez = derezParameter.getValuef();
-    
-    float zSlope = (zSlopeParameter.getValuef() - 0.5f) * 2;
-    
-    int i = -1;
-    for (Point p : model.points) {
-      ++i;
-      
-      int value = 0;
-      for (Pinwheel pw : pinwheels) {
-        value += (pw.isOnBlade(p.x, p.y - p.z * zSlope) ? 1 : 0);
-      }
-      if (value == 1) {
-        values[i] = 1;
-//        colors[p.index] = lx.hsb(120, 0, 100);
-      } else {
-        values[i] = max(0, values[i] - fadeAmount);
-        //color c = colors[p.index];
-        //colors[p.index] = lx.hsb(max(0, lx.h(c) - 10), min(100, lx.s(c) + 10), lx.b(c) - 5 );
-      }
-      
-      if (random(1.0f) >= derez) {
-        float v = values[i];
-        colors[p.index] = lx.hsb((360 + hue + pow(v, 2) * hueSpread) % 360, 30 + pow(1 - v, 0.25f) * 60, v * 100);
-      }      
-    }
-  }
-}
-
-/**
- * This tries to figure out neighboring pixels from one cube to another to
- * let you have a bunch of moving points tracing all over the structure.
- * Adds a couple seconds of startup time to do the calculation, and in the
- * end just comes out looking a lot like a screensaver.  Probably not worth
- * it but there may be useful code here.
- */
-class TimTrace extends SCPattern {
-  private Map<Point, List<Point>> pointToNeighbors;
-  private Map<Point, Strip> pointToStrip;
-  //  private final Map<Strip, List<Strip>> stripToNearbyStrips;
-  
-  int extraMs;
-  
-  class MovingPoint {
-    Point currentPoint;
-    float hue;
-    private Strip currentStrip;
-    private int currentStripIndex;
-    private int direction; // +1 or -1
-    
-    MovingPoint(Point p) {
-      this.setPointOnNewStrip(p);
-      hue = random(360);
-    }
-    
-    private void setPointOnNewStrip(Point p) {
-      this.currentPoint = p;
-      this.currentStrip = pointToStrip.get(p);
-      for (int i = 0; i < this.currentStrip.points.size(); ++i) {
-        if (this.currentStrip.points.get(i) == p) {
-          this.currentStripIndex = i;
-          break;
-        }
-      }
-      if (this.currentStripIndex == 0) {
-        // we are at the beginning of the strip; go forwards
-        this.direction = 1;
-      } else if (this.currentStripIndex == this.currentStrip.points.size()) {
-        // we are at the end of the strip; go backwards
-        this.direction = -1;
-      } else {
-        // we are in the middle of a strip; randomly go one way or another
-        this.direction = ((random(1.0f) < 0.5f) ? -1 : 1);
-      }
-    }
-    
-    public void step() {
-      List<Point> neighborsOnOtherStrips = pointToNeighbors.get(this.currentPoint);
-
-      Point nextPointOnCurrentStrip = null;      
-      this.currentStripIndex += this.direction;
-      if (this.currentStripIndex >= 0 && this.currentStripIndex < this.currentStrip.points.size()) {
-        nextPointOnCurrentStrip = this.currentStrip.points.get(this.currentStripIndex);
-      }
-      
-      // pick which option to take; if we can keep going on the current strip then
-      // add that as another option
-      int option = floor(random(neighborsOnOtherStrips.size() + (nextPointOnCurrentStrip == null ? 0 : 100)));
-      
-      if (option < neighborsOnOtherStrips.size()) {
-        this.setPointOnNewStrip(neighborsOnOtherStrips.get(option));
-      } else {
-        this.currentPoint = nextPointOnCurrentStrip;
-      }
-    }
-  }
-  
-  List<MovingPoint> movingPoints;
-  
-  TimTrace(GLucose glucose) {
-    super(glucose);
-    
-    extraMs = 0;
-    
-    pointToNeighbors = this.buildPointToNeighborsMap();
-    pointToStrip = this.buildPointToStripMap();
-    
-    int numMovingPoints = 1000;
-    movingPoints = new ArrayList();
-    for (int i = 0; i < numMovingPoints; ++i) {
-      movingPoints.add(new MovingPoint(model.points.get(floor(random(model.points.size())))));
-    }
-    
-  }
-  
-  private Map<Strip, List<Strip>> buildStripToNearbyStripsMap() {
-    Map<Strip, Vector3> stripToCenter = new HashMap();
-    for (Strip s : model.strips) {
-      Vector3 v = new Vector3();
-      for (Point p : s.points) {
-        v.add(p.x, p.y, p.z);
-      }
-      v.divide(s.points.size());
-      stripToCenter.put(s, v);
-    }
-    
-    Map<Strip, List<Strip>> stripToNeighbors = new HashMap();
-    for (Strip s : model.strips) {
-      List<Strip> neighbors = new ArrayList();
-      Vector3 sCenter = stripToCenter.get(s);
-      for (Strip potentialNeighbor : model.strips) {
-        if (s != potentialNeighbor) {
-          float distance = sCenter.distanceTo(stripToCenter.get(potentialNeighbor));
-          if (distance < 25) {
-            neighbors.add(potentialNeighbor);
-          }
-        }
-      }
-      stripToNeighbors.put(s, neighbors);
-    }
-    
-    return stripToNeighbors;
-  }
-  
-  private Map<Point, List<Point>> buildPointToNeighborsMap() {
-    Map<Point, List<Point>> m = new HashMap();
-    Map<Strip, List<Strip>> stripToNearbyStrips = this.buildStripToNearbyStripsMap();
-    
-    for (Strip s : model.strips) {
-      List<Strip> nearbyStrips = stripToNearbyStrips.get(s);
-      
-      for (Point p : s.points) {
-        Vector3 v = new Vector3(p.x, p.y, p.z);
-        
-        List<Point> neighbors = new ArrayList();
-        
-        for (Strip nearbyStrip : nearbyStrips) {
-          Point closestPoint = null;
-          float closestPointDistance = 100000;
-          
-          for (Point nsp : nearbyStrip.points) {
-            float distance = v.distanceTo(nsp.x, nsp.y, nsp.z);
-            if (closestPoint == null || distance < closestPointDistance) {
-              closestPoint = nsp;
-              closestPointDistance = distance;
-            }
-          }
-          
-          if (closestPointDistance < 15) {
-            neighbors.add(closestPoint);
-          }
-        }
-        
-        m.put(p, neighbors);
-      }
-    }
-    
-    return m;
-  }
-  
-  private Map<Point, Strip> buildPointToStripMap() {
-    Map<Point, Strip> m = new HashMap();
-    for (Strip s : model.strips) {
-      for (Point p : s.points) {
-        m.put(p, s);
-      }
-    }
-    return m;
-  }
-  
-  public void run(double deltaMs) {
-    for (Point p : model.points) {
-      int c = colors[p.index];
-      colors[p.index] = lx.hsb(lx.h(c), lx.s(c), lx.b(c) - 3);
-    }
-    
-    for (MovingPoint mp : movingPoints) {
-      mp.step();
-      colors[mp.currentPoint.index] = blendColor(colors[mp.currentPoint.index], lx.hsb(mp.hue, 10, 100), ADD);
-    }
-  }
-}
-class GlitchPlasma extends SCPattern {
-  private int pos = 0;
-  private float satu = 100;
-  private float speed = 1;
-  private float glitch = 0;
-  BasicParameter saturationParameter = new BasicParameter("SATU", 1.0f);
-  BasicParameter speedParameter = new BasicParameter("SPEED", 0.1f);
-  BasicParameter glitchParameter = new BasicParameter("GLITCH", 0.0f);
-  
-  public GlitchPlasma(GLucose glucose) {
-    super(glucose);
-    addParameter(saturationParameter);
-    addParameter(speedParameter);
-    addParameter(glitchParameter);
-  }
-  public void onParameterChanged(LXParameter parameter) {
-    if (parameter == saturationParameter) {
-      satu = 100*parameter.getValuef();
-    } else if (parameter == speedParameter) {
-      speed = 8*parameter.getValuef();
-    } else if (parameter == glitchParameter) {
-      glitch = parameter.getValuef();
-    }
-  }
-
-  public void run(double deltaMs) {
-    for (Point p : model.points) {
-      float hv = sin(dist(p.x + pos, p.y, 128.0f, 128.0f) / 8.0f)
-         + sin(dist(p.x, p.y, 64.0f, 64.0f) / 8.0f)
-         + sin(dist(p.x, p.y + pos / 7, 192.0f, 64.0f) / 7.0f)
-         + sin(dist(p.x, p.z + pos, 192.0f, 100.0f) / 8.0f);
-      float bv = 100;
-      colors[p.index] = lx.hsb((hv+2)*50, satu, bv);
-    }
-    if (random(1.0f)<glitch/20) {
-      pos=pos-PApplet.parseInt(random(10,30));
-    }
-    pos+=speed;
-    if (pos >= MAX_INT-1) pos=0;    
-  }
-}
-
-// This is very much a work in progress. Trying to get a flame effect.
-class FireEffect extends SCPattern {
-  private float[][] intensity;
-  private float hotspot;
-  private float decay = 0.3f;
-  private int xm;
-  private int ym;
-  BasicParameter decayParameter = new BasicParameter("DECAY", 0.3f);
-  
-  public FireEffect(GLucose glucose) {
-    super(glucose);
-    xm = PApplet.parseInt(model.xMax);
-    ym = PApplet.parseInt(model.yMax);
-    
-    intensity = new float[xm][ym];
-    addParameter(decayParameter);
-  }
-  public void onParameterChanged(LXParameter parameter) {
-    if (parameter == decayParameter) {
-      decay = parameter.getValuef();
-    }
-  } 
-  private int flameColor(float level) {
-    if (level<=0) return lx.hsb(0,0,0);
-    float br=min(100,sqrt(level)*15);
-    return lx.hsb(level/1.7f,100,br);
-  }
-  public void run(double deltaMs) {
-    for (int x=10;x<xm-10;x++) {
-        if (x%50>45 || x%50<5) {
-          intensity[x][ym-1] = random(30,100);
-        } else {
-          intensity[x][ym-1] = random(0,50);
-        }
-    }
-    for (int x=1;x<xm-1;x++) {
-      for (int y=0;y<ym-1;y++) {        
-        intensity[x][y] = (intensity[x-1][y+1]+intensity[x][y+1]+intensity[x+1][y+1])/3-decay;
-      }
-    }
-    
-    for (Point p : model.points) {
-      int x = max(0,(PApplet.parseInt(p.x)+PApplet.parseInt(p.z))%xm);
-      int y = constrain(ym-PApplet.parseInt(p.y),0,ym-1);
-      colors[p.index] = flameColor(intensity[x][y]);
-    }
-  }
-}
-
-class StripBounce extends SCPattern {
-  private final int numOsc = 30;
-  SinLFO[] fX = new SinLFO[numOsc]; //new SinLFO(0, model.xMax, 5000);
-  SinLFO[] fY = new SinLFO[numOsc]; //new SinLFO(0, model.yMax, 4000);
-  SinLFO[] fZ = new SinLFO[numOsc]; //new SinLFO(0, model.yMax, 3000);
-  SinLFO[] sat = new SinLFO[numOsc];
-  float[] colorOffset = new float[numOsc];
-  
-  public StripBounce(GLucose glucose) {
-    super(glucose);
-    for (int i=0;i<numOsc;i++) {
-      fX[i] = new SinLFO(0, model.xMax, random(2000,20000)); 
-      fY[i] = new SinLFO(0, model.yMax, random(2000,20000)); 
-      fZ[i] = new SinLFO(0, model.zMax, random(2000,20000)); 
-      sat[i] = new SinLFO(60, 100, random(2000,50000)); 
-      addModulator(fX[i]).trigger();      
-      addModulator(fY[i]).trigger();
-      addModulator(fZ[i]).trigger();
-      colorOffset[i]=random(0,256);
-    }
-  }
-  
-  public void run(double deltaMs) {
-    float[] bright = new float[model.points.size()];
-    for (Strip strip : model.strips) {
-      for (int i=0;i<numOsc;i++) {
-        float avgdist=0.0f;
-        avgdist = dist(strip.points.get(8).x,strip.points.get(8).y,strip.points.get(8).z,fX[i].getValuef(),fY[i].getValuef(),fZ[i].getValuef());
-        boolean on = avgdist<30;
-        float hv = (lx.getBaseHuef()+colorOffset[i])%360;
-        float br = max(0,100-avgdist*4);
-        for (Point p : strip.points) {
-          if (on && br>bright[p.index]) {
-            colors[p.index] = lx.hsb(hv,sat[i].getValuef(),br);
-            bright[p.index] = br;
-          }
-        }
-      }
-    }
-  }
-}
-
-class SoundRain extends SCPattern {
-
-  private FFT fft = null; 
-  private LinearEnvelope[] bandVals = null;
-  private float[] lightVals = null;
-  private int avgSize;
-  private float gain = 25;
-  SawLFO pos = new SawLFO(0, 9, 8000);
-  SinLFO col1 = new SinLFO(0, model.xMax, 5000);
-  BasicParameter gainParameter = new BasicParameter("GAIN", 0.5f);
-  
-  public SoundRain(GLucose glucose) {
-    super(glucose);
-    addModulator(pos).trigger();
-    addModulator(col1).trigger();
-    addParameter(gainParameter);
-  }
-
-  public void onParameterChanged(LXParameter parameter) {
-    if (parameter == gainParameter) {
-      gain = 50*parameter.getValuef();
-    }
-  }
-  protected void onActive() {
-    if (this.fft == null) {
-      this.fft = new FFT(lx.audioInput().bufferSize(), lx.audioInput().sampleRate());
-      this.fft.window(FFT.HAMMING);
-      this.fft.logAverages(40, 1);
-      this.avgSize = this.fft.avgSize();
-      this.bandVals = new LinearEnvelope[this.avgSize];
-      for (int i = 0; i < this.bandVals.length; ++i) {
-        this.addModulator(this.bandVals[i] = (new LinearEnvelope(0, 0, 700+i*4))).trigger();
-      }
-      lightVals = new float[avgSize];
-    }
-  }
-  
-  public void run(double deltaMs) {
-    this.fft.forward(this.lx.audioInput().mix);
-    for (int i = 0; i < avgSize; ++i) {
-      float value = this.fft.getAvg(i);
-      this.bandVals[i].setEndVal(value,40).trigger();
-      float lv = min(value*gain,100);
-      if (lv>lightVals[i]) {
-        lightVals[i]=min(lightVals[i]+15,lv,100);
-      } else {
-        lightVals[i]=max(lv,lightVals[i]-5,0);
-      }
-    }
-    for (Cube c : model.cubes) {
-      for (int j=0; j<c.strips.size(); j++) {
-        Strip s = c.strips.get(j);
-        if (j%4!=0 && j%4!=2) {
-          for (Point p : s.points) {
-            int seq = PApplet.parseInt(p.y*avgSize/model.yMax+pos.getValuef()+sin(p.x+p.z)*2)%avgSize;
-            seq=min(abs(seq-(avgSize/2)),avgSize-1);
-            colors[p.index] = lx.hsb(200,max(0,100-abs(p.x-col1.getValuef())/2),lightVals[seq]);
-          }
-        }
-      }
-    }
-  }  
-}
-
-class FaceSync extends SCPattern {
-  SinLFO xosc = new SinLFO(-10, 10, 3000);
-  SinLFO zosc = new SinLFO(-10, 10, 3000);
-  SinLFO col1 = new SinLFO(0, model.xMax, 5000);
-  SinLFO col2 = new SinLFO(0, model.xMax, 4000);
-
-  public FaceSync(GLucose glucose) {
-    super(glucose);
-    addModulator(xosc).trigger();
-    addModulator(zosc).trigger();
-    zosc.setValue(0);
-    addModulator(col1).trigger();
-    addModulator(col2).trigger();    
-    col2.setValue(model.xMax);
-  }
-
-  public void run(double deltaMs) {
-    int i=0;
-    for (Strip s : model.strips) {
-      i++;
-      for (Point p : s.points) {
-        float dx, dz;
-        if (i%32 < 16) {
-          dx = p.x - (s.cx+xosc.getValuef());
-          dz = p.z - (s.cz+zosc.getValuef());
-        } else {
-          dx = p.x - (s.cx+zosc.getValuef());
-          dz = p.z - (s.cz+xosc.getValuef());
-        }                
-        //println(dx);
-        float a1=max(0,100-abs(p.x-col1.getValuef()));
-        float a2=max(0,100-abs(p.x-col2.getValuef()));        
-        float sat = max(a1,a2);
-        float h = (359*a1+200*a2) / (a1+a2);
-        colors[p.index] = lx.hsb(h,sat,100-abs(dx*5)-abs(dz*5));
-      }
-    }
-  }
-}
-
-class SoundSpikes extends SCPattern {
-  private FFT fft = null; 
-  private LinearEnvelope[] bandVals = null;
-  private float[] lightVals = null;
-  private int avgSize;
-  private float gain = 25;
-  BasicParameter gainParameter = new BasicParameter("GAIN", 0.5f);
-  SawLFO pos = new SawLFO(0, model.xMax, 8000);
-
-  public SoundSpikes(GLucose glucose) {
-    super(glucose);
-    addParameter(gainParameter);
-    addModulator(pos).trigger();
-  }
-
-  public void onParameterChanged(LXParameter parameter) {
-    if (parameter == gainParameter) {
-      gain = 50*parameter.getValuef();
-    }
-  }
-  protected void onActive() {
-    if (this.fft == null) {
-      this.fft = new FFT(lx.audioInput().bufferSize(), lx.audioInput().sampleRate());
-      this.fft.window(FFT.HAMMING);
-      this.fft.logAverages(40, 1);
-      this.avgSize = this.fft.avgSize();
-      this.bandVals = new LinearEnvelope[this.avgSize];
-      for (int i = 0; i < this.bandVals.length; ++i) {
-        this.addModulator(this.bandVals[i] = (new LinearEnvelope(0, 0, 700+i*4))).trigger();
-      }
-      lightVals = new float[avgSize];
-    }
-  }
-  
-  public void run(double deltaMs) {
-    this.fft.forward(this.lx.audioInput().mix);
-    for (int i = 0; i < avgSize; ++i) {
-      float value = this.fft.getAvg(i);
-      this.bandVals[i].setEndVal(value,40).trigger();
-      float lv = min(value*gain,model.yMax+10);
-      if (lv>lightVals[i]) {
-        lightVals[i]=min(lightVals[i]+30,lv,model.yMax+10);
-      } else {
-        lightVals[i]=max(lv,lightVals[i]-10,0);
-      }
-    }
-    int i = 0;
-    for (Cube c : model.cubes) {
-      for (int j=0; j<c.strips.size(); j++) {
-        Strip s = c.strips.get(j);
-        if (j%4!=0 && j%4!=2) {
-          for (Point p : s.points) {
-            float dis = (abs(p.x-model.xMax/2)+pos.getValuef())%model.xMax/2;
-            int seq = PApplet.parseInt((dis*avgSize*2)/model.xMax);
-            if (seq>avgSize) seq=avgSize-seq;
-            seq=constrain(seq,0,avgSize-1);
-            float br=max(0, lightVals[seq]-p.y);
-            colors[p.index] = lx.hsb((dis*avgSize*65)/model.xMax,90,br);
-          }
-        }
-      }
-    }
-  }  
-}
-
-  static public void main(String[] passedArgs) {
-    String[] appletArgs = new String[] { "SugarCubes" };
-    if (passedArgs != null) {
-      PApplet.main(concat(appletArgs, passedArgs));
-    } else {
-      PApplet.main(appletArgs);
-    }
-  }
-}
diff --git a/code/GLucose.jar b/code/GLucose.jar
deleted file mode 100755 (executable)
index e8290f8..0000000
Binary files a/code/GLucose.jar and /dev/null differ
index 23d5bf8656e6653b38af29b640d1a6d441324b2c..7c388a7187aa6cce3490c50164ba4cf90dbee62f 100755 (executable)
Binary files a/code/HeronLX.jar and b/code/HeronLX.jar differ
diff --git a/code/JGraphT.jar b/code/JGraphT.jar
new file mode 100644 (file)
index 0000000..1db92e6
Binary files /dev/null and b/code/JGraphT.jar differ
diff --git a/code/oscP5.jar b/code/oscP5.jar
deleted file mode 100755 (executable)
index 24c6756..0000000
Binary files a/code/oscP5.jar and /dev/null differ
diff --git a/libraries/HeronLX.jar b/libraries/HeronLX.jar
new file mode 100755 (executable)
index 0000000..7c388a7
Binary files /dev/null and b/libraries/HeronLX.jar differ
diff --git a/libraries/JGraphT.jar b/libraries/JGraphT.jar
new file mode 100644 (file)
index 0000000..1db92e6
Binary files /dev/null and b/libraries/JGraphT.jar differ
diff --git a/libraries/ScreenShot.dll b/libraries/ScreenShot.dll
new file mode 100755 (executable)
index 0000000..68a6c99
Binary files /dev/null and b/libraries/ScreenShot.dll differ
diff --git a/libraries/ScreenShot.jar b/libraries/ScreenShot.jar
new file mode 100755 (executable)
index 0000000..c75b8de
Binary files /dev/null and b/libraries/ScreenShot.jar differ
diff --git a/libraries/rwmidi.jar b/libraries/rwmidi.jar
new file mode 100755 (executable)
index 0000000..4788ff6
Binary files /dev/null and b/libraries/rwmidi.jar differ
diff --git a/libraries/toxiclibscore.jar b/libraries/toxiclibscore.jar
new file mode 100755 (executable)
index 0000000..18fbbfe
Binary files /dev/null and b/libraries/toxiclibscore.jar differ
diff --git a/sketch.properties b/sketch.properties
new file mode 100644 (file)
index 0000000..8630fa2
--- /dev/null
@@ -0,0 +1,2 @@
+mode.id=processing.mode.java.JavaMode
+mode=Java