annotate src/melodyTriangle.cpp @ 15:9d7e139cd0a3

Voices can now be dragged along the edges of the triangle. Also added screenui.sh script to run executable.
author samer
date Tue, 31 Jan 2012 12:43:21 +0000
parents 578c1acf1cc4
children add71da95cb4
rev   line source
hekeus@6 1 #include "melodyTriangle.h"
hekeus@6 2 #include <GLUT/GLUT.h>
hekeus@6 3
samer@15 4 #define BUFFER_ZONE 80 // have to drag this far to snap out of triange.
hekeus@6 5 /*
hekeus@6 6 /birth id
hekeus@6 7 /death id
hekeus@6 8 /start id
hekeus@6 9 /stop id
hekeus@6 10 /track id x y left right top bottom area
hekeus@6 11 /tempo
hekeus@6 12
hekeus@6 13
hekeus@6 14 */
hekeus@8 15 melodyTriangle::melodyTriangle(const char *host, int port, int numVoices, bool enableKeys,int voiceIdOffset,int receivePort){
hekeus@8 16 printf("in constructor: %s %i %i %i %i %i\n",host,port,numVoices,enableKeys,voiceIdOffset,receivePort);
hekeus@6 17 this->numVoices=numVoices;
hekeus@6 18 this->enableKeys=enableKeys;
hekeus@6 19 this->voiceIdOffset=voiceIdOffset;
hekeus@6 20 //voices=*Voice[numVoices];
hekeus@6 21 sender.setup( host,port );
hekeus@8 22 receiver.setup( receivePort );
hekeus@8 23
hekeus@6 24 }
hekeus@6 25
hekeus@6 26 //--------------------------------------------------------------
hekeus@6 27 void melodyTriangle::setup(){
hekeus@6 28 //voices = new Voice[NUMVOICES];
hekeus@6 29
hekeus@6 30 ofSetCircleResolution(100);
hekeus@6 31 ofBackground(0,0,0);
hekeus@6 32 ofSetWindowTitle("Melody Triangle");
hekeus@6 33 triangleHeight=ofGetHeight()*0.75;
hekeus@6 34 ofSetFrameRate(40); // if vertical sync is off, we can go a bit fast... this caps the framerate at 60fps.
hekeus@6 35 ofEnableSmoothing();
hekeus@6 36 x1=ofGetWidth()/2;
hekeus@6 37 y1=(ofGetHeight()-triangleHeight)/2;
hekeus@6 38 x2=ofGetWidth()/2-triangleHeight/sqrt(3);
hekeus@6 39 y2=ofGetHeight()-(ofGetHeight()-triangleHeight)/2;
hekeus@6 40 x3=ofGetWidth()/2+triangleHeight/sqrt(3);
hekeus@6 41 y3=y2;
hekeus@6 42
samer@15 43 // used for clipping
samer@15 44 DX13=x3-x1; DY13=y3-y1;
samer@15 45 SQLEN13=DX13*DX13+DY13*DY13;
samer@15 46
samer@12 47 sendCalibrate();
samer@12 48 for (int i=0;i<numVoices;i++){
samer@12 49 voices[i]=new Voice(i+1+voiceIdOffset,x2+15,y1+20+i*30);
samer@12 50 }
samer@12 51 voiceGrabbed=-1;
samer@12 52 }
samer@12 53
samer@12 54 void melodyTriangle::sendCalibrate(){
hekeus@6 55 ofxOscMessage m;
hekeus@6 56 m.setAddress( "/calibrate" );
hekeus@6 57 m.addIntArg( x1 );
hekeus@6 58 m.addIntArg( y1 );
hekeus@6 59 m.addIntArg( x2 );
hekeus@6 60 m.addIntArg( y2 );
hekeus@6 61 m.addIntArg( x3 );
hekeus@6 62 m.addIntArg( y3 );
hekeus@6 63 sender.sendMessage( m );
hekeus@6 64 printf("sent /calibrate %i %i %i %i %i %i\n",x1,y1,x2,y2,x3,y3);
samer@12 65 }
samer@12 66
samer@12 67 void melodyTriangle::sendPeriod(int id, int num, int den){
samer@12 68 ofxOscMessage m;
samer@12 69 m.setAddress("/period");
samer@12 70 m.addIntArg(id);
samer@12 71 m.addIntArg(num);
samer@12 72 m.addIntArg(den);
samer@12 73 sender.sendMessage(m);
samer@12 74 printf("sent /period %i %i %i\n",id,num,den);
samer@12 75 }
samer@12 76
samer@12 77 void melodyTriangle::sendShift(int id, int num, int den){
samer@12 78 ofxOscMessage m;
samer@12 79 m.setAddress("/shift");
samer@12 80 m.addIntArg(id);
samer@12 81 m.addIntArg(num);
samer@12 82 m.addIntArg(den);
samer@12 83 sender.sendMessage(m);
samer@12 84 printf("sent /shift %i %i %i\n",id,num,den);
samer@12 85 }
samer@12 86
samer@12 87 void melodyTriangle::sendOctave(int id, int oct){
samer@12 88 ofxOscMessage m;
samer@12 89 m.setAddress("/octave");
samer@12 90 m.addIntArg(id);
samer@12 91 m.addIntArg(oct);
samer@12 92 sender.sendMessage(m);
samer@12 93 printf("sent /octave %i %i\n",id,oct);
hekeus@6 94 }
hekeus@6 95
samer@13 96 void melodyTriangle::sendAmplitude(int id, float amp){
samer@13 97 ofxOscMessage m;
samer@13 98 m.setAddress("/amplitude");
samer@13 99 m.addIntArg(id);
samer@13 100 m.addFloatArg(amp);
samer@13 101 sender.sendMessage(m);
samer@13 102 printf("sent /amplitude %i %1.3f\n",id,amp);
samer@13 103 }
samer@13 104
hekeus@6 105 //--------------------------------------------------------------
hekeus@6 106 void melodyTriangle::update(){
hekeus@8 107 while( receiver.hasWaitingMessages() )
hekeus@8 108 {
hekeus@8 109 // get the next message
hekeus@8 110 ofxOscMessage m;
hekeus@8 111 receiver.getNextMessage( &m );
hekeus@8 112 string msg_string;
hekeus@8 113 msg_string = m.getAddress();
hekeus@8 114 msg_string += ": ";
hekeus@8 115 for ( int i=0; i<m.getNumArgs(); i++ )
hekeus@8 116 {
hekeus@8 117 // get the argument type
hekeus@8 118 msg_string += m.getArgTypeName( i );
hekeus@8 119 msg_string += ":";
hekeus@8 120 // display the argument - make sure we get the right type
hekeus@8 121 if( m.getArgType( i ) == OFXOSC_TYPE_INT32 )
hekeus@8 122 msg_string += ofToString( m.getArgAsInt32( i ) );
hekeus@8 123 else if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT )
hekeus@8 124 msg_string += ofToString( m.getArgAsFloat( i ) );
hekeus@8 125 else if( m.getArgType( i ) == OFXOSC_TYPE_STRING )
hekeus@8 126 msg_string += m.getArgAsString( i );
hekeus@8 127 else
hekeus@8 128 msg_string += "unknown";
hekeus@8 129 }
hekeus@8 130 cout<< msg_string << "\n";
hekeus@8 131
hekeus@8 132 }
hekeus@6 133 }
hekeus@6 134
samer@15 135 bool melodyTriangle::clipToTriangle(int *x, int *y) {
samer@15 136 bool clipped;
samer@15 137
samer@15 138 if (*y>y2) { // off the bottom
samer@15 139 clipped=true;
samer@15 140 *y=y2;
samer@15 141 if (*x<x2) *x=x2;
samer@15 142 else if (*x>x3) *x=x3;
samer@15 143 } else { // have to be a bit cleverer
samer@15 144 bool reflect=false;
samer@15 145 if (*x<x1) { // work in reflected coordinates
samer@15 146 reflect=true;
samer@15 147 *x=2*x1-*x;
samer@15 148 }
hekeus@6 149
samer@15 150 int dx=(*x-x1), dy=(*y-y1); // deltas from top
samer@15 151 if (dx*DY13 > dy*DX13) {
samer@15 152 // (x,y) must be somewhere right of triangle now
samer@15 153 clipped=true;
samer@15 154 int dp=dx*DX13 + dy*DY13;
samer@15 155 if (dp<0) { *x=x1; *y=y1; } // off the top
samer@15 156 else if (dp>SQLEN13) { *x=x3; *y=y3; } // off the bottom right
samer@15 157 else { // project onto right edge
samer@15 158 *x=x1+dp*DX13/SQLEN13;
samer@15 159 *y=y1+dp*DY13/SQLEN13;
samer@15 160 }
samer@15 161 } else {
samer@15 162 clipped=false;
hekeus@6 163 }
hekeus@6 164
samer@15 165 if (reflect) *x=2*x1 - *x; // reflect back if necessary
hekeus@6 166 }
samer@15 167 return clipped;
hekeus@6 168 }
hekeus@6 169
samer@15 170
samer@14 171 void melodyTriangle::sendPosition(Voice v){
hekeus@6 172
hekeus@6 173 ofxOscMessage m;
hekeus@6 174 ///track id x y left right top bottom area
hekeus@6 175 m.setAddress( "/track2d" );
hekeus@6 176 m.addIntArg( v.id );
hekeus@6 177 m.addIntArg( v.posx );
hekeus@6 178 m.addIntArg( v.posy );
hekeus@6 179 sender.sendMessage( m );
hekeus@6 180 printf("sent - /track2d %i %i %i\n",v.id,v.posx,v.posy);
hekeus@6 181
hekeus@6 182 }
hekeus@6 183
hekeus@6 184 //--------------------------------------------------------------
hekeus@6 185 void melodyTriangle::draw(){
samer@10 186 bool constrained=false;
hekeus@6 187 bool sendStart=false;
samer@15 188
hekeus@6 189 if (voiceGrabbed!=-1){
samer@14 190 Voice *vg=voices[voiceGrabbed];
samer@14 191 if (mouseX!=vg->posx || mouseY!=vg->posy){
samer@15 192 int clipx=mouseX, clipy=mouseY;
samer@15 193 bool clipped=clipToTriangle(&clipx,&clipy);
samer@15 194
samer@15 195 if (vg->inTriangle) {
hekeus@6 196
samer@15 197 if (clipped) {
samer@15 198 // check how far we clipped
samer@15 199 if (ofDist(clipx, clipy, mouseX, mouseY) > BUFFER_ZONE) {
samer@15 200 // if far enough, we pop out of triangle and send
samer@15 201 // /death <id>
samer@15 202 ofxOscMessage m;
samer@15 203 m.setAddress( "/death" );
samer@15 204 m.addIntArg( vg->id );
samer@15 205 sender.sendMessage( m );
hekeus@6 206
samer@15 207 printf("sent /death %i \n",vg->id);
samer@15 208 vg->posx=mouseX;
samer@15 209 vg->posy=mouseY;
samer@15 210 vg->inTriangle=false;
samer@15 211 } else {
samer@15 212 // otherwise, we move to clipped point
samer@15 213 constrained=true;
samer@15 214 vg->posx=clipx;
samer@15 215 vg->posy=clipy;
samer@15 216 }
samer@15 217 } else { // not clipped; normal move
samer@15 218 vg->posx=mouseX;
samer@15 219 vg->posy=mouseY;
samer@15 220 }
samer@15 221 } else { // token was outside triangle
samer@15 222 vg->posx=mouseX;
samer@15 223 vg->posy=mouseY;
samer@15 224 if (!clipped){ // ie mouse now in triangle
samer@15 225 //birth id
hekeus@7 226
samer@10 227 ofxOscMessage m;
samer@15 228 m.setAddress( "/birth" );
samer@14 229 m.addIntArg( vg->id );
samer@10 230 sender.sendMessage( m );
samer@15 231
samer@15 232 printf("sent /birth %i \n",vg->id);
samer@15 233 sendOctave(vg->id,vg->octave);
samer@15 234 sendAmplitude(vg->id,vg->amplitude);
samer@15 235 sendStart=true;
samer@15 236 vg->inTriangle=true;
hekeus@6 237 }
hekeus@6 238 }
hekeus@6 239
samer@14 240 if (vg->inTriangle){
samer@14 241 sendPosition(*vg);
samer@15 242 if (sendStart && vg->isActive){
samer@15 243 ofxOscMessage m;
samer@15 244 ///track id x y left right top bottom area
samer@15 245 m.setAddress( "/start" );
samer@15 246 m.addIntArg( vg->id );
samer@15 247 sender.sendMessage( m );
samer@15 248 printf("sent /start %i \n",vg->id);
hekeus@6 249 }
hekeus@6 250 }
hekeus@6 251 }
hekeus@6 252 };
samer@10 253
samer@10 254 //let's draw our triangle
samer@11 255 ofSetLineWidth(2);
samer@12 256 ofSetColor(96,96,96);
samer@10 257 ofFill();
samer@10 258 ofTriangle(x1, y1, x2, y2, x3, y3);
samer@12 259 if (constrained) ofSetColor(255,96,96);
samer@10 260
samer@10 261 // draw smooth edge, brighter if a token is constrained
samer@10 262 ofNoFill();
samer@10 263 ofTriangle(x1, y1, x2, y2, x3, y3);
samer@10 264
hekeus@6 265 for (int i=0; i<numVoices; i++){
hekeus@6 266 (*voices[i]).draw();
hekeus@6 267 }
hekeus@6 268
hekeus@6 269
hekeus@6 270 }
hekeus@6 271
hekeus@6 272 //--------------------------------------------------------------
hekeus@6 273 void melodyTriangle::keyPressed (int key){
hekeus@6 274 //printf("key %i",key);
hekeus@6 275 if (enableKeys){
samer@12 276 switch (key) {
samer@12 277 case ' ': {
samer@12 278 ofxOscMessage m;
samer@12 279 m.setAddress( "/marker" );
samer@12 280 sender.sendMessage(m);
samer@12 281 printf("sent /marker\n");
samer@12 282 break;
samer@12 283 }
samer@12 284
samer@12 285 case '1':
samer@12 286 case '2':
samer@12 287 case '3':
samer@12 288 case '4': {
samer@12 289 int tempo=30 + 30*(key-'1');
samer@12 290 ofxOscMessage m;
samer@12 291 m.setAddress( "/tempo" );
samer@12 292 m.addIntArg(tempo);
samer@12 293 sender.sendMessage( m );
samer@12 294 printf("sent /tempo %d\n",tempo);
samer@12 295 }
samer@12 296 break;
samer@12 297
samer@12 298 case 'c': sendCalibrate(); break;
samer@12 299
samer@12 300 default: { // otherwise, send key to all active voices
samer@12 301 for (int i=0; i<numVoices; i++){
samer@12 302 if (voices[i]->isInVoice(mouseX,mouseY)){
samer@12 303 Voice *v=voices[i];
samer@12 304 switch (key) {
samer@12 305 case 'a': {
samer@12 306 ofxOscMessage m;
samer@12 307 const char *addr = v->isActive ? "/stop" : "/start";
samer@12 308 v->isActive=!v->isActive;
samer@12 309 m.setAddress(addr);
samer@12 310 m.addIntArg(v->id );
samer@12 311 sender.sendMessage( m );
samer@12 312 printf("sent %s %i \n",addr,v->id);
samer@12 313 break;
samer@12 314 }
samer@12 315 case OF_KEY_LEFT: sendShift(v->id,-1,2); break;
samer@12 316 case OF_KEY_RIGHT: sendShift(v->id,1,2); break;
samer@12 317 case OF_KEY_UP: sendPeriod(v->id,1,2); break;
samer@12 318 case OF_KEY_DOWN: sendPeriod(v->id,2,1); break;
samer@12 319 case '.': sendPeriod(v->id,1,3); break;
samer@12 320 case ',': sendPeriod(v->id,3,1); break;
samer@12 321 case '+': sendOctave(v->id, ++v->octave); break;
samer@12 322 case '-': sendOctave(v->id, --v->octave); break;
samer@13 323 case '*': sendAmplitude(v->id, v->louder()); break;
samer@13 324 case '/': sendAmplitude(v->id, v->quieter()); break;
samer@13 325 default: printf("unrecognised key: %d.\n",key);
samer@12 326 }
hekeus@6 327 }
hekeus@6 328 }
hekeus@6 329 }
hekeus@6 330 }
hekeus@6 331 }
hekeus@6 332 }
hekeus@6 333
hekeus@6 334 //--------------------------------------------------------------
hekeus@6 335 void melodyTriangle::keyReleased (int key){
hekeus@6 336
hekeus@6 337 }
hekeus@6 338
hekeus@6 339 //--------------------------------------------------------------
hekeus@6 340 void melodyTriangle::mouseMoved(int x, int y ){
hekeus@6 341 for (int i=0; i<numVoices;i++){
hekeus@6 342 if ((*voices[i]).isInVoice(x,y)){
hekeus@6 343 (*voices[i]).highlight=true;
hekeus@6 344 }else {
hekeus@6 345 (*voices[i]).highlight=false;
hekeus@6 346 }
hekeus@6 347
hekeus@6 348 }
hekeus@6 349
hekeus@6 350
hekeus@6 351 }
hekeus@6 352
hekeus@6 353 //--------------------------------------------------------------
hekeus@6 354 void melodyTriangle::mouseDragged(int x, int y, int button){
hekeus@6 355
hekeus@6 356 }
hekeus@6 357
hekeus@6 358 //--------------------------------------------------------------
hekeus@6 359 void melodyTriangle::mousePressed(int x, int y, int button){
hekeus@6 360
hekeus@6 361 for (int i=0; i<numVoices;i++){
hekeus@6 362 if ((*voices[i]).isInVoice(x,y)){
hekeus@6 363 voiceGrabbed=i;
hekeus@6 364 //printf("grabbed %i",voiceGrabbed);
hekeus@6 365 }else{
hekeus@6 366 //printf("didnt grab %i",i);
hekeus@6 367 }
hekeus@6 368 }
hekeus@6 369 }
hekeus@6 370
hekeus@6 371
hekeus@6 372
hekeus@6 373 //--------------------------------------------------------------
hekeus@6 374 void melodyTriangle::mouseReleased(int x, int y, int button){
hekeus@6 375 //printf("released %i",voiceGrabbed);
hekeus@6 376 voiceGrabbed=-1;
hekeus@6 377 }
hekeus@6 378
hekeus@6 379 //--------------------------------------------------------------
hekeus@6 380 void melodyTriangle::windowResized(int w, int h){
hekeus@6 381
hekeus@6 382 }