How to Reset at the End of a Switch Statement

Hello Everyone

I am currently working on a project that uses face detection with computer vision. I have setup my sketch so that when a face is detected for longer than 2 seconds it triggers a function that calls a series of animations. I have set up up a switch statement so that I cycle through each class one at a time, however I want it to revert back to the beginning once all of the animations are completed.

I tried calling the draw function again in the last section of the switch statement, however that created an error. I was wondering how you guys would recommend resetting the sketch back to the beginning?
Below is the code in my cpp file:

//--------------------------------------------------------------
void ofApp::setup() {
	//ofSetFrameRate(60);
	finder.setup("haarcascade_righteye_2splits.xml");

	videoGrabber.setDeviceID(0);

	videoGrabber.setDesiredFrameRate(30);
	videoGrabber.setup(960, 540);

	millis = ofGetElapsedTimeMillis();
	phaser = 0;
	col = ofColor(ofColor::red);

	animation1.setup();
	animation2.setup();
	animation3.setup();
	animation4.setup();
	typography.setup();

	timings.push_back(100);
	timings.push_back(100);
	timings.push_back(150);
	timings.push_back(150);
	timings.push_back(150);
}

//--------------------------------------------------------------
void ofApp::update() {
	finder.setScaleHaar(3.5);
	videoGrabber.update();
	img.setFromPixels(videoGrabber.getPixels());
	finder.blobs.clear();
	finder.findHaarObjects(img);
	img.setImageType(OF_IMAGE_GRAYSCALE);


	minX = 10000;
	minPos = -1;
	phaser++;

}

//--------------------------------------------------------------
void ofApp::draw() {
	img.draw(0, 0, ofGetWidth(), ofGetHeight());
	if (finder.blobs.size() > 0 && ofGetElapsedTimeMillis() >= (millis + 5000))
	{
		render();
	}
}

void ofApp::render() {
	ofSetColor(col);
	img.draw(0, 0, ofGetWidth(), ofGetHeight());


	for (unsigned int i = 0; i < finder.blobs.size(); i++) { // loop over all the found faces/blobs
		ofRectangle cur2 = finder.blobs[i].boundingRect;     // and put a rectangle around the face
		if (cur2.getCenter().x < minX) {
			minX = cur2.getCenter().x;
			minPos = i;
		}

	}

	if (minPos > -2) {
		ofRectangle cur = finder.blobs[minPos].boundingRect;

		ofScale(1600. / 960.);
		ofNoFill();
		ofDrawRectangle(cur);

		ofPoint cntr = cur.getCenter();

		int duration = timings[selector];

		if (ofGetFrameNum() % duration == 0) {
			selector = (selector + 1) % 5;
		}


			switch (selector) {
			case 0:	
				typography.update();
				typography.draw(cntr.x, cntr.y + 13);
				typography.getStringPoints(s);
				break;
			case 1:
				animation2.update();
				animation2.draw();
				animation2.calculateLissajousPoints();
				animation2.drawLissajous(cntr.x, cntr.y + 13);
				break;
			case 2:
				animation3.update();
				animation3.draw(cntr.x, cntr.y + 13);
				break;
			case 3:
				animation1.update();
				animation1.fractal(cntr.x, cntr.y + 13);
				break;
			case 4:
				animation4.update();
				animation4.draw(cntr.x, cntr.y + 13);
				break;
			default:
				break;
			}
	}

}

If you’re just wanting to index again through the switch, maybe you could reset the switch/selector value at the end of the switch, then begin incrementing it once again as you cycle through.

default:
	selector = 0;
	break;

I believe thats what I have at the moment, however I am looking to reset the sketch back to the very beginning once you reach the end of the switch. You will notice in my code that the switch statement is inside a function called render - this gets triggered when a face is detected in front of a camera for a certain amount of seconds. I am looking to revert the sketch back to this original state, before the render function is triggered. Does that make sense?

Aha, I think I’m with you, in essence you want to reset your animations & typography objects so they are in their virgin default state?

What you might try is using your animation objects as std::unique_pointers. Then just let them go out of scope and they’ll be deleted from the heap. A few ways you could go about that depending on your use case but this might suffice?

switch (selector) {
	case 0:
	{   //added curly braces for a scope here, not sure if its neccessary. 
		auto typography = std::make_unique<YourTypographyObject>(); //Create a unique_ptr of your typography object a new virgin object!
		typography->setup(); // setup is now called here, this may make things too slow?
		typography->update(); //note these are pointers so need "->" instead of "." for reasons.
		typography->draw(cntr.x, cntr.y + 13);
		typography->getStringPoints(s);
		break;
	} //scope ends object automatically deleted. 

I think with regard to resetting the whole sketch, you might have to go so far as to delete the openGL context and reinstate it which would probably be pretty slow and overcomplicated for what you’re trying to achieve?

Hi Samuel

I’m a bit confused as to what needs to go into the ‘YourTypographyObject’ section? I don’t believe I have used unique pointers before.

The process of resetting a sketch seems a lot easier in p5js, like in the Daniel Shiffman video: 9.10: Reset a Sketch with Button Click - p5.js Tutorial - YouTube

Hey! No problem, I would say it’s not easier just different, what it looks like Daniel is doing is not too dissimilar from what I am suggesting. You see where in his resetSketch() function he writes:

flock = new Flock();

So bear in mind this is P5 not C++…

What he’s doing here is deleting or freeing (we don’t see the deleting process in the video due to the differences in java vs C++) the memory taken up by the old ‘flock’ and allocating a new Flock object on the heap (…also called ‘flock’). So that old object is gone, a brand new object with all the initial values etc is created which can get on with running from first principles.

I guess you created some classes or structs that form your animations and typography things? The name of this class should go inside the std::make_unique<> call.

class typographyObject {
public:
	void Update();
private:
	int a = 1;
	int b = 69;
};

// The above is in another file in your code presumably; 

auto typography = std::make_unique<typographyObject>();
//now we have allocated a typographyObject on the heap, we can use it like a regular 
//object inside of the current scope. But magically, if it goes out scope it is deleted!

Smart pointers are the Sh*t!

Here is a pretty decent video explaining them much better than I can, I recommend this series, it taught me all the basics.

I should admit that I’m being very lazy here using “auto”, what I mean is:

std::unique_ptr<typographyObject> typography = std::make_unique<typographyObject>();

If you’d like some more help drop me a DM!