UnigineScript
The Language
Core Library
Engine Library
Node-Related Classes
GUI-Related Classes
Plugins Library
High-Level Systems
Samples
C++ API
API Reference
Integration Samples
C++ Plugins
Content Creation
Materials
Unigine Material Library
Tutorials

App Class

Each Unigine-based application has a part, which is called a main loop and does most of the job required for window updating and drawing. The required code can be embedded directly into the main loop of the application as described here. Or it can be handled by the Unigine::App class.

For example, the need to use the Unigine::App class can arise when you want to integrate the Unigine engine into a custom application window.

To correctly use the Unigine::App class, you should perform the following:

  1. Include the UnigineApp.h header file into the source code.
  2. Create a custom class and inherit it from the Unigine::App class.
  3. Override all of the virtual functions specified in the include/UnigineApp.h file.
  4. Create the application window and initialize the graphics in your source code.

Notice
There are several examples of custom applications that can be found in the source/samples/App/ subfolder of the Unigine installation folder. These examples demonstrate how to integrate the engine into MFC, Qt and SDL applications.

Main Loop

In the general case, the main loop starts after the engine initialization and looks as follows:

Source code (C++)
int main(int argc,char **argv) {
	
	// AppUser class is inherited from the App class
	AppUser app;
	
	Engine *engine = Engine::init(UNIGINE_VERSION,&app,argc,argv);
	
	// start the main loop
	while(app->isDone() == 0) {
		app->doUpdate();
		app->doRender();
		app->doSwap();
	}
	
	Engine::shutdown();
}

Based on how the main loop is controlled, Unigine-based applications can be divided into two groups:

  • The engine controls the main loop.
  • The application controls the main loop by itself.

Unigine Controls the Main Loop

In this case, the engine cycles through the main loop by itself.

Inside the custom class inherited from the Unigine::App class, you should implement virtual functions doUpdate(), doRender(), and doSwap() that must call the update(), render(), swap() functions respectively. These functions request the engine to update, render a world and swap render buffers.

Furthermore, the custom logic, which is implemented in the doUpdate(), doRender(), and doSwap() functions, will be performed on the corresponding stages of the main loop.

Notice
This approach is used in the example of the engine integration into the SDL application (see the source/samples/App/GLAppSDL/ sample folder).
Source code (C++)
#include <Unigine.h>
#include <UnigineApp.h>

using namespace Unigine;

class AppUser : public App {
	
	// main loop
	virtual void doUpdate();
	virtual void doRender();
	virtual void doSwap();
	
	// list of other class methods and variables
	// ...
	
}

void AppUser::doUpdate() {
	// some code that will be executed on the engine update 
	update();
	// some more code
}
void AppUser::doRender() {
	// some code that will be executed on the engine render() function call 
	render();
	// some more code
}
void AppUser::doSwap() {
	// some code that will be executed on the engine swap() function call
	swap();
	// some more code
}

int main(int argc,char **argv) {
	AppUser app;
	Engine *engine = Engine::init(UNIGINE_VERSION,&app,argc,argv);
	// start the main loop
	engine->main();
	Engine::shutdown();
}
Notice
The AppUser::setVideoMode() implementation should unconditionally call either initGL(), initD3D9() or initD3D11() in order to correctly initialize the window.

Application Controls the Main Loop

In this case, the application decides when update, rendering and swapping should be done.

Therefore, implementations of doUpdate(), doRender(), doSwap() functions can be left empty to ignore engine requests. The update(), render(), and swap() functions are called directly when necessary (e.g. when some message from the operating system is received).

Notice
This approach is used in the examples of the engine integration into the Qt and MFC applications (see the source/samples/App/ folder).

In the example below, the AppUser::main() function manages the main loop: it handles events and call the update(), render() and swap() functions when some specific event occurs.

Source code (C++)
#include <Unigine.h>
#include <UnigineApp.h>

using namespace Unigine;

class AppUser : public App {
	
	// main loop
	virtual void doUpdate();
	virtual void doRender();
	virtual void doSwap();
	
	// list of other class methods and variables
	// ...
	
}

// empty implementations
void AppUser::doUpdate() { }
void AppUser::doRender() { }
void AppUser::doSwap() { }

// application is smart enough to handle drawing by itself
void AppUser::main() {

	// handle events that come from the operating system
	// ...
	// call the engine update(), render() and swap() functions when necessary
	if(some_event_occured) {
		paintEvent();
	}

}

// the paintEvent() function should be called in AppUser::main()
void AppUser::paintEvent() {
	update();
	render();
	swap();
}

int main(int argc,char **argv) {
	AppUser app;
	Engine::init(UNIGINE_VERSION,0,&app,argc,argv);
	
	// run the function that manages the main loop
	app.main();
	Engine::shutdown();
}
Notice
The AppUser::setVideoMode() implementation should unconditionally call either initGL(), initD3D9() or initD3D11() in order to correctly initialize the window.
Last update: 2017-07-03