Mercurial > hg > wabletios
view testApp.mm @ 15:d5758530a039 tip
oF0.84
Retina, and iPhone support
author | Robert Tubb <rt300@eecs.qmul.ac.uk> |
---|---|
date | Tue, 12 May 2015 15:48:52 +0100 |
parents | 4ba81a12b008 |
children |
line wrap: on
line source
#include "testApp.h" /* TODO list video out !!!!! ios buttons etc circular line string with invisible "identify" between two points symmetry touch mode new mesh popup menu type x,y rings spokes update to ofx0.8 save presets: create mesh methods: save to json, construct from json all the stuff in control (and off screen OSC ones) lump positions, constraints the scan path the touch mode the midi hit mode (rewrite this whole thing!) preset recall list modulation points: make filter new touch mode, drop modulation point pop up list of destinations (or drag line?) new super knobs new supermenus algorithmic scan path auto- join up scan path...? floating scan path, with interpolation band limited touch points (invisible springs connecting to mesh?) iphone */ extern GlobalForces globalForces; extern GlobalUI globalUI; extern ScanPath scanPath; extern PresetAlertViewController *presetAlertViewController; //-------------------------------------------------------------- void testApp::setup(){ theMesh = NULL; ofxAccelerometer.setup(); try{ receiver.setup( INPORT ); OscOK = true; } catch (std::runtime_error e){ cout << "OSC couldn't connect. Exception: " << e.what() << '\n'; OscOK = false; } try{ sender.setup( HOST, OUTPORT ); OscOK = true; } catch (std::runtime_error e){ cout << "OSC couldn't connect. Exception: " << e.what() << '\n'; OscOK = false; } ofBackground(0, 0, 0); ofSetFullscreen(true); ofSetFrameRate(60); timeStep = 1/ofGetFrameRate(); ofEnableSmoothing(); ofEnableAlphaBlending(); pitch = 60.0; phasorIncr = pitch/SAMPLE_RATE; globalForces.gravityAmt = 0.0; globalForces.avFilterAmt = 0.01; initialiseMidi(); // ofSoundStreamSetup(2,0,this, SAMPLE_RATE,256, 2); paused = false; audioOn = false; drawingOn = true; audioAccessFlag = false; meshConstructionFlag = false; ofxiPhoneSetOrientation( OF_ORIENTATION_90_RIGHT ); setupGui(); setupMesh(); scanPath.init(); globalUI.touchMode = globalUI.GRAB; scanPath.scanMode = scanPath.DISPLACEMENT; globalUI.borderSize = ofGetWidth()/8; ofSoundStreamStart(); paused = false; audioOn = true; //ofxiPhoneExternalDisplay::mirrorOn(); cout << "Width: " << ofGetWidth() << endl; cout << "Height: " << ofGetHeight() << endl; // stupid hack for control vis hideControls(); showControls(); //[ofxiPhoneGetGLView() updateDimensions]; } //-------------------------------------------------------------------------- void testApp::initialiseMidi(){ ///////////////////////// // MIDI midiChannel = 7; // enables the network midi session between iOS and Mac OSX on a // local wifi network // // in ofxMidi: open the input/outport network ports named "Session 1" // // on OSX: use the Audio MIDI Setup Utility to connect to the iOS device // ofxMidi::enableNetworking(); // list the number of available input & output ports ofxMidiIn::listPorts(); ofxMidiOut::listPorts(); // create and open input ports for(int i = 0; i < ofxMidiIn::getNumPorts(); ++i) { // new object inputs.push_back(new ofxMidiIn); // set this class to receive incoming midi events inputs[i]->addListener(this); // open input port via port number inputs[i]->openPort(i); } // create and open output ports for(int i = 0; i < ofxMidiOut::getNumPorts(); ++i) { // new object outputs.push_back(new ofxMidiOut); // open input port via port number outputs[i]->openPort(i); } // set this class to receieve midi device (dis)connection events ofxMidi::setConnectionListener(this); // END MIDI } //-------------------------------------------------------------- Json::Value testApp::convertToJsonForSaving(){ Json::Value root; root["pitch"] = pitch; // root["globalForces"] = globalForces.convertToJsonForSaving(); root["mesh"] = theMesh->convertToJsonForSaving(); return root; } // //-------------------------------------------------------------- void testApp::showPresetNameDialog(){ if(!presetAlertViewController.alertShowing){ // this is to stop wierd infinite loop in ios5 (simulator) [presetAlertViewController showPresetNamePrompt]; } } //-------------------------------------------------------------- void testApp::savePreset(const string name = "default" ){ static int presetNumber; presetNumber++; Json::Value jpreset = convertToJsonForSaving(); //save json to file string fname = ofxiPhoneGetDocumentsDirectory() + "presetFile"; // write to file ofFile logFile(fname,ofFile::WriteOnly); logFile << jpreset; logFile.close(); } //-------------------------------------------------------------- Json::Value testApp::loadPresetFile(){ Json::Value jpreset; //save json to file string fname = ofxiPhoneGetDocumentsDirectory() + "presetFile"; Json::Value root; Json::Reader reader; ///////////// // read file ifstream theFile(fname.c_str()); stringstream fileText; string line; if(!theFile){ cout<<"No preset file found\n"; return root; }else{ while(theFile){ theFile >> line; // cout << line; // lots!!!! fileText << line; } theFile.close(); } cout << "size of preset JSON string:" << fileText.str().length() << "BYTES \n"; bool parsingSuccessful = reader.parse( fileText.str(), root ); if ( !parsingSuccessful ) { // report to the user the failure and their locations in the document. std::cout << "Failed to parse preset JSON: \n" << reader.getFormattedErrorMessages(); return root; // will be null } return root; } //-------------------------------------------------------------- void testApp::constructPresetFromJson(Json::Value& presetJson){ // construct mesh with right type and size // impose saved constraints // make saved scanpath // recall global settings pitch = presetJson["pitch"].asDouble(); theMesh = new Mesh(presetJson["mesh"]); globalForces.setFromJson(presetJson["globalForces"]); } //-------------------------------------------------------------- void testApp::loadPreset(){ if(audioAccessFlag) return; // or rather wait ! meshConstructionFlag = TRUE; deleteMesh(); Json::Value jp = loadPresetFile(); constructPresetFromJson(jp); // check these stupid tyhings numTouches = 0; meshConstructionFlag = FALSE; paused = false; audioOn = true; drawingOn = true; ofSoundStreamStart(); cout << "PRESET WAS LOADED\n"; } //-------------------------------------------------------------- //-------------------------------------------------------------- // App running stuff //-------------------------------------------------------------- //-------------------------------------------------------------- //-------------------------------------------------------------- void testApp::exit(){ ofSoundStreamClose(); // save everything... delete guiL; if(theMesh != NULL){ scanPath.clear(); delete theMesh; } } //-------------------------------------------------------------- void testApp::update(){ if(!paused){ if (theMesh != NULL){ theMesh->update(); } } handleMessages(); // !?!?? // if(ofxiPhoneExternalDisplay::isExternalScreenConnected()){ // if(!ofxiPhoneExternalDisplay::isMirroring()){ // ofxiPhoneExternalDisplay::mirrorOn(); // //printf("turned on Mirroring!\n"); // } // } } //-------------------------------------------------------------- void testApp::draw(){ if(drawingOn){ if(theMesh != NULL) theMesh->draw(); } if(controlsShowing){ drawSidePanels(); }else{ if (!controlsShowing) scanPath.draw(); // uncomment if you want to see the output waveform } } //-------------------------------------------------------------- // background for UI void testApp::drawSidePanels(){ ofSetColor(123, 123, 123); ofRect(0, 0, globalUI.borderSize, ofGetHeight()); ofRect(ofGetWidth()-globalUI.borderSize, 0, globalUI.borderSize, ofGetHeight()); } //-------------------------------------------------------------- void testApp::drawMessages(){ for ( int i=0; i<NUM_MSG_STRINGS; i++ ) { ofDrawBitmapString( msg_strings[i], 10, 40+15*i ); } } //-------------------------------------------------------------- //-------------------------------------------------------------- //------------------------CHANGING MESH---------------------------- //-------------------------------------------------------------- //-------------------------------------------------------------- //-------------------------------------------------------------- //-------------------------------------------------------------- void testApp::setupMesh(){ // SET UP THE MESH STRUCTURE if(audioAccessFlag) return; // or rather wait ! meshConstructionFlag = TRUE; static int type = 0; int numTypes = 8; if(type % numTypes == 0){ theMesh = new SquareCrossMesh(6,6); }else if (type % numTypes == 1){ // different for iphone if(ofGetWidth() == 480){ //PHONE theMesh = new SpiderCrossMesh(60,5); }else{ //PAD //theMesh = new SpiderCrossMesh(140,5); theMesh = new SpiderCrossMesh(100,9); } }else if(type % numTypes ==2){ theMesh = new DropletMesh(2000); }else if(type % numTypes ==3){ theMesh = new SquareCrossMesh(28,28); }else if(type % numTypes ==4){ theMesh = new TriangleMesh(34,34); }else if(type % numTypes ==5){ theMesh = new SpiderCrossMesh(30,30); }else if(type % numTypes ==6){ theMesh = new DropletMesh(128); }else if(type % numTypes ==7){ theMesh = new LineMesh(4000); } type++; //theMesh = new LineMesh(123); //theMesh = new GroundedLineMesh(400); //theMesh = new TriangleMesh(40,40); //theMesh = new LineMesh(100); // SET CONSTANTS UP FOR MESH theMesh->setSpringConstant(0.8); theMesh->setMass(1); theMesh->setFriction(0.99991); numTouches = 0; meshConstructionFlag = FALSE; paused = false; audioOn = true; drawingOn = true; ofSoundStreamStart(); cout << "MESH SETUP\n"; } //-------------------------------------------------------------- void testApp::deleteMesh(){ // TODO - OTHER THREADS FUCK THIS UP if(audioAccessFlag) return; // or rather wait ! //stop everything scanPath.clear(); ofSoundStreamStop(); paused = true; audioOn = false; drawingOn = false; scanPath.clear(); // trash it delete theMesh; theMesh = NULL; cout << "MESH DELETED\n"; } //-------------------------------------------------------------- void testApp::regenerateMesh(string meshType, int dim1, int dim2){ // more customisable version of setupMesh() if(audioAccessFlag) return; if (theMesh != NULL) return; if (meshType == "LineMesh"){ theMesh = new LineMesh(dim1); }else if (meshType == "DropletMesh"){ theMesh = new DropletMesh(dim1); }else if (meshType == "SpiderMesh"){ theMesh = new SpiderMesh(dim1,dim2); }else if (meshType == "SpiderCrossMesh"){ theMesh = new SpiderCrossMesh(dim1,dim2); }else if (meshType == "SquareCrossMesh"){ theMesh = new SquareCrossMesh(dim1,dim2); }else if (meshType == "TriangleMesh"){ theMesh = new TriangleMesh(dim1,dim2); }else if (meshType == "GroundedLineMesh"){ theMesh = new GroundedLineMesh(dim1); }else{ cout << "OSC message error: unrecognised mesh type" << endl; return; } ofSoundStreamStart(); drawingOn = true; paused = false; audioOn = true; cout << "MESH REGENERATED\n"; } //-------------------------------------------------------------- //-------------------------------------------------------------- //------------------------KEYS (OSX)---------------------------- //-------------------------------------------------------------- //-------------------------------------------------------------- // all this is now osc messages void testApp::keyPressed(int key){ if (key == 'p'){ paused = !paused; } if (key == 's'){ theMesh->toggleSyrup(true); } if (key == 'f'){ theMesh->toggleSpringForces(false); } if (key == '='){ theMesh->increasePropagationSpeed(); } if (key == '-'){ theMesh->decreasePropagationSpeed(); } if (key == 'a'){ if(audioOn){ audioOn = false; }else{ audioOn = true; } } if (key == 'r'){ theMesh->resetPositions(); theMesh->resetVelocities(); } if (key == 'e'){ theMesh->constrain(.0,.0,Mesh::CONSTRAIN_EDGES); } if (key == 'c'){ theMesh->constrain(.0,.0,Mesh::CONSTRAIN_CORNERS); } if (key == 'u'){ theMesh->unconstrain(); } if (key == 'l'){ theMesh->setRestLength(); } if (key == '0'){ theMesh->zeroRestLength(); } if (key == 'd'){ drawingOn = !drawingOn; } } //--------------------------------------------------------------- void testApp::keyReleased(int key){ if (key == 's'){ theMesh->toggleSyrup(false); } if (key == 'f'){ theMesh->toggleSpringForces(true); } } //-------------------------------------------------------------- //-------------------------------------------------------------- //------------------------TOUCH--------------------------------- //-------------------------------------------------------------- //-------------------------------------------------------------- void testApp::touchDown(ofTouchEventArgs &touch){ if(theMesh == NULL) return; double dax, day; // touchDown //cout << "touchDown ID: " << touch.id << endl; if(globalUI.handleTouchDown(touch.x, touch.y)) return; addTouch(); dax = (double(touch.x) - globalUI.borderSize)/ofGetHeight(); day = double(touch.y)/ofGetHeight(); switch (globalUI.touchMode){ case globalUI.GRAB: theMesh->grab(dax,day,touch.id); break; case globalUI.INSCRIBE_PATH: // start a new path, with touch id? ie:polyphonic paths!??! break; case globalUI.FORCE_FIELD: globalForces.createForceTouchPoint(dax,day, touch.id); break; case globalUI.SPATIAL_HARMONIC: // work out theMesh->spatialHarmonic(numTouches, 0); break; case globalUI.CONSTRAIN: theMesh->constrain(dax,day,Mesh::CONSTRAIN_GRAB_REGION); break; case globalUI.UNCONSTRAIN: theMesh->unconstrain(dax,day,Mesh::CONSTRAIN_GRAB_REGION); break; case globalUI.VIBRATE: break; default: break; } } //-------------------------------------------------------------- void testApp::touchMoved(ofTouchEventArgs &touch){ if(theMesh == NULL) return; if(globalUI.handleTouchMove(touch.x, touch.y)) return; //cout << "touchMoved ID: " << touch.id << endl; double dax, day; dax = (double(touch.x) - globalUI.borderSize)/ofGetHeight(); day = double(touch.y)/ofGetHeight(); /* if(kslider->checkForTouch(touch.x, touch.y)){ cout << "kslider touched"; kslider->adjust(touch.x,touch.y); return; } */ switch (globalUI.touchMode){ case globalUI.GRAB: theMesh->drag(dax,day,touch.id); break; case globalUI.INSCRIBE_PATH: theMesh->inscribeScanPath(dax,day); break; case globalUI.FORCE_FIELD: //theMesh->forceField(dax,day,touch.id); globalForces.moveForceTouchPoint(dax,day, touch.id); break; case globalUI.SPATIAL_HARMONIC: // makes no sense break; case globalUI.CONSTRAIN: theMesh->constrain(dax,day,Mesh::CONSTRAIN_GRAB_REGION); break; case globalUI.UNCONSTRAIN: theMesh->unconstrain(dax,day,Mesh::CONSTRAIN_GRAB_REGION); break; case globalUI.VIBRATE: break; default: break; } } //-------------------------------------------------------------- void testApp::touchUp(ofTouchEventArgs &touch){ if(theMesh == NULL) return; if(globalUI.handleTouchUp(touch.x, touch.y)) return; removeTouch(); switch (globalUI.touchMode){ case globalUI.GRAB: theMesh->unGrab(touch.id); break; case globalUI.INSCRIBE_PATH: theMesh->disconnectDraw(); break; case globalUI.FORCE_FIELD: globalForces.removeForceTouchPoint(touch.id); break; case globalUI.SPATIAL_HARMONIC: break; case globalUI.CONSTRAIN: break; case globalUI.UNCONSTRAIN: break; case globalUI.VIBRATE: break; default: break; } } //-------------------------------------------------------------- void testApp::touchDoubleTap(ofTouchEventArgs &touch){ // pretty much useless. /* ofxOscMessage m; m.setAddress( "/test" ); m.addIntArg( 1 ); m.addFloatArg( 3.5f ); m.addStringArg( "hello" ); m.addFloatArg( ofGetElapsedTimef() ); sender.sendMessage( m ); */ //ofxiPhoneScreenGrab(NULL); } //-------------------------------------------------------------- void testApp::addTouch(){ numTouches++; //cout << "numtouches " << numTouches << endl; } //-------------------------------------------------------------- void testApp::removeTouch(){ numTouches--; } //-------------------------------------------------------------- //-------------------------------------------------------------- // MOUSE - NOT NEEDED FOR IPAD //-------------------------------------------------------------- //-------------------------------------------------------------- void testApp::mouseMoved(int x, int y ){ //cout << "mouse moved " << x << 'y' << y << '\n'; /* double dax, day; // normalise dax = double(x)/ofGetWidth(); day = double(y)/ofGetHeight(); theMesh->checkHover(dax,day); */ } //-------------------------------------------------------------- void testApp::mouseDragged(int x, int y, int button){ //cout << "mouse DRAGGED " << x << 'y' << y << '\n'; /* double dax, day; dax = double(x)/ofGetWidth(); day = double(y)/ofGetHeight(); if(button == 0){ if(!paused){ theMesh->drag(dax,day, 0); }else{ // pause mode - draw a scan path! theMesh->drawScanPath(dax,day); audioOn = false; } }else if(button == 2){ } */ } //-------------------------------------------------------------- void testApp::mousePressed(int x, int y, int button){ /* double dax, day; // normalise dax = double(x)/ofGetWidth(); day = double(y)/ofGetHeight(); if(button == 0){ if(paused){ // draw a path audioOn = false; theMesh->deleteScanPath(); }else{ theMesh->grab(dax,day, 0); } }else if(button == 2){ theMesh->constrain(dax,day,Mesh::CONSTRAIN_GRAB_REGION); }else{ cout << "OTHER BUTTON?\n"; } */ } //-------------------------------------------------------------- void testApp::mouseReleased(int x, int y, int button){ /* if(button == 0){ theMesh->unGrab(0); }else if(button == 2){ }else{ cout << "butt other"; } */ } //-------------------------------------------------------------- //-------------------------------------------------------------- //-------------------------AUDIO----------------------------- //-------------------------------------------------------------- //-------------------------------------------------------------- void testApp::restartAudioStream(){ ofSoundStreamStart(); audioOn = true; } //-------------------------------------------------------------- void testApp::audioReceived(float * input, int bufferSize, int nChannels){ } //-------------------------------------------------------------- void testApp::audioRequested (float * output, int bufferSize, int nChannels){ float sample; static double phasor; if(meshConstructionFlag) return; // if no mesh , scanpath will still be there, but empty should be fine phasorIncr = pitch/SAMPLE_RATE; if(audioOn){ audioAccessFlag = TRUE; for (int i = 0; i < bufferSize; i++){ sample = float(scanPath.getNextSample(phasor)); // hipass to get rid of DC //sample = mydspTools.highpass1(sample); sample = mydspTools.butter(sample); // clip after volume sample = sample*globalForces.volume; if (sample >= 1.0){ sample = 0.999999999; }else if (sample <= -1.0){ sample = -0.999999999; } output[i*nChannels ] = sample; output[i*nChannels + 1] = sample; phasor += phasorIncr; if(phasor >= 1.0){ phasor -= 1.0; } } audioAccessFlag = FALSE; }else{ for (int i = 0; i < bufferSize; i++){ output[i*nChannels ] = 0.0; output[i*nChannels + 1] = 0.0; } } } //-------------------------------------------------------------- //-------------------------------------------------------------- //-------------------------OSC MSGS-------------------------------- //-------------------------------------------------------------- //-------------------------------------------------------------- void testApp::handleMessages(){ // hide old messages for ( int i=0; i<NUM_MSG_STRINGS; i++ ) { if ( timers[i] < ofGetElapsedTimef() ) msg_strings[i] = ""; } // check for waiting messages while( receiver.hasWaitingMessages() ) { // get the next message ofxOscMessage m; receiver.getNextMessage( &m ); //cout << "OSC message: " << m.getAddress() << endl; /****************/ /* REGENERATION OF NEW MESH */ /****************/ // if the mesh is not there check for regenerate , otherwise ignore everything if(theMesh == NULL){ if ( m.getAddress() == "regenerate" ) { string meshType; int dim1, dim2; int numArgs = m.getNumArgs(); cout << "REGEN num args: " << numArgs << endl; // we want to do some error checking here meshType = m.getArgAsString(0); cout << "REGEN meshType: " << meshType << endl; dim1 = m.getArgAsInt32(1); if(numArgs == 3){ dim2 = m.getArgAsInt32(2); }else{ dim2 = 3; } regenerateMesh(meshType,dim1,dim2); }else{ return; } } else if ( m.getAddress() == "restartNewMesh" ) { ofSoundStreamStart(); drawingOn = true; paused = false; audioOn = true; } /****************/ /* NOTE HANDLER */ /****************/ else if ( m.getAddress() == "note" ) { int note = m.getArgAsInt32(0); int velocity = m.getArgAsInt32(1); if(velocity > 0){ cout << "note pitch = " << pitch << endl; pitch = 440.0/pow(2.0,((69.0 - double(note))/12.0)); theMesh->hit(0.5,0.5,velocity,globalForces.excitationType,globalForces.excitationShape); }else{ theMesh->damp(); } } else if ( m.getAddress() == "excitationStrength" ) { globalForces.excitationStrength = m.getArgAsFloat(0); } else if ( m.getAddress() == "excitationType" ) { // set MIDI twanger mode if(m.getArgAsString(0) == "POSITION"){ globalForces.excitationType = GlobalForces::POSITION; }else if (m.getArgAsString(0) == "VELOCITY"){ cout << "excitationType = VELOCITY" << endl; globalForces.excitationType = GlobalForces::VELOCITY; } } else if ( m.getAddress() == "excitationShape" ) { // set MIDI twanger twang shape if(m.getArgAsString(0) == "NOISE"){ globalForces.excitationShape = GlobalForces::NOISE; }else if (m.getArgAsString(0) == "GAUSS"){ cout << "excitationType = GAUSS" << endl; globalForces.excitationShape = GlobalForces::GAUSS; }else if (m.getArgAsString(0) == "SINE"){ cout << "excitationType = SINE" << endl; globalForces.excitationShape = GlobalForces::SINE; } // set size globalForces.exciteShapeX = m.getArgAsInt32(1); globalForces.exciteShapeY = m.getArgAsInt32(2); } // touchModes: {GRAB,FORCE_FIELD,SPATIAL_HARMONIC,CONSTRAIN,VIBRATE,INSCRIBE_PATH}; else if ( m.getAddress() == "touchMode" ) { // set touch mode if(m.getArgAsString(0) == "GRAB"){ globalUI.touchMode = globalUI.GRAB; }else if (m.getArgAsString(0) == "FORCE_FIELD"){ cout << "touchMode = FORCE_FIELD" << endl; globalUI.touchMode = globalUI.FORCE_FIELD; }else if (m.getArgAsString(0) == "SPATIAL_HARMONIC"){ //cout << "touchMode = SPATIAL_HARMONIC" << endl; globalUI.touchMode = globalUI.SPATIAL_HARMONIC; }else if (m.getArgAsString(0) == "CONSTRAIN"){ //cout << "touchMode = CONSTRAIN" << endl; globalUI.touchMode = globalUI.CONSTRAIN; }else if (m.getArgAsString(0) == "VIBRATE"){ //cout << "touchMode = VIBRATE" << endl; globalUI.touchMode = globalUI.VIBRATE; }else if (m.getArgAsString(0) == "UNCONSTRAIN"){ //cout << "touchMode = UNCONSTRAIN" << endl; globalUI.touchMode = globalUI.UNCONSTRAIN; }else if (m.getArgAsString(0) == "INSCRIBE_PATH"){ //cout << "touchMode = INSCRIBE_PATH" << endl; globalUI.touchMode = globalUI.INSCRIBE_PATH; theMesh->clearScanPath(); } } else if ( m.getAddress() == "pause" ) { paused = !paused; } else if ( m.getAddress() == "touchStrength" ) { for ( int i=0; i<m.getNumArgs(); i++ ) { if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT ){ cout << "touchStrength = " << m.getArgAsFloat(i) << endl; globalForces.touchStrength = m.getArgAsFloat(i); globalForces.excitationStrength = globalForces.touchStrength; } } } else if ( m.getAddress() == "homingAmt" ) { for ( int i=0; i<m.getNumArgs(); i++ ) { if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT ){ globalForces.homingAmt = m.getArgAsFloat(i); } } } else if ( m.getAddress() == "avFilterAmt" ) { for ( int i=0; i<m.getNumArgs(); i++ ) { if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT ){ globalForces.avFilterAmt = m.getArgAsFloat(i); } } } else if ( m.getAddress() == "scanMode" ) { // set scan mode if (m.getArgAsString(0) == "DISPLACEMENT"){ cout << "touchMode = DISPLACEMENT" << endl; scanPath.scanMode = scanPath.DISPLACEMENT; }else if (m.getArgAsString(0) == "SPEED"){ cout << "scanMode = SPEED" << endl; scanPath.scanMode = scanPath.SPEED; }else if (m.getArgAsString(0) == "SPRING_FORCE"){ cout << "scanMode = SPRING_FORCE" << endl; scanPath.scanMode = scanPath.SPRING_FORCE; }else if (m.getArgAsString(0) == "YPOS"){ cout << "scanMode = YPOS" << endl; scanPath.scanMode = scanPath.YPOS; }else if (m.getArgAsString(0) == "OTHER"){ cout << "scanMode = OTHER" << endl; //scanMode = OTHER; } } else if ( m.getAddress() == "inscribeScanPath" ) { if (globalUI.touchMode != globalUI.INSCRIBE_PATH){ theMesh->resetPositions(); theMesh->resetVelocities(); paused = true; audioOn = false; globalUI.touchMode = globalUI.INSCRIBE_PATH; theMesh->clearScanPath(); theMesh->update(); }else{ paused = false; audioOn = true; globalUI.touchMode = globalUI.GRAB; } } else if ( m.getAddress() == "clearScanPath" ) { theMesh->clearScanPath(); } else if ( m.getAddress() == "toggleForce" ) { theMesh->toggleSpringForces(); } else if ( m.getAddress() == "toggleGravity" ) { theMesh->toggleGravity(); } else if ( m.getAddress() == "resetPositions" ) { theMesh->resetPositions(); } else if ( m.getAddress() == "resetVelocities" ) { theMesh->resetVelocities(); } else if ( m.getAddress() == "reset" ) { theMesh->resetPositions(); theMesh->resetVelocities(); theMesh->update(); } else if ( m.getAddress() == "deleteMesh" ) { deleteMesh(); } else if ( m.getAddress() == "regenerate" ) { // ignore it - the mesh is not deleted } else if ( m.getAddress() == "zeroRestLength" ) { theMesh->zeroRestLength(); } else if ( m.getAddress() == "setThisRestLength" ) { theMesh->setRestLength(); } else if ( m.getAddress() == "setZeroAudioLine" ) { theMesh->setZeroAudioLine(); } else if ( m.getAddress() == "speedLimit" ) { for ( int i=0; i<m.getNumArgs(); i++ ) { if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT ){ globalForces.speedLimit = m.getArgAsFloat(i); } } } else if ( m.getAddress() == "gravityAmt" ) { for ( int i=0; i<m.getNumArgs(); i++ ) { if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT ){ globalForces.gravityAmt = m.getArgAsFloat(i); } } } else if ( m.getAddress() == "pressureAmt" ) { for ( int i=0; i<m.getNumArgs(); i++ ) { if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT ){ globalForces.pressureAmt = m.getArgAsFloat(i); } } } else if ( m.getAddress() == "wallBounce" ) { for ( int i=0; i<m.getNumArgs(); i++ ) { if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT ){ //params::wallBounce = m.getArgAsFloat(i); } } } else if ( m.getAddress() == "toggleSyrup" ) { theMesh->toggleSyrup(); } else if ( m.getAddress() == "toggleAudio" ) { if(audioOn){ ofSoundStreamStop(); audioOn = false; }else{ restartAudioStream(); } } else if ( m.getAddress() == "constrainEdges" ) { theMesh->constrain(.0,.0,Mesh::CONSTRAIN_EDGES); } else if ( m.getAddress() == "constrainCorners" ) { theMesh->constrain(.0,.0,Mesh::CONSTRAIN_CORNERS ); } else if ( m.getAddress() == "unconstrain" ) { theMesh->unconstrain(); } else if ( m.getAddress() == "mass" ) { for ( int i=0; i<m.getNumArgs(); i++ ) { if( m.getArgType( i ) == OFXOSC_TYPE_INT32 ){ theMesh->setMass(m.getArgAsInt32( i )); } else if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT ) { theMesh->setMass(m.getArgAsFloat( i )<0.01?0.01:m.getArgAsFloat( i ) ); } } } else if ( m.getAddress() == "springk" ) { for ( int i=0; i<m.getNumArgs(); i++ ) { if( m.getArgType( i ) == OFXOSC_TYPE_INT32 ){ theMesh->setSpringConstant(m.getArgAsInt32( i )); } else if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT ) { theMesh->setSpringConstant(m.getArgAsFloat( i )<0.01?0.01:m.getArgAsFloat( i ) ); } } } else if ( m.getAddress() == "friction" ) { for ( int i=0; i<m.getNumArgs(); i++ ) { if( m.getArgType( i ) == OFXOSC_TYPE_INT32 ){ theMesh->setFriction(m.getArgAsInt32( i )); } else if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT ) { theMesh->setFriction(m.getArgAsFloat( i )<0.01?0.01:m.getArgAsFloat( i ) ); } } } //////////////// asym else if ( m.getAddress() == "massAsym" ) { for ( int i=0; i<m.getNumArgs(); i++ ) { if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT ) { theMesh->setMassAsym(m.getArgAsFloat( i )<0.01?0.01:m.getArgAsFloat( i ) ); } } } else if ( m.getAddress() == "springkAsym" ) { for ( int i=0; i<m.getNumArgs(); i++ ) { if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT ) { theMesh->setSpringConstantAsym(m.getArgAsFloat( i )<0.00?0.00:m.getArgAsFloat( i ) ); } } } else if ( m.getAddress() == "frictionAsym" ) { for ( int i=0; i<m.getNumArgs(); i++ ) { if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT ) { theMesh->setFrictionAsym(m.getArgAsFloat( i )<0.01?0.01:m.getArgAsFloat( i ) ); } } } else if ( m.getAddress() == "volume" ) { for ( int i=0; i<m.getNumArgs(); i++ ) { if( m.getArgType( i ) == OFXOSC_TYPE_FLOAT ) { cout << "change volume\n"; globalForces.volume = m.getArgAsFloat( i ); } } } /////////////////////// else { // unrecognized message: display on the bottom of the screen 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 ) pitch = 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"; } // add to the list of strings to display msg_strings[current_msg_string] = msg_string; timers[current_msg_string] = ofGetElapsedTimef() + 5.0f; current_msg_string = ( current_msg_string + 1 ) % NUM_MSG_STRINGS; // clear the next line msg_strings[current_msg_string] = ""; } } } //-------------------------------------------------------------- //-------------------------------------------------------------- // GUI stuff //-------------------------------------------------------------- //-------------------------------------------------------------- void testApp::loadLogXML(){ ofxXmlSettings XMLlog; string message; if( XMLlog.loadFile(ofxiPhoneGetDocumentsDirectory() + "wabletlogs.xml") ){ message = "mySettings.xml loaded from documents folder!"; }else if( XMLlog.loadFile("Logs/wabletlogs.xml") ){ message = "mySettings.xml loaded from data folder!"; }else{ message = "unable to load mySettings.xml check data/ folder"; return; } cout << message << "\n"; // get all the values from log timesOpened = XMLlog.getValue("wabletlogs:timesOpened", 0); timesOpened++; } //-------------------------------------------------------------- void testApp::saveLogXML(){ ofxXmlSettings XMLlog; XMLlog.setValue("wabletlogs:timesOpened", timesOpened); if(XMLlog.saveFile(ofxiPhoneGetDocumentsDirectory() + "wabletlogs.xml")){ cout << "Saved wabletlogs.XML in iphone documents OK"; }else if(XMLlog.saveFile("Logs/wabletlogs.xml")){ cout << "Saved wabletlogs.XML in data folder"; }else{ cout << "wabletlogs file did not save :("; } } //-------------------------------------------------------------- void testApp::setupGui(){ float xInit = OFX_UI_GLOBAL_WIDGET_SPACING; int heightS = ofGetHeight(); int widthS = ofGetWidth(); float sidebarWidth = widthS/8; float length = sidebarWidth-xInit*2; float widgetHeight = heightS/18; /* setWidgetColor(OFX_UI_WIDGET_COLOR_BACK, cb); setWidgetColor(OFX_UI_WIDGET_COLOR_OUTLINE, co); setWidgetColor(OFX_UI_WIDGET_COLOR_OUTLINE_HIGHLIGHT, coh); setWidgetColor(OFX_UI_WIDGET_COLOR_FILL, cf); setWidgetColor(OFX_UI_WIDGET_COLOR_FILL_HIGHLIGHT, cfh); setWidgetColor(OFX_UI_WIDGET_COLOR_PADDED, cp); setWidgetColor(OFX_UI_WIDGET_COLOR_PADDED_OUTLINE, cpo); */ ofColor bgCol = ofColor(23,23,23); ofColor paddingCol = ofColor(56,56,56); ofColor padOutlineCol = ofColor(200,0,0); ofColor fillCol = ofColor(0,0,205); ofColor fillHicol = ofColor(0,0,255); ofColor outlineCol = ofColor(255,255,255); ofColor outlineHiCol = ofColor(255,255,255); // LEFT GUI ------------------ guiL = new ofxUICanvas(0,0,sidebarWidth,heightS); guiL->addSpacer(length-xInit, 2); //guiL->setUIColors(bgCol, outlineCol, outlineHiCol, fillCol, fillHicol, paddingCol, padOutlineCol); guiL->addWidgetDown(new ofxUILabel("Physics", OFX_UI_FONT_LARGE)); ofxUIWidget *slider; //ofxUISlider_<<#typename T#>>(<#string _name#>, <#T _min#>, <#T _max#>, <#T _value#>, <#float w#>, <#float h#>) slider = guiL->addWidgetDown(new ofxUISlider("SPRING K",0.0,0.8,0.4,length,widgetHeight)); slider->setDrawPadding(true); slider->setDrawPaddingOutline(true); slider->setColorFill(fillHicol); slider->setColorFillHighlight(fillHicol); slider = guiL->addWidgetDown(new ofxUISlider("GRAVITY", 0.0, 4.0, 0.0,length,widgetHeight )); slider->setDrawPadding(true); slider->setDrawPaddingOutline(true); slider->setColorFill(fillHicol); slider->setColorFillHighlight(fillHicol); slider = guiL->addWidgetDown(new ofxUISlider("HOMING",0.0,0.3,0.0,length,widgetHeight)); slider->setDrawPadding(true); slider->setDrawPaddingOutline(true); slider->setColorFill(fillHicol); slider->setColorFillHighlight(fillHicol); slider = guiL->addWidgetDown(new ofxUISlider("SMOOTHING", 0.0, 0.5, 0.01,length,widgetHeight)); slider->setDrawPadding(true); slider->setDrawPaddingOutline(true); slider->setColorFill(fillHicol); slider->setColorFillHighlight(fillHicol); guiL->addSpacer(length-xInit, 2); //guiL->setWidgetPosition(OFX_UI_WIDGET_POSITION_DOWN); slider = guiL->addSlider("PITCH", 2.0, 100.0, 80.0, length, heightS/2); slider->setDrawPadding(true); slider->setDrawPaddingOutline(true); slider->setColorFill(fillHicol); slider->setColorFillHighlight(fillHicol); ofAddListener(guiL->newGUIEvent, this, &testApp::guiLEvent); //guiL->setUIColors( ofColor(56,56,56), ofColor(255,255,56), ofColor(255,255,56), ofColor(0,0,255), ofColor(0,0,255), ofColor(0,0,255), ofColor(0,0,255) ); // RIGHT GUI ----------------------- guiR = new ofxUICanvas(ofGetWidth()-sidebarWidth, 0, sidebarWidth, ofGetHeight()-64); guiR->addSpacer(length-xInit, 2); vector<string> names; names.push_back("GRAB"); names.push_back("FORCE"); names.push_back("SINE"); names.push_back("STICK"); names.push_back("UNSTICK"); names.push_back("NEWPATH"); ofxUIRadio* radio; radio = guiR->addRadio("TOUCH MODE", names, OFX_UI_ORIENTATION_VERTICAL, widgetHeight, widgetHeight); radio->setDrawPadding(true); radio->setColorFill(fillHicol); radio->setColorFillHighlight(fillHicol); slider = guiR->addWidgetDown(new ofxUISlider( "TOUCH AMT", -0.4, 4.0, 1.0,length,widgetHeight)); slider->setDrawPadding(true); slider->setColorFill(fillHicol); slider->setColorFillHighlight(fillHicol); guiR->addSpacer(length-xInit, 2); guiR->addToggle("PAUSE", false, widgetHeight, widgetHeight); guiR->addButton("RESET", false, widgetHeight, widgetHeight); guiR->addButton("NEW", false, widgetHeight, widgetHeight); guiR->addButton("SAVE", false, widgetHeight, widgetHeight); guiR->addButton("LOAD", false, widgetHeight, widgetHeight); ofAddListener(guiR->newGUIEvent, this, &testApp::guiREvent); //guiR->loadSettings(ofxiPhoneGetDocumentsDirectory() + "guiSettings.xml"); radio->activateToggle("GRAB"); // show hide ctrls guiSH = new ofxUICanvas(ofGetWidth() - sidebarWidth, ofGetHeight()-64, sidebarWidth, 64); guiSH->addSpacer(length-xInit, 2); ofxUIToggle* t = guiSH->addToggle("CTRLS", false, widgetHeight, widgetHeight); // turn toggle on t->setState(true); ofAddListener(guiSH->newGUIEvent, this, &testApp::guiSHEvent); } //-------------------------------------------------------------- void testApp::UIcallBack(int buttID){ cout << " BUTT ID " << buttID << "\n"; } void testApp::hideControls(){ cout << "CTRLS ooff"; guiR->setVisible(false); guiL->setVisible(false); controlsShowing = false; } void testApp::showControls(){ cout << "CTRLS onnn"; guiR->setVisible(true); guiL->setVisible(true); controlsShowing = true; } //-------------------------------------------------------------- void testApp::guiSHEvent(ofxUIEventArgs &e) { if(e.widget->getName() == "CTRLS"){ // ???? cout << ((ofxUIButton *)e.widget)->getValue(); if( ((ofxUIButton *)e.widget)->getValue() == 0) { hideControls(); }else{ showControls(); } } } //-------------------------------------------------------------- void testApp::guiREvent(ofxUIEventArgs &e) { if(e.widget->getName() == "TOUCH MODE") { cout << "TOUCH MODE"; } if(e.widget->getName() == "GRAB"){ cout << "GRAB"; globalUI.touchMode = globalUI.GRAB; }else if(e.widget->getName() == "FORCE"){ globalUI.touchMode = globalUI.FORCE_FIELD; }else if(e.widget->getName() == "STICK"){ globalUI.touchMode = globalUI.CONSTRAIN; }else if(e.widget->getName() == "UNSTICK"){ globalUI.touchMode = globalUI.UNCONSTRAIN; }else if(e.widget->getName() == "NEWPATH"){ if(globalUI.touchMode != globalUI.INSCRIBE_PATH){ theMesh->resetPositions(); theMesh->resetVelocities(); globalUI.touchMode = globalUI.INSCRIBE_PATH; theMesh->clearScanPath(); theMesh->update(); } }else if(e.widget->getName() == "SINE"){ globalUI.touchMode = globalUI.SPATIAL_HARMONIC; }else if(e.widget->getName() == "RESET"){ theMesh->resetAll(); numTouches = 0; }else if(e.widget->getName() == "NEW"){ // ???? cout << ((ofxUIButton *)e.widget)->getValue(); if( ((ofxUIButton *)e.widget)->getValue() == 0) { deleteMesh(); setupMesh(); }else{ } }else if(e.widget->getName() == "SAVE"){ // save the preset somehow if( ((ofxUIButton *)e.widget)->getValue() == 0) { savePreset(); } }else if(e.widget->getName() == "LOAD"){ // save the preset somehow if( ((ofxUIButton *)e.widget)->getValue() == 0) { loadPreset(); } }else if(e.widget->getName() == "PAUSE"){ paused = !paused; }else if(e.widget->getName() == "TOUCH AMT"){ ofxUISlider *slider = (ofxUISlider *) e.widget; slider->setDrawPadding(true); globalForces.touchStrength = slider->getScaledValue(); } } //-------------------------------------------------------------- void testApp::guiLEvent(ofxUIEventArgs &e) { if(e.widget->getName() == "SPRING K") { ofxUISlider *slider = (ofxUISlider *) e.widget; theMesh->setSpringConstant( slider->getScaledValue() ); }else if(e.widget->getName() == "GRAVITY") { ofxUISlider *slider = (ofxUISlider *) e.widget; slider->setDrawPadding(true); globalForces.gravityAmt = slider->getScaledValue(); //radio->getScaledValue() ); }else if(e.widget->getName() == "HOMING") { ofxUISlider *slider = (ofxUISlider *) e.widget; globalForces.homingAmt = slider->getScaledValue(); //radio->getScaledValue() ); }else if(e.widget->getName() == "SMOOTHING") { ofxUISlider *slider = (ofxUISlider *) e.widget; globalForces.avFilterAmt = slider->getScaledValue(); //radio->getScaledValue() ); }else if(e.widget->getName() == "FRICTION") { ofxUISlider *slider = (ofxUISlider *) e.widget; theMesh->setFriction(slider->getScaledValue()); //radio->getScaledValue() ); }else if(e.widget->getName() == "PITCH") { ofxUISlider *slider = (ofxUISlider *) e.widget; pitch = slider->getScaledValue(); //radio->getScaledValue() ); } } //-------------------------------------------------------------- void testApp::deviceOrientationChanged(int newOrientation){ cout << "orientation: " << newOrientation; if(newOrientation == 4){ ofxiPhoneSetOrientation( OF_ORIENTATION_90_RIGHT ); } } //------------------------------------------------------------------------- //-------------------------------------------------------------- #pragma mark MIDI void testApp::addMessage(string msg) { cout << msg << endl; messages.push_back(msg); while(messages.size() > maxMessages) messages.pop_front(); } //-------------------------------------------------------------- void testApp::newMidiMessage(ofxMidiMessage& msg) { // recieved one static int p; // remembers last note on int v; // look at what it is if(msg.status == MIDI_CONTROL_CHANGE){ int ctl_num = msg.control; int ctl_val = msg.value; // TODO route control change message here } if(msg.status == MIDI_NOTE_ON){ p = msg.pitch; v = msg.velocity; // TODO handle note on here if(v > 0){ //cout << "note pitch = " << p << endl; pitch = 440.0/pow(2.0,((69.0 - double(p))/12.0)); globalForces.excitationShape = GlobalForces::SINE; if(theMesh != NULL && !meshConstructionFlag){ theMesh->hit(0.5,0.5,v,globalForces.excitationType,globalForces.excitationShape); } }else{ //theMesh->damp(); } } if(msg.status == MIDI_NOTE_OFF){ if(msg.pitch == p){ //theMesh->damp(); } // otherwise ignore it, it's not the currenttly playing note } } //-------------------------------------------------------------- void testApp::midiInputAdded(string name, bool isNetwork) { stringstream msg; msg << "ofxMidi: input added: " << name << " network: " << isNetwork; cout << msg.str(); addMessage(msg.str()); // create and open a new input port ofxMidiIn * newInput = new ofxMidiIn; newInput->openPort(name); newInput->addListener(this); inputs.push_back(newInput); } //-------------------------------------------------------------- void testApp::midiInputRemoved(string name, bool isNetwork) { stringstream msg; msg << "ofxMidi: input removed: " << name << " network: " << isNetwork << endl; cout << msg.str(); addMessage(msg.str()); // close and remove input port vector<ofxMidiIn*>::iterator iter; for(iter = inputs.begin(); iter != inputs.end(); ++iter) { ofxMidiIn * input = (*iter); if(input->getName() == name) { input->closePort(); input->removeListener(this); delete input; inputs.erase(iter); break; } } } //-------------------------------------------------------------- void testApp::midiOutputAdded(string name, bool isNetwork) { stringstream msg; msg << "ofxMidi: output added: " << name << " network: " << isNetwork << endl; cout << msg.str(); addMessage(msg.str()); // create and open new output port ofxMidiOut * newOutput = new ofxMidiOut; newOutput->openPort(name); outputs.push_back(newOutput); } //-------------------------------------------------------------- void testApp::midiOutputRemoved(string name, bool isNetwork) { stringstream msg; msg << "ofxMidi: output removed: " << name << " network: " << isNetwork << endl; cout << msg.str(); addMessage(msg.str()); // close and remove output port vector<ofxMidiOut*>::iterator iter; for(iter = outputs.begin(); iter != outputs.end(); ++iter) { ofxMidiOut * output = (*iter); if(output->getName() == name) { output->closePort(); delete output; outputs.erase(iter); break; } } } //--------------------------------------------------------------