moving synthesis by hand

This commit is contained in:
benfry
2012-04-08 18:07:42 +00:00
parent c7b41d2887
commit 8b9f86265c
48 changed files with 3976 additions and 0 deletions
@@ -0,0 +1,35 @@
class Button extends Control {
boolean selected = false;
boolean down = false;
Button(int x, int y, int w, int h, String label) {
super(x,y,w,h,label);
}
boolean mousePressed() {
if (super.mousePressed() && !selected)
down = true;
return down;
}
boolean mouseReleased() {
down = false;
if (super.mouseIn()) {
selected = !selected;
return true;
}
return false;
}
void drawContents() {
if (selected||down) {
if (!selected&&(over^down))
fill(0xDD,0xDD,0xDD);
else
fill(0x00,0x99,0xFF);
noStroke();
rect(x+1,y+1,w-1,h-1);
}
}
}
@@ -0,0 +1,48 @@
class Control {
int x,y,w,h;
boolean over = false;
String label;
Control(int x, int y, int w, int h, String label) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.label = label;
}
boolean mouseIn() {
return over = mouseX>x&&mouseX<x+w&&mouseY>y&&mouseY<y+h;
}
boolean mousePressed() {
return mouseIn();
}
void mouseDragged() {
mouseIn();
}
boolean mouseReleased() {
return mouseIn();
}
void display() {
stroke(0x00,0x99,0xFF);
if (over)
fill(0xDD,0xDD,0xDD);
else
fill(0xFF,0xFF,0xFF);
rect(x,y,w,h);
drawContents();
stroke(0);
fill(0);
text(label, x+2, (y+h)-3);
}
void drawContents() {
}
}
@@ -0,0 +1,79 @@
class Mass {
static final float diamter = 5;
static final float radius = 1+diamter/2;
float x,y,xv,yv;
Mass(int x, int y) {
this.x = x;
this.y = y;
}
void update() {
yv += g.value;
double speed = sqrt(xv*xv+yv*yv);
double fs = 1-f.value;
if (speed>speedFrictionThreshold)
fs *= speedFrictionThreshold/speed;
xv *= fs;
yv *= fs;
x += xv;
y += yv;
if (x<radius) {
x -= x-radius;
xv = -xv;
} else if (x>width-radius) {
x -= x-(width-radius);
xv = -xv;
}
if (y<sliderHeight+radius) {
y -= y-(sliderHeight+radius);
yv = -yv;
} else if (y>height-radius) {
y -= y-(height-radius);
yv = -yv;
}
}
void clamp() {
if (x<radius) {
x = radius;
} else if (x>width-radius) {
x = width-radius;
}
if (y<sliderHeight+radius) {
y = sliderHeight+radius;
} else if (y>height-radius) {
y = height-radius;
}
}
void display() {
if (this == overMass) {
stroke(0x00,0x99,0xFF);
line(x,y,mouseX,mouseY);
noStroke();
fill(0x00,0x99,0xFF);
}
else {
noStroke();
fill(0);
}
ellipse(x,y,diamter,diamter);
}
float distanceTo(Mass m) {
return distanceTo(m.x,m.y);
}
float distanceTo(float x,float y) {
float dx = this.x-x;
float dy = this.y-y;
return sqrt(dx*dx+dy*dy);
}
}
@@ -0,0 +1,48 @@
class Slider extends Control {
float min,max,value;
int labelW = 8;
Slider(int x, int y, int w, int h, float min, float max, float value,String label) {
super(x,y,w,h,label);
this.min = min;
this.max = max;
this.value = value;
}
void mouseDragged() {
setValueToMouse();
}
boolean mousePressed() {
boolean down;
if (down = super.mousePressed())
setValueToMouse();
return down;
}
void setValueToMouse() {
int mw = (w-labelW)-1;
float mv = (mouseX-(x+labelW+1.0))/mw;
if (mv>0)
value = min+(mv*mv)*(max-min);
else
value = min;
value = min(value,max);
}
void drawContents() {
fill(0x00,0x99,0xFF);
noStroke();
int mw = (w-labelW)-1;
float vw = sqrt((value-min)/(max-min))*mw;
rect(x+labelW+1,y+1,vw,h-1);
}
void display() {
super.display();
stroke(0x00,0x99,0xFF);
line(x+labelW,y,x+labelW,y+h);
}
}
@@ -0,0 +1,81 @@
class Spring {
Mass a,b;
float restLength;
Spring(Mass a,Mass b) {
this.a = a;
this.b = b;
restLength = a.distanceTo(b);
}
void display() {
if (this == overSpring) {
stroke(0x00,0x99,0xFF);
float vx = b.x-a.x;
float vy = b.y-a.y;
float dot = (vx*vx + vy*vy);
float rx = mouseX-a.x;
float ry = mouseY-a.y;
float dot2 = (vx*rx + vy*ry);
float value = dot2/dot;
value = min(value,1);
value = max(value,0);
float x = ((b.x*value)+(a.x*(1-value)));
float y = ((b.y*value)+(a.y*(1-value)));
line(x,y,mouseX,mouseY);
}
else {
stroke(0);
}
line(a.x,a.y,b.x,b.y);
}
void applyForces() {
double d = a.distanceTo(b);
if (d>0)
{
double f = (d-restLength)*k.value;
double fH = (f/d)*(a.x-b.x);
double fV = (f/d)*(a.y-b.y);
a.xv -= fH;
a.yv -= fV;
b.xv += fH;
b.yv += fV;
}
}
float distanceTo(float x,float y) {
if (x>(min(a.x,b.x)-mouseTolerance)
&&x<(max(a.x,b.x)+mouseTolerance)
&&y>(min(a.y,b.y)-mouseTolerance)
&&y<(max(a.y,b.y)+mouseTolerance))
{
float vx = b.x-a.x;
float vy = b.y-a.y;
float dot = (vx*vx + vy*vy);
float rx = x-a.x;
float ry = y-a.y;
float dot2 = (vx*rx + vy*ry);
float value = dot2/dot;
if (value<0) {
float d = a.distanceTo(x,y);
return d <= mouseTolerance?d:-1;
} else if (value>1) {
float d = b.distanceTo(x,y);
return d <= mouseTolerance?d:-1;
}
float px = ((b.x*value)+(a.x*(1-value)))-x;
float py = ((b.y*value)+(a.y*(1-value)))-y;
float d = sqrt(px*px+py*py);
return d <= mouseTolerance?d:-1;
}
else
return -1;
}
}
@@ -0,0 +1,329 @@
/**
* Synthesis 4: Structure and Interface
* SodaProcessing by Ed Burton (www.soda.co.k)
* p. 499
*
* A simplified version of the Soda Constructor to demonstrate how it works.
* The complete Soda Constructor may be visited at http://www.sodaplay.com.
*/
Mass masses[];
int massCount = 0;
float mouseTolerance = 15;
Mass dragMass = null;
float dragDx,dragDy;
float tempDistance;
Mass drawMass = null;
Mass overMass;
Spring springs[];
int springCount = 0;
Spring overSpring;
Control controls[];
Control activeControl = null;
Button make,move,delete;
Slider g,f,k;
int sliderHeight = 13;
float speedFrictionThreshold = 20;
PFont font;
int mode;
static final int MAKE = 0;
static final int MOVE = 1;
static final int DELETE = 2;
String toolTips[];
void setup()
{
size(600, 600);
background(0xFF);
masses = new Mass[8];
springs = new Spring[8];
font = loadFont("RotisSanSer-Bold.vlw.gz");
textFont(font, 15);
//hint(SMOOTH_IMAGES);
smooth();
controls = new Control[6];
int x = 0;
int i = 0;
int controlWidth = width/(controls.length)+1;
controls[i++] = make = new Button(0,0,controlWidth-1,sliderHeight,"make");
controls[i++] = move = new Button(controls[i-2].x+controls[i-2].w,0,controlWidth-1,sliderHeight,"move");
controls[i++] = delete = new Button(controls[i-2].x+controls[i-2].w,0,controlWidth-1,sliderHeight,"delete");
controls[i++] = g = new Slider(controls[i-2].x+controls[i-2].w,0,controlWidth,sliderHeight,0,4,0.0,"g");
controls[i++] = f = new Slider(controls[i-2].x+controls[i-2].w,0,controlWidth,sliderHeight,0,1,0.1,"f");
controls[i++] = k = new Slider(controls[i-2].x+controls[i-2].w,0,controlWidth,sliderHeight,0,0.75,0.5,"k");
make.selected = true;
checkMode();
toolTips = new String [] {
": click to make masses and springs"
,": click, drag and throw masses"
,": click to delete masses and springs"
," = gravity (hint, set to zero to before choosing to make)"
," = friction"
," = spring stiffness"};
}
void draw()
{
doUpdate();
display();
}
void checkMode() {
for (int i = 0;i<controls.length;i++)
if (controls[i] instanceof Button && ((Button)controls[i]).selected)
mode = i;
if (mode != MAKE)
drawMass = null;
}
void keyPressed() {
// saveFrame();
}
void mouseMoved() {
for (int i = 0;i<controls.length;i++)
controls[i].mouseIn();
tempDistance = -1;
Mass m = null;
if (mode == MOVE || mode == MAKE || mode == DELETE)
m = mouseMass();
float md = tempDistance;
tempDistance = -1;
Spring s = null;
if (mode == DELETE)
s = mouseSpring();
float sd = tempDistance;
if (m != null && md != -1 && (md <= sd || sd == -1) && md < mouseTolerance) {
overMass = m;
overSpring = null;
} else if (s != null && sd != -1 && (sd<md || md == -1) && sd<mouseTolerance) {
overSpring = s;
overMass = null;
} else {
overMass = null;
overSpring = null;
}
}
void mouseDragged() {
if (activeControl != null)
activeControl.mouseDragged();
else
if (dragMass != null) {
dragMass.x = mouseX+dragDx;
dragMass.y = mouseY+dragDy;
dragMass.xv = mouseX-pmouseX;
dragMass.yv = mouseY-pmouseY;
dragMass.clamp();
}
}
void mouseReleased() {
if (activeControl != null) {
if (activeControl.mouseReleased() && activeControl instanceof Button) {
for (int i = 0;i<controls.length;i++)
if (controls[i] != activeControl && controls[i] instanceof Button)
((Button)controls[i]).selected = false;
checkMode();
}
activeControl = null;
}
if (dragMass != null) {
if (overMass == dragMass)
overMass = null;
dragMass = null;
}
}
void mousePressed() {
activeControl = null;
for (int i = 0;i<controls.length && activeControl == null;i++)
if ( controls[i].mousePressed() && !(controls[i] instanceof Button && ((Button)controls[i]).selected))
activeControl = controls[i];
if (activeControl == null) {
switch(mode) {
case MAKE:
Mass m = mouseMass();
if (m != null && tempDistance<mouseTolerance) {
if (drawMass != null) {
if (drawMass != m) {
boolean springExists = false;
for (int i = 0;i<springCount&&!springExists;i++)
springExists = ((springs[i].a == drawMass && springs[i].b == m)||(springs[i].b == drawMass && springs[i].a == m));
if (!springExists)
addSpring(new Spring(drawMass,m));
}
drawMass = null;
} else {
drawMass = m;
}
} else {
Mass newMass;
addMass(newMass = new Mass(mouseX,mouseY));
if (drawMass != null)
addSpring(new Spring(drawMass,newMass));
drawMass = newMass;
}
break;
case MOVE:
m = mouseMass();
if (m != null && tempDistance<mouseTolerance) {
overMass = dragMass = m;
dragDx = m.x-mouseX;
dragDy = m.y-mouseY;
} else
overMass = dragMass = null;
break;
case DELETE:
if (overMass != null) {
for (int i = 0;i<springCount;i++)
if (springs[i].a == overMass || springs[i].b == overMass)
deleteSpring(springs[i--]);
deleteMass(overMass);
if (overMass == dragMass)
dragMass = null;
overMass = null;
} else if (overSpring != null) {
deleteSpring(overSpring);
overSpring = null;
}
break;
}
}
}
Mass mouseMass() {
tempDistance = -1;
Mass m = null;
for (int i = 0;i<massCount;i++) {
float d = masses[i].distanceTo(mouseX,mouseY);
if (d != -1 && (d<tempDistance || tempDistance == -1)) {
tempDistance = d;
m = masses[i];
}
}
return m;
}
Spring mouseSpring() {
tempDistance = -1;
Spring s = null;
for (int i = 0;i<springCount;i++) {
float d = springs[i].distanceTo(mouseX,mouseY);
if (d != -1 && (d<tempDistance || tempDistance == -1)) {
tempDistance = d;
s = springs[i];
}
}
return s;
}
void doUpdate() {
for (int i = 0;i<springCount;i++)
springs[i].applyForces();
for (int i = 0;i<massCount;i++)
if (masses[i] != dragMass)
masses[i].update();
}
void display() {
stroke(0x00,0x99,0xFF);
fill(0xFF,0xFF,0xFF);
rect(0,0,width-1,height-1);
for (int i = 0;i<springCount;i++)
springs[i].display();
if (drawMass != null) {
stroke(0x00,0x99,0xFF);
line(drawMass.x,drawMass.y,mouseX,mouseY);
}
for (int i = 0;i<massCount;i++)
masses[i].display();
for (int i = 0;i<controls.length;i++) {
controls[i].display();
}
fill(0x00,0x99,0xFF);
for (int i = 0;i<controls.length;i++)
if (controls[i].over)
text(controls[i].label+toolTips[i], 2, sliderHeight*3-3);
}
// list handling for masses
void addMass(Mass mass) {
if (massCount == masses.length) {
Mass temp[] = new Mass[massCount*2];
System.arraycopy(masses, 0, temp, 0, massCount);
masses = temp;
}
masses[massCount++] = mass;
}
void deleteMass(Mass mass) {
int index = massIndex(mass);
if (index >= 0)
deleteMassIndex(index);
}
void deleteMassIndex(int index) {
if (index<massCount)
System.arraycopy(masses, index+1, masses, index, massCount-index);
massCount--;
}
int massIndex(Mass mass) {
for (int i = 0;i<massCount;i++)
if (masses[i] == mass)
return i;
return -1;
}
// list handling for springs
void addSpring(Spring spring) {
if (springCount == springs.length) {
Spring temp[] = new Spring[springCount*2];
System.arraycopy(springs, 0, temp, 0, springCount);
springs = temp;
}
springs[springCount++] = spring;
}
void deleteSpring(Spring spring) {
int index = springIndex(spring);
if (index >= 0)
deleteSpringIndex(index);
}
void deleteSpringIndex(int index) {
if (index<springCount)
System.arraycopy(springs, index+1, springs, index, springCount-index);
springCount--;
}
int springIndex(Spring spring) {
for (int i = 0;i<springCount;i++)
if (springs[i] == spring)
return i;
return -1;
}
// end of list handling