Live Views

One of the most empowering features of Gameface is its ability to render a dynamically-changing texture taken directly from the engine.

This allows you to achieve some otherwise very difficult effects:

  • Render the player’s avatar in a living, breathing 3D instead of a static image. Place a camera in front of the player’s character and display the camera’s texture in the UI. Or use the same texture in the character customization screen for a similar effect!
  • Render the world from a top-down view and paint that as a 3D mini-map! You just saved tons of time for your artists that they would’ve needed to draw the world map in a format usable for a mini-map.

Cohtml differentiates between using static and dynamic textures from the engine/game. Static textures are called User Images and dynamic textures are called live views. A live view is set up and performs exactly as a user texture. See the docs about User Images to learn how to work with them first.

To turn your user textures into live views, you need to:

  • Provide an image handle - live views are identified via an image handle (cohtml::IAsyncResourceResponse::UserImageData::ImageHandle). Static user textures don’t have custom identification.
  • Tell Cohtml they’ve changed - as an optimization, Cohtml will only repaint the live view if the game tells it changed. Whenever you change the live view, you are required to call cohtml::System::UserImagesChanged with the appropriate image handle to notify the SDK.

Here’s some pseudocode, based on the code in the User Images section, which demonstrates that:

// Store the image handles in some container
std::vector<unsigned> ActiveLiveViews;
...
virtual void MyResponseHandler::OnResourceRequest(
    const cohtml::IAsyncResourceRequest* request,
    html::IAsyncResourceResponse* response) override
{
    ...
    // Provide texture information to Cohtml
    cohtml::IAsyncResourceResponse::UserImageData data;
    data.Width = texture->Width;
    data.Height = texture->Height;
    data.ContentRectX = 0;
    data.ContentRectY = 0;
    data.ContentRectWidth = data.Width;
    data.ContentRectHeight = data.Height;
    data.Format = texture->Format;
    data.Texture = texture->Resource;
    // NOTE: Setting a non-zero image handle tells Cohtml this is a live view
    static int imageHandleCounter = 1;
    data.ImageHandle = imageHandleCounter++;
    ActiveLiveViews.push_back(data.ImageHandle);

    response->ReceiveUserImage(data);
    response->Finish(cohtml::IAsyncResourceResponse::Status::Success);
}
...
// Whenever the image(s) change(s), call UserImageChanged with your handle(s)
system->UserImageChanged(ActiveLiveViews.data(), ActiveLiveViews.size());