annotate src/melodyTriangle.cpp @ 19:055d7524bae4

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