A possible solution for apps with a slow setup(). What do you think?

Hi,
my application needs a lot of initialization stuff to be done in the setup() method (like loading graphics and even downloading something on the fly from a server). All of that takes 2-3 seconds, and in the meanwhile nothing happens from user’s perspective.

This is enough to make people nervous and even double click a second time on app icon, and should of course be avoided. After playing for a while with splash screens I couldn’t find anything satisfactory, they made the code heavily platform dependent and did not solve the problem after all.

So I tried a much simpler way that (for me at least) does the trick. Since I am not an expert at all in OF I am asking for comments and may be possible drawbacks. The idea is to delay setup() after a few frames have been drawn, so that the window can appear with a message to the user. Since the message is static it does not matter if the framerate is extremely low during the initialization.

here is a little snippet:

in ofApp.h:

void first_setup();
int framesDrawn;
ofTrueTypeFont messageFont; // this is only needed if you want to show a message while loading

and in ofApp.cpp:

const int SETUP_FRAMES = 2;

void ofApp::setup()
{
    ofSetVerticalSync(true);
    ofSetFrameRate(60);

    messageFont.load("font/F25_Executive.otf", 32, true, true);
    
    framesDrawn = 0;
}

void ofApp::first_setup()
{
    // do all heavy initialization stuff here
}

void ofApp::update()
{
    if(framesDrawn <= SETUP_FRAMES) return;

    // regular update() code goes here
}

void ofApp::draw()
{
    ofBackground(80);
    if(framesDrawn < SETUP_FRAMES)
    {
        string line = "Application is loading. Please wait.";
    
        // draw a message on screen, centered on X and Y

        int lineH = messageFont.getLineHeight();
        int y = (ofGetHeight()-lineH)/2 + messageFont.getAscenderHeight();
    
        int lineW = messageFont.stringWidth(line);
        int x = (ofGetWidth()-lineW)/2;
        
        messageFont.drawString(line, x, y);
    
        framesDrawn++;
        return;
    }
    else if(framesDrawn == SETUP_FRAMES)
    {
       first_setup();
       framesDrawn++;
    }

    // here goes all draw() code
}
1 Like

I just used this in a similar situation, its a nice feature from elliotwoods

1 Like

cool, before reinventing the wheel I searched for a solution to my splash screen problem but for some reason I missed this one.

did you have any workaround to use this?

I am getting this errors, so maybe
elliotwoods/ofxSplashScreen
Is not compatible with OF 0.10?

Severity	Code	Description	Project	File	Line	Suppression State
Error	C3861	'glfwShowWindow': identifier not found	Example	f:\openframeworks\addons\ofxsplashscreen\src\ofxsplashscreen.cpp	74	
Error (active)	E0757	overloaded function "std::chrono::duration<_Rep, _Period>::duration [with _Rep=long long, _Period=std::nano]" is not a type name	Example	C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.16.27023\include\chrono	195	
Error	C3861	'glfwGetCurrentContext': identifier not found	Example	f:\openframeworks\addons\ofxsplashscreen\src\ofxsplashscreen.cpp	34	
Error	C3861	'glfwHideWindow': identifier not found	Example	f:\openframeworks\addons\ofxsplashscreen\src\ofxsplashscreen.cpp	36	
Error	C2065	'GLFW_DECORATED': undeclared identifier	Example	f:\openframeworks\addons\ofxsplashscreen\src\ofxsplashscreen.cpp	37	
Error	C3861	'glfwWindowHint': identifier not found	Example	f:\openframeworks\addons\ofxsplashscreen\src\ofxsplashscreen.cpp	37	
Error	C3861	'glfwCreateWindow': identifier not found	Example	f:\openframeworks\addons\ofxsplashscreen\src\ofxsplashscreen.cpp	38	
Error	C3861	'glfwSetWindowPos': identifier not found	Example	f:\openframeworks\addons\ofxsplashscreen\src\ofxsplashscreen.cpp	39	
Error	C2065	'GLFW_DECORATED': undeclared identifier	Example	f:\openframeworks\addons\ofxsplashscreen\src\ofxsplashscreen.cpp	40	
Error	C3861	'glfwWindowHint': identifier not found	Example	f:\openframeworks\addons\ofxsplashscreen\src\ofxsplashscreen.cpp	40	
Error	C3861	'glfwMakeContextCurrent': identifier not found	Example	f:\openframeworks\addons\ofxsplashscreen\src\ofxsplashscreen.cpp	41	
Error	C3861	'glfwSwapBuffers': identifier not found	Example	f:\openframeworks\addons\ofxsplashscreen\src\ofxsplashscreen.cpp	53	
Error	C3861	'glfwMakeContextCurrent': identifier not found	Example	f:\openframeworks\addons\ofxsplashscreen\src\ofxsplashscreen.cpp	57	
Error	C3861	'glfwDestroyWindow': identifier not found	Example	f:\openframeworks\addons\ofxsplashscreen\src\ofxsplashscreen.cpp	71

hey @davidemania @pandereto,
any idea to make this addon work?

well… I am not sure if it’s the expected behavior, but maybe the png is drawing during a single frame.
I was expecting that the window is drawn until ofApp is fully loaded and the switch from the png/splash to the running loaded ofApp.

I’ve been doing something like what you do in the original post. I combined it with a pattern I’m using to have different pages/display-states/UI-modes. So I have a class UIMode which has its own Draw() method, and I make derived classes of that, and then call the current UI Mode’s Draw() from ofApp::Draw(). Then one of the UI modes is typically a “load stuff while showing something” mode, which the program starts out in.

I.e. Yes, the pattern you first suggested makes good sense. You can even have the loading state have multiple levels of progress and show different things depending on the loading state, so users know something is continuing to happen during loading.

1 Like

Sorry las time i used was loooong time ago