Coherent UI  2.5.3
A modern user interface library for games
 All Classes Namespaces Functions Variables Enumerations Enumerator Pages
Base Application Framework

CoherentApplication is simple multiplatform abstraction for an application loop and rendering. You can find it in Coherent/Libraries/Application.

Framework components

The framework supplies the following components:

  1. A PlatformWindow class, encapsulating the application main loop and various callbacks, such as OnResize, OnIdle and others.
  2. An IRenderer interface, used for seamless usage of either OpenGL or DirectX.
  3. Input event conversion utilities helping convert native input events to Coherent UI input events.
  4. A header file, Coherent/Libraries/Application/Entry.h, which abstracts the entry point (main function) of the application.

The PlatformWindow class

The PlatformWindow class is designed to abstract the platform differences for creating a window and running a game loop. The PlatformWindow::GetNativeWindowInfo returns a structure that exposes the native window handles for custom code.

PlatformWindow::Initialize creates the window and PlatformWindow::Run starts the game loop an processes events until the application is closed. While running the game loop, PlatfromWindow fires various events. The full list is as follows:

std::function<void (float dt)> OnIdle;
std::function<void (const Coherent::UI::KeyEventData&)> OnKeyEvent;
std::function<void (const Coherent::UI::MouseEventData&)> OnMouseEvent;
std::function<void (const Coherent::UI::TouchEventData* events, unsigned count)> OnTouchEvent;
std::function<void (int width, int height)> OnResize;
std::function<void ()> OnWindowShow;
std::function<void ()> OnWindowClose;
std::function<void ()> OnKillFocus;
std::function<void ()> OnSetFocus;
std::function<void ()> OnMouseActivate;

The most widely used ones are the first three - OnIdle is called every frame so user code can be executed, and OnKeyEvent, OnMouseEvent and OnTouchEvent are called when an input event is received.

Note
Touch events are currently supported on Windows and Mac OS X only

These events are public, so you can attach your methods by doing something in the line of:

// UserCode.cpp
void MyIdleFunc(float dt)
{
// Process frame
}
...
bool Initialize()
{
// Initialization code...
PlatformWindow window;
window.OnIdle = std::bind(&MyIdleFunc, std::placeholders::_1); // Or just window.OnIdle = &MyIdleFunc;
// More initialization code...
}

You should call Run in your main function, after you've subscribed for the events you want.

The IRenderer interface

The IRenderer (Coherent/Libraries/Application/Renderer.h) interface enacapsulates low level rendering functions, such as DrawPrimive, DrawIndexedPrimitive, CreateEffect and so on.

There are two implementations of IRenderer - one using OpenGL and another one using DirectX 9.

The renderer manages resources, such as textures, vertex declarations, effects and buffers. Resources can be created with the Create*** methods of the renderer, which return an integer. This integer is a unique ID that represents the resource and can be used by other IRenderer methods, such as SetTexture.

There are auxiliary structures (descriptions), representing an abstract resource (TextureDesc, BufferDesc, etc.), and specific implementations for each renderer, such as TextureDescOpenGL or TextureDescDirectX. There are interface methods for getting a pointer to base description, which can be cast to the appropriate implementation if you know what renderer you're using, thus giving you raw access to an OpenGL/DirectX resource.

To draw anything with the IRenderer, you have to enclose the drawing code inside a IRenderer::BeginFrame - IRenderer::EndFrame section. You can create resources outside such section, but all drawing code, setting of buffers and effects must take place inside one. There usually should be only one such section and all the drawing in the frame happens there.

When drawing, you also need an effect. An effect is a combination of a vertex and pixel shaders (Effect in D3DX terminology, program in OpenGL). Due to differences in OpenGL and DirectX, the IRenderer has 3 methods for creating an effect - CreateEffectFromFile(const wchar_t* fileName, const char* technique), CreateEffectFromMemory(const char* code, const char* technique), CreateEffect(const char* vertexShaderCode, const char* pixelShaderCode), but in reality CreateEffectFromFile and CreateEffectFromMemory can only be used when the renderer is using DirectX, and CreateEffect can only be used by the OpenGL renderer.

Each effect has various parameters that can be set. Currently the types supported are float, matrix and texture. You can obtain a handle to the parameter by calling the size_t GetParameterHandleByName(int effectId, const char* name) method, and set a value for that parameter by using one of the Set*** functions, such as IRenderer::SetTexture. When using an effect, any Set*** and Draw*** functions must take place in a IRenderer::EffectBegin - IRenderer::EffectEnd section.

There's also a convenience method, IRenderer::RenderFullscreenTexture, which renders a texture on the whole screen (given its ID).

Other methods include enabling/disabling alpha blending, enabling/disabling the Z-buffer, clearing the backbuffer and so on. Check Renderer.h for the full list.

Any other special behavior should be documented in the header file for the specific renderer. For example, when using the OpenGL renderer, you should always call SetVertexBuffer before SetVertexDeclaration for it to work.

You can check the samples for an actual usage of the IRenderer interface, or the FullScreenQuadOpenGL / FullScreenQuadDirectX classes, located in Coherent/Libraries/Application/Detail/RendererOpenGL.cpp / Coherent/Libraries/Application/Detail/RendererDirectXWin.cpp respectively.

Input event conversion utilities

In order to forward input events to Coherent UI, you must first convert them to Coherent UI input events, as defined in Coherent/UI/InputEvents.h.

Converting mouse events is usually no problem, as they are represented by position, pressed buttons and wheel value, which can be easily obtained in most game frameworks.

Keyboard events, on the other side are different on each platform, and most games have their own events, handled by the input subsystem. Coherent UI uses Windows virtual key codes, which means that you have to convert your game specific key code to a Windows key code before sending it to Coherent UI. This is not always trivial, as you have to translate a native (or game) keyboard event to a Windows event. For example, printable characters, such as 'a', 'b', 'c', etc. must be sent as Char events, while pressing the arrow keys, for example, must be KeyDown events. This code is very game specific, and the best we can do is supply platform specific conversion utilities that you can adapt for your game.

Windows

For Windows, it's easiest to convert native events to Coherent events, since they are largely the same. If you have access to the message loop of the application, you can use Coherent/Libraries/Application/Detail/CoherentInputEventsConvertorWin.h for converting key/mouse/wheel/touch events.

Linux

For Linux, we have supplied a sample conversion utility for key/mouse/wheel events in Coherent/Libraries/Application/Detail/CoherentInputEventsConvertorX11Linux.h. It works with X11 events, but adapting it to GTK is trivial. The utility function translates X11 events to Windows events and also supports Unicode. It uses 2 auxiliary files, WindowsKeyCodeForKeyEventX11Linux.h and KeySym2UCSLinux.h for doing that.

Entry abstraction

By including Coherent/Libraries/Application/Entry.h, you'll get predefined platform specific main functions. Those function call another function, called coherent_sample_main, having the signature int (*)().

This is the main function that you have to define in your code and will be used as the entry point of the program.