Integrating OpenGUI         Trivial OpenGUI (0.8) Screen viewer

OpenGUI is a -GUI library, written by an Ogre user, so he has also created an Ogre renderer for it.

This is a code snippet that initializes the OpenGUI environment with the relevant Ogre objects and displays a screen layout loaded from -XML. It shows basic integration of OpenGUI in an Ogre project :

/*
    Trivial OpenGUI (0.8) Screen viewer.
    File containing screen has to be "OpenGuiTest.xml"
    Screen name has to be "DesignScreen"
    F5 to refresh screen after making changes while running
    Assumes that the file has the amethyst plugin and only that
    ESC to exit.
    Enjoy.
*/

#define GUI_SCREEN_FILE_NAME "OpenGuiTest.xml"
#define GUI_SCREEN_NAME "DesignScreen"

#include "ExampleApplication.h"
#include <OpenGUI.h>
#include <Renderer_Ogre.h>

//Trivial class just to not seperate this app into files.
class Refresher 
{
public:
    virtual void refreshScreen() {}
};

class RefresherFrameListener : public ExampleFrameListener
{
public:
    RefresherFrameListener( RenderWindow* win, Camera* cam, SceneManager *sceneMgr, Refresher* refresher)
        : ExampleFrameListener(win, cam, false, false)
    {
        // key and mouse state tracking
        mRefreshDown = false;
        mRefresher = refresher;
    }

    bool frameStarted(const FrameEvent &evt)
    {    
        mInputDevice->capture();
        if (mRefreshDown == false && mInputDevice->isKeyDown(KC_F5)) 
        {
            mRefresher->refreshScreen();
        }
        mRefreshDown = mInputDevice->isKeyDown(KC_F5);
        //If we press escape, return.
        return !mInputDevice->isKeyDown(KC_ESCAPE);
    }
protected:
    bool mRefreshDown;       // Whether or not the refresh button is down last frame
    Refresher* mRefresher;
    
};

class OpenGUIViewer : public ExampleApplication, public Refresher
{
protected:
    OpenGUI::OgreRenderer* mGuiRenderer;
    OpenGUI::System* mGuiSystem;
    OpenGUI::OgreResourceProvider* mGuiProvider;
    OpenGUI::OgreViewport* mGuiViewport;
    OpenGUI::Screen* mGuiScreen;
public:
    OpenGUIViewer()
    {
    }

    ~OpenGUIViewer() 
    {
    }
    void refreshScreen() 
    {
        //Unload the previous screen
        OpenGUI::ScreenManager::getSingleton().destroyScreen(mGuiScreen);
        mGuiSystem->unloadPlugin("Amethyst"); //Have to unload plugin - workaround
        //Reload the screen and set it as the active one.
        OpenGUI::XMLParser::getSingleton().LoadFromFile(GUI_SCREEN_FILE_NAME);
        
        mGuiScreen = OpenGUI::ScreenManager::getSingleton().getScreen(GUI_SCREEN_NAME);
        mGuiScreen->setViewport(mGuiViewport);
    }
protected:
    void createScene(void)
    {
        mGuiRenderer = new OpenGUI::OgreRenderer(mRoot, mRoot->getRenderSystem());
        mGuiProvider = new OpenGUI::OgreResourceProvider();
        mGuiSystem = new OpenGUI::System(mGuiRenderer, mGuiProvider);
        OpenGUI::XMLParser::getSingleton().LoadFromFile(GUI_SCREEN_FILE_NAME);
        mGuiViewport = new OpenGUI::OgreViewport(mWindow->getViewport(0));
        //Screen has been created already when the xml was loaded, we just need to get it.
        mGuiScreen = OpenGUI::ScreenManager::getSingleton().getScreen(GUI_SCREEN_NAME);
        mGuiScreen->setViewport(mGuiViewport);
    }

    void createFrameListener(void)
    {
        // Create the FrameListener
        mFrameListener = new RefresherFrameListener(mWindow, mCamera, mSceneMgr, this);
        mRoot->addFrameListener(mFrameListener);
        mFrameListener->showDebugOverlay(false);
    }
};

#if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"

INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
int main(int argc, char **argv)
#endif
{
    // Create application object
    OpenGUIViewer app;

    try {
        app.go();
    } catch( OpenGUI::Exception& e ) {
#if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32
        MessageBox( NULL, e.getFullMessage().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
        fprintf(stderr, "An exception has occured: %s\n",
                e.getFullDescription().c_str());
#endif
    } catch( Exception& e ) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
        MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
        std::cerr << "An exception has occured: " << e.getFullDescription();
#endif
    }

    return 0;
}


Some notes :


- OpenGUI knows to search for its resources in the Ogre resource dir if you initialized it with the OgreResourceProvider


- As of the time of this article (OpenGUI 0.8), plugins can not be loaded twice. Amethyst is a plugin that comes with OpenGUI and provides basic high level widgets (buttons, labels etc). The -XML will usually <Include> it, so I unload it in refreshScreen(). Perhaps multiple load will just ignore the load in the future rather than crash, then this line will not be neccesary. But, for now it means that the -XML you give it must include amethyst.


- To build this sample, you need to include the opengui, ogre and opengui ogre renderer include libraries, and link with OgreMain.lib, OpenGUI.lib and Renderer_Ogre.lib.


- This sample does not destroy the environment, it is just a trivial screen viewer. Feel free to edit this page and add OpenGUI environment destruction.


- As you can see in the code, the application expects to see a screen named "DesignScreen" in a file called "OpenGuiTest.xml". You can change this if you want. Here is an example of such an -XML :

<?xml version="1.0" ?>
<OpenGUI>
    <Plugin File="Amethyst"/>

    <Font Name="solo5" File="solo5.ttf" />

    <Screen Name="DesignScreen" Size="(320x240)" UPI="(96x96)" AutoUpdating="True" AutoTiming="True" >
        <Widget Name="TheButton" BaseName="Button" BaseLibrary="Amethyst">
            <Property ValueName="Font" ValueType="FONT" ValueData="solo5 @ 36" />
            <Property ValueName="Text" ValueType="STRING" ValueData="OpenGUI" />
            <Property ValueName="FontColor" ValueType="COLOR" ValueData="1.0:1.0:1.0:1.0" />
        </Widget>
    </Screen>
</OpenGUI>


It is a very basic -XML, the OpenGUI SDK contains documentation+samples on how to do pretty stuff with it.


All in all, OpenGUI is a promising -GUI library, and is pretty easy to integrate into OGRE. I hope this how-to helped you a bit.