hekeus@6: #include "melodyTriangle.h" hekeus@6: #include hekeus@6: samer@19: #define BUFFER_ZONE 50 // have to drag this far to snap out of triange. hekeus@6: /* hekeus@6: /birth id hekeus@6: /death id hekeus@6: /start id hekeus@6: /stop id hekeus@6: /track id x y left right top bottom area hekeus@6: /tempo hekeus@6: hekeus@6: hekeus@6: */ samer@22: samer@22: melodyTriangle::melodyTriangle(const char *host, int port, int numVoices, samer@22: bool enableKeys,int voiceIdOffset,int receivePort): samer@22: numVoices(numVoices), enableKeys(enableKeys), receivePort(receivePort), samer@22: display_msg(""), samer@22: display_frames(0) samer@22: { hekeus@8: printf("in constructor: %s %i %i %i %i %i\n",host,port,numVoices,enableKeys,voiceIdOffset,receivePort); samer@22: for (int i=0;isetPos(x2+voices[i]->radius+i*30,48); samer@12: voiceGrabbed=-1; samer@12: } samer@12: hekeus@6: //-------------------------------------------------------------- hekeus@6: void melodyTriangle::update(){ samer@22: bool sendStart=false; samer@22: samer@22: while( receiver.hasWaitingMessages() ) { hekeus@8: // get the next message hekeus@8: ofxOscMessage m; hekeus@8: receiver.getNextMessage( &m ); samer@22: handleMessage(m); hekeus@8: } samer@15: samer@22: constrained=false; hekeus@6: if (voiceGrabbed!=-1){ samer@14: Voice *vg=voices[voiceGrabbed]; samer@14: if (mouseX!=vg->posx || mouseY!=vg->posy){ samer@15: int clipx=mouseX, clipy=mouseY; samer@15: bool clipped=clipToTriangle(&clipx,&clipy); samer@15: samer@15: if (vg->inTriangle) { hekeus@6: samer@15: if (clipped) { samer@15: // check how far we clipped samer@15: if (ofDist(clipx, clipy, mouseX, mouseY) > BUFFER_ZONE) { samer@15: // if far enough, we pop out of triangle and send samer@15: // /death samer@15: ofxOscMessage m; samer@15: m.setAddress( "/death" ); samer@15: m.addIntArg( vg->id ); samer@15: sender.sendMessage( m ); samer@22: samer@15: printf("sent /death %i \n",vg->id); samer@15: vg->posx=mouseX; samer@15: vg->posy=mouseY; samer@15: vg->inTriangle=false; samer@18: vg->status=Voice::clear; samer@15: } else { samer@15: // otherwise, we move to clipped point samer@15: constrained=true; samer@15: vg->posx=clipx; samer@15: vg->posy=clipy; samer@15: } samer@15: } else { // not clipped; normal move samer@15: vg->posx=mouseX; samer@15: vg->posy=mouseY; samer@15: } samer@15: } else { // token was outside triangle samer@15: vg->posx=mouseX; samer@15: vg->posy=mouseY; samer@15: if (!clipped){ // ie mouse now in triangle samer@15: //birth id hekeus@7: samer@10: ofxOscMessage m; samer@15: m.setAddress( "/birth" ); samer@14: m.addIntArg( vg->id ); samer@10: sender.sendMessage( m ); samer@15: samer@15: printf("sent /birth %i \n",vg->id); samer@15: sendOctave(vg->id,vg->octave); samer@15: sendAmplitude(vg->id,vg->amplitude); samer@15: sendStart=true; samer@15: vg->inTriangle=true; hekeus@6: } hekeus@6: } hekeus@6: samer@14: if (vg->inTriangle){ samer@14: sendPosition(*vg); samer@18: vg->status=Voice::moved; samer@15: if (sendStart && vg->isActive){ samer@15: ofxOscMessage m; samer@15: ///track id x y left right top bottom area samer@15: m.setAddress( "/start" ); samer@15: m.addIntArg( vg->id ); samer@15: sender.sendMessage( m ); samer@15: printf("sent /start %i \n",vg->id); hekeus@6: } hekeus@6: } hekeus@6: } hekeus@6: }; samer@22: } samer@10: samer@22: samer@22: samer@22: //-------------------------------------------------------------- samer@22: void melodyTriangle::draw(){ samer@11: ofSetLineWidth(2); samer@19: ofSetColor(80,80,80); samer@10: ofFill(); samer@10: ofTriangle(x1, y1, x2, y2, x3, y3); samer@12: if (constrained) ofSetColor(255,96,96); samer@10: samer@10: // draw smooth edge, brighter if a token is constrained samer@10: ofNoFill(); samer@10: ofTriangle(x1, y1, x2, y2, x3, y3); samer@10: hekeus@6: for (int i=0; i0) { samer@22: ofSetColor(220,220,220); samer@22: display_font.drawString(display_msg,x2,y1+32); samer@22: display_frames--; samer@22: } hekeus@6: } hekeus@6: samer@22: bool melodyTriangle::clipToTriangle(int *x, int *y) { samer@22: bool clipped; samer@22: samer@22: if (*y>y2) { // off the bottom samer@22: clipped=true; samer@22: *y=y2; samer@22: if (*xx3) *x=x3; samer@22: } else { // have to be a bit cleverer samer@22: bool reflect=false; samer@22: if (*x dy*DX13) { samer@22: // (x,y) must be somewhere right of triangle now samer@22: clipped=true; samer@22: int dp=dx*DX13 + dy*DY13; samer@22: if (dp<0) { *x=x1; *y=y1; } // off the top samer@22: else if (dp>SQLEN13) { *x=x3; *y=y3; } // off the bottom right samer@22: else { // project onto right edge samer@22: *x=x1+dp*DX13/SQLEN13; samer@22: *y=y1+dp*DY13/SQLEN13; samer@22: } samer@22: } else { samer@22: clipped=false; samer@22: } samer@22: samer@22: if (reflect) *x=2*x1 - *x; // reflect back if necessary samer@22: } samer@22: return clipped; samer@22: } samer@22: samer@22: samer@22: samer@22: //- Keyboard ---------------------------------------------------------- samer@22: samer@22: void melodyTriangle::keyReleased(int key){} hekeus@6: void melodyTriangle::keyPressed (int key){ hekeus@6: //printf("key %i",key); hekeus@6: if (enableKeys){ samer@12: switch (key) { samer@12: case ' ': { samer@12: ofxOscMessage m; samer@12: m.setAddress( "/marker" ); samer@12: sender.sendMessage(m); samer@12: printf("sent /marker\n"); samer@12: break; samer@12: } samer@12: samer@12: case '1': samer@12: case '2': samer@12: case '3': samer@12: case '4': { samer@12: int tempo=30 + 30*(key-'1'); samer@12: ofxOscMessage m; samer@12: m.setAddress( "/tempo" ); samer@12: m.addIntArg(tempo); samer@12: sender.sendMessage( m ); samer@12: printf("sent /tempo %d\n",tempo); samer@12: } samer@12: break; samer@12: samer@22: case 'c': sendReplyTo(); sendCalibrate(); break; samer@22: case 'f': ofToggleFullscreen(); break; samer@12: samer@12: default: { // otherwise, send key to all active voices samer@12: for (int i=0; iisInVoice(mouseX,mouseY)){ samer@12: Voice *v=voices[i]; samer@12: switch (key) { samer@12: case 'a': { samer@12: ofxOscMessage m; samer@12: const char *addr = v->isActive ? "/stop" : "/start"; samer@12: v->isActive=!v->isActive; samer@12: m.setAddress(addr); samer@12: m.addIntArg(v->id ); samer@12: sender.sendMessage( m ); samer@12: printf("sent %s %i \n",addr,v->id); samer@12: break; samer@12: } samer@12: case OF_KEY_LEFT: sendShift(v->id,-1,2); break; samer@12: case OF_KEY_RIGHT: sendShift(v->id,1,2); break; samer@12: case OF_KEY_UP: sendPeriod(v->id,1,2); break; samer@12: case OF_KEY_DOWN: sendPeriod(v->id,2,1); break; samer@12: case '.': sendPeriod(v->id,1,3); break; samer@12: case ',': sendPeriod(v->id,3,1); break; samer@12: case '+': sendOctave(v->id, ++v->octave); break; samer@12: case '-': sendOctave(v->id, --v->octave); break; samer@13: case '*': sendAmplitude(v->id, v->louder()); break; samer@13: case '/': sendAmplitude(v->id, v->quieter()); break; samer@13: default: printf("unrecognised key: %d.\n",key); samer@12: } hekeus@6: } hekeus@6: } hekeus@6: } hekeus@6: } hekeus@6: } hekeus@6: } hekeus@6: samer@22: //- Mouse ------------------------------------------------------ hekeus@6: samer@22: void melodyTriangle::mouseDragged(int x, int y, int button){} hekeus@6: void melodyTriangle::mouseMoved(int x, int y ){ hekeus@6: for (int i=0; ihighlight = voices[i]->isInVoice(x,y); hekeus@6: } hekeus@6: } hekeus@6: hekeus@6: void melodyTriangle::mousePressed(int x, int y, int button){ hekeus@6: hekeus@6: for (int i=0; iisInVoice(x,y)){ hekeus@6: voiceGrabbed=i; hekeus@6: //printf("grabbed %i",voiceGrabbed); hekeus@6: }else{ hekeus@6: //printf("didnt grab %i",i); hekeus@6: } hekeus@6: } hekeus@6: } hekeus@6: samer@22: void melodyTriangle::mouseReleased(int x, int y, int button){ samer@22: voiceGrabbed=-1; hekeus@6: } hekeus@6: hekeus@6: //-------------------------------------------------------------- samer@22: hekeus@6: void melodyTriangle::windowResized(int w, int h){ samer@22: fitTriangleIn(w,h); samer@22: sendCalibrate(); samer@22: } hekeus@6: samer@22: samer@22: // OSC Message handling ----------------------------------------- samer@22: samer@22: void melodyTriangle::handleMessage(ofxOscMessage &m) { samer@22: string msg_path=m.getAddress(); samer@22: samer@22: if (msg_path=="/notify") { samer@22: int id=m.getArgAsInt32(0)-1; samer@22: string st=m.getArgAsString(1); samer@22: samer@22: if (id>=0 && idstatus=Voice::clear; samer@22: else if (st=="pending") v->status=Voice::pending; samer@22: else if (st=="requested") v->status=Voice::waiting; samer@22: else cout << "** unrecognised voice status: " << st << ".\n"; samer@22: } else { samer@22: cout << "** voice id "<