Coherent UI  2.5.3
A modern user interface library for games
 All Classes Namespaces Functions Variables Enumerations Enumerator Pages
Sample - On-Demand Views

This sample demonstrates redirecting the usage of on-demand views. It represents a simple application that draws a plane and some game units like in a real-time strategy game. Around every unit Coherent UI draws an animated element that in a real game could be a nameplate or a health bar. The sample shows the perfect synchonization of the game frame with the interface even though Coherent UI actually works completely asynchronously to the client application.

Note
Supplied code is not representative for a well-designed, high-performance solution. It's written for simplicity and its purpose is to demonstrate a feature of Coherent UI.

Building the sample

The sample solution is already configured and you only have to compile and run it.

It uses a sample mini game framework that provides very basic functionality.

The output will be in the Coherent/Samples/UI/bin directory.

Key points

  1. When the units are updated (move) their new positions are sent to the UI via triggering an event.
  2. A new frame gets requested from Coherent UI
  3. The game frame is drawn
  4. The interface frame is fetched and composited on the game

Sample walkthrough

On-demand views are created by specifyng the appropriate flag in the ViewInfo strucure:

info.Width = m_Width;
info.Height = m_Height;
info.UsesSharedMemory = m_ViewListener->IsUsingSharedMemory();
info.IsTransparent = true;
info.SupportClickThrough = false;
info.UsesSharedMemory = USE_SHARED_MEMORY;
info.IsOnDemand = true;
m_Context->CreateView(info, L"coui://html/nameplates.html", m_ViewListener);

Every frame the units move a bit and their new nameplate positions are sent to the interface and a new frame is requested.

ComputeNameplatesPositions(m_Pawns, m_PawnsXs, m_PawnsYs, m_NormalizedScreenPositions);
if(m_View && m_IsReady)
{
m_View->TriggerEvent("MoveNameplates", ids, m_PawnsXs, m_PawnsYs);
if(m_View->RequestFrame() != Coherent::UI::VE_Success)
{
assert(false);
}
m_HasRequestedFrame = true;
}
Note
Requesting frames and fecthing surfaces for individual views is mandatory for on-demand views.

After drawing the game frame the interface surface is fetched.

bool NameplatesScene::FetchFrame()
{
if(m_HasRequestedFrame && m_View)
{
m_View->FetchSurface();
m_HasRequestedFrame = false;
return true;
}
else
{
return false;
}
}

The order of operations is not casual. The best possible performance is gained when you structure your interaction with the view context as follows:

  • new frame starts
  • trigger all events that should be visible in this frame
  • draw the game frame
  • fetch the view and composite

You should always try to put as much computation between the frame requests and their fetches as possible because Coherent UI renders in multi-threaded way. Thus by drawing the game frame simultaneously with the UI you maximise the chances that the interface will be already rendered when you try to fetch it, leveraging modern multi-core systems.