Coherent UI  2.5.3
A modern user interface library for games
 All Classes Namespaces Functions Variables Enumerations Enumerator Pages
Sample - C++ and JavaScript Binding

This sample demonstrates the communication between C++ and JavaScript

  • transferring data
  • executing C++ from JavaScript and JavaScript from C++
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 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.

Prerequisites

This sample builds upon the Input in 2D sample and assumes that you understand it.

For a more detailed explanation of how binding works, you can check the Detailed Binding Guide

Key points

  1. Coherent::UI::ViewListener::OnBindingsReady is overridden to allow registration of C++ handlers to be called from JavaScript.
  2. The debugger port is set inside the Coherent::UI::ContextSettings to allow easier development and troubleshooting.
  3. A simple C++ structure is exposed to Coherent UI so it can be transferred between C++ and JavaScript

Sample walkthrough

Initialize the context factory, then create a view context, enabling support for cookies.

Coherent::UI::ViewContextFactory* contextFactory = InitializeCoherentUI(
COHERENT_UI_SDK_VER, COHERENT_KEY, renderingParams, factorySettings);
if (!contextFactory)
{
return 3;
}
ctxSettings.AllowCookies = true;
= contextFactory->CreateViewContext(ctxSettings, &listener);

When the view is ready for the registration of C++ call and event handlers Coherent::UI::ViewListener::OnReadyForBindings is called

virtual void OnReadyForBindings(int frameId, const wchar_t* path, bool isMainFrame) override
{
if(!isMainFrame)
{
return;
}
// When a routine is called in JS with these identifiers we specify what functions must be called in C++
m_View->BindCall("ApplyOptions", Coherent::UI::MakeHandler(&g_OptionsHandler, &OptionsHandler::ApplyOptions));
m_View->BindCall("GetLatency", Coherent::UI::MakeHandler(&GetNetworkLatency));
m_View->BindCall("GetGameTime", Coherent::UI::MakeHandler(&GetGameTime));
// register handler for an engine event
m_View->RegisterForEvent("ViewReady", Coherent::UI::MakeHandler(this, &ViewEventListener::ViewReady));
}

The HTML and Javascript code for this sample is in Coherent/Samples/UI/bin/html/binding.html.

When the document has been loaded and C++ handlers have been registered the Ready event is fired.

engine.on('Ready', function () {
// trigger event handled by C++
engine.trigger('ViewReady');
});

This actually triggers

void ViewReady()
{
m_View->TriggerEvent("OpenOptions", m_Options);
}

Because the Options structure is exposed to Coherent UI it may be transferred between C++ and JavaScript.

void CoherentBind(Coherent::UI::Binder* binder, Options* options)
{
// Specify the exposed name of the type
if(auto type = binder->RegisterType("GameOptions", options))
{
// expose normal data properties
type.Property("Backend", &Options::Backend)
.Property("Width", &Options::Width)
.Property("Height", &Options::Height)
// expose read-only property with getter function
.PropertyReadOnly("Username", &Options::GetUserName)
// expose read/write property with get/set functions
.Property("NetworkPort", &Options::GetNetPort, &Options::SetNetPort);
}
}

JavaScript functions bound to event "OptionOptions" receive an JavaScript object with the described properties and values taken from the C++ options object given to Coherent::UI::View::TriggerEvent.

function openOptions(options) {
$("#options").dialog( "open" );
$("#backend").text(options.Backend);
$("#gameWidth").val(options.Width);
$("#gameHeight").val(options.Height);
$("#user").text(options.Username);
$("#netPort").val(options.NetworkPort);
}
engine.on("OpenOptions", openOptions);

If JavaScript calls C++ function that takes an Options as an argument, the JavaScript object must have a property __Type with the registered name for the Options structure - GameOptions

function onApplyButton(){
var options = {};
options.__Type = "GameOptions";
options.Backend = $("#backend").text();
options.Width = Number($("#gameWidth").val());
options.Height = Number($("#gameHeight").val());
options.Username = $("#user").text();
options.NetworkPort = Number($("#netPort").val());
// This will call the C++ engine code with the just created structure. It'll be correclty populated
engine.call("ApplyOptions", options);
}