[release]Irrlicht Awesomium Handler

A forum to store posts deemed exceptionally wise and useful
Post Reply
kklouzal
Posts: 343
Joined: Sun Mar 28, 2010 8:14 pm
Location: USA - Arizona

[release]Irrlicht Awesomium Handler

Post by kklouzal »

Hello!

Irrlicht Awesomium Handler
https://github.com/kklouzal/AwesomiumHandler
http://www.awesomium.com/

Code: Select all

Awesomium provides everything you need to start displaying beautiful HTML-powered interfaces and web-content within your application fast.

Code: Select all

Awesomium is free for any team making less than $100K revenue and free to use in any educational or non-commercial apps.
For all others, it’s just $2900 per application. No royalties, no monthly fees, no hidden costs. You only need to buy a license once you begin distribution.
I wrote a class to handle Awesomium in Irrlicht,


Credit to the Irrlicht IRC Chat & sudi


It works like this:
Basically you create a Handler
The handler gets updated once every frame and allows you to create WebViews
Creating a WebView returns an object which you can get an ITexture* or draw the WebView in 2D on screen

Example:
You're going to need to go to http://www.awesomium.com/ and download their installer for C++
Once it's installed you'll have a new environment path variable AWE_DIR which will be the installation directory for Awesomium

Setup:
Make sure to include these directories in your IDE:
Include: $(AWE_DIR)include
Library: $(AWE_DIR)build\lib
You'll also need to link Awesomium.lib
Don't forget Irrlicht :)

Go into the download and take the files in the Source directory and move them into your projects directory

Start off by setting up the basic Irrlicht skeleton
We'll be using pieces from a few different tutorials

Code: Select all

#pragma comment(lib, "irrlicht.lib")
//Include Awesomium.lib
#pragma comment(lib, "awesomium.lib")
 
#include <irrlicht.h>
#include <iostream>
#include "driverChoice.h"
 
//Window Size
#define ScrW 800
#define ScrH 600
 
int main()
{
    // ask user for driver
    irr::video::E_DRIVER_TYPE driverType = irr::driverChoiceConsole();
    if (driverType == irr::video::EDT_COUNT){ return -1; }
 
    // create device
    irr::IrrlichtDevice *device =
        irr::createDevice(driverType, irr::core::dimension2d<irr::u32>(ScrW, ScrH), 32, false);
    if (device == 0) { return -2; }
 
    irr::video::IVideoDriver* driver = device->getVideoDriver();
    irr::scene::ISceneManager* smgr = device->getSceneManager();
 
    // Create a camera
    irr::scene::ICameraSceneNode* cam = smgr->addCameraSceneNode();
    cam->setTarget(irr::core::vector3df(0, 0, 0));
    // Attach fly circle animator
    irr::scene::ISceneNodeAnimator* anim =
        smgr->createFlyCircleAnimator(irr::core::vector3df(0, 20, 0), 60.0f);
    cam->addAnimator(anim);
    anim->drop();
    // Create a cube for it to circle
    irr::scene::ISceneNode* cube = smgr->addCubeSceneNode(20);
    // Attach a couple materials to make it look awesome sauce
    cube->setMaterialTexture(0, driver->getTexture("./wall.bmp"));
    cube->setMaterialTexture(1, driver->getTexture("./media/water.jpg"));
    cube->setMaterialFlag(irr::video::EMF_LIGHTING, false);
    cube->setMaterialType(irr::video::EMT_REFLECTION_2_LAYER);
    // Don't forget a skybox
    smgr->addSkyBoxSceneNode(
        driver->getTexture("./irrlicht2_up.jpg"),
        driver->getTexture("./irrlicht2_dn.jpg"),
        driver->getTexture("./irrlicht2_lf.jpg"),
        driver->getTexture("./irrlicht2_rt.jpg"),
        driver->getTexture("./irrlicht2_ft.jpg"),
        driver->getTexture("./irrlicht2_bk.jpg"));
 
    irr::u32 LastFPS = -1;
    const irr::core::stringw sDriver = driver->getName();
    irr::video::SColor ZColor(255, 100, 0, 0);
    while (device->run())
    {
        if (device->isWindowActive())
        {
            driver->beginScene(true, true, ZColor);
 
            smgr->drawAll();
            driver->endScene();
 
            const irr::u32 FPS = driver->getFPS();
            if (LastFPS != FPS)
            {
                irr::core::stringw wCaption = L"Irrlicht Awesomium Surface - Driver: ";
                wCaption += sDriver;
                wCaption += " FPS: ";
                wCaption += driver->getFPS();
                device->setWindowCaption(wCaption.c_str());
                LastFPS = FPS;
            }
        }
    }
 
    // Cleanup
    device->drop();
    return 0;
}
That will gives an 800x600 window of our camera circling a textured cube with a skybox
You'll need to grab those images out of the irrlicht/media folder and put it on the same level as your .exe
Don't forget irrlicht.dll

The first thing you'll need to do is include AwesomiumHandle.h

Code: Select all

#pragma comment(lib, "irrlicht.lib")
//Include Awesomium.lib
#pragma comment(lib, "awesomium.lib")
 
//Include  the  Awesomium Irrlicht Handler
#include "AwesomiumHandle.h"
 
#include <irrlicht.h>
#include <iostream>
#include "driverChoice.h"
 
//Window Size
#define ScrW 800
#define ScrH 600
You can edit the desired screen resolution here and everything will scale

Let's setup the handler and create a WebView
First create a Pointer to an aweView to hold your WebView

Code: Select all

// Window Size
#define ScrW 800
#define ScrH 600
 
// Our WebView
aweView *View1;
Now go ahead and get the location of our .exe so we can display our .htm file

Code: Select all

    //get .exe file path
    wchar_t buffer[MAX_PATH];
    GetModuleFileName(NULL, buffer, MAX_PATH);
    std::wstring FilePath = buffer;
    FilePath = FilePath.substr(0, FilePath.rfind(L"\\"));
    FilePath = L"file:///" + FilePath + L"//html//index.htm";
Create the handler and Event Receiver

Code: Select all

    // create Awesomium Handler
    AwesomiumHandle aHandle(driver);
    //Setup Event Receiver and pass it the Handler
    MyEventReceiver eReceive(&aHandle);
    device->setEventReceiver(&eReceive);
When you call CreateView you get an aweView pointer you can manipulate
Let's send it to our .htm file and add some transparency

Code: Select all

    // create a WebView
    View1 = aHandle.CreateView(irr::core::position2d<irr::s32>(0, 0), irr::core::position2d<irr::s32>(ScrW, ScrH));
    // send them somewhere!
    View1->SetURL(std::string(FilePath.begin(), FilePath.end()));
    // transparency
    View1->SetAlpha(155);
Now we're going to add the EventReceiver
Here is where we relay the users mouse and keyboard input into the Handler

Code: Select all

class MyEventReceiver : public irr::IEventReceiver
{
public:
    // This is the one method that we have to implement
    virtual bool OnEvent(const irr::SEvent& event)
    {
        // Remember whether each key is down or up
        if (event.EventType == irr::EET_MOUSE_INPUT_EVENT)
        {
            switch(event.MouseInput.Event)
            {
                case irr::EMIE_MOUSE_WHEEL:
                    aweHandle->ScrollWheel(event.MouseInput.Wheel);
                    break;
 
                case irr::EMIE_LMOUSE_PRESSED_DOWN:
                    aweHandle->MouseDown(0);
                    break;
 
                case irr::EMIE_LMOUSE_LEFT_UP:
                    aweHandle->MouseUp(0);
                    break;
 
                case irr::EMIE_MMOUSE_PRESSED_DOWN:
                    aweHandle->MouseDown(1);
                    break;
 
                case irr::EMIE_MMOUSE_LEFT_UP:
                    aweHandle->MouseUp(1);
                    break;
 
                case irr::EMIE_RMOUSE_PRESSED_DOWN:
                    aweHandle->MouseDown(2);
                    break;
 
                case irr::EMIE_RMOUSE_LEFT_UP:
                    aweHandle->MouseUp(2);
                    break;
 
                case irr::EMIE_MOUSE_MOVED:
                    aweHandle->MoveMouse(event.MouseInput.X, event.MouseInput.Y);
                    break;
            }
        }
 
        if (event.EventType == irr::EET_KEY_INPUT_EVENT)
        {
            aweHandle->KeyInput(event);
        }
 
        return false;
    }
 
    MyEventReceiver(AwesomiumHandle* aHandle)
    {
        aweHandle = aHandle;
    }
 
private:
    AwesomiumHandle* aweHandle;
};
Finally the update method, needs to be called after everything else draws

Code: Select all

        driver->beginScene(true, true, ZColor);
 
            smgr->drawAll();
 
            // Update Awesomium Handle
            aHandle.Update();
            driver->endScene();



Now the entire code looks like this

Code: Select all

#pragma comment(lib, "irrlicht.lib")
// Include Awesomium.lib
#pragma comment(lib, "awesomium.lib")
 
// Include  the  Awesomium Irrlicht Handler
#include "AwesomiumHandle.h"
 
#include <irrlicht.h>
#include <iostream>
#include "driverChoice.h"
 
// Window Size
#define ScrW 800
#define ScrH 600
 
// Our WebView
aweView *View1;
 
class MyEventReceiver : public irr::IEventReceiver
{
public:
    // This is the one method that we have to implement
    virtual bool OnEvent(const irr::SEvent& event)
    {
        // Remember whether each key is down or up
        if (event.EventType == irr::EET_MOUSE_INPUT_EVENT)
        {
            switch (event.MouseInput.Event)
            {
            case irr::EMIE_MOUSE_WHEEL:
                aweHandle->ScrollWheel(event.MouseInput.Wheel);
                break;
 
            case irr::EMIE_LMOUSE_PRESSED_DOWN:
                aweHandle->MouseDown(0);
                break;
 
            case irr::EMIE_LMOUSE_LEFT_UP:
                aweHandle->MouseUp(0);
                break;
 
            case irr::EMIE_MMOUSE_PRESSED_DOWN:
                aweHandle->MouseDown(1);
                break;
 
            case irr::EMIE_MMOUSE_LEFT_UP:
                aweHandle->MouseUp(1);
                break;
 
            case irr::EMIE_RMOUSE_PRESSED_DOWN:
                aweHandle->MouseDown(2);
                break;
 
            case irr::EMIE_RMOUSE_LEFT_UP:
                aweHandle->MouseUp(2);
                break;
 
            case irr::EMIE_MOUSE_MOVED:
                aweHandle->MoveMouse(event.MouseInput.X, event.MouseInput.Y);
                break;
            }
        }
 
        if (event.EventType == irr::EET_KEY_INPUT_EVENT)
        {
            aweHandle->KeyInput(event);
        }
 
        return false;
    }
 
    MyEventReceiver(AwesomiumHandle* aHandle)
    {
        aweHandle = aHandle;
    }
 
private:
    AwesomiumHandle* aweHandle;
};
 
int main()
{
    // ask user for driver
    irr::video::E_DRIVER_TYPE driverType = irr::driverChoiceConsole();
    if (driverType == irr::video::EDT_COUNT){ return -1; }
 
    // create device
    irr::IrrlichtDevice *device =
        irr::createDevice(driverType, irr::core::dimension2d<irr::u32>(ScrW, ScrH), 32, false);
    if (device == 0) { return -2; }
    irr::video::IVideoDriver* driver = device->getVideoDriver();
    irr::scene::ISceneManager* smgr = device->getSceneManager();
 
    // create Awesomium Handler
    AwesomiumHandle aHandle(driver);
    //Setup Event Receiver and pass it the Handler
    MyEventReceiver eReceive(&aHandle);
    device->setEventReceiver(&eReceive);
 
    // Create a camera
    irr::scene::ICameraSceneNode* cam = smgr->addCameraSceneNode();
    cam->setTarget(irr::core::vector3df(0, 0, 0));
    // Attach fly circle animator
    irr::scene::ISceneNodeAnimator* anim =
        smgr->createFlyCircleAnimator(irr::core::vector3df(0, 20, 0), 60.0f);
    cam->addAnimator(anim);
    anim->drop();
 
    // Create a cube for it to circle
    irr::scene::ISceneNode* cube = smgr->addCubeSceneNode(20);
    // Attach a couple materials to make it look awesome sauce
    cube->setMaterialTexture(0, driver->getTexture("./wall.bmp"));
    cube->setMaterialTexture(1, driver->getTexture("./media/water.jpg"));
    cube->setMaterialFlag(irr::video::EMF_LIGHTING, false);
    cube->setMaterialType(irr::video::EMT_REFLECTION_2_LAYER);
    // Don't forget a skybox
    smgr->addSkyBoxSceneNode(
        driver->getTexture("./irrlicht2_up.jpg"),
        driver->getTexture("./irrlicht2_dn.jpg"),
        driver->getTexture("./irrlicht2_lf.jpg"),
        driver->getTexture("./irrlicht2_rt.jpg"),
        driver->getTexture("./irrlicht2_ft.jpg"),
        driver->getTexture("./irrlicht2_bk.jpg"));
 
    //get .exe file path
    wchar_t buffer[MAX_PATH];
    GetModuleFileName(NULL, buffer, MAX_PATH);
    std::wstring FilePath = buffer;
    FilePath = FilePath.substr(0, FilePath.rfind(L"\\"));
    FilePath = L"file:///" + FilePath + L"//html//index.htm";
 
    // create a WebView
    View1 = aHandle.CreateView(irr::core::position2d<irr::s32>(0, 0), irr::core::position2d<irr::s32>(ScrW, ScrH));
    // send them somewhere!
    View1->SetURL(std::string(FilePath.begin(), FilePath.end()));
    // transparency
    View1->SetAlpha(130);
 
    irr::u32 LastFPS = -1;
    const irr::core::stringw sDriver = driver->getName();
    irr::video::SColor ZColor(255, 100, 100, 100);
    while (device->run())
    {
        if (device->isWindowActive())
        {
            driver->beginScene(true, true, ZColor);
 
            smgr->drawAll();
 
            // Update Awesomium Handle
            aHandle.Update();
            driver->endScene();
 
            const irr::u32 FPS = driver->getFPS();
            if (LastFPS != FPS)
            {
                irr::core::stringw wCaption = L"Irrlicht Awesomium Surface - Driver: ";
                wCaption += sDriver;
                wCaption += " FPS: ";
                wCaption += driver->getFPS();
                device->setWindowCaption(wCaption.c_str());
                LastFPS = FPS;
            }
        }
    }
 
    // Cleanup
    device->drop();
    return 0;
}
Compile and run!
Don't forget all the Awesomium DLL files and the html folder needs to be in with your .exe!
The next tutorial will show you how to setup callbacks
Last edited by kklouzal on Tue Sep 30, 2014 10:03 pm, edited 1 time in total.
Dream Big Or Go Home.
Help Me Help You.
kklouzal
Posts: 343
Joined: Sun Mar 28, 2010 8:14 pm
Location: USA - Arizona

Re: [release]Irrlicht Awesomium Handler

Post by kklouzal »

Were going to expand on the last tutorial and add callbacks
You can call a c++ function from within javascript
And you can call javascript functions from within C++

To add a global javascript object call this method on your aweView

Code: Select all

// create a global javascript object
    const unsigned int gNum = View1->AddJSGlobalObject("SomeShits");
It will return a number which you will later use to identify this global javascript object

Now we want to setup our C++ function
The only requirements is that the function accept only these parameters

Code: Select all

(Awesomium::WebView* caller, const Awesomium::JSArray& args)
Let's call our function Callback1

Code: Select all

void Callback1(Awesomium::WebView* caller, const Awesomium::JSArray& args)
{
    std::cout << "Yay a callback from JavaScript!" << std::endl;
}
Now let's add a function to that global javascript object
When this function is called within javascript it will run our Callback1 function
Pass the name of the javascript function and the c++ function

Code: Select all

// add a callback to that object
    View1->AddJSCallback(gNum, "CoolBeans", Callback1);
We're going to call back into javascript during our Callbac1 function
To call into javascript use this method on your aweView
Pass the name of the javascript and one argument as a string

Code: Select all

  View1->CallJS("CalledFromCPP", "Sent From C++");
Now our function looks like this

Code: Select all

void Callback1(Awesomium::WebView* caller, const Awesomium::JSArray& args)
{
    std::cout << "Yay a callback from JavaScript!" << std::endl;
    View1->CallJS("CalledFromCPP", "Sent From C++");
}
 
Here's the whole code

Code: Select all

#pragma comment(lib, "irrlicht.lib")
// Include Awesomium.lib
#pragma comment(lib, "awesomium.lib")
 
// Include  the  Awesomium Irrlicht Handler
#include "AwesomiumHandle.h"
 
#include <irrlicht.h>
#include <iostream>
#include "driverChoice.h"
 
// Window Size
#define ScrW 800
#define ScrH 600
 
// Our WebView
aweView *View1;
 
void Callback1(Awesomium::WebView* caller, const Awesomium::JSArray& args)
{
    std::cout << "Yay a callback from JavaScript!" << std::endl;
    View1->CallJS("CalledFromCPP", "Sent From C++");
}
 
class MyEventReceiver : public irr::IEventReceiver
{
public:
    // This is the one method that we have to implement
    virtual bool OnEvent(const irr::SEvent& event)
    {
        // Remember whether each key is down or up
        if (event.EventType == irr::EET_MOUSE_INPUT_EVENT)
        {
            switch (event.MouseInput.Event)
            {
            case irr::EMIE_MOUSE_WHEEL:
                aweHandle->ScrollWheel(event.MouseInput.Wheel);
                break;
 
            case irr::EMIE_LMOUSE_PRESSED_DOWN:
                aweHandle->MouseDown(0);
                break;
 
            case irr::EMIE_LMOUSE_LEFT_UP:
                aweHandle->MouseUp(0);
                break;
 
            case irr::EMIE_MMOUSE_PRESSED_DOWN:
                aweHandle->MouseDown(1);
                break;
 
            case irr::EMIE_MMOUSE_LEFT_UP:
                aweHandle->MouseUp(1);
                break;
 
            case irr::EMIE_RMOUSE_PRESSED_DOWN:
                aweHandle->MouseDown(2);
                break;
 
            case irr::EMIE_RMOUSE_LEFT_UP:
                aweHandle->MouseUp(2);
                break;
 
            case irr::EMIE_MOUSE_MOVED:
                aweHandle->MoveMouse(event.MouseInput.X, event.MouseInput.Y);
                break;
            }
        }
 
        if (event.EventType == irr::EET_KEY_INPUT_EVENT)
        {
            aweHandle->KeyInput(event);
        }
 
        return false;
    }
 
    MyEventReceiver(AwesomiumHandle* aHandle)
    {
        aweHandle = aHandle;
    }
 
private:
    AwesomiumHandle* aweHandle;
};
 
int main()
{
    // ask user for driver
    irr::video::E_DRIVER_TYPE driverType = irr::driverChoiceConsole();
    if (driverType == irr::video::EDT_COUNT){ return -1; }
 
    // create device
    irr::IrrlichtDevice *device =
        irr::createDevice(driverType, irr::core::dimension2d<irr::u32>(ScrW, ScrH), 32, false);
    if (device == 0) { return -2; }
    irr::video::IVideoDriver* driver = device->getVideoDriver();
    irr::scene::ISceneManager* smgr = device->getSceneManager();
 
    // create Awesomium Handler
    AwesomiumHandle aHandle(driver);
    //Setup Event Receiver and pass it the Handler
    MyEventReceiver eReceive(&aHandle);
    device->setEventReceiver(&eReceive);
 
    // Create a camera
    irr::scene::ICameraSceneNode* cam = smgr->addCameraSceneNode();
    cam->setTarget(irr::core::vector3df(0, 0, 0));
    // Attach fly circle animator
    irr::scene::ISceneNodeAnimator* anim =
        smgr->createFlyCircleAnimator(irr::core::vector3df(0, 20, 0), 60.0f);
    cam->addAnimator(anim);
    anim->drop();
 
    // Create a cube for it to circle
    irr::scene::ISceneNode* cube = smgr->addCubeSceneNode(20);
    // Attach a couple materials to make it look awesome sauce
    cube->setMaterialTexture(0, driver->getTexture("./wall.bmp"));
    cube->setMaterialTexture(1, driver->getTexture("./media/water.jpg"));
    cube->setMaterialFlag(irr::video::EMF_LIGHTING, false);
    cube->setMaterialType(irr::video::EMT_REFLECTION_2_LAYER);
    // Don't forget a skybox
    smgr->addSkyBoxSceneNode(
        driver->getTexture("./irrlicht2_up.jpg"),
        driver->getTexture("./irrlicht2_dn.jpg"),
        driver->getTexture("./irrlicht2_lf.jpg"),
        driver->getTexture("./irrlicht2_rt.jpg"),
        driver->getTexture("./irrlicht2_ft.jpg"),
        driver->getTexture("./irrlicht2_bk.jpg"));
 
    //get .exe file path
    wchar_t buffer[MAX_PATH];
    GetModuleFileName(NULL, buffer, MAX_PATH);
    std::wstring FilePath = buffer;
    FilePath = FilePath.substr(0, FilePath.rfind(L"\\"));
    FilePath = L"file:///" + FilePath + L"//html//index.htm";
 
    // create a WebView
    View1 = aHandle.CreateView(irr::core::position2d<irr::s32>(0, 0), irr::core::position2d<irr::s32>(ScrW, ScrH));
    // send them somewhere!
    View1->SetURL(std::string(FilePath.begin(), FilePath.end()));
    // transparency
    View1->SetAlpha(130);
    // create a global javascript object
    const unsigned int gNum = View1->AddJSGlobalObject("SomeShits");
    // add a callback to that object
    View1->AddJSCallback(gNum, "CoolBeans", Callback1);
 
    irr::u32 LastFPS = -1;
    const irr::core::stringw sDriver = driver->getName();
    irr::video::SColor ZColor(255, 100, 100, 100);
    while (device->run())
    {
        if (device->isWindowActive())
        {
            driver->beginScene(true, true, ZColor);
 
            smgr->drawAll();
 
            // Update Awesomium Handle
            aHandle.Update();
            driver->endScene();
 
            const irr::u32 FPS = driver->getFPS();
            if (LastFPS != FPS)
            {
                irr::core::stringw wCaption = L"Irrlicht Awesomium Surface - Driver: ";
                wCaption += sDriver;
                wCaption += " FPS: ";
                wCaption += driver->getFPS();
                device->setWindowCaption(wCaption.c_str());
                LastFPS = FPS;
            }
        }
    }
 
    // Cleanup
    device->drop();
    return 0;
}
Compile and run
Now the Callback To C++ button works, you get a message in console, then it prints on the Awesomium WebView
Last edited by kklouzal on Wed Mar 19, 2014 4:35 pm, edited 1 time in total.
Dream Big Or Go Home.
Help Me Help You.
kklouzal
Posts: 343
Joined: Sun Mar 28, 2010 8:14 pm
Location: USA - Arizona

Re: [release]Irrlicht Awesomium Handler

Post by kklouzal »

reserved
Dream Big Or Go Home.
Help Me Help You.
chronologicaldot
Competition winner
Posts: 688
Joined: Mon Sep 10, 2012 8:51 am

Re: [release]Irrlicht Awesomium Handler

Post by chronologicaldot »

Reminds me of a project I worked on a while back I called "XPLOsion" (it's somewhere on my old website projects page). It used Irrlicht's native serialization/deserialization system and loaded native Irrlicht GUI elements. I couldn't decide how I wanted to do button triggering, so I changed the system once (though I could change it back I guess).

Nice work on your project there. Do you plan on using it for something specific or is it just a tool?
kklouzal
Posts: 343
Joined: Sun Mar 28, 2010 8:14 pm
Location: USA - Arizona

Re: [release]Irrlicht Awesomium Handler

Post by kklouzal »

It's just a tool/wrapper for others to use which will be updated if any bugs are found or features needed!
Dream Big Or Go Home.
Help Me Help You.
Post Reply