Mercurial > hg > screen-ui
diff src/melodyTriangle.cpp @ 22:4dcc4312b5fa
Bit of a tidy up, adding text display, added full screen toggle and window resize handler.
author | samer |
---|---|
date | Thu, 02 Feb 2012 18:17:24 +0000 |
parents | 055d7524bae4 |
children | 460c05dd74d0 |
line wrap: on
line diff
--- a/src/melodyTriangle.cpp Wed Feb 01 16:17:32 2012 +0000 +++ b/src/melodyTriangle.cpp Thu Feb 02 18:17:24 2012 +0000 @@ -12,207 +12,62 @@ */ -melodyTriangle::melodyTriangle(const char *host, int port, int numVoices, bool enableKeys,int voiceIdOffset,int receivePort){ + +melodyTriangle::melodyTriangle(const char *host, int port, int numVoices, + bool enableKeys,int voiceIdOffset,int receivePort): + numVoices(numVoices), enableKeys(enableKeys), receivePort(receivePort), + display_msg(""), + display_frames(0) +{ printf("in constructor: %s %i %i %i %i %i\n",host,port,numVoices,enableKeys,voiceIdOffset,receivePort); - this->numVoices=numVoices; - this->enableKeys=enableKeys; - this->voiceIdOffset=voiceIdOffset; - //voices=*Voice[numVoices]; + for (int i=0;i<numVoices;i++) voices[i]=new Voice(i+1+voiceIdOffset); + sender.setup( host,port ); receiver.setup( receivePort ); - - { - ofxOscMessage m; - m.setAddress( "/reply_to" ); - m.addIntArg( receivePort ); - sender.sendMessage( m ); - printf("sent /reply_to %i\n",receivePort); - } + display_font.loadFont("/System/Library/Fonts/HelveticaLight.ttf",32); } +melodyTriangle::~melodyTriangle() { + printf("Deleting voice objects...\n"); + for (int i=0;i<numVoices;i++) delete voices[i]; +} + //-------------------------------------------------------------- void melodyTriangle::setup(){ - ofSetCircleResolution(100); + ofSetCircleResolution(64); ofBackground(0,0,0); ofSetWindowTitle("Melody Triangle"); + // if vertical sync is off, we can go a bit fast... // this caps the framerate at 40fps. ofSetFrameRate(40); ofEnableSmoothing(); + sendReplyTo(); + // Set up triange coordinates. // NB. whatever happens here, the triangle must be // isosceles and left-right symmetric around x=x1. // Otherwise the clipping won't work - triangleHeight=ofGetHeight()*0.75; - x1=ofGetWidth()/2; - y1=(ofGetHeight()-triangleHeight)/2; - x2=ofGetWidth()/2-triangleHeight/sqrt(3); - y2=ofGetHeight()-(ofGetHeight()-triangleHeight)/2; - x3=ofGetWidth()/2+triangleHeight/sqrt(3); - y3=y2; + fitTriangleIn(ofGetWidth(),ofGetHeight()); + sendCalibrate(); - // used for clipping - DX13=x3-x1; DY13=y3-y1; - SQLEN13=DX13*DX13+DY13*DY13; - - sendCalibrate(); - for (int i=0;i<numVoices;i++){ - voices[i]=new Voice(i+1+voiceIdOffset,x2+15,y1+20+i*30); - } + for (int i=0;i<numVoices;i++) voices[i]->setPos(x2+voices[i]->radius+i*30,48); voiceGrabbed=-1; } -void melodyTriangle::sendCalibrate(){ - ofxOscMessage m; - m.setAddress( "/calibrate" ); - m.addIntArg( x1 ); - m.addIntArg( y1 ); - m.addIntArg( x2 ); - m.addIntArg( y2 ); - m.addIntArg( x3 ); - m.addIntArg( y3 ); - sender.sendMessage( m ); - printf("sent /calibrate %i %i %i %i %i %i\n",x1,y1,x2,y2,x3,y3); -} - -void melodyTriangle::sendPeriod(int id, int num, int den){ - ofxOscMessage m; - m.setAddress("/period"); - m.addIntArg(id); - m.addIntArg(num); - m.addIntArg(den); - sender.sendMessage(m); - printf("sent /period %i %i %i\n",id,num,den); -} - -void melodyTriangle::sendShift(int id, int num, int den){ - ofxOscMessage m; - m.setAddress("/shift"); - m.addIntArg(id); - m.addIntArg(num); - m.addIntArg(den); - sender.sendMessage(m); - printf("sent /shift %i %i %i\n",id,num,den); -} - -void melodyTriangle::sendOctave(int id, int oct){ - ofxOscMessage m; - m.setAddress("/octave"); - m.addIntArg(id); - m.addIntArg(oct); - sender.sendMessage(m); - printf("sent /octave %i %i\n",id,oct); -} - -void melodyTriangle::sendAmplitude(int id, float amp){ - ofxOscMessage m; - m.setAddress("/amplitude"); - m.addIntArg(id); - m.addFloatArg(amp); - sender.sendMessage(m); - printf("sent /amplitude %i %1.3f\n",id,amp); -} - //-------------------------------------------------------------- void melodyTriangle::update(){ - while( receiver.hasWaitingMessages() ) - { + bool sendStart=false; + + while( receiver.hasWaitingMessages() ) { // get the next message ofxOscMessage m; receiver.getNextMessage( &m ); - if (m.getAddress()=="/notify") { - int id=m.getArgAsInt32(0)-1; - string st=m.getArgAsString(1); - - if (id>=0 && id<numVoices) { - Voice *v=voices[id]; - - if (st=="received") v->status=Voice::clear; - else if (st=="pending") v->status=Voice::pending; - else if (st=="requested") v->status=Voice::waiting; - else cout << "** unrecognised voice status: " << st << ".\n"; - } else { - cout << "** voice id "<<id<<" out of range.\n"; - } - } else { - string msg_string; - msg_string = m.getAddress(); - msg_string += ": "; - for ( int i=0; i<m.getNumArgs(); i++ ) - { - // get the argument type - msg_string += m.getArgTypeName( i ); - msg_string += ":"; - // display the argument - make sure we get the right type - if( m.getArgType( i ) == OFXOSC_TYPE_INT32 ) - msg_string += ofToString( m.getArgAsInt32( i ) ); - else if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT ) - msg_string += ofToString( m.getArgAsFloat( i ) ); - else if( m.getArgType( i ) == OFXOSC_TYPE_STRING ) - msg_string += m.getArgAsString( i ); - else - msg_string += "unknown"; - } - cout<< msg_string << "\n"; - } + handleMessage(m); } -} - -bool melodyTriangle::clipToTriangle(int *x, int *y) { - bool clipped; - if (*y>y2) { // off the bottom - clipped=true; - *y=y2; - if (*x<x2) *x=x2; - else if (*x>x3) *x=x3; - } else { // have to be a bit cleverer - bool reflect=false; - if (*x<x1) { // work in reflected coordinates - reflect=true; - *x=2*x1-*x; - } - - int dx=(*x-x1), dy=(*y-y1); // deltas from top - if (dx*DY13 > dy*DX13) { - // (x,y) must be somewhere right of triangle now - clipped=true; - int dp=dx*DX13 + dy*DY13; - if (dp<0) { *x=x1; *y=y1; } // off the top - else if (dp>SQLEN13) { *x=x3; *y=y3; } // off the bottom right - else { // project onto right edge - *x=x1+dp*DX13/SQLEN13; - *y=y1+dp*DY13/SQLEN13; - } - } else { - clipped=false; - } - - if (reflect) *x=2*x1 - *x; // reflect back if necessary - } - return clipped; -} - - -void melodyTriangle::sendPosition(Voice v){ - - ofxOscMessage m; - ///track id x y left right top bottom area - m.setAddress( "/track2d" ); - m.addIntArg( v.id ); - m.addIntArg( v.posx ); - m.addIntArg( v.posy ); - sender.sendMessage( m ); - printf("sent - /track2d %i %i %i\n",v.id,v.posx,v.posy); - -} - -//-------------------------------------------------------------- -void melodyTriangle::draw(){ - bool constrained=false; - bool sendStart=false; - + constrained=false; if (voiceGrabbed!=-1){ Voice *vg=voices[voiceGrabbed]; if (mouseX!=vg->posx || mouseY!=vg->posy){ @@ -230,7 +85,7 @@ m.setAddress( "/death" ); m.addIntArg( vg->id ); sender.sendMessage( m ); - + printf("sent /death %i \n",vg->id); vg->posx=mouseX; vg->posy=mouseY; @@ -279,8 +134,12 @@ } } }; +} - //let's draw our triangle + + +//-------------------------------------------------------------- +void melodyTriangle::draw(){ ofSetLineWidth(2); ofSetColor(80,80,80); ofFill(); @@ -295,10 +154,54 @@ (*voices[i]).draw(); } - + // display message if any + if (display_frames>0) { + ofSetColor(220,220,220); + display_font.drawString(display_msg,x2,y1+32); + display_frames--; + } } -//-------------------------------------------------------------- +bool melodyTriangle::clipToTriangle(int *x, int *y) { + bool clipped; + + if (*y>y2) { // off the bottom + clipped=true; + *y=y2; + if (*x<x2) *x=x2; + else if (*x>x3) *x=x3; + } else { // have to be a bit cleverer + bool reflect=false; + if (*x<x1) { // work in reflected coordinates + reflect=true; + *x=2*x1-*x; + } + + int dx=(*x-x1), dy=(*y-y1); // deltas from top + if (dx*DY13 > dy*DX13) { + // (x,y) must be somewhere right of triangle now + clipped=true; + int dp=dx*DX13 + dy*DY13; + if (dp<0) { *x=x1; *y=y1; } // off the top + else if (dp>SQLEN13) { *x=x3; *y=y3; } // off the bottom right + else { // project onto right edge + *x=x1+dp*DX13/SQLEN13; + *y=y1+dp*DY13/SQLEN13; + } + } else { + clipped=false; + } + + if (reflect) *x=2*x1 - *x; // reflect back if necessary + } + return clipped; +} + + + +//- Keyboard ---------------------------------------------------------- + +void melodyTriangle::keyReleased(int key){} void melodyTriangle::keyPressed (int key){ //printf("key %i",key); if (enableKeys){ @@ -324,7 +227,8 @@ } break; - case 'c': sendCalibrate(); break; + case 'c': sendReplyTo(); sendCalibrate(); break; + case 'f': ofToggleFullscreen(); break; default: { // otherwise, send key to all active voices for (int i=0; i<numVoices; i++){ @@ -360,24 +264,15 @@ } } -//-------------------------------------------------------------- -void melodyTriangle::keyReleased (int key){ +//- Mouse ------------------------------------------------------ -} - -//-------------------------------------------------------------- +void melodyTriangle::mouseDragged(int x, int y, int button){} void melodyTriangle::mouseMoved(int x, int y ){ for (int i=0; i<numVoices;i++){ voices[i]->highlight = voices[i]->isInVoice(x,y); } } -//-------------------------------------------------------------- -void melodyTriangle::mouseDragged(int x, int y, int button){ - -} - -//-------------------------------------------------------------- void melodyTriangle::mousePressed(int x, int y, int button){ for (int i=0; i<numVoices;i++){ @@ -390,15 +285,149 @@ } } - - -//-------------------------------------------------------------- -void melodyTriangle::mouseReleased(int x, int y, int button){ - //printf("released %i",voiceGrabbed); - voiceGrabbed=-1; +void melodyTriangle::mouseReleased(int x, int y, int button){ + voiceGrabbed=-1; } //-------------------------------------------------------------- + void melodyTriangle::windowResized(int w, int h){ + fitTriangleIn(w,h); + sendCalibrate(); +} + +// OSC Message handling ----------------------------------------- + +void melodyTriangle::handleMessage(ofxOscMessage &m) { + string msg_path=m.getAddress(); + + if (msg_path=="/notify") { + int id=m.getArgAsInt32(0)-1; + string st=m.getArgAsString(1); + + if (id>=0 && id<numVoices) { + Voice *v=voices[id]; + + if (st=="received") v->status=Voice::clear; + else if (st=="pending") v->status=Voice::pending; + else if (st=="requested") v->status=Voice::waiting; + else cout << "** unrecognised voice status: " << st << ".\n"; + } else { + cout << "** voice id "<<id<<" out of range.\n"; + } + } else if (msg_path=="/display") { + display_msg=m.getArgAsString(0); + display_frames=m.getArgAsInt32(1); + if (display_frames<0) display_frames=0; + } else { + string msg_string; + msg_string = m.getAddress(); + msg_string += ": "; + for ( int i=0; i<m.getNumArgs(); i++ ) + { + // get the argument type + msg_string += m.getArgTypeName( i ); + msg_string += ":"; + // display the argument - make sure we get the right type + if( m.getArgType( i ) == OFXOSC_TYPE_INT32 ) + msg_string += ofToString( m.getArgAsInt32( i ) ); + else if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT ) + msg_string += ofToString( m.getArgAsFloat( i ) ); + else if( m.getArgType( i ) == OFXOSC_TYPE_STRING ) + msg_string += m.getArgAsString( i ); + else + msg_string += "unknown"; + } + cout<< msg_string << "\n"; + } } + +// OSC Message sending ----------------------------------------- + +void melodyTriangle::sendPosition(Voice v){ + + ofxOscMessage m; + ///track id x y left right top bottom area + m.setAddress( "/track2d" ); + m.addIntArg( v.id ); + m.addIntArg( v.posx ); + m.addIntArg( v.posy ); + sender.sendMessage( m ); + printf("sent - /track2d %i %i %i\n",v.id,v.posx,v.posy); + +} +void melodyTriangle::sendCalibrate(){ + ofxOscMessage m; + m.setAddress( "/calibrate" ); + m.addIntArg( x1 ); + m.addIntArg( y1 ); + m.addIntArg( x2 ); + m.addIntArg( y2 ); + m.addIntArg( x3 ); + m.addIntArg( y3 ); + sender.sendMessage( m ); + printf("sent /calibrate %i %i %i %i %i %i\n",x1,y1,x2,y2,x3,y3); +} + +void melodyTriangle::sendReplyTo(){ + ofxOscMessage m; + m.setAddress( "/reply_to" ); + m.addIntArg( receivePort ); + sender.sendMessage( m ); + printf("sent /reply_to %i\n",receivePort); +} + +void melodyTriangle::sendPeriod(int id, int num, int den){ + ofxOscMessage m; + m.setAddress("/period"); + m.addIntArg(id); + m.addIntArg(num); + m.addIntArg(den); + sender.sendMessage(m); + printf("sent /period %i %i %i\n",id,num,den); +} + +void melodyTriangle::sendShift(int id, int num, int den){ + ofxOscMessage m; + m.setAddress("/shift"); + m.addIntArg(id); + m.addIntArg(num); + m.addIntArg(den); + sender.sendMessage(m); + printf("sent /shift %i %i %i\n",id,num,den); +} + +void melodyTriangle::sendOctave(int id, int oct){ + ofxOscMessage m; + m.setAddress("/octave"); + m.addIntArg(id); + m.addIntArg(oct); + sender.sendMessage(m); + printf("sent /octave %i %i\n",id,oct); +} + +void melodyTriangle::sendAmplitude(int id, float amp){ + ofxOscMessage m; + m.setAddress("/amplitude"); + m.addIntArg(id); + m.addFloatArg(amp); + sender.sendMessage(m); + printf("sent /amplitude %i %1.3f\n",id,amp); +} + + +void melodyTriangle::fitTriangleIn(int width, int height) { + int triHeight = height*0.75; + int triHalfWidth = triHeight/sqrt(3); + + x1=width/2; + x2=x1-triHalfWidth; + x3=x1+triHalfWidth; + y1=(height-triHeight)/2; + y2=y3=height - (height-triHeight)/2; + + // used for clipping + DX13=x3-x1; DY13=y3-y1; + SQLEN13=DX13*DX13+DY13*DY13; +}