changeset 38:fea11c3d1d94

tweaking endlessly
author Robert Tubb <rt300@eecs.qmul.ac.uk>
date Thu, 04 Dec 2014 17:03:01 +0000
parents 52dbd5b4cfa9
children 96ff7b41923a
files ExpMessageOrganiser.mm MessageOrganiser.h MessageOrganiser.mm PDSynthWrapper.h SequenceController.h SequenceController.mm TrainingMessageOrganiser.h TrainingMessageOrganiser.mm TrainingScoreManager.h UI code/6Dbox.mm UI code/Buttron.h UI code/Buttron.mm UI code/ButtronSlider.h UI code/ButtronSlider.mm UI code/TextPanel.mm UI code/UIElement.h UI code/UIProperties.h UI code/sliderPanel.mm eventLogger.h globalVariables.h testApp.h testApp.mm
diffstat 22 files changed, 291 insertions(+), 225 deletions(-) [+]
line wrap: on
line diff
--- a/ExpMessageOrganiser.mm	Wed Dec 03 11:38:26 2014 +0000
+++ b/ExpMessageOrganiser.mm	Thu Dec 04 17:03:01 2014 +0000
@@ -99,7 +99,7 @@
         if(finished){
             instructionPanel->setText("ALL PRESETS MADE\n Please restart and go to TRAIN stage");
             instructionPanel->show();
-            bottomPanel->hide();
+            bottomPanel->show();
 
             controlPanel->hide();
             
--- a/MessageOrganiser.h	Wed Dec 03 11:38:26 2014 +0000
+++ b/MessageOrganiser.h	Thu Dec 04 17:03:01 2014 +0000
@@ -70,11 +70,13 @@
     void setInstructionPanel(TextPanel * ip);
     void setSeqNumPanel(TextPanel * snp);
     void setScoreNumPanel(TextPanel * snp);
+    void setDistanceSlider(ButtronSlider * s);
     //-----------------------------------------------------------------------------
     void hideMyPanels();
     void showMyPanels();
     void midiFromLeap(int ctl_num, int ctl_val);
     void setPanelType(controlPanelType p);
+    void update();
 protected:
 
     PDSynthWrapper candidateSynth;
@@ -94,6 +96,7 @@
     void sendSynthValuesAgain();
     void setAllSlidersToValues(vector<int> values);
     void setCandidateAndSlidersToRandom();
+    void setSlidersToCandidate();
     // we want to set UI object
     void setUIToParam(int index, int value);
     void mapControlToParam(UIElement* control, int mappingID);
@@ -115,5 +118,6 @@
     bool onlyChangeCandidateOnTrigger;
     bool okToGetMidi;
     controlPanelType panelType;
+    ButtronSlider * distanceSlider;
 };
 
--- a/MessageOrganiser.mm	Wed Dec 03 11:38:26 2014 +0000
+++ b/MessageOrganiser.mm	Thu Dec 04 17:03:01 2014 +0000
@@ -69,6 +69,9 @@
     instructionPanel = ip;
     instructionPanel->show();
 }
+void MessageOrganiser::setDistanceSlider(ButtronSlider * s){
+    distanceSlider = s;
+}
 //----------------------------------------------------------------------------------
 void MessageOrganiser::setSeqNumPanel(TextPanel * snp){
     seqNumPanel = snp;
@@ -246,6 +249,13 @@
         setUIToParam(i, vals[i]);
     }
 }
+void MessageOrganiser::setSlidersToCandidate(){
+
+    vector<int> vals = candidateSynth.getAllParamValues();
+    for(int i=0; i < vals.size(); i++){
+        setUIToParam(i, vals[i]);
+    }
+}
 void MessageOrganiser::showTargetAsHints(){
 //    int i = 0;
 //    vector<int> vals = targetSynth.getAllParamValues();
@@ -295,7 +305,6 @@
         candidateSynth.paramChangeCallback(mids[ctl_num], ctl_val, true);
     }
     
-
     setUIToParam(ctl_num, ctl_val);
     
     // wait for a certain distance travelled AND time then record?
@@ -311,7 +320,12 @@
         //cout << "skipped! so far logged " << howManyLogged << endl;
     }
 
-    
+    if(distanceSlider->isShowing()){
+        // get euc dist between cand and target
+        float d = euclideanDistance(newVals, targetSynth.getAllParamValues());
+        
+        distanceSlider->setValueAndScale(d);
+    }
 }
 
 
--- a/PDSynthWrapper.h	Wed Dec 03 11:38:26 2014 +0000
+++ b/PDSynthWrapper.h	Thu Dec 04 17:03:01 2014 +0000
@@ -45,6 +45,7 @@
             cout << "ERROR ERROR: WRONG NUM OF timbreParams or TOTAL_NUM_PARAMS" << endl;
         }
         cout << "initialised synth: " << sp << " with " << timbreParams.size() << " params" << endl;
+        metronomeRunning = false;
     };
     
 // PD SENDERS
@@ -272,13 +273,16 @@
         // play the noise
         List toPD;
         core->pd.sendMessage("fromOF", "startMetro", toPD);
-        
+        metronomeRunning = true;
     }
     void stopMetronome(){
         // play the noise
         List toPD;
         core->pd.sendMessage("fromOF", "stopMetro", toPD);
-        
+        metronomeRunning = false;
+    }
+    bool isMetronomeRunning(){
+        return metronomeRunning;
     }
     void setMetroTime(float t){
         List toPD;
@@ -300,7 +304,7 @@
     string synthPrefix;
     AppCore* core;
     vector<SynthParam> timbreParams; // array of everything in synth
-  
+    bool metronomeRunning;
 };
 
 //---------------------------------------------------------------------
--- a/SequenceController.h	Wed Dec 03 11:38:26 2014 +0000
+++ b/SequenceController.h	Thu Dec 04 17:03:01 2014 +0000
@@ -18,11 +18,11 @@
 #define NUM_REPETITIONS_AT_LEVEL 1
 #define MAX_TARGETS_IN_SEQUENCE 4
 #define MIN_TEMPO   70
-#define MAX_TEMPO   480
+#define MAX_TEMPO   500
 #define TEMPO_RANDOM_AMOUNT
 #define MAX_TIME 2800
 #define MIN_TIME 200
-#define NUM_TEMPO_STEPS 17
+#define NUM_TEMPO_STEPS 20
 
 #define NUM_PRESETS 8
 #define SPACER_BARS false
--- a/SequenceController.mm	Wed Dec 03 11:38:26 2014 +0000
+++ b/SequenceController.mm	Thu Dec 04 17:03:01 2014 +0000
@@ -523,9 +523,12 @@
         nextStep.tempo = curTempo;
         nextStep.tempoLevel = tempoLevel;
         nextStep.setTimeFromTempo();
-        nextStep.showsGuides = true;
+        nextStep.showsGuides = false;
         nextStep.type = AnimStep::PREVIEW_NEUTRAL_COUNT;
         nextStep.showsResultsAtEnd = false;
+        // two neutrals between the new sequences
+        steps.push_back(nextStep);
+        nextStep.showsGuides = true;
         steps.push_back(nextStep);
         
         // generate a sequence of random preset indices
@@ -590,6 +593,7 @@
         nextStep.showsResultsAtEnd = false;
         steps.push_back(nextStep);
         
+        
         // make matching sequence with icon seq help
         n = 1;
         for(auto si = stepPresetIndices.begin(); si < stepPresetIndices.end(); si++){
--- a/TrainingMessageOrganiser.h	Wed Dec 03 11:38:26 2014 +0000
+++ b/TrainingMessageOrganiser.h	Thu Dec 04 17:03:01 2014 +0000
@@ -34,7 +34,7 @@
     void onNextTickAnim(int tickNumber);
     
     void showMyPanels();
-
+    void setForgotButton(Buttron* butt);
     //void midiFromLeap(int ctl_num, int ctl_val);
     //-----------------------------------------------------------------------
 protected:
@@ -82,7 +82,7 @@
     TextPanel* middlePanel;
     SequenceController sequenceController;
     TrainingScoreManager trainingScoreManager;
-    
+    Buttron* forgotButton;
 
     
 };
--- a/TrainingMessageOrganiser.mm	Wed Dec 03 11:38:26 2014 +0000
+++ b/TrainingMessageOrganiser.mm	Thu Dec 04 17:03:01 2014 +0000
@@ -35,7 +35,9 @@
 void TrainingMessageOrganiser::setMiddlePanel(TextPanel* tp){
     middlePanel = tp;
 }
-
+void TrainingMessageOrganiser::setForgotButton(Buttron* butt){
+    forgotButton = butt;
+}
 //----------------------------------------------------------------------------------------
 void TrainingMessageOrganiser::showMyPanels(){
     presetIconPanel->show();
@@ -78,7 +80,11 @@
     }
     
     if (mappingID == START_TRAINING_SEQUENCE_ID){
-
+        // start next run
+        if (candidateSynth.isMetronomeRunning()){
+            // skip to next run?
+            eventLogger.logEvent(RUN_SKIPPED);
+        }else{
         candidateSynth.setMetroTime(sequenceController.getStartTickTime());
         candidateSynth.startMetronome();
         bottomPanel->hide();
@@ -86,12 +92,24 @@
         vector<int> details;
         
         eventLogger.logEvent(START_NEW_RUN);
+        }
         return;
     }
     
     if(mappingID == TO_MENU_ID){
         // tell testapp to start again?
+        candidateSynth.stopMetronome();
+        controlPanel->hide();
+        controlPanel->setColor(ofColor::black);
+        seqNumPanel->hide();
+        eventLogger.logEvent(RUN_SKIPPED);
+        eventLogger.saveSessionToFile();
+    }
     
+    if(mappingID == FORGOT_SEQ_ID){
+        //
+        eventLogger.logEvent(FORGOT_SEQ);
+        cout << "FORGOT" << endl;
     }
     
 }
@@ -104,7 +122,6 @@
     downCounter = 4 - tickNumber % 4;
     
     if (showingCountdown){
-        middlePanel->setColor(ofColor::white);
         middlePanel->setText(ofToString(downCounter));
     }
     
@@ -122,7 +139,6 @@
     s << "FINISHED RUN " << which+1 << " OF " << sequenceController.getTotNumRuns() << endl;
     controlPanel->hide();
     controlPanel->setColor(ofColor::black);
-    middlePanel->setColor(ofColor::white);
     middlePanel->setText(s.str());
     middlePanel->show();
     //playCandidateButton->setLabel("NEXT");
@@ -136,7 +152,6 @@
     cout << "FINISHED BLOCK" << endl;
     controlPanel->hide();
     controlPanel->setColor(ofColor::black);
-    middlePanel->setColor(ofColor::white);
     middlePanel->setText("CONGRATULATIONS. FINISHED BLOCK!");
     middlePanel->show();
     bottomPanel->show();
@@ -294,6 +309,9 @@
     seqNumPanel->hide();
     oldTargetValues = newTargetValues;
     controlPanel->setColor(ofColor::black);
+    
+    bottomPanel->show(); // so people can say they forgot
+    forgotButton->show();
 }
 //-----------------------------------------------------------------------------
 void TrainingMessageOrganiser::previewMove(AnimStep newStep, Preset * currentTargetPreset){
@@ -319,6 +337,9 @@
     oldTargetValues = newTargetValues;
     
     controlPanel->setColor(ofColor::black);
+    bottomPanel->hide(); // so people can say they forgot, or quit
+    forgotButton->hide();
+    forgotButton->turnOff();
 }
 
 
@@ -344,90 +365,6 @@
 }
 
 //-----------------------------------------------------------------------------
-//void TrainingMessageOrganiser::guidedMove(AnimStep newStep){
-//    targetSynth.trigger(); // plays LAST target (?)
-//    triggerCandidateSound();
-//    middlePanel->hide();
-//    
-//    Preset * currentTargetPreset;
-//    if(newStep.presetIndex == -1){
-//        currentTargetPreset =  expPresetManager.getNeutralPreset();
-//    }else{
-//        
-//        currentTargetPreset =  expPresetManager.getPresetAtIndex(newStep.presetIndex);
-//    }
-//
-//    vector<int> newTargetValues = currentTargetPreset->getValues();
-//  
-//    targetSynth.setAllParamsWithoutSend(newTargetValues);
-//    
-//    
-//    controlPanel->setActive(true);
-//    // show icon and guide markers
-//    presetIconPanel->setTextAndImage(currentTargetPreset->name, currentTargetPreset->getImage(), false);
-//    presetIconPanel->show();
-//    
-//    controlPanel->setAndShowHint(newTargetValues, currentTargetPreset->getImage());
-//    
-//    
-//    // show your hand and allow movement
-//    controlPanel->showValueIndicators(true);
-//    okToGetMidi = true;
-//    
-//    stringstream instruct;
-//    instruct << "GUIDED MOVE" << endl;;
-//    instruct << newStep.whichInSequence+1 << endl;
-//    displayInstructions(instruct.str());
-//    
-//    showSeqNum(newStep.whichInSequence+1);
-//
-//    oldTargetValues = newTargetValues;
-//}
-//
-////======================================================================
-//void TrainingMessageOrganiser::guidedHit(AnimStep newStep){
-//    Preset * currentTargetPreset;
-//    currentTargetPreset =  expPresetManager.getPresetAtIndex(newStep.presetIndex);
-//    vector<int> newTargetValues = currentTargetPreset->getValues();
-//    eventLogger.logEvent(NEW_TARGET, newTargetValues);
-//    sendSynthValuesAgain();
-//    
-//    // show your hand and allow movement (so you can set off to next target??)
-//    
-//    controlPanel->showValueIndicators(true);
-//    okToGetMidi = true;
-//    
-//    targetSynth.setAllParamsWithoutSend(newTargetValues);
-//    triggerCandidateSound();
-//    targetSynth.trigger();
-//    displayInstructions("GUIDED HIT");
-//    vector<int> startPosition = expPresetManager.getNeutralPreset()->getValues();
-//    
-//    oldTargetValues = newTargetValues;
-//}
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-//void TrainingMessageOrganiser::matchingNeutralCount(AnimStep newStep, Preset * currentTargetPreset){
-//    Preset * currentTargetPreset = expPresetManager.getNeutralPreset();
-//    vector<int> newTargetValues = currentTargetPreset->getValues();
-//    // if showing guides show all the targets as transparent ghosts
-//    if (newStep.showsGuides){
-//        controlPanel->setAndShowHint(newTargetValues, currentTargetPreset->getImage());
-//
-//    }else{
-//        controlPanel->showHint(false);
-//    }
-//    
-//    // show your hand and allow movement
-//    controlPanel->showValueIndicators(true);
-//    okToGetMidi = true;
-//    
-//        displayInstructions("Match Count");
-//    seqNumPanel->hide();
-//    oldTargetValues = newTargetValues;
-//}
-//-----------------------------------------------------------------------------
 void TrainingMessageOrganiser::matchingMove(AnimStep newStep, Preset * currentTargetPreset){
 
     
@@ -550,10 +487,11 @@
         
         // show where we're going
         controlPanel->setAndShowHint(currentTargetPreset->getValues(), currentTargetPreset->getImage());
-        
+        if (panelType == LEAP6DOF) distanceSlider->show();
         
     }else{
         controlPanel->showHint(false);
+        distanceSlider->hide();
     }
     
 }
@@ -573,6 +511,7 @@
             okToGetMidi = true; // allow midi input to thing
         }else{
             okToGetMidi = false;
+            setSlidersToCandidate(); // cos hand won't be controlling them
         }
         
     }else{
--- a/TrainingScoreManager.h	Wed Dec 03 11:38:26 2014 +0000
+++ b/TrainingScoreManager.h	Thu Dec 04 17:03:01 2014 +0000
@@ -35,8 +35,99 @@
 public:
     TrainingScoreManager(){
         totalScored = 0;
+    };
+    int getBandForDistance(float dist) const{
+        int band = -1;
+        auto dimComp = sqrt(TOTAL_NUM_PARAMS);
+        if (dist < TARGET_SCORE_CC_BAND*dimComp){
+            
+            band = 1;
+            
+        }else if (dist < TARGET_SCORE_CC_BAND*2*dimComp){
+            
+            band = 2;
+
+        }else if (dist < TARGET_SCORE_CC_BAND*3*dimComp){
+            
+            band = 3;
+
+        }else if (dist < TARGET_SCORE_CC_BAND*4*dimComp){
+
+            band = 4;
+            
+        }else if (dist < TARGET_SCORE_CC_BAND*6*dimComp){ // 30
+            
+            band = 5;
+
+            
+        }else if (dist < TARGET_SCORE_CC_BAND*9*dimComp){ // 45
+            
+            band = 6;
+
+            
+        }else{
+            
+            band = 7;
+
+            
+        }
+        return band;
+    };
+    
+    string getMessageForBand(int band) const{
+        stringstream msg;
+        if (band == 1){
+            
+            msg << "DOUBLE BULLSEYE!" << endl;
+            
+            
+        }else if (band == 2){
+
+            
+            msg << "SINGLE BULLSEYE!" << endl;
+            
+        }else if (band == 3){
+          
+            msg << "CLOSE..." << endl;
+            
+        }else if (band == 4){
+
+            msg << "OK...ISH" << endl;
+            
+        }else if (band == 5){ // 30
+
+            msg << "MEDIOCRE" << endl;
+            
+        }else if (band == 6){ // 45
+
+            msg << "POOR..." << endl;
+            
+        }else{
+
+            msg << "MISSED COMPLETELY!" << endl;
+            
+            
+        }
+        return msg.str();
     }
-    
+    ofColor getColorForBand(int band) const {
+        
+        
+        ofColor c;
+        if(band == 1){
+            
+            c = ofColor(255,255,0,255);     // yellow 1
+        }else if(band == 2){
+            c = ofColor(255,0,0,255);       // red 2
+        }else if(band == 3){
+            c = ofColor(45,45,255,255);     // blue 3
+        }else if(band == 4){
+            c = ofColor(0,255,0,255);       // green 4
+        }else{
+            c = ofColor(123,123,123,255);         // grey worst
+        }
+        return c;
+    };
     TrainingTestResult getScoreForAnswer(vector<int> targetParams,
                                          vector<int> startPosition,
                                          vector<int> answer,
@@ -61,53 +152,13 @@
         cout << "Preset index " << presetIndex << endl;
         cout << "whichInSequence " << whichInSequence << endl;
         
-        auto dimComp = sqrt(TOTAL_NUM_PARAMS);
-        int band = -1;
-        if (dist < TARGET_SCORE_CC_BAND*dimComp){
-     
-            band = 1;
-            
-            msg << "DOUBLE BULLSEYE!" << endl;
-            
-            
-        }else if (dist < TARGET_SCORE_CC_BAND*2*dimComp){
-       
-            band = 2;
-            
-            msg << "SINGLE BULLSEYE!" << endl;
-            
-        }else if (dist < TARGET_SCORE_CC_BAND*3*dimComp){
-       
-            band = 3;
-            msg << "CLOSE..." << endl;
-            
-        }else if (dist < TARGET_SCORE_CC_BAND*4*dimComp){
-           
-            band = 4;
-            msg << "OK...ISH" << endl;
-            
-        }else if (dist < TARGET_SCORE_CC_BAND*6*dimComp){ // 30
-           
-            band = 5;
-            msg << "MEDIOCRE" << endl;
-            
-        }else if (dist < TARGET_SCORE_CC_BAND*9*dimComp){ // 45
-           
-            band = 6;
-            msg << "POOR..." << endl;
-            
-        }else{
-           
-            band = 7;
-            msg << "MISSED COMPLETELY!" << endl;
-            
-            
-        }
-        msg << "Distance from target: " << dist << endl;
+        int band = getBandForDistance(dist);
+        
+        msg << getMessageForBand(band) << endl;
+        msg << "Distance: " << dist << endl;
         msg << "Score: " << round(TP*10) << endl;
         msg << "-----" << endl;
         msg << "Time allowed: " << timeAllowed/1000.0 << endl;
-
         msg << "-----" << endl;
 
         result.realDistanceToTarget = dist;
@@ -116,22 +167,7 @@
         result.score = int(round(TP*10.0));
         result.displayText = msg.str();
         result.difficultyLevel = difficulty;
-    
-        
-        ofColor c;
-        if(result.targetBandHit == 1){
-            
-            c = ofColor(255,255,0,255);     // yellow 1
-        }else if(result.targetBandHit == 2){
-            c = ofColor(255,0,0,255);       // red 2
-        }else if(result.targetBandHit == 3){
-            c = ofColor(45,45,255,255);     // blue 3
-        }else if(result.targetBandHit == 4){
-            c = ofColor(0,255,0,255);       // green 4
-        }else{
-            c = ofColor(123,123,123,255);         // grey worst
-        }
-        result.colorBand = c;
+        result.colorBand = getColorForBand(band);
 
         if(result.score > 0) totalScored += result.score;
         
--- a/UI code/6Dbox.mm	Wed Dec 03 11:38:26 2014 +0000
+++ b/UI code/6Dbox.mm	Thu Dec 04 17:03:01 2014 +0000
@@ -110,10 +110,10 @@
 
 void Leap6DBox::makeTexFace(ofPoint LT, ofPoint RT, ofPoint  RB, ofPoint LB){
     
-    ofPoint texCoordLT = ofPoint(0, 1.);
+    ofPoint texCoordLT = ofPoint(0, 0.5);
     ofPoint texCoordLB = ofPoint(0, 0);
-    ofPoint texCoordRT = ofPoint(1., 1.);
-    ofPoint texCoordRB = ofPoint(1., 0);
+    ofPoint texCoordRT = ofPoint(0.5, 0.5);
+    ofPoint texCoordRB = ofPoint(0.5, 0);
     
     handMesh.addVertex(LT);
     handMesh.addTexCoord(texCoordLT);
--- a/UI code/Buttron.h	Wed Dec 03 11:38:26 2014 +0000
+++ b/UI code/Buttron.h	Thu Dec 04 17:03:01 2014 +0000
@@ -70,6 +70,9 @@
     void setMode(Mode m){
         behaviourMode = m;
     };
+    void turnOff(){
+        on = false;
+    }
     virtual bool handleMyTouch(int x, int y, touchType ttype, int touchID);
 
 protected:
--- a/UI code/Buttron.mm	Wed Dec 03 11:38:26 2014 +0000
+++ b/UI code/Buttron.mm	Thu Dec 04 17:03:01 2014 +0000
@@ -16,50 +16,51 @@
 }
 //------------------------------------------------------------------
 Buttron::Buttron(
-        float ax,
-        float ay,
-        float awidth,
-        float aheight,
-        float athickness,
-        float aradius,
-        ofColor aforegroundHi,
-        ofColor abackgroundHi,
-        ofColor aforegroundLo,
-        ofColor abackgroundLo) :
-        UIElement(ax,ay,awidth,aheight,abackgroundLo),
-        thickness(athickness),
-        radius(aradius),
-        foregroundHi(aforegroundHi),
-        backgroundHi(abackgroundHi),
-        foregroundLo(aforegroundLo),
-        backgroundLo(abackgroundLo) {
+                 float ax,
+                 float ay,
+                 float awidth,
+                 float aheight,
+                 float athickness,
+                 float aradius,
+                 ofColor aforegroundHi,
+                 ofColor abackgroundHi,
+                 ofColor aforegroundLo,
+                 ofColor abackgroundLo) :
+UIElement(ax,ay,awidth,aheight,abackgroundLo),
+thickness(athickness),
+radius(aradius),
+foregroundHi(aforegroundHi),
+backgroundHi(abackgroundHi),
+foregroundLo(aforegroundLo),
+backgroundLo(abackgroundLo) {
     //cout << "phew, buttron big constructur\n";
+    behaviourMode = MOMENTARY;
     on = false;
 }
 //------------------------------------------------------------------
 Buttron::Buttron(float ax,
                  float ay,
                  const UIProps& props):
-        UIElement(ax,ay,props.buttonWidth,props.buttonHeight, props)
+UIElement(ax,ay,props.buttonWidth,props.buttonHeight, props)
 
 {
-
+    
     thickness = props.borderThickness;
     radius = props.cornerRadius;
     foregroundHi = props.buttonHi;
-    backgroundHi = props.generalBackground;
+    backgroundHi = props.backgroundHi;
     foregroundLo = props.buttonLo;
     backgroundLo = props.generalBackground;
-    
+    behaviourMode = MOMENTARY;
     on = false;
 }
 //------------------------------------------------------------------
 Buttron::Buttron(float ax,
-        float ay,
-        float awidth,
-        float aheight,
-        const UIProps& props):
-    UIElement(ax,ay,awidth,aheight, props)
+                 float ay,
+                 float awidth,
+                 float aheight,
+                 const UIProps& props):
+UIElement(ax,ay,awidth,aheight, props)
 
 {
     //cout << "slider (meh) recommended constructor\n";
@@ -67,12 +68,13 @@
     thickness = props.borderThickness;
     radius = props.cornerRadius;
     foregroundHi = props.buttonHi;
-    backgroundHi = props.generalBackground;
+    backgroundHi = props.backgroundHi;
     foregroundLo = props.buttonLo;
     backgroundLo = props.generalBackground;
     fgInactive = props.inactiveGreyedOut;
     
     on = false;
+    behaviourMode = MOMENTARY;
 }
 //------------------------------------------------------------------
 void Buttron::draw(){
@@ -138,28 +140,28 @@
     
     //tl
     ofCircle(x+cornerSize, y+cornerSize, cornerSize);
-
+    
     
     //tr
-
+    
     ofCircle(x+width-cornerSize, y+cornerSize, cornerSize);
-
+    
     //bl
-
+    
     ofCircle(x+cornerSize, y+height-cornerSize, cornerSize);
-
+    
     //br
-
+    
     ofCircle(x+width-cornerSize, y+height-cornerSize, cornerSize);
-
+    
     // draw corner inner bg circles
     ofSetColor(bg);
     ofCircle(x+cornerSize, y+cornerSize, radius);
-
+    
     ofCircle(x+width-cornerSize, y+cornerSize, radius);
-
+    
     ofCircle(x+cornerSize, y+height-cornerSize, radius);
-
+    
     ofCircle(x+width-cornerSize, y+height-cornerSize, radius);
     
     // fill in background
@@ -173,15 +175,22 @@
 bool Buttron::handleMyTouch(int tx, int ty, touchType ttype, int touchID){
     
     //cout << "buttron handling touch\n";
-    if(ttype == TOUCH_DOWN){
-        on = true;
-        if(callback) callback(myParamID,1);
-        
-    }else if(ttype == TOUCH_MOVED){
-        
-    }else if(ttype == TOUCH_UP){
-        on = false;
+    if(behaviourMode == MOMENTARY){
+        if(ttype == TOUCH_DOWN){
+            on = true;
+            if(callback) callback(myParamID,1);
+            
+        }else if(ttype == TOUCH_MOVED){
+            
+        }else if(ttype == TOUCH_UP){
+            on = false;
+        }
     }
+    if(behaviourMode == TOGGLE)
+        if(ttype == TOUCH_DOWN){
+            on = !on;
+            if(callback) callback(myParamID,1);
+        }
     return true; // necessary?
     
 }
--- a/UI code/ButtronSlider.h	Wed Dec 03 11:38:26 2014 +0000
+++ b/UI code/ButtronSlider.h	Thu Dec 04 17:03:01 2014 +0000
@@ -36,6 +36,7 @@
     
     void init();
     void draw(){
+        if(!isShowing()) return;
         Buttron::draw();
         ofDisableDepthTest();
         drawIndicator(value);
@@ -65,6 +66,8 @@
     void setValueAndScale(double avalue){
         // scale appropriately to 0-1   (maxVal - minVal)*prop + minVal
         value =  (avalue - minVal)/(maxVal - minVal);
+        if (value > 1.) value = 1.;
+        if (value < 0.) value = 0.;
     };
     void showValueIndicator(bool show){
         indicatorShowing = show;
--- a/UI code/ButtronSlider.mm	Wed Dec 03 11:38:26 2014 +0000
+++ b/UI code/ButtronSlider.mm	Thu Dec 04 17:03:01 2014 +0000
@@ -49,6 +49,8 @@
     string fname = ofFilePath::getAbsolutePath(ofToDataPath("buttron.png"));
     defaultImage.loadImage(fname);
     setHandTexture(&defaultImage);
+    showScoreForFrames = 0;
+    hintPosAnimIncr = 0;
 }
 //
 //---------------------------------------------------------------------
@@ -66,8 +68,6 @@
     if(showScoreForFrames > 0){
         ofSetColor(flashColor);
         showScoreForFrames--;
-    }else{
-        ofSetColor(foregroundHi);
     }
     if(sliderType == FILL){
 
@@ -76,7 +76,9 @@
         double barheight = value*maxH;
         double top = y + height - thickness - barheight;
         ofRect(x+thickness, top, w, barheight);
+        
     }else if(sliderType == TEXTURE_FILL){
+        
         double maxH = height - 2 * thickness; //
         double w = width - 2 * thickness;//
         double barheight = value*maxH;
@@ -84,7 +86,9 @@
         //ofRect(x+thickness, top, w, barheight);
         ofSetColor(255,255, 255);
         (*handTextureRef).draw(x+thickness, top, w, barheight);
+        
     }else if(sliderType == LINE){
+        
         double loc = y + thickness +  (1 -value)*(height-3*thickness);
         ofRect(x+thickness,loc, width-2*thickness,thickness);
     }
@@ -94,11 +98,12 @@
 
 void ButtronSlider::drawHintIndicator(){
 
-    ofSetColor(hintColor);
-    float hthick = 6;
-    double loc = y + hthick +  (1 - hintValue)*(height-3*hthick);
-    ofRect(x-thickness,loc, width+2*thickness,hthick);
-
+    //ofSetColor(hintColor);
+    float hthick = 16;
+    double loc = y + thickness +  (1 - hintValue)*(height-3*thickness);
+    //ofRect(x-thickness,loc, width+2*thickness,hthick);
+    ofSetColor(255, 255, 255);
+    (*handTextureRef).draw(x-thickness,loc-hthick/2, width+2*thickness,hthick);
 }
 
 void ButtronSlider::animateHintToNewValue(int newVal, float timeToTake){
@@ -118,7 +123,7 @@
 void ButtronSlider::update(){
     if (!animating) return;
     value += posAnimIncr;
-    hintValue += hintPosAnimIncr;
+    //hintValue += hintPosAnimIncr;
     
     // TODO when we've hit the target stop.
 //    if (abs(targVal - value) < 0.01){
--- a/UI code/TextPanel.mm	Wed Dec 03 11:38:26 2014 +0000
+++ b/UI code/TextPanel.mm	Thu Dec 04 17:03:01 2014 +0000
@@ -27,6 +27,7 @@
 //------------------------------------------------------------------
 void TextPanel::draw(){
     if (hidden) return;
+    ofDisableDepthTest();
     if(!transparent) UIElement::draw(); // should do background
     ofSetColor(foregroundHi);
     
--- a/UI code/UIElement.h	Wed Dec 03 11:38:26 2014 +0000
+++ b/UI code/UIElement.h	Thu Dec 04 17:03:01 2014 +0000
@@ -108,6 +108,13 @@
         return zLayer;
         
     }
+    void setPosition(float ax, float ay){
+        x = ax;
+        y = ay;
+    }
+    void setXPosition(float ax){
+        x = ax;
+    }
     void setZLayer(int z){
         zLayer = z;
     }
--- a/UI code/UIProperties.h	Wed Dec 03 11:38:26 2014 +0000
+++ b/UI code/UIProperties.h	Thu Dec 04 17:03:01 2014 +0000
@@ -22,7 +22,7 @@
     float sliderMaxVal;
     ofColor buttonLo;
     ofColor buttonHi;
-    
+    ofColor backgroundHi;
     ofColor inactiveGreyedOut;
     
     ofColor sliderMultiActive;
@@ -72,7 +72,7 @@
         hintColor = ofColor(255,0,0,255);
         
         buttonLo = ofColor(123,200,180,255);
-        buttonHi = ofColor(150,235,200,255);
+        buttonHi = ofColor(150,235,210,255);
         
         inactiveGreyedOut = ofColor(78,78,78,255);
         
@@ -82,5 +82,6 @@
         sliderSimulActive = ofColor(0,255,0,255);
         
         generalBackground = ofColor(23,23,23,255);
+        backgroundHi = ofColor(50,80,60,255);
     };
 };
--- a/UI code/sliderPanel.mm	Wed Dec 03 11:38:26 2014 +0000
+++ b/UI code/sliderPanel.mm	Thu Dec 04 17:03:01 2014 +0000
@@ -181,7 +181,7 @@
                 cout << l << endl;
             }
             
-            ButtronSlider * revslider = new ButtronSlider(l , top , myProps.sliderWidth, myProps.sliderHeight,TEXTURE_FILL, myProps);
+            ButtronSlider * revslider = new ButtronSlider(l , top , myProps.sliderWidth, myProps.sliderHeight,FILL, myProps);
             revslider->setLabel("unassigned");
             subElements.push_back(revslider);
             revslider->showHint(false);
--- a/eventLogger.h	Wed Dec 03 11:38:26 2014 +0000
+++ b/eventLogger.h	Thu Dec 04 17:03:01 2014 +0000
@@ -82,7 +82,8 @@
                 FINISHED_RUN,
                 CANDIDATE_PARAM_ADJUSTED_ALL,
                 TARGET_AND_MATCH,
-    
+                FORGOT_SEQ,
+    RUN_SKIPPED
     
 };
 
--- a/globalVariables.h	Wed Dec 03 11:38:26 2014 +0000
+++ b/globalVariables.h	Thu Dec 04 17:03:01 2014 +0000
@@ -27,6 +27,7 @@
 #define START_TRAINING_SEQUENCE_ID 99189938
 #define SAVE_PRESET_HIT     99245748
 #define TO_MENU_ID          99545741
+#define FORGOT_SEQ_ID       99123123
 #define RECALL_PRESET_HIT   99298750
 #define ALTERNATION_SPEED 180 // ms that target / candidate sounds play
 // globles
--- a/testApp.h	Wed Dec 03 11:38:26 2014 +0000
+++ b/testApp.h	Thu Dec 04 17:03:01 2014 +0000
@@ -75,7 +75,7 @@
     void draw();
     void drawUIElements();
     void exit();
-
+    void backToMainMenu();
     HelpViewController *helpViewController;
     QuestionnaireViewController *questionnaireViewController;
     UsernameAlertViewController *usernameAlertViewController;
@@ -156,6 +156,8 @@
 	
 	void midiOutputAdded(string nam, bool isNetwork);
 	void midiOutputRemoved(string name, bool isNetwork);
+    void mapButtonToAction(UIElement* control, int mappingID);
+     void buttonPressCallback(int mappingID, int value);
     
 	vector<ofxMidiIn*> inputs;
 	vector<ofxMidiOut*> outputs;
--- a/testApp.mm	Wed Dec 03 11:38:26 2014 +0000
+++ b/testApp.mm	Thu Dec 04 17:03:01 2014 +0000
@@ -135,6 +135,16 @@
     ButtonPanel* bottomButtonPanel = new ButtonPanel(1,160+props->sliderPanelHeight,ofGetWidth(),250,*props);
     
     // play and submit are now same thing
+
+
+    Buttron * forgotButton = new Buttron(props->buttonWidth*1.4,680, *props);
+    forgotButton->setLabel("FORGOT SEQ");
+    trainingMessageOrganiser.mapButtonToAction(forgotButton, FORGOT_SEQ_ID);
+    trainingMessageOrganiser.setForgotButton(forgotButton);
+    UIElements.push_back(forgotButton);
+    forgotButton->setMode(Buttron::TOGGLE);
+    forgotButton->setXPosition(40);
+    
     Buttron * playCandidateButton = new Buttron(props->buttonWidth*1.4,680, *props);
     playCandidateButton->setLabel("START RUN");
     trainingMessageOrganiser.mapButtonToAction(playCandidateButton, START_TRAINING_SEQUENCE_ID);
@@ -142,12 +152,16 @@
     
     Buttron * menuButton = new Buttron(props->buttonWidth*1.4,680, *props);
     menuButton->setLabel("TO MENU");
+    mapButtonToAction(menuButton, TO_MENU_ID);
     trainingMessageOrganiser.mapButtonToAction(menuButton, TO_MENU_ID);
     bottomButtonPanel->addButton(menuButton);
     
     bottomButtonPanel->hide();
     
-    
+    ButtronSlider* distanceSlider = new ButtronSlider(ofGetWidth()-80, 200, 60, ofGetHeight()-400, FILL, *props);
+    trainingMessageOrganiser.setDistanceSlider(distanceSlider);
+    distanceSlider->hide();
+    UIElements.push_back(distanceSlider);
     
     trainingMessageOrganiser.setBottomPanel(bottomButtonPanel);
     UIElements.push_back(bottomButtonPanel);
@@ -473,6 +487,12 @@
     }
     
 }
+void testApp::backToMainMenu(){
+    expMessageOrganiser.hideMyPanels();
+    trainingMessageOrganiser.hideMyPanels();
+    searchMessageOrganiser.hideMyPanels();
+    [introViewController show:(__bridge id)this];
+}
 //-------------------------------
 void testApp::interfaceSelected(int interfaceSelection){
     if (interfaceSelection == 0){
@@ -510,6 +530,7 @@
 }
 //--------------------------------------------------------------
 void testApp::startTheSearchTests(){
+    searchMessageOrganiser.init(targetSynth,candidateSynth);
     eventLogger.logEvent(START_THE_SEARCH_TESTS);
     whichInterfaceShowing = COUNT_DOWN;
     // do countdown etc
@@ -522,7 +543,7 @@
 //--------------------------------------------------------------
 void testApp::startTheTrainingTests(){
     eventLogger.logEvent(START_THE_TRAINING_TESTS);
-    
+    expMessageOrganiser.hideMyPanels();
     trainingMessageOrganiser.init(targetSynth,candidateSynth, false);
     
     trainingMessageOrganiser.setup(whichInterfaceAreWeUsing);
@@ -865,3 +886,14 @@
 		}
 	}
 }
+//-----------------------------------------------------------
+void testApp::mapButtonToAction(UIElement* control, int mappingID){
+    UICallbackFunction callbackF;
+    callbackF = boost::bind(&testApp::buttonPressCallback, this, _1,_2);
+    control->addHandler(callbackF, mappingID);
+}
+void testApp::buttonPressCallback(int mappingID, int value){
+    if (mappingID == TO_MENU_ID){
+        backToMainMenu();
+    }
+}