*SOLVED* Class variables constructed with garbage every 'n'th compile...? Recursive ofMouseEventArgs to blame?

I am having a sanity destroying problem with the below code. I’m trying to make a click down menu that has recursive branches in a similar way that most applications have implemented in the menu bar.

I feel like everything is coded correctly because sometimes it will compile and run fine 10 times in a row. However other times as soon as i move the mouse it will give me a runtime error because the class variables are assigned garbage.

I’ve double checked my constructor, copy-constructor and destructor a hundred times and can’t see where its going wrong. Is it because I have registering and unregistering ofMouseEvents to be used recursively? If someone would be able either look over or compile the code to help me understand why this is happening that would be HUGELY appreciated. @mindtree @arturo ??

I’ve uploaded the source files for you to download to make it easier to compile. -> https://dl.dropboxusercontent.com/u/14581304/ofxMenu_code.zip

ofApp.h

#pragma once
#include "ofMain.h"
#include "ofxMenu.h"

class ofApp : public ofBaseApp{

public:
    ofApp(): modulatorMenu("ModMenu") {}

    void setup();
    void draw();
    void mouseReleased(int x, int y, int button);

    ofxMenu modulatorMenu;
};

ofApp.cpp

#include "ofApp.h"
//--------------------------------------------------------------
void ofApp::setup(){
   // LFOS
   ofxMenu lfos("LFOS");
   for(int i=0; i < 12; i++){
       lfos.addButton("LFO" + ofToString(1+i));
   }

   // Jen Instruments
   ofxMenu instruments("Instruments");
   instruments.addButton("Kick Amp");
   instruments.addButton("Snare Amp");
   instruments.addButton("Ride Amp");

   // Jen Playheads
   ofxMenu playheads("Playheads");
   playheads.addButton("Song");
   playheads.addButton("Part");
   playheads.addButton("Segment");

   // Jen Type
   ofxMenu menu1("MENU1");
   menu1.addMenu(instruments);
   menu1.addMenu(playheads);

   modulatorMenu.addMenu(menu1indent preformatted text by 4 spaces;
   modulatorMenu.addMenu(lfos);
}

//--------------------------------------------------------------
void ofApp::draw(){
  ofBackgroundGradient(ofColor::black, ofColor::blue, OF_GRADIENT_LINEAR); 
  ofSetHexColor(0xFFFFFF);
  ofDrawBitmapString("Click & open Menu Dialog.", 30,30);

  modulatorMenu.draw();
}

//--------------------------------------------------------------
`void ofApp::mouseReleased(int x, int y, int button){
`    modulatorMenu.openByClick(x, y);
}

And the ofxMenu class…

ofxMenu.h

#pragma once
#include "ofMain.h"

enum ElementKind {
    MENU,
    BUTTON,
};

class MenuElement{
public:
    MenuElement(ElementKind _kind, string _name): kind(_kind), name(_name), isHighlighted(false){}
    ElementKind kind;
    string name;
    bool isHighlighted;
};

class Button : public MenuElement {
public:
    Button(string name): MenuElement(BUTTON, name) {}
};

class ofxMenu : public MenuElement {
    ~ofxMenu();
     ofxMenu(string name);
     ofxMenu(const ofxMenu& other);

     void addMenu(ofxMenu menu);
     void addButton(string name);
     void draw();
     void openByClick(int x, int y);

     //Mouse Events
     void mousePressed(ofMouseEventArgs& mouse){}
     void mouseDragged(ofMouseEventArgs& mouse){}
     void mouseMoved(ofMouseEventArgs& mouse);
     void mouseReleased(ofMouseEventArgs& mouse){}
     void mouseScrolled(ofMouseEventArgs& mouse){}

     // Unhighlight and close all children elements.
     void closeChildren();
     void setHighlighted(int mouseX, int mouseY);
     void setPosition(int x, int y);
     bool isOverRect(int rectX, int rectY, int rectW, int rectH, int x, int y);

private: 
    const int WIDTH = 100;
    const int HEIGHT = 20;
    const int TEXT_PAD_WIDTH = 10;
    const int TEXT_PAD_HEIGHT = 14;

    ofTrueTypeFont font;
    string highlightedName;
    ofPoint pos;
    bool bIsOpen;

    vector<MenuElement*> elements;
};

and finally, ofxMenu.cpp

#include "ofxMenu.h"

//-----------------------------------------
ofxMenu::~ofxMenu(){
    ofUnregisterMouseEvents(this);

    for(vector<MenuElement*>::iterator it = elements.begin(); it != elements.end(); it++){
        delete (*it);
        *it = NULL;
    }
}

//-----------------------------------------
ofxMenu::ofxMenu(string name): MenuElement(MENU, name), bIsOpen(false) {
    font.loadFont("HelveticaNeue.ttf", 10);
    bIsOpen = false;
    highlightedName = "NONE";
    pos = ofPoint(0,0);

    ofRegisterMouseEvents(this);

    cout << "isOpen = " << bIsOpen << endl;
}

//-----------------------------------------
ofxMenu::ofxMenu(const ofxMenu& other): MenuElement(MENU, other.name),
font(other.font),
highlightedName(other.highlightedName),
pos(other.pos),
bIsOpen(false)
{
    for(vector<MenuElement*>::const_iterator it = other.elements.begin(); it != other.elements.end(); it++){
        switch ((*it)->kind) {
            case MENU: {
                // Cast MenuElement ptr to ofxMenu ptr.
                ofxMenu* menuPtr = (ofxMenu*)(*it);
                elements.push_back((MenuElement*)new ofxMenu(*menuPtr));
                break;
            }
            case BUTTON: {
                // Cast MenuElement ptr to Button ptr.
                Button* buttonPtr = (Button*)(*it);
                elements.push_back((MenuElement*)new Button(*buttonPtr));
                break;
            }
            default:
                break;
        }
    }
    ofRegisterMouseEvents(this);
}

//-----------------------------------------
void ofxMenu::addButton(string name){
    this->elements.push_back((MenuElement*) new Button(name));
}

//-----------------------------------------
void ofxMenu::addMenu(ofxMenu menu){
    this->elements.push_back((MenuElement*) new ofxMenu(menu));
}

//-----------------------------------------
void ofxMenu::draw(){

    // If the menu is open, draw like this.
    if (bIsOpen) {
    
        int yOffset = 0;
    
        for(vector<MenuElement*>::iterator it = elements.begin(); it != elements.end(); it++){
            MenuElement* elem = (*it);
            int elemX = pos.x;
            int elemY = pos.y + yOffset;
        
            // Box That is the size of 1 element
            if(!elem->isHighlighted){
                ofSetColor(238, 237, 234);
            } else if(elem->isHighlighted==true){
                ofSetColor(0,100,255);
            }
            ofRect(elemX, elemY, WIDTH, HEIGHT);
        
            // Draw the name.
            ofSetColor(0);
            switch (elem->kind) {
                case MENU:
                    font.drawString(elem->name + " >", elemX + TEXT_PAD_WIDTH, elemY + TEXT_PAD_HEIGHT);
                    break;
                case BUTTON:
                    font.drawString(elem->name, elemX + TEXT_PAD_WIDTH, elemY + TEXT_PAD_HEIGHT);
                    break;
            }
        
            // Draw Divider Line
            ofSetColor(230,225,20);
            ofNoFill();
            ofRect(elemX, elemY, WIDTH, HEIGHT);
            ofFill();
            ofSetColor(255);
        
            // Draw the branch.
            switch (elem->kind) {
                case MENU: {
                ofxMenu* menuPtr = (ofxMenu*)elem;
                menuPtr->draw();
                break;
            }
                default:
                    break;
            }
            yOffset += HEIGHT;
        }
    }
}

//-----------------------------------------
void ofxMenu::openByClick(int x, int y){
    bIsOpen = true;
    this->setPosition(x, y);
}

//-----------------------------------------
void ofxMenu::setPosition(int x, int y) {
    pos.x = x;
    pos.y = y;
    int yOffset = 0;

    // Recursively set the position of all children menus.
    for(vector<MenuElement*>::iterator it = elements.begin(); it != elements.end(); it++){
        MenuElement* elem = (*it);
    
        if (elem->kind == MENU) {
            ofxMenu* menuPtr = (ofxMenu*)elem;
            menuPtr->setPosition(x + WIDTH, y + yOffset);
        }
    
        yOffset += HEIGHT;
    }
}

//-----------------------------------------
bool ofxMenu::isOverRect(int rectX, int rectY, int rectW, int rectH, int x, int y){
    return x < rectX + rectW && x > rectX
        && y < rectY + rectH && y > rectY;
}

//-----------------------------------------
void ofxMenu::closeChildren() {
    // Make sure all the children menus are closed.
    for (int i=0; i < elements.size(); i++) {
        MenuElement* elem = elements[i];
        elem->isHighlighted = false;
    
        // If over a menu, open the menu.
        if (elem->kind == MENU) {
            ofxMenu* menuPtr = (ofxMenu*)elem;
            menuPtr->bIsOpen = false;
            menuPtr->closeChildren();
        }
    }
}

//-----------------------------------------
void ofxMenu::setHighlighted(int mouseX, int mouseY){
    if(bIsOpen){
        int yOffset = 0;
        // Recursively set the highlighting for all child elements.
        for (int i=0; i < elements.size(); i++) {
            MenuElement* elem = elements[i];

            // Check if the mouse is over the child element.
            if(isOverRect(pos.x, pos.y + yOffset, WIDTH, HEIGHT, mouseX, mouseY)){
                elem->isHighlighted = true;

                // If over a menu, open the menu.
                if (elem->kind == MENU) {
                    ofxMenu* menuPtr = (ofxMenu*)elem;
                    menuPtr->bIsOpen = true;
                    menuPtr->closeChildren();
                }
            
                // Check for menus at all other elements and set them to be closed.
                for (int j=0; j < elements.size(); j++) {
                    if (j != i) {
                        if (elements[j]->kind == MENU) {
                            ofxMenu* menuPtr = (ofxMenu*)elements[j];
                            menuPtr->bIsOpen = false;
                        }
                    }
                }
            } else {
                elem->isHighlighted = false;
            }
            yOffset += HEIGHT;
        }
    }
}

//-----------------------------------------
void ofxMenu::mouseMoved(ofMouseEventArgs &mouse){
    setHighlighted(mouse.x, mouse.y);
}

Thanks @mindtree for helping me out.

Have changed the code so i’m not using the copy constructor and all is working once again. If you would like to see the current code here is the github repo -> https://github.com/MindBuffer/ofxClickMenu