2.9.16
Coherent GT
A modern user interface library for games
Sample - Preloaded resources

This sample demonstrates how to use Coherent GT's preloaded textures feature which lets you manually prepare textures used by your UI.

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

Building the sample

The sample solution is based on a minimal game framework that provides basic functionality. The sample is already configured and you only have to compile and run it.

The output will be in the Coherent/bin directory.

Prerequisites

This sample builds upon the HelloGT sample and assumes that you understand it.

Key points

  1. FileResourceHandlerWithPreloadedSupport is a custom implementation of Coherent::UIGT::ResourceHandler and does most of the work in the sample.
    • It loads a predefined list of textures and uploads them to the GPU
    • Overrides OnResourceRead and sends texture information to the current backend
    • Disposes of the textures when they are no longer needed

Sample walk-through

The sample shows a page with <img> and <div> elements each displaying an image.

<style>
.with-background-image {
background: url("logo.png");
background-size: contain;
}
</style>
<body>
<img src="logo_padded.png"></img>
<div class="with-background-image"></div>
</body>

Let's now take a look at the C++ side.

The key part of the sample is the class FileResourceHandlerWithPreloadedSupport. As an implementation of Coherent::UIGT::ResourceHandler it lets Coherent GT request files from the disk. Unlike the resource handlers in the rest of the samples, this one also knows how to use preloaded resources.

virtual void OnResourceRead(
Coherent::UIGT::ResourceResponseUIGT* response) COHERENT_OVERRIDE
{
std::string asciiUrl(request->GetURL());
// Any png used in the sample page is already preloaded
if (asciiUrl.find("png") != std::string::npos)
{
OnPreloadedResourceRequest(request, response);
}
else
{
// Other files such as fonts and scripts use the standard file reader
FileResourceHandler::OnResourceRead(request, response);
}
}
virtual void OnPreloadedResourceRequest(const Coherent::UIGT::ResourceRequestUIGT* request,
Coherent::UIGT::PreloadedResourceResponseUIGT* response) override
{
std::string path = ... // Get the path to the file from the request
const auto textureFound = std::find_if(m_TextureFilepaths.begin(), m_TextureFilepaths.end(),
[&path](const std::string& texturePath)
{
return texturePath.find(path, 0) != std::string::npos;
});
assert(textureFound != m_TextureFilepaths.end());
const auto id = m_TextureIds[std::distance(m_TextureFilepaths.begin(), textureFound)];
bool isPadded = textureFound->find("padded") != std::string::npos;
using PreloadedResourceResponseUIGT = Coherent::UIGT::PreloadedResourceResponseUIGT;
PreloadedResourceResponseUIGT::UserImageData data;
const auto description = m_Renderer->GetTextureDesc(id);
data.Width = description->Width;
data.Height = description->Height;
data.ContentRectX = isPadded ? 10 : 0;
data.ContentRectY = isPadded ? 10 : 0;
data.ContentRectWidth = isPadded ? data.Width - 20 : data.Width;
data.ContentRectHeight = isPadded ? data.Height - 20 : data.Height;
data.Format = renoir::PF_R8G8B8A8;
data.Texture = GetPreloadedTexture(id);
response->ReceiveUserImage(data);
response->SignalSuccess();
response->Release();
}

The preloaded textures that the method above is referencing are a list of textures loaded by the handler prior to running the application.

void PreloadTextures(const std::vector<std::string>& textureFilepaths)
{
m_TextureFilepaths = textureFilepaths;
for (const auto& path : m_TextureFilepaths)
{
// See Coherent::Application::IRenderer::CreateTextureFromFile for the decoding / GPU uploading implementation
const auto id = m_Renderer->CreateTextureFromFile(path.c_str());
assert(id != Coherent::Application::IRenderer::INVALID_ID && "Failed to load texture!");
m_TextureIds.push_back(id);
}
}
void UnloadTextures()
{
for (const auto id : m_TextureIds)
{
m_Renderer->DestroyTexture(id);
}
}

The textures are preloaded in the main method of the application:

fileHandler.SetRenderer(options.Renderer, app.GetRenderer());
// Preload all required textures
std::vector<std::string> preloadedTextures;
preloadedTextures.push_back("uiresources/Sample_PreloadedResources/logo.png");
fileHandler.PreloadTextures(preloadedTextures);
app.Run();
app.RemoveView(view);
fileHandler.UnloadTextures();
app.Uninitialize();
}