From: Alexander Green Date: Fri, 18 Oct 2013 04:19:04 +0000 (-0400) Subject: Merge branch 'master' of https://github.com/sugarcubes/SugarCubes X-Git-Url: https://git.piment-noir.org/?a=commitdiff_plain;h=6b163a98976a5f2adf9da1b7bd3297e39d6dd7bf;hp=f1370a0bca7f37bcb607734f3622358fd8efb023;p=SugarCubes.git Merge branch 'master' of https://github.com/sugarcubes/SugarCubes Conflicts: _Mappings.pde --- diff --git a/AlexGreen.pde b/AlexGreen.pde old mode 100755 new mode 100644 index 6b076f6..e240f7d --- a/AlexGreen.pde +++ b/AlexGreen.pde @@ -72,14 +72,14 @@ float distfromcirclecenter(float px, float py, float pz, float f1x, float f1y, f color spheryvalue (float px, float py, float pz , float f1xc, float f1yc, float f1zc) { //switch(sShpape.cur() ) {} - return color(constrain(huespread.getValuef()*5*px, 0, 360) , dist(px, py, pz, f1xc, f1yc, f1zc) , + 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() ) ) ); } color ellipsevalue(float px, float py, float pz , float f1xc, float f1yc, float f1zc, float f2xc, float f2yc, float f2zc) { //switch(sShpape.cur() ) {} - return color(huespread.getValuef()*5*px, dist(model.xMax-px, model.yMax-py, model.zMax-pz, f1xc, f1yc, f1zc) , + 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 @@ -159,10 +159,10 @@ final Sphery[] spherys; // 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 color(0,0,0); + // return lx.hsb(0,0,0); // // else if(spheremode ==2) // { color c = 0; - // return color(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) ); // } @@ -273,7 +273,7 @@ HueTestHSB(GLucose glucose) { for (Point p : model.points) { color c = 0; - c = blendColor(c, color(360*HueT.getValuef(), 100*SatT.getValuef(), 100*BriT.getValuef()), ADD); + c = blendColor(c, lx.hsb(360*HueT.getValuef(), 100*SatT.getValuef(), 100*BriT.getValuef()), ADD); colors[p.index]= c; } int now= millis(); @@ -283,4 +283,4 @@ HueTestHSB(GLucose glucose) { } } - } \ No newline at end of file + } diff --git a/ArjunBanker.pde b/ArjunBanker.pde index 6af635a..c8fe1a6 100644 --- a/ArjunBanker.pde +++ b/ArjunBanker.pde @@ -16,7 +16,7 @@ class TelevisionStatic extends SCPattern { void run(double deltaMs) { boolean d = direction.getValuef() > 5.0; for (Point p : model.points) { - colors[p.index] = color((lx.getBaseHuef() + random(hueParameter.getValuef() * 360))%360, random(saturationParameter.getValuef() * 100), random(brightParameter.getValuef() * 100)); + colors[p.index] = lx.hsb((lx.getBaseHuef() + random(hueParameter.getValuef() * 360))%360, random(saturationParameter.getValuef() * 100), random(brightParameter.getValuef() * 100)); } } } @@ -40,7 +40,7 @@ class AbstractPainting extends SCPattern { void run(double deltaMs) { for (Point p : model.points) { color c = img.get((int)((p.x / model.xMax) * img.width), img.height - (int)((p.y / model.yMax) * img.height)); - colors[p.index] = color(hue(c) + colorMod.getValuef()%360, saturation(c), brightness(c) - ((p.fz - brightMod.getValuef())/p.fz)); + colors[p.index] = lx.hsb(hue(c) + colorMod.getValuef()%360, saturation(c), brightness(c) - ((p.z - brightMod.getValuef())/p.z)); } } } @@ -56,7 +56,7 @@ class Spirality extends SCPattern { super(glucose); addParameter(r); for (Point p : model.points) { - colors[p.index] = color(0, 0, 0); + colors[p.index] = lx.hsb(0, 0, 0); } } @@ -66,16 +66,16 @@ class Spirality extends SCPattern { 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.fx,p.fy); + float b = dist(x,y,p.x,p.y); if (b < 90) { colors[p.index] = blendColor( colors[p.index], - color(lx.getBaseHuef() + 25, 10, map(b, 0, 10, 100, 0)), + lx.hsb(lx.getBaseHuef() + 25, 10, map(b, 0, 10, 100, 0)), ADD); } else { colors[p.index] = blendColor( colors[p.index], - color(25, 10, map(b, 0, 10, 0, 15)), + lx.hsb(25, 10, map(b, 0, 10, 0, 15)), SUBTRACT); } } diff --git a/BenMorrow.pde b/BenMorrow.pde index 1eb8ae1..7024148 100644 --- a/BenMorrow.pde +++ b/BenMorrow.pde @@ -50,7 +50,6 @@ class TowerParams extends SCPattern } towerSize = model.towers.size(); colorSpan = 255 / towerSize; - println("towers "+towerSize); } void run(double deltaMs) @@ -64,7 +63,7 @@ class TowerParams extends SCPattern { if(p.y 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-Dist(P,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.8; - - b += n.den/100 -.4 + pDensity.Val() -1; - b += transAdd; - c = blendColor(c,color(n.hue,100*n.sat,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; - float fixAngle (float a, float b) { return a abs(a+2*PI-b) ? a : a+2*PI) : - (abs(a-b) > abs(a-2*PI-b) ? a : a-2*PI) ; } - float getX(float r) { return mCtr.x + _cos*r; } - float getY(float r) { return mCtr.y + _sin*r; } - void move() { c = interp(t,prvA,dstA); - r = interp(t,prvR,dstR); - _cos = cos(c); _sin = sin(c); - x = getX(r); y = getY(r); } - void set() { prvA = dstA; dstA = random(2*PI); prvA = fixAngle(prvA, dstA); - prvR = dstR; dstR = random(mCtr.y); } - } - - int nBeats = 0; - DParam pAmp, pRadius, pBounce; - - float t,amp,rad,bnc; - float zTheta=0; - ArrayList waves = new ArrayList(10); - - rAngle a1 = new rAngle(), a2 = new rAngle(), - a3 = new rAngle(), a4 = new rAngle(); - xyz cPrev = new xyz(), cRand = new xyz(), - cMid = new xyz(), V = new xyz(), - Theta = new xyz(), TSin = new xyz(), - TCos = new xyz(), cMidNorm = new xyz(), - Pn = new xyz(); - float LastBeat=3, LastMeasure=3; - int CurRandTempo = 1, CurRandTPat = 1; - - Pick pTimePattern, pTempoMult, pShape; - int RandCube; - - Play(GLucose glucose) { - super(glucose); - pRadius = addParam("Rad" , .1 ); - pBounce = addParam("Bnc" , .2 ); - pAmp = addParam("Amp" , .2 ); - pTempoMult = addPick ("TMult" , 0 , 5 , new String[] {"1x", "2x", "4x", "8x", "16x", "Rand" } ); - pTimePattern= addPick ("TPat" , 6 , 7 , new String[] {"Bounce", "Sin", "Roll", "Quant", "Accel", "Deccel", "Slide", "Rand"} ); - pShape = addPick ("Shape" , 3 , 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; } - void move(double deltaMs) { - t += deltaMs*.001; - if (t>4) bDone=true; - } - 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)/(.2*len)); // * max(0,1-t/dur) - return -a*sin(dist); - } - } - - void StartPattern() { zTheta=0; } - void StartRun(double deltaMs) { - t = lx.tempo.rampf(); - amp = pAmp.Val(); - rad = pRadius.getValuef(); - bnc = pBounce.getValuef(); - zTheta += deltaMs*(pSpin .Val()-.5)*.01; - - Theta .set(pRotX.Val()*PI*2, pRotY.Val()*PI*2, pRotZ.Val()*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 6 ? 2+int(random(5)) : int(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. )%1.; break; - case 2: t = (t*4. )%1.; break; - case 3: t = (t*8. )%1.; break; - case 4: t = (t*16.)%1.; 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-1) { - waves.add(new rWave( - pKey.b ? map(DG.KeyPressed,0,7,0,1) : random(1), // location - bnc*10, // bounciness - 7, // velocity - 2*(1-amp))); // dampiness - DG.KeyPressed=-1; - if (waves.size() > 5) waves.remove(0); - } - - if (t .5?1:0)); // cone - - case 12: return color(100 + noise(Pn.x,Pn.y,Pn.z + (NoiseMove+50000)/1000.)*200, - 85,c1c(Pn.y < noise(Pn.x + NoiseMove/2000.,Pn.z)*(1+amp)-amp/2.-.1 ? 1 : 0)); // noise - - case 13: float y=0; for (rWave w : waves) y += .5*w.val(Pn.x); - V.set(Pn.x, .7+y, Pn.z); - break; - - default: return color(0,0,0); - } - - return color(0, - 150-c1c(1 - V.distance(Pn)/rad), - c1c(1 - V.distance(Pn)/rad)); - } -} -//---------------------------------------------------------------------------------------------------------------------------------- -// 0 - TLB, L (b), BLB, B (l) // Fwd , Down, Back, Up -// 4 - TLF, F (l), BLF, L (f) // Fwd , Down, Back, Up -// 8 - TRF, R (f), BRF, F (r) // Back, Down, Fwd , Up -// 12- TRB, B (r), BRB, R (b) // Back, Down, Fwd , Up -// 1->7, 15->9 - -class dBolt { - dStrip v, h; - int vpos, hpos; - dBolt(dStrip _v, dStrip _h, int _vpos, int _hpos) { - v=_v; h=_h; vpos=_vpos; hpos=_hpos; - if (v.b0 == null) { v.b0=this; h.b0=this; } - else { v.b1=this; h.b1=this; } - } -} - -class dVertex { - dStrip s1 , s2 ; - int dir1, dir2 ; - dVertex(dStrip s, int d) { - int _a = (s.iS%4==1)? (d==1? 5: 3) : - (s.iS%4==3)? (d==1? 9:11) : - (d==1) ? (s.Top()?4:12) : (s.Top()?12:4); - dir1 = d * (s.isVert() ? -1 : 1); - dir2 = d; - s1 = DL_.DS[s.iCube() + ((s.iS+_a) % 16)]; - s2 = DL_.DS[d == 1 ? (s.idx == s.iFace()+3 ? s.idx-3 : s.idx+1): - (s.idx == s.iFace() ? s.idx+3 : s.idx-1)]; - swapout(1 , 6); - swapout(15,-6); - } - void swapout(int a, int b) { - if (s1.iS == a) { s1 = DL_.DS[s1.idx + b]; dir1 = -dir1; } - if (s2.iS == a) { s2 = DL_.DS[s2.idx + b]; dir2 = -dir2; } - } - -} - -class dStrip { // THIS WAS SUCH A PAIN! - int row, col, ci, idx, iS, axis; // 1-y, 2-left, 3-right - Strip s; - boolean bTop; // direction: top ccw, bottom cw. - - boolean Top (){ return axis!=1 && bTop ; } - boolean Bottom(){ return axis!=1 && !bTop; } - boolean isVert(){ return axis==1; } - boolean isHorz(){ return axis!=1; } - int iCube (){ return 16*floor(idx/16); } - int iFace (){ return iCube() + 4*floor(iS/4); } - - void init(Strip _s, int _i, int _row, int _col) { - idx = _i; row = _row; col = _col; s = _s; - iS = idx%16; bTop = (iS%4==0); - ci = s.points.get(0).index; - DL_.DQ[col][row] = iCube(); - switch (iS) { - case 4: case 6 : case 12: case 14: axis=2; break; - case 0: case 2 : case 8 : case 10: axis=3; break; - default: axis=1; break; - } - } - - void addBolts() { - v0 = new dVertex(this, 1); - v1 = new dVertex(this,-1); - - - if (iS == 7 && col != 0 && row != 0) // left bottom - new dBolt(this, DL_.GetStrip(row-1,col-1,(col % 2 == 1) ? 8 : 12), - 4, (col % 2 == 1) ? 6 : 9); - - if (iS == 7 && col != 0 && row < MaxCubeHeight*2-2) // left top - new dBolt(this, DL_.GetStrip(row+1,col-1,(col % 2 == 1) ? 10 : 14), - 11, (col % 2 == 1) ? 9 : 6); - - if (iS == 9 && col < NumBackTowers-1 && row < MaxCubeHeight*2-2) // right top - new dBolt(this, DL_.GetStrip(row+1,col+1,(col % 2 == 1) ? 6 : 2), - 4, (col % 2 == 1) ? 6 : 9); - - if (iS == 9 && col < NumBackTowers-1 && row != 0) // right bottom - new dBolt(this, DL_.GetStrip(row-1,col+1,(col % 2 == 1) ? 4 : 0), - 11, (col % 2 == 1) ? 9 : 6); - } - - dBolt b0, b1; - dVertex v0, v1; -} - -class dCursor { - dStrip s, sNext; - int nLast,pos,posNext,end; // 0 - 65535 - int dir; // 1 or -1 - color clr; - - dCursor(color _c) { clr=_c;} - - boolean isDone() { return pos==end; } - void set(dStrip _s, int _dir) { - s=_s; dir=_dir; pos = 0; end=65536; nLast=-1; sNext=null; - } - - boolean MakeTurn(dBolt b) { - int nEnd= (s.isVert() ? b.vpos : b.hpos) <<12; - nEnd= (dir==1 ? nEnd : 65536-nEnd); - if (nEnd < pos) return false; - if (s.isVert()) { sNext = b.h; posNext = b.hpos<<12; end = nEnd; } - else { sNext = b.v; posNext = b.vpos<<12; end = nEnd; } - return true; - } - - void PickNext() { - if (sNext != null) { - if (end == 65536) exit(); - end = 65536; - pos = posNext; - dir = randDir(); - if (dir<0) pos = end-pos; - s = sNext; sNext = null; - nLast = -1; - return;// could switch again!! - } else { - dVertex v = (dir == 1 ? s.v0 : s.v1); - int r = floor(random(2)); - set(r==0 ? v.s1 : v.s2,r==0 ? v.dir1 : v.dir2); - } - - // plan to turn the corner - if (random(6)<1 && s.b0 != null && MakeTurn(s.b0)) return; - if (random(6)<1 && s.b1 != null && MakeTurn(s.b1)) return; - } -} - -int randDir() { return round(random(1))*2-1; } - -class dLattice { - int iTowerStrips=-1; - dStrip[] DS = new dStrip[glucose.model.strips.size()]; - int[][] DQ = new int[NumBackTowers][MaxCubeHeight*2]; - - int nStrips() { return iTowerStrips; } - dStrip GetStrip (int row, int col, int off) { return DS[DQ[col][row]+off]; } - dLattice() { - DL_=this; - int col = 0, row = -2, i=-1; - for (Strip strip : glucose.model.strips ) { i++; - if (i % 16 == 0) row+=2; - if (row >= MaxCubeHeight*2-1) { col++; row = (col%2==1)?1:0; } - if (col >= NumBackTowers) continue; - iTowerStrips++ ; - dStrip s = DS[iTowerStrips] = new dStrip(); - s.init(strip, iTowerStrips, row, col); - } - - for (int j=0; j> 12); - int nTo = min(15,(c.pos+nAmount) >> 12); c.nLast=nTo; - int nMv = min(nAmount, c.end-c.pos); - c.pos += nMv; - for (int i = nFrom; i <= nTo; i++) { - int n = c.s.ci + (c.dir>0 ? i : 15-i); - colors[n] = c.clr; - } - return nAmount - nMv; - } - - float StripsPerSec = 6; - float TrailTime = 1500; - int Cursors = 40; - dCursor cur[] = new dCursor[Cursors]; - - Worms(GLucose glucose) { - super(glucose); - if (DL_ == null) DL_ = new dLattice(); - for (int i=0; i= d.vpos) colors[d.v.ci+i] = color(0,0,30); - if (s == d.h && i >= d.hpos) colors[d.h.ci+i] = color(0,0,30); - }} - } - } else { - for (int i=0; i 0) { - nLeft = draw(cur[i], nLeft); - if (cur[i].isDone()) cur[i].PickNext(); - } - } - - for (int i=0,s=model.points.size(); i0) colors[i] = color(hue(c), saturation(c), - (float)(b-100*deltaMs/TrailTime)); - } - } - } -} -//---------------------------------------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------------------------------------- +public class Pong extends DPat { + SinLFO x,y,z,dx,dy,dz; + float cRad; DParam pSize; + Pick pChoose; + xyz v = new xyz(), vMir = new xyz(); + + 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.4 ); + pChoose = addPick ("Animiation" , 0, 2, new String[] {"Pong", "Ball", "Cone"} ); + } + + void StartRun(double deltaMs) { cRad = mMax.x*pSize.Val()/6; } + color CalcPoint(xyz 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.subtract(p); + return lx.hsb(0,0,c1c(1 - min(v.distance(p), v.distance(vMir))*.5/cRad)); // balls + case 1: return lx.hsb(0,0,c1c(1 - v.distance(p)*.5/cRad)); // ball + case 2: vMir.set(mMax.x/2,0,mMax.z/2); + return lx.hsb(0,0,c1c(1 - CalcCone(p,v,vMir) * max(.02,.45-pSize.Val()))); // spot + } + return lx.hsb(0,0,0); + } +} +//---------------------------------------------------------------------------------------------------------------------------------- +public class NDat { + float xz, yz, zz, hue, sat, speed, angle, den; + float xoff,yoff,zoff; + float sinAngle, cosAngle; + boolean isActive; + NDat () { isActive=false; } + boolean Active() { return isActive; } + void set (float _hue, float _sat, float _xz, float _yz, float _zz, float _den, float _speed, float _angle) { + isActive = true; + hue=_hue; sat=_sat; xz=_xz; yz=_yz; zz =_zz; den=_den; speed=_speed; angle=_angle; + xoff = random(100e3); yoff = random(100e3); zoff = random(100e3); + } +} + +public class Noise extends DPat +{ + int CurAnim, iSymm; + int XSym=1,YSym=2,RadSym=3; + float zTime , zTheta=0, zSin, zCos, rtime, ttime, transAdd; + DParam pSpeed , pDensity; + Pick pChoose, pSymm; + int _ND = 4; + NDat N[] = new NDat[_ND]; + + Noise(GLucose glucose) { + super(glucose); + pSpeed = addParam("Fast" , .55); + pDensity = addParam("Dens" , .5); + 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(); + } + + void StartPattern() { zTime = random(500); zTheta=0; rtime = 0; ttime = 0; transAdd=0; } + void StartRun(double deltaMs) { + zTime += deltaMs*(pSpeed.Val()-.5)*.002 ; + zTheta += deltaMs*(pSpin .Val()-.5)*.01 ; + rtime += deltaMs; + iSymm = pSymm.Cur(); + transAdd = 1*(1 - constrain(rtime - ttime,0,1000)/1000); + 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 sat xz yz zz den mph angle + case 0: N[0].set(0 ,0 ,75 ,75 ,150,45 ,3 ,0 ); pSharp.set(1 ); break; // drip + case 1: N[0].set(0 ,0 ,100,100,200,45 ,3 ,180); pSharp.set(0 ); break; // clouds + case 2: N[0].set(0 ,0 ,2 ,400,2 ,20 ,3 ,0 ); pSharp.set(.5); break; // rain + case 3: N[0].set(40 ,1 ,100,100,200,10 ,1 ,180); + N[1].set(0 ,1 ,100,100,200,10 ,5 ,180); pSharp.set(0 ); break; // fire 1 + case 4: N[0].set(0 ,1 ,40 ,40 ,40 ,15 ,2.5,180); + N[1].set(20 ,1 ,40 ,40 ,40 ,15 ,4 ,0 ); + N[2].set(40 ,1 ,40 ,40 ,40 ,15 ,2 ,90 ); + N[3].set(60 ,1 ,40 ,40 ,40 ,15 ,3 ,-90); pSharp.set(.5); break; // machine + case 5: N[0].set(0 ,1 ,400,100,2 ,15 ,3 ,90 ); + N[1].set(20 ,1 ,400,100,2 ,15 ,2.5,0 ); + N[2].set(40 ,1 ,100,100,2 ,15 ,2 ,180); + N[3].set(60 ,1 ,100,100,2 ,15 ,1.5,270); pSharp.set(.5); break; // spark + } + + DG.UpdateLights(); + } + + 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)); + } + } + + color CalcPoint(xyz P) { + color c = 0; + P.RotateZ(mCtr, zSin, zCos); + + if (CurAnim == 6 || CurAnim == 7) { + P.setNorm(); + return lx.hsb(0,0, 100 * ( + constrain(1-50*(1-pDensity.Val())*abs(P.y-sin(zTime*10 + P.x*(300))*.5 - .5),0,1) + + (CurAnim == 7 ? constrain(1-50*(1-pDensity.Val())*abs(P.x-sin(zTime*10 + P.y*(300))*.5 - .5),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-Dist(P,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.8; + + b += n.den/100 -.4 + pDensity.Val() -1; + b += transAdd; + c = blendColor(c,color(n.hue,100*n.sat,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; + float fixAngle (float a, float b) { return a abs(a+2*PI-b) ? a : a+2*PI) : + (abs(a-b) > abs(a-2*PI-b) ? a : a-2*PI) ; } + float getX(float r) { return mCtr.x + _cos*r; } + float getY(float r) { return mCtr.y + _sin*r; } + void move() { c = interp(t,prvA,dstA); + r = interp(t,prvR,dstR); + _cos = cos(c); _sin = sin(c); + x = getX(r); y = getY(r); } + void set() { prvA = dstA; dstA = random(2*PI); prvA = fixAngle(prvA, dstA); + prvR = dstR; dstR = random(mCtr.y); } + } + + int nBeats = 0; + DParam pAmp, pRadius, pBounce; + + float t,amp,rad,bnc; + float zTheta=0; + ArrayList waves = new ArrayList(10); + + rAngle a1 = new rAngle(), a2 = new rAngle(), + a3 = new rAngle(), a4 = new rAngle(); + xyz cPrev = new xyz(), cRand = new xyz(), + cMid = new xyz(), V = new xyz(), + Theta = new xyz(), TSin = new xyz(), + TCos = new xyz(), cMidNorm = new xyz(), + Pn = new xyz(); + float LastBeat=3, LastMeasure=3; + int CurRandTempo = 1, CurRandTPat = 1; + + Pick pTimePattern, pTempoMult, pShape; + int RandCube; + + Play(GLucose glucose) { + super(glucose); + pRadius = addParam("Rad" , .1 ); + pBounce = addParam("Bnc" , .2 ); + pAmp = addParam("Amp" , .2 ); + pTempoMult = addPick ("TMult" , 0 , 5 , new String[] {"1x", "2x", "4x", "8x", "16x", "Rand" } ); + pTimePattern= addPick ("TPat" , 6 , 7 , new String[] {"Bounce", "Sin", "Roll", "Quant", "Accel", "Deccel", "Slide", "Rand"} ); + pShape = addPick ("Shape" , 3 , 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; } + void move(double deltaMs) { + t += deltaMs*.001; + if (t>4) bDone=true; + } + 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)/(.2*len)); // * max(0,1-t/dur) + return -a*sin(dist); + } + } + + void StartPattern() { zTheta=0; } + void StartRun(double deltaMs) { + t = lx.tempo.rampf(); + amp = pAmp.Val(); + rad = pRadius.getValuef(); + bnc = pBounce.getValuef(); + zTheta += deltaMs*(pSpin .Val()-.5)*.01; + + Theta .set(pRotX.Val()*PI*2, pRotY.Val()*PI*2, pRotZ.Val()*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 6 ? 2+int(random(5)) : int(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. )%1.; break; + case 2: t = (t*4. )%1.; break; + case 3: t = (t*8. )%1.; break; + case 4: t = (t*16.)%1.; 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-1) { + waves.add(new rWave( + pKey.b ? map(DG.KeyPressed,0,7,0,1) : random(1), // location + bnc*10, // bounciness + 7, // velocity + 2*(1-amp))); // dampiness + DG.KeyPressed=-1; + if (waves.size() > 5) waves.remove(0); + } + + if (t .5?1:0)); // cone + + case 12: return lx.hsb(100 + noise(Pn.x,Pn.y,Pn.z + (NoiseMove+50000)/1000.)*200, + 85,c1c(Pn.y < noise(Pn.x + NoiseMove/2000.,Pn.z)*(1+amp)-amp/2.-.1 ? 1 : 0)); // noise + + case 13: float y=0; for (rWave w : waves) y += .5*w.val(Pn.x); + V.set(Pn.x, .7+y, Pn.z); + break; + + default: return lx.hsb(0,0,0); + } + + return lx.hsb(0, + 150-c1c(1 - V.distance(Pn)/rad), + c1c(1 - V.distance(Pn)/rad)); + } +} +//---------------------------------------------------------------------------------------------------------------------------------- +// 0 - TLB, L (b), BLB, B (l) // Fwd , Down, Back, Up +// 4 - TLF, F (l), BLF, L (f) // Fwd , Down, Back, Up +// 8 - TRF, R (f), BRF, F (r) // Back, Down, Fwd , Up +// 12- TRB, B (r), BRB, R (b) // Back, Down, Fwd , Up +// 1->7, 15->9 + +int randDir() { return round(random(1))*2-1; } +//---------------------------------------------------------------------------------------------------------------------------------- +boolean dDebug = true; +class dCursor { + dVertex v, vNext; + int pos,posNext; // 0 - 65535 + int stop; // 0-15 + color clr; + + dCursor(color _c) { clr=_c;} + + boolean isDone() { return pos==stop<<12; } + void set(dVertex _v, int _pos) { pos = _pos; v = _v; vNext = null; stop=16; } + + boolean Turn(dTurn t) { + if (t.pos0<<12 < pos) return false; + vNext = t.v; + stop = t.pos0; + posNext = t.pos1<<12; + if (randDir()<0) { vNext = t.v.opp; posNext = (16<<12)-posNext; } + return true; + } + + void PickNext() { + if (vNext != null) { set(vNext, posNext); } + else { set(random(2) < 1 ? v.c0 : v.c1, 0); } + // plan to turn the corner + float r = random(3); + if (r<1 && v.t0 != null && Turn(v.t0)) return; + if (r<2 && v.t1 != null && Turn(v.t1)) return; + } + Point p1, p2; int i2; +} + +//---------------------------------------------------------------------------------------------------------------------------------- +class Worms extends SCPattern { + float StripsPerSec = 10; + float TrailTime = 1000; + int Cursors = 25; + dCursor cur[] = new dCursor[Cursors]; + + int draw(dCursor c, int nAmount) { + int nFrom = (c.pos ) >> 12; + int nMv = min(nAmount, (c.stop<<12)-c.pos); + int nTo = min(15,(c.pos+nMv) >> 12); + + if (dDebug) { c.p1 = c.v.getPoint(nFrom); float d = (c.p2 == null ? 0 : PointDist(c.p1,c.p2)); if (d>5) { println("too wide! quitting: " + d); exit(); }} + for (int i = nFrom; i <= nTo; i++) { colors[c.v.ci + c.v.dir*i ] = c.clr; } + if (c.v.same != null) for (int i = nFrom; i <= nTo; i++) { colors[c.v.same.ci + c.v.same.dir*i] = c.clr; } + if (dDebug) { c.p2 = c.v.getPoint(nTo); c.i2 = nTo; } + + c.pos += nMv; return nAmount - nMv; + } + + Worms(GLucose glucose) { + super(glucose); + if (DL_ == null) DL_ = new dLattice(); + for (int i=0; i0) colors[i] = color(hue(c), saturation(c), (float)(b-100*deltaMs/TrailTime)); + } + + for (int i=0; i 0) { nLeft = draw(cur[i], nLeft); if (cur[i].isDone()) cur[i].PickNext(); } + } + } +} +//---------------------------------------------------------------------------------------------------------------------------------- diff --git a/DanKaminsky.pde b/DanKaminsky.pde index 3dd9d14..5364669 100644 --- a/DanKaminsky.pde +++ b/DanKaminsky.pde @@ -84,7 +84,7 @@ class ObjectMuckerEffect extends SCEffect { for(int i=0; i0) b = b < .5 ? pow(b,fSharp) : 1-pow(1-b,fSharp); - if (DG._Trails()>0 && fQuant == 0) b = max(b, (float) (brightness(cOld)/100. - (1-DG._Trails()) * deltaMs/200.)); - if (DG.bSustain == true) b = max(b, (float) (brightness(cOld)/100.)); + if (DG._Trails()>0 && fQuant == 0) b = max(b, (float) (lx.b(cOld)/100. - (1-DG._Trails()) * deltaMs/200.)); + if (DG.bSustain == true) b = max(b, (float) (lx.b(cOld)/100.)); if (pInvert.b) { b = 1-b; s = 1-s; } - colors[p.index] = color( - (hue(cNew) + zSpinHue) % 360, + colors[p.index] = lx.hsb( + (lx.h(cNew) + zSpinHue) % 360, s, 100 * b * DG._Level() ); -// colors[p.index] = color(0,0, p.fx >= modmin.x && p.fy >= modmin.y && p.fz >= modmin.z && -// p.fx <= modmin.x+mMax.x && p.fy <= modmin.y+mMax.y && p.fz <= modmin.z+mMax.z ? 100 : 0); +// colors[p.index] = lx.hsb(0,0, p.x >= modmin.x && p.y >= modmin.y && p.z >= modmin.z && +// p.x <= modmin.x+mMax.x && p.y <= modmin.y+mMax.y && p.z <= modmin.z+mMax.z ? 100 : 0); } } } -//---------------------------------------------------------------------------------------------------------------------------------- \ No newline at end of file +//---------------------------------------------------------------------------------------------------------------------------------- +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, opp, same; + dTurn t0, t1; + dStrip s; + int dir, ci; + + dVertex(dStrip _s, Point _p) { s = _s; ci = _p.index; } + Point getPoint(int i) { return s.s.points.get(dir>0 ? i : 15-i); } + void setOpp(dVertex _opp) { opp = _opp; dir = (ci < opp.ci ? 1 : -1); } +} + +class dStrip { + dVertex v0, v1; + int row, col; + Strip s; + dStrip(Strip _s, int _i, int _row, int _col) { s = _s; row = _row; col = _col; } +} +//---------------------------------------------------------------------------------------------------------------------------------- +float PointDist(Point p1, Point p2) { return dist(p1.x,p1.y,p1.z,p2.x,p2.y,p2.z); } + +class dLattice { + private int iTowerStrips=0; + + dStrip[] DS = new dStrip[glucose.model.strips.size()]; + int[][] DQ = new int[NumBackTowers][MaxCubeHeight*2]; + dStrip GetStrip (int row, int col, int off) { + return (!btwn(off,0,15) || !btwn(row,0,MaxCubeHeight*2-1) || !btwn(col,0,NumBackTowers-1) || DQ[col][row]<0) ? null : + DS[DQ[col][row]+off]; + } + + void addTurn(dVertex v0, int pos0, dVertex v1, int pos1) { dTurn t = new dTurn(pos0, v1, pos1); if (v0.t0 == null) v0.t0=t; else v0.t1=t; } + void setRand(dCursor c) { c.set(DS[floor(random(iTowerStrips))].v0,0); } + float Dist2 (Strip s1, int pos1, Strip s2, int pos2) { return PointDist(s1.points.get(pos1), s2.points.get(pos2)); } + boolean SameSame (Strip s1, Strip s2) { return max(Dist2(s1, 0, s2, 0), Dist2(s1,15, s2,15)) < 5 ; } + boolean SameOpp (Strip s1, Strip s2) { return max(Dist2(s1, 0, s2,15), Dist2(s1,15, s2,0 )) < 5 ; } + boolean SameBar (Strip s1, Strip s2) { return SameSame(s1,s2) || SameOpp(s1,s2); } + void AddJoint (dVertex v1, dVertex v2) { + // should probably replace parallel but further with the new one + if (v1.c0 != null && SameBar(v2.s.s, v1.c0.s.s)) return; + if (v1.c1 != null && SameBar(v2.s.s, v1.c1.s.s)) return; + if (v1.c0 == null) v1.c0 = v2; + else if (v1.c1 == null) v1.c1 = v2; + } + + dLattice() { + DL_=this; + for (int i=0;i= MaxCubeHeight*2-1) { col++; row = (col%2==1)?1:0; } // only include lattice parts! + iTowerStrips++; + dStrip s = DS[iTowerStrips-1] = new dStrip(strip, iTowerStrips-1, row, col); + s.v0 = new dVertex(s,strip.points.get(0 )); + s.v1 = new dVertex(s,strip.points.get(15)); + s.v0.setOpp(s.v1); s.v1.setOpp(s.v0); + if (col < NumBackTowers) DQ[col][row] = 16*floor((iTowerStrips-1)/16); + } + + for (int j=0; j0) 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.s, pos1+1, s2.s, pos2+0); if (d2 < d) { d=d2; pos1++; } } + if (pos2<15) { float d2 = Dist2(s1.s, pos1+0, s2.s, pos2+1); if (d2 < d) { d=d2; pos2++; } } + if (d > 50 || oldD == d) break ; + } + + if (d>5) continue; + addTurn(s1.v0, pos1, s2.v0, pos2); addTurn(s1.v1, 15-pos1, s2.v0, pos2); + addTurn(s2.v0, pos2, s1.v0, pos1); addTurn(s2.v1, 15-pos2, s1.v0, pos1); + + }} + } +} + +dLattice DL_; +//---------------------------------------------------------------------------------------------------------------------------------- diff --git a/GranimPattern.pde b/GranimPattern.pde index abe2237..450c17e 100644 --- a/GranimPattern.pde +++ b/GranimPattern.pde @@ -27,7 +27,7 @@ class Granim extends Graphic { while(width()< g.position+1) { - graphicBuffer.add(color(0,0,0)); + graphicBuffer.add(lx.hsb(0,0,0)); } drawAll(); displayList.put(name , g); @@ -55,7 +55,7 @@ class Granim extends Graphic { while(width()< g.position + g.width()) { - graphicBuffer.add(color(0,0,0)); + graphicBuffer.add(lx.hsb(0,0,0)); } if(g.changed) { @@ -141,7 +141,7 @@ class RedsGraphic extends Graphic { for(int i = 0; i < len ;i++) { - graphicBuffer.add(color(0,255,255)); + graphicBuffer.add(lx.hsb(0,255,255)); } } }; @@ -229,7 +229,7 @@ class ColorDotsGraphic extends Graphic super(); for (int colorVal : colorSequence) { - graphicBuffer.add(color(colorVal, 255, 255)); + graphicBuffer.add(lx.hsb(colorVal, 255, 255)); } changed = true; } diff --git a/JR.pde b/JR.pde index cd494fa..6692baa 100644 --- a/JR.pde +++ b/JR.pde @@ -1,4 +1,4 @@ -color BLACK = color(0, 0, 0); +color BLACK = #000000; class Gimbal extends SCPattern { @@ -121,7 +121,7 @@ class Gimbal extends SCPattern { + pow(nearest_circle_z - c.z * ringExtendParam.getValuef(), 2)); float xy_distance = sqrt(c.x*c.x + c.y*c.y); - return color(this.hue, 100, (1 - distance_to_circle / girth * fadeFromCoreParam.getValuef()) * 100); + return lx.hsb(this.hue, 100, (1 - distance_to_circle / girth * fadeFromCoreParam.getValuef()) * 100); } } @@ -166,18 +166,18 @@ class Zebra extends SCPattern { int stripe_count = 12; float stripe_width = model.xMax / (float)stripe_count; if (Math.floor((c.x) / stripe_width) % 2 == 0) { - return color(hue, 100, 100); + return lx.hsb(hue, 100, 100); } else { - return color((hue + 90) % 360, 100, 100); + return lx.hsb((hue + 90) % 360, 100, 100); } /* OCTANTS if ((isPositiveBit(c.x) + isPositiveBit(c.y) + isPositiveBit(c.z)) % 2 == 0) { - return color(lx.getBaseHuef(), 100, 100); + return lx.hsb(lx.getBaseHuef(), 100, 100); } else { - return color(0, 0, 0); + return lx.hsb(0, 0, 0); } */ } @@ -271,7 +271,7 @@ color specialBlend(color c1, color c2, color c3) { float relative_b2 = b2 / (b1 + b2 + b3); float relative_b3 = b3 / (b1 + b2 + b3); - return color( + 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) diff --git a/JackStahl.pde b/JackStahl.pde index a840882..081ea40 100644 --- a/JackStahl.pde +++ b/JackStahl.pde @@ -64,7 +64,7 @@ class Swim extends SCPattern { 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.)*.3 + abs(p.y-model.yMax/2)*.9 + abs(p.z - model.zMax/2.))) % 360; - colors[p.index] = color(hue_color, 70, v1); + colors[p.index] = lx.hsb(hue_color, 70, v1); } } } @@ -172,7 +172,7 @@ class Balance extends SCPattern { 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.) + abs(p.y-model.yMax/2)*.2 + abs(p.z - model.zMax/2.)*.5)) % 360; - color c = color(hue_color, 80, v1); + color c = lx.hsb(hue_color, 80, v1); // Now draw the spheres for (Sphere s : spheres) { @@ -197,7 +197,7 @@ class Balance extends SCPattern { float sphere_color = (lx.getBaseHuef() - (1 - hueScale.getValuef()) * d/r * 45) % 360; - c = blendColor(c, color((sphere_color + 270) % 360, 60, min(1, value) * 100), ADD); + c = blendColor(c, lx.hsb((sphere_color + 270) % 360, 60, min(1, value) * 100), ADD); } colors[p.index] = c; } diff --git a/MarkSlee.pde b/MarkSlee.pde index ee686b7..649d61c 100644 --- a/MarkSlee.pde +++ b/MarkSlee.pde @@ -1,3 +1,202 @@ +class MidiMusic extends SCPattern { + + private final Map lightMap = new HashMap(); + private final List allLights = new ArrayList(); + + private final Stack newLayers = new Stack(); + + MidiMusic(GLucose glucose) { + super(glucose); + } + + class LightUp extends LXLayer { + + private LinearEnvelope brt = new LinearEnvelope(0, 0, 0); + private Accelerator yPos = new Accelerator(0, 0, 0); + private float xPos; + + LightUp() { + addModulator(brt); + addModulator(yPos); + } + + boolean isAvailable() { + return brt.getValuef() <= 0; + } + + void noteOn(Note note) { + xPos = lerp(0, model.xMax, constrain(0.5 + (note.getPitch() - 64) / 12., 0, 1)); + yPos.setValue(lerp(20, model.yMax, note.getVelocity() / 127.)); + brt.setRangeFromHereTo(lerp(40, 100, note.getVelocity() / 127.), 20).start(); + } + + void noteOff(Note note) { + yPos.setVelocity(0).setAcceleration(-380).start(); + brt.setRangeFromHereTo(0, 1000).start(); + } + + public void run(double deltaMs, color[] colors) { + float bVal = brt.getValuef(); + if (bVal <= 0) { + return; + } + float yVal = yPos.getValuef(); + for (Point p : model.points) { + float b = max(0, bVal - 3*dist(p.x, p.y, xPos, yVal)); + if (b > 0) { + colors[p.index] = blendColor(colors[p.index], lx.hsb( + (lx.getBaseHuef() + abs(p.x - model.cx) + abs(p.y - model.cy)) % 360, + 100, + b + ), ADD); + } + } + } + } + + public synchronized boolean noteOn(Note note) { + if (note.getChannel() == 0) { + for (LightUp light : allLights) { + if (light.isAvailable()) { + light.noteOn(note); + lightMap.put(note.getPitch(), light); + return true; + } + } + LightUp newLight = new LightUp(); + newLight.noteOn(note); + lightMap.put(note.getPitch(), newLight); + synchronized(newLayers) { + newLayers.push(newLight); + } + } else if (note.getChannel() == 1) { + } + 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; + } + + public synchronized void run(double deltaMs) { + setColors(#000000); + 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.5); + 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.74, 0.84)); + } + } + } + + // A little silliness to test the grid API + for (int i = 0; i < 7; ++i) { + for (int j = 0; j < 8; ++j) { + int gi = (int) constrain(j * NUM_DIVISIONS / 8, 0, NUM_DIVISIONS-1); + float b = 1 - 4.*abs((6-i)/7. - gravity[gi].getValuef() / model.yMax); + midiEngine.grid.setState(i, j, (b < 0) ? 0 : 1); + } + } + + float fPos = 1 - lx.tempo.rampf(); + if (fPos < .2) { + fPos = .2 + 4 * (.2 - fPos); + } + float falloff = 100. / (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)*.8 + p.y*.4) % 360, + constrain(130 - p.y*.8, 0, 100), + max(0, 100 - abs(p.y - gravity[gi].getValuef())*falloff) + ); + } + } +} + class ViolinWave extends SCPattern { BasicParameter level = new BasicParameter("LVL", 0.45); @@ -62,7 +261,7 @@ class ViolinWave extends SCPattern { 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], color( + colors[p.index] = blendColor(colors[p.index], lx.hsb( lx.getBaseHuef(), 20, b ), ADD); } @@ -113,7 +312,7 @@ class ViolinWave extends SCPattern { for (Point p : model.points) { int ci = (int) lerp(0, centers.length-1, (p.x - model.xMin) / (model.xMax - model.xMin)); float rFactor = 1.0 - 0.9 * abs(p.x - model.cx) / (model.xMax - model.cx); - colors[p.index] = color( + 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) @@ -170,7 +369,7 @@ class BouncyBalls extends SCPattern { float d = sqrt((p.x-xv)*(p.x-xv) + (p.y-yv)*(p.y-yv) + .1*(p.z-zPos)*(p.z-zPos)); float b = constrain(130 - falloff*d, 0, 100); if (b > 0) { - colors[p.index] = blendColor(colors[p.index], color( + colors[p.index] = blendColor(colors[p.index], lx.hsb( (lx.getBaseHuef() + p.y*.5 + abs(model.cx - p.x) * .5) % 360, max(0, 100 - .45*(p.y - flrLevel)), b @@ -203,7 +402,7 @@ class BouncyBalls extends SCPattern { } } - public boolean noteOnReceived(Note note) { + public boolean noteOn(Note note) { int pitch = (note.getPitch() + note.getChannel()) % NUM_BALLS; balls[pitch].bounce(note.getVelocity()); return true; @@ -252,8 +451,8 @@ class SpaceTime extends SCPattern { for (Strip strip : model.strips) { int i = 0; for (Point p : strip.points) { - colors[p.index] = color( - (lx.getBaseHuef() + 360 - p.fx*.2 + p.fy * .3) % 360, + colors[p.index] = lx.hsb( + (lx.getBaseHuef() + 360 - p.x*.2 + p.y * .3) % 360, constrain(.4 * min(abs(s - sVal1), abs(s - sVal2)), 20, 100), max(0, 100 - fVal*abs(i - pVal*(strip.metrics.numPoints - 1))) ); @@ -301,9 +500,9 @@ class Swarm extends SCPattern { for (Strip strip : model.strips ) { int i = 0; for (Point p : strip.points) { - float fV = max(-1, 1 - dist(p.fx/2., p.fy, fX.getValuef()/2., fY.getValuef()) / 64.); - colors[p.index] = color( - (lx.getBaseHuef() + 0.3 * abs(p.fx - hOffX.getValuef())) % 360, + float fV = max(-1, 1 - dist(p.x/2., p.y, fX.getValuef()/2., fY.getValuef()) / 64.); + colors[p.index] = lx.hsb( + (lx.getBaseHuef() + 0.3 * 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) ); @@ -328,7 +527,7 @@ class SwipeTransition extends SCTransition { float bleedf = 10 + bleed.getValuef() * 200.; float xPos = (float) (-bleedf + progress * (model.xMax + bleedf)); for (Point p : model.points) { - float d = (p.fx - xPos) / bleedf; + float d = (p.x - xPos) / bleedf; if (d < 0) { colors[p.index] = c2[p.index]; } else if (d > 1) { @@ -444,17 +643,17 @@ class BassPod extends SCPattern { float bassLevel = eq.getAverageLevel(0, 5); for (Point p : model.points) { - int avgIndex = (int) constrain(1 + abs(p.fx-model.xMax/2.)/(model.xMax/2.)*(eq.numBands-5), 0, eq.numBands-5); + int avgIndex = (int) constrain(1 + abs(p.x-model.xMax/2.)/(model.xMax/2.)*(eq.numBands-5), 0, eq.numBands-5); float value = 0; for (int i = avgIndex; i < avgIndex + 5; ++i) { value += eq.getLevel(i); } value /= 5.; - float b = constrain(8 * (value*model.yMax - abs(p.fy-model.yMax/2.)), 0, 100); - colors[p.index] = color( - (lx.getBaseHuef() + abs(p.fy - model.cy) + abs(p.fx - model.cx)) % 360, - constrain(bassLevel*240 - .6*dist(p.fx, p.fy, model.cx, model.cy), 0, 100), + float b = constrain(8 * (value*model.yMax - abs(p.y-model.yMax/2.)), 0, 100); + colors[p.index] = lx.hsb( + (lx.getBaseHuef() + abs(p.y - model.cy) + abs(p.x - model.cx)) % 360, + constrain(bassLevel*240 - .6*dist(p.x, p.y, model.cx, model.cy), 0, 100), b ); } @@ -495,7 +694,7 @@ class CubeEQ extends SCPattern { float clrConst = 1.1 + clr.getValuef(); for (Point p : model.points) { - float avgIndex = constrain(2 + p.fx / model.xMax * (eq.numBands-4), 0, eq.numBands-4); + float avgIndex = constrain(2 + p.x / model.xMax * (eq.numBands-4), 0, eq.numBands-4); int avgFloor = (int) avgIndex; float leftVal = eq.getLevel(avgFloor); @@ -511,9 +710,9 @@ class CubeEQ extends SCPattern { float value = lerp(smoothValue, chunkyValue, blockiness.getValuef()); - float b = constrain(edgeConst * (value*model.yMax - p.fy), 0, 100); - colors[p.index] = color( - (480 + lx.getBaseHuef() - min(clrConst*p.fy, 120)) % 360, + 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 ); @@ -552,7 +751,7 @@ class BoomEffect extends SCEffect { for (Point p : model.points) { colors[p.index] = blendColor( colors[p.index], - color(huev, satv, constrain(brightv - falloffv*abs(boom.getValuef() - dist(p.fx, 2*p.fy, 3*p.fz, model.xMax/2, model.yMax, model.zMax*1.5)), 0, 100)), + 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.5)), 0, 100)), ADD); } } @@ -633,13 +832,13 @@ public class PianoKeyPattern extends SCPattern { return base[index % base.length]; } - public boolean noteOnReceived(Note note) { + public boolean noteOn(Note note) { LinearEnvelope env = getEnvelope(note.getPitch()); env.setEndVal(min(1, env.getValuef() + (note.getVelocity() / 127.)), getAttackTime()).start(); return true; } - public boolean noteOffReceived(Note note) { + public boolean noteOff(Note note) { getEnvelope(note.getPitch()).setEndVal(0, getReleaseTime()).start(); return true; } @@ -650,7 +849,7 @@ public class PianoKeyPattern extends SCPattern { float levelf = level.getValuef(); for (Cube c : model.cubes) { float v = max(getBase(i).getValuef() * levelf/4., getEnvelope(i++).getValuef()); - setColor(c, color( + setColor(c, lx.hsb( (huef + 20*v + abs(c.cx-model.xMax/2.)*.3 + c.cy) % 360, min(100, 120*v), 100*v @@ -727,20 +926,20 @@ class CrossSections extends SCPattern { for (Point p : model.points) { color c = 0; - c = blendColor(c, color( - (lx.getBaseHuef() + p.fx/10 + p.fy/3) % 360, - constrain(140 - 1.1*abs(p.fx - model.xMax/2.), 0, 100), - max(0, xlv - xwv*abs(p.fx - xv)) + c = blendColor(c, lx.hsb( + (lx.getBaseHuef() + p.x/10 + p.y/3) % 360, + constrain(140 - 1.1*abs(p.x - model.xMax/2.), 0, 100), + max(0, xlv - xwv*abs(p.x - xv)) ), ADD); - c = blendColor(c, color( - (lx.getBaseHuef() + 80 + p.fy/10) % 360, - constrain(140 - 2.2*abs(p.fy - model.yMax/2.), 0, 100), - max(0, ylv - ywv*abs(p.fy - yv)) + c = blendColor(c, lx.hsb( + (lx.getBaseHuef() + 80 + p.y/10) % 360, + constrain(140 - 2.2*abs(p.y - model.yMax/2.), 0, 100), + max(0, ylv - ywv*abs(p.y - yv)) ), ADD); - c = blendColor(c, color( - (lx.getBaseHuef() + 160 + p.fz / 10 + p.fy/2) % 360, - constrain(140 - 2.2*abs(p.fz - model.zMax/2.), 0, 100), - max(0, zlv - zwv*abs(p.fz - zv)) + c = blendColor(c, lx.hsb( + (lx.getBaseHuef() + 160 + p.z / 10 + p.y/2) % 360, + constrain(140 - 2.2*abs(p.z - model.zMax/2.), 0, 100), + max(0, zlv - zwv*abs(p.z - zv)) ), ADD); colors[p.index] = c; } @@ -773,9 +972,9 @@ class Blinders extends SCPattern { int i = 0; float mv = m[si % m.length].getValuef(); for (Point p : strip.points) { - colors[p.index] = color( - (hv + p.fz + p.fy*hs.getValuef()) % 360, - min(100, abs(p.fx - s.getValuef())/2.), + colors[p.index] = lx.hsb( + (hv + p.z + p.y*hs.getValuef()) % 360, + min(100, abs(p.x - s.getValuef())/2.), max(0, 100 - mv/2. - mv * abs(i - (strip.metrics.length-1)/2.)) ); ++i; @@ -809,9 +1008,9 @@ class Psychedelia extends SCPattern { int i = 0; for (Strip strip : model.strips) { for (Point p : strip.points) { - colors[p.index] = color( - (huev + i*constrain(cv, 0, 2) + p.fz/2. + p.fx/4.) % 360, - min(100, abs(p.fy-sv)), + colors[p.index] = lx.hsb( + (huev + i*constrain(cv, 0, 2) + p.z/2. + p.x/4.) % 360, + min(100, abs(p.y-sv)), max(0, 100 - 50*abs((i%NUM) - mv)) ); } @@ -874,12 +1073,12 @@ class AskewPlanes extends SCPattern { float d = MAX_FLOAT; for (Plane plane : planes) { if (plane.denom != 0) { - d = min(d, abs(plane.av*(p.fx-model.cx) + plane.bv*(p.fy-model.cy) + plane.cv) / plane.denom); + d = min(d, abs(plane.av*(p.x-model.cx) + plane.bv*(p.y-model.cy) + plane.cv) / plane.denom); } } - colors[p.index] = color( - (huev + abs(p.fx-model.cx)*.3 + p.fy*.8) % 360, - max(0, 100 - .8*abs(p.fx - model.cx)), + colors[p.index] = lx.hsb( + (huev + abs(p.x-model.cx)*.3 + p.y*.8) % 360, + max(0, 100 - .8*abs(p.x - model.cx)), constrain(140 - 10.*d, 0, 100) ); } @@ -909,9 +1108,9 @@ class ShiftingPlane extends SCPattern { float dv = d.getValuef(); float denom = sqrt(av*av + bv*bv + cv*cv); for (Point p : model.points) { - float d = abs(av*(p.fx-model.cx) + bv*(p.fy-model.cy) + cv*(p.fz-model.cz) + dv) / denom; - colors[p.index] = color( - (hv + abs(p.fx-model.cx)*.6 + abs(p.fy-model.cy)*.9 + abs(p.fz - model.cz)) % 360, + 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)*.6 + abs(p.y-model.cy)*.9 + abs(p.z - model.cz)) % 360, constrain(110 - d*6, 0, 100), constrain(130 - 7*d, 0, 100) ); @@ -979,15 +1178,15 @@ class Traktor extends SCPattern { 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] = color( + colors[p.index] = lx.hsb( (360 + lx.getBaseHuef() + .8*abs(p.x-model.cx)) % 360, 100, - constrain(9 * (bass[pos]*model.cy - abs(p.fy - model.cy)), 0, 100) + constrain(9 * (bass[pos]*model.cy - abs(p.y - model.cy)), 0, 100) ); - colors[p.index] = blendColor(colors[p.index], color( + colors[p.index] = blendColor(colors[p.index], lx.hsb( (400 + lx.getBaseHuef() + .5*abs(p.x-model.cx)) % 360, 60, - constrain(5 * (treble[pos]*.6*model.cy - abs(p.fy - model.cy)), 0, 100) + constrain(5 * (treble[pos]*.6*model.cy - abs(p.y - model.cy)), 0, 100) ), ADD); } @@ -999,6 +1198,7 @@ class ColorFuckerEffect extends SCEffect { BasicParameter hueShift = new BasicParameter("HSHFT", 0); BasicParameter sat = new BasicParameter("SAT", 1); BasicParameter bright = new BasicParameter("BRT", 1); + float[] hsb = new float[3]; ColorFuckerEffect(GLucose glucose) { super(glucose); @@ -1016,10 +1216,11 @@ class ColorFuckerEffect extends SCEffect { float hMod = hueShift.getValuef(); if (bMod < 1 || sMod < 1 || hMod > 0) { for (int i = 0; i < colors.length; ++i) { - colors[i] = color( - (hue(colors[i]) + hueShift.getValuef()*360.) % 360, - saturation(colors[i]) * sat.getValuef(), - brightness(colors[i]) * bright.getValuef() + lx.RGBtoHSB(colors[i], hsb); + colors[i] = lx.hsb( + (360. * hsb[0] + hueShift.getValuef()*360.) % 360, + 100. * hsb[1] * sat.getValuef(), + 100. * hsb[2] * bright.getValuef() ); } } diff --git a/SamMorrow.pde b/SamMorrow.pde index 0b70698..350615d 100644 --- a/SamMorrow.pde +++ b/SamMorrow.pde @@ -18,7 +18,7 @@ class JazzRainbow extends SamPattern { float a = hv%250; if (i%2 == 0) { for (int b = 0; b < 70; b++) { - colors[(i+b)%colors.length] = color(a+i%250, 100, b*a%100); + colors[(i+b)%colors.length] = lx.hsb(a+i%250, 100, b*a%100); } } } diff --git a/ShaheenGandhi.pde b/ShaheenGandhi.pde index a9428aa..d718e36 100644 --- a/ShaheenGandhi.pde +++ b/ShaheenGandhi.pde @@ -130,7 +130,7 @@ class HelixPattern extends SCPattern { // 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 color(0,0,0); + return lx.hsb(0,0,0); } // Find the appropriate point for the current rotation @@ -146,7 +146,7 @@ class HelixPattern extends SCPattern { // Soften edges by fading brightness. float b = constrain(100*(1 - ((d-.5*girth)/(girth*.5))), 0, 100); - return color((lx.getBaseHuef() + (360*(phase / TWO_PI)))%360, 80, b); + return lx.hsb((lx.getBaseHuef() + (360*(phase / TWO_PI)))%360, 80, b); } } @@ -232,7 +232,7 @@ class HelixPattern extends SCPattern { float t = axis.getTValue(pt) + spokePhase; int spokeIndex = (int)floor((t - tMin + spokePeriod/2) / spokePeriod); if (spokeIndex < 0 || spokeIndex >= basePairs.length) { - return color(0,0,0); + return lx.hsb(0,0,0); } BasePairInfo basePair = basePairs[spokeIndex]; Line spokeLine = basePair.line; @@ -240,7 +240,7 @@ class HelixPattern extends SCPattern { float d = PVector.dist(pt, pointOnSpoke); float b = (PVector.dist(pointOnSpoke, spokeLine.getPoint()) < spokeRadius) ? constrain(100*(1 - ((d-.5*spokeGirth)/(spokeGirth*.5))), 0, 100) : 0.f; float phase = spokeLine.getTValue(pointOnSpoke) < 0 ? basePair.colorPhase1 : basePair.colorPhase2; - return color((lx.getBaseHuef() + (360*(phase / TWO_PI)))%360, 80.f, b); + return lx.hsb((lx.getBaseHuef() + (360*(phase / TWO_PI)))%360, 80.f, b); } void run(double deltaMs) { @@ -259,15 +259,15 @@ class HelixPattern extends SCPattern { color spokeColor = calculateSpokeColor(pt); if (!h1on) { - h1c = color(0,0,0); + h1c = lx.hsb(0,0,0); } if (!h2on) { - h2c = color(0,0,0); + h2c = lx.hsb(0,0,0); } if (!spokesOn) { - spokeColor = color(0,0,0); + spokeColor = lx.hsb(0,0,0); } // The helices are positioned to not overlap. If that changes, diff --git a/SugarCubes.pde b/SugarCubes.pde index f9616b8..893152f 100644 --- a/SugarCubes.pde +++ b/SugarCubes.pde @@ -30,6 +30,8 @@ LXPattern[] patterns(GLucose glucose) { new CubeCurl(glucose), // Slee + // new MidiMusic(glucose), + new Pulley(glucose), new Swarm(glucose), new ViolinWave(glucose), new BouncyBalls(glucose), @@ -101,6 +103,7 @@ LXPattern[] patterns(GLucose glucose) { new TestBassMapping(glucose), new TestFloorMapping(glucose), new TestSpeakerMapping(glucose), + new TestPerformancePattern(glucose), // new TestHuePattern(glucose), // new TestXPattern(glucose), // new TestYPattern(glucose), diff --git a/TestPatterns.pde b/TestPatterns.pde index 2f04698..1c2ea70 100644 --- a/TestPatterns.pde +++ b/TestPatterns.pde @@ -26,7 +26,7 @@ class TestSpeakerMapping extends TestPattern { for (Strip strip : speaker.strips) { float b = 100; for (Point p : strip.points) { - colors[p.index] = color(h % 360, 100, b); + colors[p.index] = lx.hsb(h % 360, 100, b); b = max(0, b - 10); } h += 70; @@ -47,7 +47,7 @@ class TestBassMapping extends TestPattern { for (int si : strips) { float b = 100; for (Point p : model.bassBox.strips.get(si).points) { - colors[p.index] = color(h % 360, 100, b); + colors[p.index] = lx.hsb(h % 360, 100, b); b = max(0, b - 10); } h += 70; @@ -66,7 +66,7 @@ class TestFloorMapping extends TestPattern { for (int si : strutIndices) { float b = 100; for (Point p : model.bassBox.struts.get(si).points) { - colors[p.index] = color(h % 360, 100, b); + colors[p.index] = lx.hsb(h % 360, 100, b); b = max(0, b - 10); } h += 50; @@ -76,7 +76,7 @@ class TestFloorMapping extends TestPattern { for (int fi : floorIndices) { float b = 100; for (Point p : model.boothFloor.strips.get(fi).points) { - colors[p.index] = color(h, 100, b); + colors[p.index] = lx.hsb(h, 100, b); b = max(0, b - 3); } h += 90; @@ -84,6 +84,59 @@ class TestFloorMapping extends TestPattern { } } +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.25) { + for (Point p : model.points) { + colors[p.index] = lx.hsb( + (p.x*.1 + p.y*.1) % 360, + 100, + 100 + ); + } + } else if (iter.getValuef() < 0.5) { + for (int i = 0; i < colors.length; ++i) { + colors[i] = lx.hsb( + (90 + model.px[i]*.1 + model.py[i]*.1) % 360, + 100, + 100 + ); + } + } else if (iter.getValuef() < 0.75) { + for (int i = 0; i < colors.length; ++i) { + colors[i] = lx.hsb( + (180 + model.p[3*i]*.1 + model.p[3*i+1]*.1) % 360, + 100, + 100 + ); + } + } else { + for (int i = 0; i < colors.length; ++i) { + colors[i] = lx.hsb( + (270 + model.x(i)*.1 + model.y(i)*.1) % 360, + 100, + 100 + ); + } + } + } +} + class TestStripPattern extends TestPattern { SinLFO d = new SinLFO(4, 40, 4000); @@ -96,7 +149,7 @@ class TestStripPattern extends TestPattern { public void run(double deltaMs) { for (Strip s : model.strips) { for (Point p : s.points) { - colors[p.index] = color( + colors[p.index] = lx.hsb( lx.getBaseHuef(), 100, max(0, 100 - d.getValuef()*dist(p.x, p.y, s.cx, s.cy)) @@ -119,7 +172,7 @@ class TestHuePattern extends TestPattern { // Access the core master hue via this method call float hv = lx.getBaseHuef(); for (int i = 0; i < colors.length; ++i) { - colors[i] = color(hv, 100, 100); + colors[i] = lx.hsb(hv, 100, 100); } } } @@ -140,8 +193,8 @@ class TestXPattern extends TestPattern { // 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.fx - xPos.getValuef())); - colors[p.index] = color(hv, 100, bv); + float bv = max(0, 100 - abs(p.x - xPos.getValuef())); + colors[p.index] = lx.hsb(hv, 100, bv); } } } @@ -158,8 +211,8 @@ class TestYPattern extends TestPattern { public void run(double deltaMs) { float hv = lx.getBaseHuef(); for (Point p : model.points) { - float bv = max(0, 100 - abs(p.fy - yPos.getValuef())); - colors[p.index] = color(hv, 100, bv); + float bv = max(0, 100 - abs(p.y - yPos.getValuef())); + colors[p.index] = lx.hsb(hv, 100, bv); } } } @@ -176,8 +229,8 @@ class TestZPattern extends TestPattern { public void run(double deltaMs) { float hv = lx.getBaseHuef(); for (Point p : model.points) { - float bv = max(0, 100 - abs(p.fz - zPos.getValuef())); - colors[p.index] = color(hv, 100, bv); + float bv = max(0, 100 - abs(p.z - zPos.getValuef())); + colors[p.index] = lx.hsb(hv, 100, bv); } } } @@ -197,7 +250,7 @@ class TestTowerPattern extends TestPattern { int ti = 0; for (Tower t : model.towers) { for (Point p : t.points) { - colors[p.index] = color( + colors[p.index] = lx.hsb( lx.getBaseHuef(), 100, max(0, 100 - 80*LXUtils.wrapdistf(ti, towerIndex.getValuef(), model.towers.size())) @@ -260,7 +313,7 @@ class TestProjectionPattern extends TestPattern { 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 + .1*abs(c.z) + .02*abs(c.x)); // plane / spear thing - colors[c.index] = color( + colors[c.index] = lx.hsb( (hv + .6*abs(c.x) + abs(c.z)) % 360, 100, constrain(140 - 40*d, 0, 100) @@ -282,7 +335,7 @@ class TestCubePattern extends TestPattern { for (Cube c : model.cubes) { int i = 0; for (Point p : c.points) { - colors[p.index] = color( + colors[p.index] = lx.hsb( lx.getBaseHuef(), 100, max(0, 100 - 80.*abs(i - index.getValuef())) @@ -365,7 +418,7 @@ class MappingTool extends TestPattern { } public void run(double deltaMs) { - color off = color(0, 0, 0); + color off = #000000; color c = off; color r = #FF0000; color g = #00FF00; diff --git a/TimBavaro.pde b/TimBavaro.pde index 4da4b6e..a10e89e 100644 --- a/TimBavaro.pde +++ b/TimBavaro.pde @@ -56,13 +56,13 @@ class TimSpheres extends SCPattern { for (Point p : model.points) { float value = 0; - color c = color(0, 0, 0); + color 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, color(((s.hue + lfoValue) % 1) * 360, 100, min(1, value) * 100), ADD); + c = blendColor(c, lx.hsb(((s.hue + lfoValue) % 1) * 360, 100, min(1, value) * 100), ADD); } colors[p.index] = c; @@ -125,7 +125,7 @@ class Vector3 { } float distanceTo(Point p) { - return distanceTo(p.fx, p.fy, p.fz); + return distanceTo(p.x, p.y, p.z); } void add(Vector3 other, float multiplier) { @@ -249,16 +249,16 @@ class TimRaindrops extends SCPattern { for (Point p : model.points) { color c = blendColor( - color(210, 20, (float)Math.max(0, 1 - Math.pow((model.yMax - p.fy) / 10, 2)) * 50), - color(220, 60, (float)Math.max(0, 1 - Math.pow((p.fy - model.yMin) / 10, 2)) * 100), + 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.fx >= (raindrop.p.x - raindrop.radius) && p.fx <= (raindrop.p.x + raindrop.radius) && - p.fy >= (raindrop.p.y - raindrop.radius) && p.fy <= (raindrop.p.y + raindrop.radius)) { + 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, color(raindrop.hue, 80, (float)Math.pow(1 - d, 0.01) * 100), ADD); + c = blendColor(c, lx.hsb(raindrop.hue, 80, (float)Math.pow(1 - d, 0.01) * 100), ADD); } } } @@ -343,7 +343,7 @@ class TimCubes extends SCPattern { for (CubeFlash flash : flashes) { float hue = (hueParameter.getValuef() + (hueVarianceParameter.getValuef() * flash.hue)) % 1.0; - color c = color(hue * 360, saturationParameter.getValuef() * 100, (flash.value) * 100); + color c = lx.hsb(hue * 360, saturationParameter.getValuef() * 100, (flash.value) * 100); for (Point p : flash.c.points) { colors[p.index] = c; } @@ -464,19 +464,19 @@ class TimPlanes extends SCPattern { color c = 0; for (Plane plane : planes) { - normalizedPoint.x = p.fx - plane.center.x; - normalizedPoint.y = p.fy - plane.center.y; - normalizedPoint.z = p.fz - plane.center.z; + 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 color planeColor; if (d <= thickness) { - planeColor = color(plane.hue, saturation, 100); + planeColor = lx.hsb(plane.hue, saturation, 100); } else if (d <= thickness * 2) { float value = 1 - ((d - thickness) / thickness); - planeColor = color(plane.hue, saturation, value * 100); + planeColor = lx.hsb(plane.hue, saturation, value * 100); } else { planeColor = 0; } @@ -636,20 +636,20 @@ class TimPinwheels extends SCPattern { int value = 0; for (Pinwheel pw : pinwheels) { - value += (pw.isOnBlade(p.fx, p.fy - p.fz * zSlope) ? 1 : 0); + value += (pw.isOnBlade(p.x, p.y - p.z * zSlope) ? 1 : 0); } if (value == 1) { values[i] = 1; -// colors[p.index] = color(120, 0, 100); +// colors[p.index] = lx.hsb(120, 0, 100); } else { values[i] = max(0, values[i] - fadeAmount); //color c = colors[p.index]; - //colors[p.index] = color(max(0, hue(c) - 10), min(100, saturation(c) + 10), brightness(c) - 5 ); + //colors[p.index] = lx.hsb(max(0, lx.h(c) - 10), min(100, lx.s(c) + 10), lx.b(c) - 5 ); } if (random(1.0) >= derez) { float v = values[i]; - colors[p.index] = color((360 + hue + pow(v, 2) * hueSpread) % 360, 30 + pow(1 - v, 0.25) * 60, v * 100); + colors[p.index] = lx.hsb((360 + hue + pow(v, 2) * hueSpread) % 360, 30 + pow(1 - v, 0.25) * 60, v * 100); } } } @@ -746,7 +746,7 @@ class TimTrace extends SCPattern { for (Strip s : model.strips) { Vector3 v = new Vector3(); for (Point p : s.points) { - v.add(p.fx, p.fy, p.fz); + v.add(p.x, p.y, p.z); } v.divide(s.points.size()); stripToCenter.put(s, v); @@ -778,7 +778,7 @@ class TimTrace extends SCPattern { List nearbyStrips = stripToNearbyStrips.get(s); for (Point p : s.points) { - Vector3 v = new Vector3(p.fx, p.fy, p.fz); + Vector3 v = new Vector3(p.x, p.y, p.z); List neighbors = new ArrayList(); @@ -787,7 +787,7 @@ class TimTrace extends SCPattern { float closestPointDistance = 100000; for (Point nsp : nearbyStrip.points) { - float distance = v.distanceTo(nsp.fx, nsp.fy, nsp.fz); + float distance = v.distanceTo(nsp.x, nsp.y, nsp.z); if (closestPoint == null || distance < closestPointDistance) { closestPoint = nsp; closestPointDistance = distance; @@ -819,12 +819,12 @@ class TimTrace extends SCPattern { public void run(double deltaMs) { for (Point p : model.points) { color c = colors[p.index]; - colors[p.index] = color(hue(c), saturation(c), brightness(c) - 3); + 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], color(mp.hue, 10, 100), ADD); + colors[mp.currentPoint.index] = blendColor(colors[mp.currentPoint.index], lx.hsb(mp.hue, 10, 100), ADD); } } } diff --git a/TobySegaran.pde b/TobySegaran.pde index 32b6d82..82ad4d2 100644 --- a/TobySegaran.pde +++ b/TobySegaran.pde @@ -25,12 +25,12 @@ class GlitchPlasma extends SCPattern { public void run(double deltaMs) { for (Point p : model.points) { - float hv = sin(dist(p.fx + pos, p.fy, 128.0, 128.0) / 8.0) - + sin(dist(p.fx, p.fy, 64.0, 64.0) / 8.0) - + sin(dist(p.fx, p.fy + pos / 7, 192.0, 64.0) / 7.0) - + sin(dist(p.fx, p.fz + pos, 192.0, 100.0) / 8.0); + float hv = sin(dist(p.x + pos, p.y, 128.0, 128.0) / 8.0) + + sin(dist(p.x, p.y, 64.0, 64.0) / 8.0) + + sin(dist(p.x, p.y + pos / 7, 192.0, 64.0) / 7.0) + + sin(dist(p.x, p.z + pos, 192.0, 100.0) / 8.0); float bv = 100; - colors[p.index] = color((hv+2)*50, satu, bv); + colors[p.index] = lx.hsb((hv+2)*50, satu, bv); } if (random(1.0)bright[p.index]) { - colors[p.index] = color(hv,sat[i].getValuef(),br); + colors[p.index] = lx.hsb(hv,sat[i].getValuef(),br); bright[p.index] = br; } } @@ -185,9 +185,9 @@ class SoundRain extends SCPattern { Strip s = c.strips.get(j); if (j%4!=0 && j%4!=2) { for (Point p : s.points) { - int seq = int(p.fy*avgSize/model.yMax+pos.getValuef()+sin(p.fx+p.fz)*2)%avgSize; + int seq = int(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] = color(200,max(0,100-abs(p.fx-col1.getValuef())/2),lightVals[seq]); + colors[p.index] = lx.hsb(200,max(0,100-abs(p.x-col1.getValuef())/2),lightVals[seq]); } } } @@ -218,18 +218,18 @@ class FaceSync extends SCPattern { for (Point p : s.points) { float dx, dz; if (i%32 < 16) { - dx = p.fx - (s.cx+xosc.getValuef()); - dz = p.fz - (s.cz+zosc.getValuef()); + dx = p.x - (s.cx+xosc.getValuef()); + dz = p.z - (s.cz+zosc.getValuef()); } else { - dx = p.fx - (s.cx+zosc.getValuef()); - dz = p.fz - (s.cz+xosc.getValuef()); + dx = p.x - (s.cx+zosc.getValuef()); + dz = p.z - (s.cz+xosc.getValuef()); } //println(dx); - float a1=max(0,100-abs(p.fx-col1.getValuef())); - float a2=max(0,100-abs(p.fx-col2.getValuef())); + 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] = color(h,sat,100-abs(dx*5)-abs(dz*5)); + colors[p.index] = lx.hsb(h,sat,100-abs(dx*5)-abs(dz*5)); } } } @@ -287,12 +287,12 @@ class SoundSpikes extends SCPattern { Strip s = c.strips.get(j); if (j%4!=0 && j%4!=2) { for (Point p : s.points) { - float dis = (abs(p.fx-model.xMax/2)+pos.getValuef())%model.xMax/2; + float dis = (abs(p.x-model.xMax/2)+pos.getValuef())%model.xMax/2; int seq = int((dis*avgSize*2)/model.xMax); if (seq>avgSize) seq=avgSize-seq; seq=constrain(seq,0,avgSize-1); - float br=max(0, lightVals[seq]-p.fy); - colors[p.index] = color((dis*avgSize*65)/model.xMax,90,br); + float br=max(0, lightVals[seq]-p.y); + colors[p.index] = lx.hsb((dis*avgSize*65)/model.xMax,90,br); } } } diff --git a/_Internals.pde b/_Internals.pde index d24f13b..3aa9f3a 100644 --- a/_Internals.pde +++ b/_Internals.pde @@ -52,6 +52,7 @@ LXPattern[] patterns; MappingTool mappingTool; PandaDriver[] pandaBoards; MidiEngine midiEngine; +GridController gridController; // Display configuration mode boolean mappingMode = false; @@ -60,6 +61,7 @@ DebugUI debugUI; boolean uiOn = true; LXPattern restoreToPattern = null; PImage logo; +float[] hsb = new float[3]; // Handles to UI objects UIContext[] overlays; @@ -98,7 +100,6 @@ LXPattern[] _rightPatterns(GLucose glucose) { } return rightPatterns; } - void logTime(String evt) { int now = millis(); @@ -122,10 +123,6 @@ void setup() { lx.enableKeyboardTempo(); logTime("Built GLucose engine"); - // MIDI devices - midiEngine = new MidiEngine(); - logTime("Setup MIDI devices"); - // Set the patterns Engine engine = lx.engine; engine.setPatterns(patterns = _leftPatterns(glucose)); @@ -135,7 +132,11 @@ void setup() { logTime("Built transitions"); glucose.lx.addEffects(effects(glucose)); logTime("Built effects"); - + + // MIDI devices + midiEngine = new MidiEngine(); + logTime("Setup MIDI devices"); + // Build output driver PandaMapping[] pandaMappings = buildPandaList(); pandaBoards = new PandaDriver[pandaMappings.length]; @@ -196,16 +197,19 @@ void setup() { void draw() { // Draws the simulation and the 2D UI overlay background(40); - color[] colors = glucose.getColors(); + color[] simulationColors; + color[] sendColors; + simulationColors = sendColors = glucose.getColors(); String displayMode = uiCrossfader.getDisplayMode(); if (displayMode == "A") { - colors = lx.engine.getDeck(0).getColors(); + simulationColors = lx.engine.getDeck(0).getColors(); } else if (displayMode == "B") { - colors = lx.engine.getDeck(1).getColors(); + simulationColors = lx.engine.getDeck(1).getColors(); } if (debugMode) { - debugUI.maskColors(colors); + debugUI.maskColors(simulationColors); + debugUI.maskColors(sendColors); } camera( @@ -251,29 +255,20 @@ void draw() { strokeWeight(2); beginShape(POINTS); for (Point p : glucose.model.points) { - stroke(colors[p.index]); - vertex(p.fx, p.fy, p.fz); + stroke(simulationColors[p.index]); + vertex(p.x, p.y, p.z); } endShape(); // 2D Overlay UI drawUI(); - // Send output colors - color[] sendColors = glucose.getColors(); - if (debugMode) { - debugUI.maskColors(sendColors); - } - // Gamma correction here. Apply a cubic to the brightness // for better representation of dynamic range for (int i = 0; i < sendColors.length; ++i) { - float b = brightness(sendColors[i]) / 100.f; - sendColors[i] = color( - hue(sendColors[i]), - saturation(sendColors[i]), - (b*b*b) * 100. - ); + lx.RGBtoHSB(sendColors[i], hsb); + float b = hsb[2]; + sendColors[i] = lx.hsb(360.*hsb[0], 100.*hsb[1], 100.*(b*b*b)); } // TODO(mcslee): move into GLucose engine @@ -458,6 +453,11 @@ void keyPressed() { } } break; + case 't': + if (!midiEngine.isQwertyEnabled()) { + lx.engine.setThreaded(!lx.engine.isThreaded()); + } + break; case 'p': for (PandaDriver p : pandaBoards) { p.toggle(); @@ -512,7 +512,7 @@ void mouseReleased() { } } -void mouseWheel(int delta) {delta*=20; +void mouseWheel(int delta) { boolean wheeled = false; for (UIContext context : overlays) { wheeled |= context.mouseWheel(mouseX, mouseY, delta); diff --git a/_MIDI.pde b/_MIDI.pde index 68cc832..b0b8fc4 100644 --- a/_MIDI.pde +++ b/_MIDI.pde @@ -22,6 +22,7 @@ interface MidiEngineListener { class MidiEngine { + public final GridController grid; private final List listeners = new ArrayList(); private final List midiControllers = new ArrayList(); @@ -41,17 +42,22 @@ class MidiEngine { private int activeDeckIndex = 0; public MidiEngine() { - - midiControllers.add(midiQwertyKeys = new SCMidiInput(SCMidiInput.KEYS)); - midiControllers.add(midiQwertyAPC = new SCMidiInput(SCMidiInput.APC)); + grid = new GridController(this); + midiControllers.add(midiQwertyKeys = new VirtualKeyMidiInput(this, VirtualKeyMidiInput.KEYS)); + midiControllers.add(midiQwertyAPC = new VirtualKeyMidiInput(this, VirtualKeyMidiInput.APC)); for (MidiInputDevice device : RWMidi.getInputDevices()) { if (device.getName().contains("APC")) { - midiControllers.add(new APC40MidiInput(device).setEnabled(true)); + midiControllers.add(new APC40MidiInput(this, device).setEnabled(true)); } else if (device.getName().contains("SLIDER/KNOB KORG")) { - midiControllers.add(new KorgNanoKontrolMidiInput(device).setEnabled(true)); + midiControllers.add(new KorgNanoKontrolMidiInput(this, device).setEnabled(true)); } else { - boolean enabled = device.getName().contains("KEYBOARD KORG"); - midiControllers.add(new SCMidiInput(device).setEnabled(enabled)); + boolean enabled = device.getName().contains("KEYBOARD KORG") || device.getName().contains("Bus 1 Apple"); + midiControllers.add(new GenericDeviceMidiInput(this, device).setEnabled(enabled)); + } + } + for (MidiOutputDevice device : RWMidi.getOutputDevices()) { + if (device.getName().contains("APC")) { + new APC40MidiOutput(this, device); } } } @@ -60,6 +66,14 @@ class MidiEngine { return this.midiControllers; } + public Engine.Deck getFocusedDeck() { + return lx.engine.getDeck(activeDeckIndex); + } + + public SCPattern getFocusedPattern() { + return (SCPattern) getFocusedDeck().getActivePattern(); + } + public MidiEngine setFocusedDeck(int deckIndex) { if (this.activeDeckIndex != deckIndex) { this.activeDeckIndex = deckIndex; @@ -70,10 +84,6 @@ class MidiEngine { return this; } - public Engine.Deck getFocusedDeck() { - return lx.engine.getDeck(activeDeckIndex); - } - public boolean isQwertyEnabled() { return midiQwertyKeys.isEnabled() || midiQwertyAPC.isEnabled(); } @@ -83,30 +93,20 @@ public interface SCMidiInputListener { public void onEnabled(SCMidiInput controller, boolean enabled); } -public class SCMidiInput extends AbstractScrollItem { +public abstract class SCMidiInput extends AbstractScrollItem { - public static final int MIDI = 0; - public static final int KEYS = 1; - public static final int APC = 2; - - private boolean enabled = false; + protected boolean enabled = false; private final String name; - private final int mode; - private int octaveShift = 0; - - class NoteMeta { - int channel; - int number; - NoteMeta(int channel, int number) { - this.channel = channel; - this.number = number; - } - } - final Map keyToNote = new HashMap(); + protected final MidiEngine midiEngine; final List listeners = new ArrayList(); + protected SCMidiInput(MidiEngine midiEngine, String name) { + this.midiEngine = midiEngine; + this.name = name; + } + public SCMidiInput addListener(SCMidiInputListener l) { listeners.add(l); return this; @@ -117,25 +117,127 @@ public class SCMidiInput extends AbstractScrollItem { return this; } - SCMidiInput(MidiInputDevice d) { - mode = MIDI; - d.createInput(this); - name = d.getName().replace("Unknown vendor",""); + public String getLabel() { + return name; + } + + public boolean isEnabled() { + return enabled; + } + + public boolean isSelected() { + return enabled; + } + + public void onMousePressed() { + setEnabled(!enabled); + } + + public SCMidiInput setEnabled(boolean enabled) { + if (enabled != this.enabled) { + this.enabled = enabled; + for (SCMidiInputListener l : listeners) { + l.onEnabled(this, enabled); + } + } + return this; + } + + private boolean logMidi() { + return (uiMidi != null) && uiMidi.logMidi(); + } + + final void programChangeReceived(ProgramChange pc) { + if (!enabled) { + return; + } + if (logMidi()) { + println(getLabel() + " :: Program Change :: " + pc.getNumber()); + } + handleProgramChange(pc); + } + + final void controllerChangeReceived(rwmidi.Controller cc) { + if (!enabled) { + return; + } + if (logMidi()) { + println(getLabel() + " :: Controller :: " + cc.getChannel() + " :: " + cc.getCC() + ":" + cc.getValue()); + } + if (!handleGridControllerChange(cc)) { + if (!midiEngine.getFocusedPattern().controllerChange(cc)) { + handleControllerChange(cc); + } + } + } + + final void noteOnReceived(Note note) { + if (!enabled) { + return; + } + if (logMidi()) { + println(getLabel() + " :: Note On :: " + note.getChannel() + ":" + note.getPitch() + ":" + note.getVelocity()); + } + if (!handleGridNoteOn(note)) { + if (!midiEngine.getFocusedPattern().noteOn(note)) { + handleNoteOn(note); + } + } + } + + final void noteOffReceived(Note note) { + if (!enabled) { + return; + } + if (logMidi()) { + println(getLabel() + " :: Note Off :: " + note.getChannel() + ":" + note.getPitch() + ":" + note.getVelocity()); + } + if (!handleGridNoteOff(note)) { + if (!midiEngine.getFocusedPattern().noteOff(note)) { + handleNoteOff(note); + } + } } - SCMidiInput(int mode) { + // Subclasses may implement these to map top-level functionality + protected boolean handleGridNoteOn(Note note) { return false; } + protected boolean handleGridNoteOff(Note note) { return false; } + protected boolean handleGridControllerChange(rwmidi.Controller cc) { return false; } + protected void handleProgramChange(ProgramChange pc) {} + protected void handleControllerChange(rwmidi.Controller cc) {} + protected void handleNoteOn(Note note) {} + protected void handleNoteOff(Note note) {} +} + +public class VirtualKeyMidiInput extends SCMidiInput { + + public static final int KEYS = 1; + public static final int APC = 2; + + private final int mode; + + private int octaveShift = 0; + + class NoteMeta { + int channel; + int number; + NoteMeta(int channel, int number) { + this.channel = channel; + this.number = number; + } + } + + final Map keyToNote = new HashMap(); + + VirtualKeyMidiInput(MidiEngine midiEngine, int mode) { + super(midiEngine, "QWERTY (" + (mode == APC ? "APC" : "Key") + " Mode)"); this.mode = mode; - switch (mode) { - case APC: - name = "QWERTY (APC Mode)"; + if (mode == APC) { mapAPC(); - break; - default: - case KEYS: - name = "QWERTY (Key Mode)"; + } else { mapKeys(); - break; } + registerKeyEvent(this); } private void mapAPC() { @@ -163,7 +265,6 @@ public class SCMidiInput extends AbstractScrollItem { mapNote('v', 3, 56); mapNote('b', 4, 56); mapNote('n', 5, 56); - registerKeyEvent(this); } private void mapKeys() { @@ -183,17 +284,12 @@ public class SCMidiInput extends AbstractScrollItem { mapNote('k', 1, note++); mapNote('o', 1, note++); mapNote('l', 1, note++); - registerKeyEvent(this); } void mapNote(char ch, int channel, int number) { keyToNote.put(ch, new NoteMeta(channel, number)); } - - public String getLabel() { - return name; - } - + public void keyEvent(KeyEvent e) { if (!enabled) { return; @@ -221,101 +317,56 @@ public class SCMidiInput extends AbstractScrollItem { } } } +} - public boolean isEnabled() { - return enabled; - } - - public boolean isSelected() { - return enabled; - } - - public void onMousePressed() { - setEnabled(!enabled); - } - - public SCMidiInput setEnabled(boolean enabled) { - if (enabled != this.enabled) { - this.enabled = enabled; - for (SCMidiInputListener l : listeners) { - l.onEnabled(this, enabled); - } - } - return this; +public class GenericDeviceMidiInput extends SCMidiInput { + GenericDeviceMidiInput(MidiEngine midiEngine, MidiInputDevice d) { + super(midiEngine, d.getName().replace("Unknown vendor","")); + d.createInput(this); } +} - protected SCPattern getFocusedPattern() { - return (SCPattern) midiEngine.getFocusedDeck().getActivePattern(); - } +public class APC40MidiInput extends GenericDeviceMidiInput { - private boolean logMidi() { - return (uiMidi != null) && uiMidi.logMidi(); + private boolean shiftOn = false; + private LXEffect releaseEffect = null; + + APC40MidiInput(MidiEngine midiEngine, MidiInputDevice d) { + super(midiEngine, d); } - final void programChangeReceived(ProgramChange pc) { - if (!enabled) { - return; - } - if (logMidi()) { - println(getLabel() + " :: Program Change :: " + pc.getNumber()); + private class GridPosition { + public final int row, col; + GridPosition(int r, int c) { + row = r; + col = c; } - handleProgramChange(pc); } - - final void controllerChangeReceived(rwmidi.Controller cc) { - if (!enabled) { - return; - } - if (logMidi()) { - println(getLabel() + " :: Controller :: " + cc.getCC() + ":" + cc.getValue()); - } - if (!getFocusedPattern().controllerChangeReceived(cc)) { - handleControllerChange(cc); + + private GridPosition getGridPosition(Note note) { + int channel = note.getChannel(); + int pitch = note.getPitch(); + if (channel < 8) { + if (pitch >= 53 && pitch <=57) return new GridPosition(pitch-53, channel); + else if (pitch == 52) return new GridPosition(5, channel); } + return null; } - final void noteOnReceived(Note note) { - if (!enabled) { - return; - } - if (logMidi()) { - println(getLabel() + " :: Note On :: " + note.getChannel() + ":" + note.getPitch() + ":" + note.getVelocity()); - } - if (!getFocusedPattern().noteOnReceived(note)) { - handleNoteOn(note); + protected boolean handleGridNoteOn(Note note) { + GridPosition p = getGridPosition(note); + if (p != null) { + return midiEngine.grid.gridPressed(p.row, p.col); } + return false; } - final void noteOffReceived(Note note) { - if (!enabled) { - return; - } - if (logMidi()) { - println(getLabel() + " :: Note Off :: " + note.getChannel() + ":" + note.getPitch() + ":" + note.getVelocity()); - } - if (!getFocusedPattern().noteOffReceived(note)) { - handleNoteOff(note); + protected boolean handleGridNoteOff(Note note) { + GridPosition p = getGridPosition(note); + if (p != null) { + return midiEngine.grid.gridReleased(p.row, p.col); } - } - - // Subclasses may implement these to map top-level functionality - protected void handleProgramChange(ProgramChange pc) { - } - protected void handleControllerChange(rwmidi.Controller cc) { - } - protected void handleNoteOn(Note note) { - } - protected void handleNoteOff(Note note) { - } -} - -public class APC40MidiInput extends SCMidiInput { - - private boolean shiftOn = false; - private LXEffect releaseEffect = null; - - APC40MidiInput(MidiInputDevice d) { - super(d); + return false; } protected void handleControllerChange(rwmidi.Controller cc) { @@ -334,7 +385,7 @@ public class APC40MidiInput extends SCMidiInput { parameterIndex = 8 + (number-16); } if (parameterIndex >= 0) { - List parameters = getFocusedPattern().getParameters(); + List parameters = midiEngine.getFocusedPattern().getParameters(); if (parameterIndex < parameters.size()) { parameters.get(parameterIndex).setValue(cc.getValue() / 127.); } @@ -349,43 +400,52 @@ public class APC40MidiInput extends SCMidiInput { } } - + private long tap1 = 0; - private double Tap1 = 0; - private double getNow() { return millis() + 1000*second() + 60*1000*minute() + 3600*1000*hour(); } - private boolean dbtwn (double a,double b,double c) { return a >= b && a <= c; } + private boolean lbtwn(long a, long b, long c) { + return a >= b && a <= c; + } protected void handleNoteOn(Note note) { - int nPitch = note.getPitch(), nChan = note.getChannel(); + int nPitch = note.getPitch(), nChan = note.getChannel(); switch (nPitch) { - case 82: EFF_boom .trigger(); break; // BOOM! - case 83: EFF_flash .trigger(); break; // Flash - - case 90: lx.tempo.trigger(); Tap1 = getNow(); break; // dan's dirty tapping mechanism + case 82: // scene 1 + EFF_boom.trigger(); + break; + + case 83: // scene 2 + EFF_flash.trigger(); + break; + + case 90: + // dan's dirty tapping mechanism + lx.tempo.trigger(); + tap1 = millis(); + break; case 91: // play - case 95: // bank + case 97: // left bank midiEngine.setFocusedDeck(0); break; case 93: // rec - case 94: // right bank + case 96: // right bank midiEngine.setFocusedDeck(1); break; - case 96: // up bank + case 94: // up bank if (shiftOn) { - glucose.incrementSelectedEffectBy(1); + glucose.incrementSelectedEffectBy(-1); } else { - midiEngine.getFocusedDeck().goNext(); + midiEngine.getFocusedDeck().goPrev(); } break; - case 97: // down bank + case 95: // down bank if (shiftOn) { - glucose.incrementSelectedEffectBy(-1); + glucose.incrementSelectedEffectBy(1); } else { - midiEngine.getFocusedDeck().goPrev(); + midiEngine.getFocusedDeck().goNext(); } break; @@ -403,7 +463,7 @@ public class APC40MidiInput extends SCMidiInput { lx.tempo.setBpm(lx.tempo.bpm() - (shiftOn ? 1 : .1)); break; - case 62: // Detail View + case 62: // Detail View / red 5 releaseEffect = glucose.getSelectedEffect(); if (releaseEffect.isMomentary()) { releaseEffect.enable(); @@ -412,26 +472,29 @@ public class APC40MidiInput extends SCMidiInput { } break; - case 63: // rec quantize + case 63: // rec quantize / red 6 glucose.getSelectedEffect().disable(); break; } } protected void handleNoteOff(Note note) { - int nPitch = note.getPitch(), nChan = note.getChannel(); + int nPitch = note.getPitch(), nChan = note.getChannel(); switch (nPitch) { - case 90: - if (dbtwn(getNow() - Tap1,5000,300*1000)) { // hackish tapping mechanism - double bpm = 32.*60000./(getNow()-Tap1); - while (bpm < 20) bpm*=2; - while (bpm > 40) bpm/=2; - lx.tempo.setBpm(bpm); lx.tempo.trigger(); Tap1=0; println("Tap Set - " + bpm + " bpm"); - } - break; - + case 90: // SEND C + long tapDelta = millis() - tap1; + if (lbtwn(tapDelta,5000,300*1000)) { // hackish tapping mechanism + double bpm = 32.*60000./(tapDelta); + while (bpm < 20) bpm*=2; + while (bpm > 40) bpm/=2; + lx.tempo.setBpm(bpm); + lx.tempo.trigger(); + tap1 = 0; + println("Tap Set - " + bpm + " bpm"); + } + break; - case 63: // rec quantize + case 63: // rec quantize / RED 6 if (releaseEffect != null) { if (releaseEffect.isMomentary()) { releaseEffect.disable(); @@ -441,22 +504,22 @@ public class APC40MidiInput extends SCMidiInput { case 98: // shift shiftOn = false; - break; + break; } } } -class KorgNanoKontrolMidiInput extends SCMidiInput { +class KorgNanoKontrolMidiInput extends GenericDeviceMidiInput { - KorgNanoKontrolMidiInput(MidiInputDevice d) { - super(d); + KorgNanoKontrolMidiInput(MidiEngine midiEngine, MidiInputDevice d) { + super(midiEngine, d); } protected void handleControllerChange(rwmidi.Controller cc) { int number = cc.getCC(); if (number >= 16 && number <= 23) { int parameterIndex = number - 16; - List parameters = getFocusedPattern().getParameters(); + List parameters = midiEngine.getFocusedPattern().getParameters(); if (parameterIndex < parameters.size()) { parameters.get(parameterIndex).setValue(cc.getValue() / 127.); } @@ -485,3 +548,167 @@ class KorgNanoKontrolMidiInput extends SCMidiInput { } } +class APC40MidiOutput implements LXParameter.Listener, GridOutput { + + private final MidiEngine midiEngine; + private final MidiOutput output; + private LXPattern focusedPattern = null; + private LXEffect focusedEffect = null; + + APC40MidiOutput(MidiEngine midiEngine, MidiOutputDevice device) { + this.midiEngine = midiEngine; + output = device.createOutput(); + midiEngine.addListener(new MidiEngineListener() { + public void onFocusedDeck(int deckIndex) { + resetPatternParameters(); + } + }); + glucose.addEffectListener(new GLucose.EffectListener() { + public void effectSelected(LXEffect effect) { + resetEffectParameters(); + } + }); + Engine.Listener deckListener = new Engine.AbstractListener() { + public void patternDidChange(Engine.Deck deck, LXPattern pattern) { + resetPatternParameters(); + } + }; + for (Engine.Deck d : lx.engine.getDecks()) { + d.addListener(deckListener); + } + resetParameters(); + midiEngine.grid.addOutput(this); + } + + private void resetParameters() { + resetPatternParameters(); + resetEffectParameters(); + } + + private void resetPatternParameters() { + LXPattern newPattern = midiEngine.getFocusedDeck().getActivePattern(); + if (newPattern == focusedPattern) { + return; + } + if (focusedPattern != null) { + for (LXParameter p : focusedPattern.getParameters()) { + ((LXListenableParameter) p).removeListener(this); + } + } + focusedPattern = newPattern; + int i = 0; + for (LXParameter p : focusedPattern.getParameters()) { + ((LXListenableParameter) p).addListener(this); + sendKnob(i++, p); + } + while (i < 12) { + sendKnob(i++, 0); + } + for (int row = 0; row < 7; ++row) { + for (int col = 0; col < 8; ++col) { + setGridState(row, col, 0); + } + } + } + + private void resetEffectParameters() { + LXEffect newEffect = glucose.getSelectedEffect(); + if (newEffect == focusedEffect) { + return; + } + if (focusedEffect != null) { + for (LXParameter p : focusedPattern.getParameters()) { + ((LXListenableParameter) p).removeListener(this); + } + } + focusedEffect = newEffect; + int i = 0; + for (LXParameter p : focusedEffect.getParameters()) { + ((LXListenableParameter) p).addListener(this); + sendKnob(12 + i++, p); + } + while (i < 4) { + sendKnob(12 + i++, 0); + } + } + + private void sendKnob(int i, LXParameter p) { + sendKnob(i, (int) (p.getValuef() * 127.)); + } + + private void sendKnob(int i, int value) { + if (i < 8) { + output.sendController(0, 48+i, value); + } else if (i < 16) { + output.sendController(0, 8+i, value); + } + } + + public void onParameterChanged(LXParameter parameter) { + int i = 0; + for (LXParameter p : focusedPattern.getParameters()) { + if (p == parameter) { + sendKnob(i, p); + break; + } + ++i; + } + i = 12; + for (LXParameter p : focusedEffect.getParameters()) { + if (p == parameter) { + sendKnob(i, p); + break; + } + ++i; + } + } + + public void setGridState(int row, int col, int state) { + if (col < 8) { + if (row < 5) output.sendNoteOn(col, 53+row, state); + else if (row == 6) output.sendNoteOn(col, 52, state); + } + } +} + +interface GridOutput { + public static final int OFF = 0; + public static final int GREEN = 1; + public static final int GREEN_BLINK = 2; + public static final int RED = 3; + public static final int RED_BLINK = 4; + public static final int YELLOW = 5; + public static final int YELLOW_BLINK = 6; + public static final int ON = 127; + + public void setGridState(int row, int col, int state); +} + +class GridController { + private final List outputs = new ArrayList(); + + private final MidiEngine midiEngine; + + GridController(MidiEngine midiEngine) { + this.midiEngine = midiEngine; + } + + public void addOutput(GridOutput output) { + outputs.add(output); + } + + public boolean gridPressed(int row, int col) { + return midiEngine.getFocusedPattern().gridPressed(row, col); + } + + public boolean gridReleased(int row, int col) { + return midiEngine.getFocusedPattern().gridReleased(row, col); + } + + public void setState(int row, int col, int state) { + for (GridOutput g : outputs) { + g.setGridState(row, col, state); + } + } +} + diff --git a/_Mappings.pde b/_Mappings.pde index 3f6756a..a16c467 100644 --- a/_Mappings.pde +++ b/_Mappings.pde @@ -120,7 +120,7 @@ for (StaggeredTower st : scubes) { towerList.add(new Tower(tower)); } - return new Model(towerList, cubes, bassBox, speakers); + return new Model(towerList, cubes, bassBox, speakers); } /** diff --git a/_UIFramework.pde b/_UIFramework.pde index 0e0be79..f4a0a40 100644 --- a/_UIFramework.pde +++ b/_UIFramework.pde @@ -703,7 +703,7 @@ public class UIScrollList extends UIObject { itemColor = #707070; } float factor = even ? .92 : 1.08; - itemColor = color(hue(itemColor), saturation(itemColor), min(100, factor*brightness(itemColor))); + itemColor = lx.scaleBrightness(itemColor, factor); pg.noStroke(); pg.fill(itemColor); @@ -718,7 +718,7 @@ public class UIScrollList extends UIObject { } if (hasScroll) { pg.noStroke(); - pg.fill(color(0, 0, 100, 15)); + pg.fill(0x26ffffff); pg.rect(w-12, 0, 12, h); pg.fill(#333333); pg.rect(w-12, scrollYStart, 12, scrollYHeight); diff --git a/code/GLucose.jar b/code/GLucose.jar index 9e48133..4bbff0b 100755 Binary files a/code/GLucose.jar and b/code/GLucose.jar differ diff --git a/code/HeronLX.jar b/code/HeronLX.jar index a3f6241..fa01739 100755 Binary files a/code/HeronLX.jar and b/code/HeronLX.jar differ