Hummingbird interprets and executes JavaScript code that can be used for scripting the UI. The execution itself is performed by a JavaScript virtual machine. Hummingbird uses different VMs on different platforms to provide the best available option. On platforms where code JIT compilation is allowed like Windows and Android, Hummingbird uses V8, while on iOS it uses the JavaScriptCore framework.
All currently implemented JavaScript functions and objects can be viewed in the JavaScript DOM API section of the documentation.
All communication between JavaScript and the game goes through the engine
module.
There are two ways for invoking native code from JavaScript and vice-versa.
Events allow to call multiple handlers in both directions, but they can not return any value. To register a JavaScript handler for an event use the engine.on
method.
First the JavaScript code has to attach a handler for the event using engine.on
:
Then we trigger the event in C#, using the cohtml.View.TriggerEvent
method:
There are also global functions in the cohtml
namespace which can be used such as:
cohtml.ViewExtensions.TriggerEvent(view, 'ScoreChanged', 10000);
Registering C# functions for events triggered by JavaScript should happen in the handler for the cohtml.Net.IViewListener.OnReadyForBindings
callback. There is a convenient event that you can subscribe to - cohml.ViewListener.ReadyForBindings
;
Event handlers are registered with the cohtml.Net.View.RegisterForEvent
method. They cannot return any value to JavaScript, but may trigger an event for JavaScript. There may be more than one C# handler for a given event. There also may be both C# and JavaScript handlers for the same event.
Triggering the event from JavaScript looks like:
Promises are used to return results from C# to JavaScript. Hummingbird promises are modeled after the PromisesA specification.
Call handlers are registered with the cohtml.Net.View.BindCall
method. There may be only one handler for a given call and the handler may return a result.
To get the player name in the view:
BindCall
with engine.call
when you have single handler and RegisterForEvent
with engine.trigger
when you have more that one handlers.To be able to use your C# types as arguments or results for event and call handlers, the C# type must be exposed to Hummingbird. To expose a C# type to Hummingbird you should add the cohtml.Net.CoherentType
attribute above the type.
After registering the Player
type, events can be triggered in both directions with instances of Player
as an argument and call handlers can return Player
s as return types.
Then in JavaScript, we receive the object with the specified properties. The value of each property is the same as in the moment of triggering the event. The JavaScript callback may store a reference to the object, but its properties WILL NOT be synchronized with the actual Game.playerOne
in the game.
If you want to call C# handler with an instance of Player
created in JavaScript there is one important detail - the object must have a property __Type
with value Player.
__Type: Player
will look for this type in the global namespace. If your type resides in a namespace or inside a class you should prefix the type: namespace.class.type
For some calls it's possible that there is no meaningful value to return. For example:
Custom promises have been deprecated! Now we are supporting ECMAScript 6 promises
Hummingbird provides extensions on-top of the vanilla DOM-related JavaScript as defined by the standard. The extensions are aimed to provide better performance and a more natural workflow to UI developers. The prime example of such an extension are the Node.leftXX/Node.topXX methods. In vanilla JS, to update the position of an element you have to call Node.top
/Node.left
, however the functions take a string parameter. To update an element's left
property you have to do:
The newPos
variable is a number in pixels, but the runtime will have to convert it to a string, append the 'px' specifier and send it to the native code. The native code at that moment will convert it back to a number to re-calculate the position. This is very inefficient, it creates JavaScript garbage and unnecessary work.
In Hummingbird you can just say:
No garbage is generated and the calculation is much faster both in JS and native code. A complete list of extensions is available in the JavaScript DOM API section of the documentation.