Website like openFrameworks application — click on button shows new screen

Dear openFrameworkers,

unfortunately I did not yet find an answer to this and to be honest, it’s hard to google for his, as I’m probably a little to unexperienced to call it by name, what I’d like to have here. It’s about the structure of my openFrameworks application …

In the app, I need different “screens”, like first screen is a welcome screen. Clicking a button, brings you to a wifi setup screen. Next screen is setup of some cameras, like choose which camera is right, which is left. Next screen is entering some text. Next screen …

So … what’s the way to go in openFrameworks to draw such different “screens”? Maybe imagine it like a website. You click a button and go to a new page. I don’t think it’s nice to just write everything in ofApp.h and ofApp.cpp and use functions for this. I’m sure there’s a cleaner, more appropriate and less monolithic way of doing this.

Thank you for enlightening me!

Here’s how I do it (semi-pseudo code - you will have to put things in the proper .h/.cpp files, etc)

Create a Base Class that all your Views must implement

class BaseView
{
public:
	BaseView()
	{
	
	}
	
	virtual void setup()=0;
	virtual void update()=0;
	virtual void draw()=0;

};

Then start creating your Views

#include "BaseView.h"

class FirstView: public BaseView
{
	FirstView()
	{
	
	}
	
	void setup()
	{
		// setup stuff here
	}
	
	void update()
	{
		// update stuff here
	}
	
	void draw()
	{
		// draw stuff here
	}
};

Then manage them in ofApp

#include "FirstView.h"

vector<BaseView*> views;
BaseView* currentView;
bool doSwitchViews;
int viewCounter;


void ofApp::setup()
{
	FirstView* firstView = new FirstView();
	firstView->setup();
	views.push_back(firstView);
	
	//For a SecondView you would create another Class like FirstView
	SecondView* secondView = new SecondView();
	secondView->setup();
	views.push_back(secondView);

	doSwitchViews = false;
	viewCounter = 0;
	currentView = views[viewCounter];
	
}

void ofApp::update()
{
	if(doSwitchViews)
	{
		if(viewCounter+1<views.size())
		{
			viewCounter++;
		}else
		{
			viewCounter = 0;
		}
		doSwitchViews = false;
		currentView = views[viewCounter];

	}
	currentView->update();
}

void ofApp::draw()
{
	currentView->draw();
}


void ofApp::keyPressed(int key)
{
	//allows switching of views
	if(key == 's')
	{
		doSwitchViews = true;
	}
}

I think two useful notions here are scene graph and state machines. The first would be like nested object that expose basic features (draw, update, click event, …) and that are being shown/drawn only when needed (like you could have a window class, a button class, etc. and nest those make the design you want) and if the object is not on screen its child wouldn’t be drawn/updated/receive mouse events either.

And the second is a way of representing the logic you want (first state is the welcome screen, when you click on the button you transition to the wifi configuration state, etc. ). It’s a bit of a rigid structure so it can get in the way more than it helps (like if you want to cross fade the welcome screen with the wifi screen, what does it mean to show both at the same time, which state would that be? etc.).
But this kind of stuff is useful for keeping track of what’s going on and what needs to happen next (like for instance a video player would have Unloaded-Loading-Loaded-Playing-Pause-Closed states)

That sounds reasonable. I’ll try to implement that. Thank you very much!

@jvcleave This way, I’m getting an error in ofApp.cpp, that I’m calling a private instructor. Which is strange, because you stated public there … hm.

EDIT: Seems there’s a second private missing …

class FirstView: public BaseView {
    public:
	FirstView() {
        }
}

@fooness yeah - i just wrote it in the browser to explain the concept.

I used the pattern recently here if you want a detailed look

@jvcleave Seems I got it working. Thank you very much! : )

Dear @jvcleave how would I access ofApp.h’s variables from within class FirstViews update()?

Thank you very much!

I would manage the value internally inside of FirstView (e.g. update it in FirstView::update) or update it from ofApp