Implementing Awesomium
January 2024
You can help by adding links to this article from other relevant articles.
January 2024
vgui::HTML
WebKit control can be used as a replacement for Awesomium. This tutorial applies to Source 2007, where the built-in browser control used an old version of the Internet Explorer engine. (The code below will work in the 2013 version: see the Discussion page)Awesomium is a free (to non-commercial users) SDK that allows you to embed WebKit in your project. It offers a .NET and C++ API, and can be easily added to the Source Engine.
Source 2007 does include an HTML control, but it uses the Internet Explorer rendering engine, and doesn't support JavaScript. Using Awesomium allows you to take advantage of CSS3, HTML Canvas, and WebGL. It also allows you to bridge the gap between the browser and the game world, as you can call JavaScript functions inside the game, and can call game methods from JavaScript.
HTML is a mature presentation layer, so it makes sense to use it for in-game UI that would otherwise be difficult to construct using the VGUI library alone. Counter-Strike: Global Offensive's UI previously used an implementation of Adobe Flash called Scaleform for instance.
Pre-requisites
Awesomium Linked & Included
First, you'll need to install the Awesomium SDK, and link it up in your Client project. There's a really easy to follow tutorial on the site on how to do that, so I won't cover that again: Setting up Awesomium in your C++ project
The VAwesomium Code
Second, you'll need the business end of the device- VAwesomium. VAwesomium wraps up the Awesomium functionality into an extensible VGUI Panel that you can plonk into your mod and go. I'm currently using it in my mod Estranged, where we're working on in-engine puzzles and backstory elements composed in HTML.
To use it, simply download or check out the source code, and add it to your Client project: https://github.com/alanedwardes/VAwesomium
Basic Usage
Here's an example of it being used in a vgui::Panel element:
Header:
class MyPanel : public vgui::Panel
{
public:
MyPanel(vgui::Panel *parent, const char *panelName);
[...]
private:
VAwesomium *m_Browser;
};
CPP:
MyPanel::MyPanel(vgui::Panel *parent, const char *panelName) : vgui::Panel(parent, panelName)
{
m_Browser = new VAwesomium(this, "VAwesomium");
m_Browser->SetSize(GetWidth(), GetTall());
m_Browser->OpenURL("https://developer.valvesoftware.com/wiki/Main_Page");
}
Advanced Usage
If you want to add JavaScript functions that your page can call to interface with the engine, you'll need to inherit from the VAwesomium class.
Header:
#include "VAwesomium.h"
#define EXIT_COMMAND "ExitMyVAwesomium"
#include <vgui/VGUI.h>
#include <vgui_controls/Panel.h>
class MyVAwesomium : public VAwesomium
{
DECLARE_CLASS_SIMPLE(MyVAwesomium, VAwesomium);
public:
MyVAwesomium(vgui::Panel *parent, const char *panelName) : VAwesomium(parent, panelName){};
virtual void OnDocumentReady(Awesomium::WebView* caller, const Awesomium::WebURL& url);
virtual void OnMethodCall(Awesomium::WebView* caller, unsigned int remote_object_id, const Awesomium::WebString& method_name, const Awesomium::JSArray& args);
};
CPP:
using namespace Awesomium;
#ifdef PostMessage
#undef PostMessage
#endif
void MyVAwesomium::OnDocumentReady(WebView* caller, const WebURL& url)
{
JSValue result = caller->CreateGlobalJavascriptObject(WSLit("MyObject"));
JSObject &myObject = result.ToObject();
myObject.SetCustomMethod(WSLit("ReturnToGame"), false);
caller->ExecuteJavascript(WSLit("AwesomiumInitialized()"), WSLit(""));
}
void MyVAwesomium::OnMethodCall(Awesomium::WebView* caller, unsigned int remote_object_id, const Awesomium::WebString& method_name, const Awesomium::JSArray& args)
{
if (method_name == WSLit("ReturnToGame"))
{
BaseClass::GetParent()->PostMessage(BaseClass::GetParent(), new KeyValues("command", "command", EXIT_COMMAND));
}
}
With the Above, MyObject.ReturnToGame()
will be available to your HTML page.
More JavaScript
The JavaScript interface is very powerful, you can execute JavaScript methods that return data from the page, and you can call methods in-browser that return data from the game. To find out more, see the JavaScript pages on the Awesomium wiki.
JavaScript Gotchas
The implementation isn't perfect, as with Awesomium you have to wait until the OnDocumentReady
method has fired to add JavaScript objects to the page. That's why at the end of that method I execute the JavaScript method AwesomiumInitialized()
- it allows me to notify my page that the JavaScript objects I just created in the C++ are now available on the page.
Contributing
My class is far from perfect, and is bound to be lacking in certain features or include bugs just waiting to be fixed. I put the project up on GitHub, so please feel free to contribute to the project, and if you're using it, make sure you update it now and again before you distribute it.
VAwesomium on GitHub: https://github.com/alanedwardes/VAwesomium