Wartbed:GUI evaluation

From Dark Omen Wiki

(Difference between revisions)
Jump to: navigation, search
(CEGUI)
Line 16: Line 16:
* It seems the most powerful GUI library by far.
* It seems the most powerful GUI library by far.
* It has bindings for Irrlicht and OpenSceneGraph so it might be considered a relatively inter-API-portable framework.
* It has bindings for Irrlicht and OpenSceneGraph so it might be considered a relatively inter-API-portable framework.
 +
<pre style="margin:1em; background:black;color:lightgray; size:small;">
 +
/************************************************************************/
 +
/* EVALUATION OF CEGUI                                                  */
 +
/*                                                                      */
 +
/* > Includes are in OGRE_HOME/Samples, which must be added to paths(!) */
 +
/*                                                                      */
 +
/************************************************************************/
 +
 +
#include "../source/wartbed/Wartbed.h"
 +
 +
#include <CEGUI/CEGUI.h>
 +
#include <CEGUI/CEGUIDefaultResourceProvider.h>
 +
#include <OgreCEGUIRenderer.h>
 +
 +
 +
CEGUI::System              *g_pSystem      = 0;
 +
CEGUI::OgreCEGUIRenderer    *g_pRenderer    = 0;
 +
CEGUI::WindowManager        *g_pWinMngr    = 0;
 +
CEGUI::Window              *g_pSheet      = 0;
 +
CEGUI::Window              *g_pButton      = 0;
 +
 +
 +
struct FrameListener : wb::FrameListener
 +
{
 +
    bool frameStarted(const Ogre::FrameEvent& evt)
 +
    {
 +
        using namespace wb::ogre;
 +
 +
        if (pKeyboard->isKeyDown(OIS::KC_ESCAPE))
 +
        {
 +
            Stop();
 +
            return false;
 +
        }
 +
 +
        else
 +
            wb::FrameListener::frameStarted( evt );
 +
    }
 +
};
 +
 +
 +
struct KeyListener : wb::KeyListener
 +
{
 +
    bool keyPressed( OIS::KeyEvent const &e )
 +
    {
 +
        g_pSystem->injectKeyDown( e.key );
 +
        g_pSystem->injectChar( e.text );
 +
        return true;
 +
    }
 +
 +
    bool keyReleased( OIS::KeyEvent const &e )
 +
    {
 +
        g_pSystem->injectKeyUp( e.key );
 +
        return true;
 +
    }
 +
};
 +
 +
 +
struct MouseListener : wb::MouseListener
 +
{
 +
    CEGUI::MouseButton convert( OIS::MouseButtonID buttonID )
 +
    {
 +
        switch (buttonID)
 +
        {
 +
            case OIS::MB_Left: return CEGUI::LeftButton;
 +
            case OIS::MB_Right: return CEGUI::RightButton;
 +
            case OIS::MB_Middle: return CEGUI::MiddleButton;
 +
            default: return CEGUI::LeftButton;
 +
        }
 +
    }
 +
 +
    bool mouseMoved( OIS::MouseEvent const &e )
 +
    {
 +
        g_pSystem->injectMouseMove( e.state.X.rel, e.state.Y.rel );
 +
 +
        if(e.state.Z.rel != 0)
 +
            g_pSystem->injectMouseWheelChange( e.state.Z.rel );
 +
 +
        return true;
 +
    }
 +
 +
    bool mousePressed( OIS::MouseEvent const &e, OIS::MouseButtonID id )
 +
    {
 +
        g_pSystem->injectMouseButtonDown( convert(id) );
 +
        return true;
 +
    }
 +
 +
    bool mouseReleased( OIS::MouseEvent const &e, OIS::MouseButtonID id )
 +
    {
 +
        g_pSystem->injectMouseButtonUp( convert(id) );
 +
        return true;
 +
    }
 +
};
 +
 +
 +
bool OnClick( CEGUI::EventArgs const &args )
 +
 +
    MessageBeep( MB_OK );
 +
    return true;
 +
}
 +
 +
 +
 +
//=============================================================================
 +
// Main function...
 +
//
 +
//-----------------------------------------------------------------------------
 +
 +
    std::string app_name;
 +
    std::string app_path;
 +
 +
#if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32
 +
 +
    //---------------------------------------------------------------------
 +
    // Windows main signature
 +
    //---------------------------------------------------------------------
 +
 +
    #define WIN32_LEAN_AND_MEAN
 +
    #include "windows.h"
 +
 +
    INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
 +
    {
 +
        app_name.resize( _MAX_PATH );
 +
        GetModuleFileNameA( NULL, &app_name[0], _MAX_PATH );
 +
 +
        STARTUPINFO startupInfo;
 +
        GetStartupInfo( &startupInfo );
 +
 +
 +
#else
 +
 +
    //---------------------------------------------------------------------
 +
    // POSIX main signature
 +
    //---------------------------------------------------------------------
 +
 +
    int main(int argc, char **argv)
 +
    {
 +
        app_name = argv[0];
 +
 +
#endif
 +
 +
 +
        utils::tokeniser<char> t( app_name, "\\" );
 +
        app_path = t.collate( 0, t.size()-3, "/" );
 +
 +
    //---------------------------------------------------------------------
 +
    // Common main body
 +
    //---------------------------------------------------------------------
 +
 +
        // The entire game is initialised, started and run in the FCom()
 +
        // function.
 +
        //
 +
        try
 +
        {
 +
            Wartbed::getInstance( "CEGUI Test" ).setFrameListener( new FrameListener );
 +
            Wartbed::getInstance().setKeyListener( new KeyListener );
 +
            Wartbed::getInstance().setMouseListener( new MouseListener );
 +
 +
            Ogre::ResourceGroupManager::getSingleton().addResourceLocation( "./Fonts", "FileSystem" );
 +
            Ogre::ResourceGroupManager::getSingleton().addResourceLocation( "./CEGUI", "FileSystem" );
 +
 +
            // Instruct Ogre to go through all paths set by addResourceLocation
 +
            // and add any comptible resources.
 +
            //
 +
            Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
 +
 +
            using namespace wb::ogre;
 +
 +
            g_pRenderer = new CEGUI::OgreCEGUIRenderer( pWindow, Ogre::RENDER_QUEUE_OVERLAY, false, 3000, pSceneManager );
 +
            g_pSystem = new CEGUI::System( g_pRenderer );
 +
 +
 +
            // initialise the required dirs for the DefaultResourceProvider
 +
            CEGUI::DefaultResourceProvider *rp =
 +
                static_cast<CEGUI::DefaultResourceProvider *>
 +
                    (CEGUI::System::getSingleton().getResourceProvider());
 +
 +
 +
            // Load GUI styles
 +
            //
 +
            CEGUI::SchemeManager::getSingleton().loadScheme( (CEGUI::utf8 *) "TaharezLookSkin.scheme" );
 +
            g_pSystem->setDefaultMouseCursor( (CEGUI::utf8*)"TaharezLook", (CEGUI::utf8 *) "MouseArrow" );
 +
            g_pSystem->setDefaultFont( (CEGUI::utf8 *) "BlueHighway-12" );
 +
 +
            // Create a sheet to work on
 +
            //
 +
            g_pWinMngr  = CEGUI::WindowManager::getSingletonPtr();
 +
            g_pSheet    = g_pWinMngr->createWindow( "DefaultGUISheet", "CEGUIDemo/Sheet" );
 +
            g_pButton  = g_pWinMngr->createWindow( "TaharezLook/Button", "CEGUIDemo/QuitButton" );
 +
 +
            // Create and activate a clickable button
 +
            //
 +
            g_pButton->setText( "Click me" );
 +
            g_pButton->setPosition( CEGUI::UVector2(CEGUI::UDim(0, 10), CEGUI::UDim(0, 5)) );
 +
            g_pButton->setSize( CEGUI::UVector2(CEGUI::UDim(0.15, 0), CEGUI::UDim(0.05, 0)) );
 +
            g_pSheet->addChildWindow( g_pButton );
 +
            g_pSystem->setGUISheet( g_pSheet );
 +
 +
            g_pButton->subscribeEvent
 +
                (
 +
                    CEGUI::PushButton::EventClicked,
 +
                    CEGUI::Event::Subscriber( &OnClick )
 +
                );
 +
 +
            // Show the mouse using the default mouse cursor image
 +
            //
 +
            CEGUI::MouseCursor::getSingleton().setImage( g_pSystem->getDefaultMouseCursor() );
 +
 +
 +
            Wartbed::getInstance().mainLoop();
 +
        }
 +
 +
 +
    //---------------------------------------------------------------------
 +
    // Last-ditch exception handling
 +
    //---------------------------------------------------------------------
 +
 +
        catch (Ogre::Exception &e)
 +
        {
 +
        #if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32
 +
            MessageBoxA( NULL, e.what(), "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL );
 +
        #else
 +
            stderr << "An exception has occurred: " << e.what() << std::endl;
 +
        #endif
 +
        }
 +
 +
 +
        catch (std::exception &e)
 +
        {
 +
        #if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32
 +
            MessageBoxA( NULL, e.what(), "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL );
 +
        #else
 +
            stderr << "An exception has occurred: " << e.what() << std::endl;
 +
        #endif
 +
        }
 +
 +
 +
        catch (...)
 +
        {
 +
        #if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32
 +
            MessageBoxA( NULL, "Unknows exception thrown!", "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL );
 +
        #else
 +
            stderr << "An exception has occurred: " << e.what() << std::endl;
 +
        #endif
 +
        }
 +
 +
 +
        return EXIT_SUCCESS;
 +
    }
 +
 +
//-----------------------------------------------------------------------------
 +
//
 +
// ...end main function
 +
//=============================================================================
 +
</pre>
===QuickGUI===
===QuickGUI===
Line 21: Line 275:
<br>http://stormsonggames.com/downloads/images/OgreForum/qgui_9_3.jpg
<br>http://stormsonggames.com/downloads/images/OgreForum/qgui_9_3.jpg
<br>Made for OGRE, inspired by BetGUI and CEGUI. It seems reasonably complete and is the framework I've gotten furthest with so far.  
<br>Made for OGRE, inspired by BetGUI and CEGUI. It seems reasonably complete and is the framework I've gotten furthest with so far.  
 +
<pre style="margin:1em; background:black;color:lightgray; size:small;">
 +
/************************************************************************/
 +
/* EVALUATION OF QuickGUI                                              */
 +
/*                                                                      */
 +
/*                                                                      */
 +
/************************************************************************/
 +
 +
#include "../source/wartbed/Wartbed.h"
 +
#include <QuickGUI.h>
 +
 +
 +
#pragma comment(lib, "D:/( C++ )/QuickGUI_9_03/bin/QuickGUI_d.lib")
 +
 +
 +
QuickGUI::GUIManager    *g_pGUIManager  = 0;
 +
QuickGUI::Sheet        *g_pSheet      = 0;
 +
QuickGUI::Button        *g_pButton      = 0;
 +
 +
 +
struct FrameListener : wb::FrameListener
 +
{
 +
    bool frameStarted(const Ogre::FrameEvent& evt)
 +
    {
 +
        using namespace wb::ogre;
 +
 +
        if (pKeyboard->isKeyDown(OIS::KC_ESCAPE))
 +
        {
 +
            Stop();
 +
            return false;
 +
        }
 +
 +
        else
 +
            wb::FrameListener::frameStarted( evt );
 +
    }
 +
};
 +
 +
 +
struct KeyListener : wb::KeyListener
 +
{
 +
    bool keyPressed(const OIS::KeyEvent& e)
 +
    {
 +
        g_pGUIManager->injectChar( static_cast<Ogre::UTFString::unicode_char>(e.text) );
 +
        g_pGUIManager->injectKeyDown( static_cast<QuickGUI::KeyCode>(e.key) );
 +
        return true;
 +
    }
 +
 +
    bool keyReleased(const OIS::KeyEvent& e)
 +
    {
 +
        g_pGUIManager->injectKeyUp( static_cast<QuickGUI::KeyCode>(e.key) );
 +
        return true;
 +
    }
 +
};
 +
 +
 +
struct MouseListener : wb::MouseListener
 +
{
 +
    bool mouseMoved( OIS::MouseEvent const &e )
 +
    {
 +
        g_pGUIManager->injectMousePosition( e.state.X.abs, e.state.Y.abs );
 +
 +
        if(e.state.Z.rel != 0)
 +
            g_pGUIManager->injectMouseWheelChange( e.state.Z.rel );
 +
 +
        return true;
 +
    }
 +
 +
    bool mousePressed( OIS::MouseEvent const &e, OIS::MouseButtonID id)
 +
    {
 +
        g_pGUIManager->injectMouseButtonDown( static_cast<QuickGUI::MouseButtonID>(id) );
 +
        return true;
 +
    }
 +
 +
    bool mouseReleased( OIS::MouseEvent const &e, OIS::MouseButtonID id)
 +
    {
 +
        g_pGUIManager->injectMouseButtonUp( static_cast<QuickGUI::MouseButtonID>(id) );
 +
        return true;
 +
    }
 +
};
 +
 +
 +
struct GUIEventHandler
 +
{
 +
    GUIEventHandler()
 +
    {
 +
        g_pButton->addWidgetEventHandler
 +
            (
 +
                QuickGUI::WIDGET_EVENT_MOUSE_BUTTON_UP,
 +
                &GUIEventHandler::onClick,
 +
                this
 +
            );
 +
    }
 +
 +
    // Note that this must be declared virtual because QuickGUI required a
 +
    // polymorphic class or its dynamic_cast calls will throw
 +
    //
 +
    virtual ~GUIEventHandler() {}
 +
 +
    void onClick( QuickGUI::EventArgs const &args)
 +
    { 
 +
        QuickGUI::MouseEventArgs const &mea =
 +
            static_cast<const QuickGUI::MouseEventArgs &>( args );
 +
 +
        if (mea.button == QuickGUI::MB_Left)
 +
        {
 +
        MessageBeep( MB_OK );
 +
        }
 +
 +
        if (mea.button == QuickGUI::MB_Right)
 +
        {
 +
        MessageBeep( MB_ICONEXCLAMATION );
 +
        }
 +
    }
 +
};
 +
 +
 +
//=============================================================================
 +
// Main function...
 +
//
 +
//-----------------------------------------------------------------------------
 +
 +
    std::string app_name;
 +
    std::string app_path;
 +
 +
#if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32
 +
 +
    //---------------------------------------------------------------------
 +
    // Windows main signature
 +
    //---------------------------------------------------------------------
 +
 +
    #define WIN32_LEAN_AND_MEAN
 +
    #include "windows.h"
 +
 +
    INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
 +
    {
 +
        app_name.resize( _MAX_PATH );
 +
        GetModuleFileNameA( NULL, &app_name[0], _MAX_PATH );
 +
 +
        STARTUPINFO startupInfo;
 +
        GetStartupInfo( &startupInfo );
 +
 +
 +
#else
 +
 +
    //---------------------------------------------------------------------
 +
    // POSIX main signature
 +
    //---------------------------------------------------------------------
 +
 +
    int main(int argc, char **argv)
 +
    {
 +
        app_name = argv[0];
 +
 +
#endif
 +
 +
 +
//        utils::tokeniser<char> t( app_name, "//" );
 +
//        app_path = t.collate( 0, t.size()-3, "/" );
 +
 +
    //---------------------------------------------------------------------
 +
    // Common main body
 +
    //---------------------------------------------------------------------
 +
 +
        // The entire game is initialised, started and run in the FCom()
 +
        // function.
 +
        //
 +
        try
 +
        {
 +
            Wartbed::getInstance( "QuickGUI Test" ).setFrameListener( new FrameListener );
 +
            Wartbed::getInstance().setKeyListener( new KeyListener );
 +
            Wartbed::getInstance().setMouseListener( new MouseListener );
 +
 +
            // Must be done before OGRE's initialiseAllResourceGroups()
 +
            //
 +
            QuickGUI::registerScriptReader();
 +
 +
            // QuickGUI needs at least one font to start, or it will throw
 +
            // an exception. Also, we need to add a folder containing
 +
            // QuickGUI .skinTypes (etc) files.
 +
            //
 +
            Ogre::ResourceGroupManager::getSingleton().addResourceLocation( "./Fonts", "FileSystem" );
 +
            Ogre::ResourceGroupManager::getSingleton().addResourceLocation( "./QuickGUI", "FileSystem" );
 +
            Ogre::ResourceGroupManager::getSingleton().addResourceLocation( "./QuickGUI/qgui.textures.zip", "Zip" );
 +
 +
            // Instruct Ogre to go through all paths set by addResourceLocation
 +
            // and add any comptible resources.
 +
            //
 +
            Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
 +
 +
            // Apparently, QuickGUI must be dynamically created. The normal way
 +
            // of interaction is even through a "getSingletonPtr()" method...
 +
            //
 +
            utils::shared_ptr<QuickGUI::Root> pQGUIRoot( new QuickGUI::Root() );
 +
 +
            // These are the steps that must done to set up and prepare
 +
            // QuickGUI for use:
 +
            // * Load the types detected by Ogre's resource initialisation
 +
            // * Creating a GUI manager object
 +
            // * Creating a sheet
 +
            // * Setting the active sheet
 +
            //
 +
            QuickGUI::SkinTypeManager::getSingleton().loadTypes();
 +
            QuickGUI::GUIManagerDesc d;
 +
            d.sceneManager = wb::ogre::pSceneManager;
 +
            d.viewport = wb::ogre::pViewport;
 +
            //d.queueID = Ogre::RENDER_QUEUE_OVERLAY;
 +
            g_pGUIManager = pQGUIRoot->createGUIManager( d );
 +
            g_pSheet = QuickGUI::SheetManager::getSingleton().createSheet( QuickGUI::Size(800,600) );
 +
            g_pGUIManager->setActiveSheet( g_pSheet );
 +
 +
            // Creating widgets:
 +
            //
 +
//            QuickGUI::Sheet* defaultSheet = mGUIManager->getActiveSheet();
 +
//            QuickGUI::FactoryManager::getSingleton().getDescFactory();
 +
//            QuickGUI::FactoryManager::getSingleton().getWidgetFactory();
 +
//            QuickGUI::FactoryManager::getSingleton().getDescFactory()->getInstance("MyButtonDescObject");
 +
            QuickGUI::ButtonDesc* bd =
 +
                dynamic_cast<QuickGUI::ButtonDesc*>(
 +
                    QuickGUI::FactoryManager::getSingleton().
 +
                        getDescFactory()->
 +
                            getInstance<QuickGUI::ButtonDesc>("DefaultButtonDesc"));
 +
 +
            bd->widget_name = "MyButton";
 +
            bd->textDesc.segments.push_back( QuickGUI::TextSegment("micross.12",Ogre::ColourValue::Red,"Click Me!") );
 +
            bd->widget_dimensions.size = QuickGUI::Size(100,25);
 +
            bd->widget_dimensions.position = QuickGUI::Point(50,50);
 +
            g_pButton = g_pSheet->createButton(bd);
 +
 +
 +
            // Registering events with a widget. Since the event handlers
 +
            // use a pointer-to-member-function signature we need to wrap
 +
            // them in classes, which however could be useful...
 +
            //
 +
            GUIEventHandler handler;
 +
 +
   
 +
            Wartbed::getInstance().mainLoop();
 +
        }
 +
 +
 +
    //---------------------------------------------------------------------
 +
    // Last-ditch exception handling
 +
    //---------------------------------------------------------------------
 +
 +
        catch (Ogre::Exception &e)
 +
        {
 +
        #if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32
 +
            MessageBoxA( NULL, e.what(), "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL );
 +
        #else
 +
            stderr << "An exception has occurred: " << e.what() << std::endl;
 +
        #endif
 +
        }
 +
 +
 +
        catch (std::exception &e)
 +
        {
 +
        #if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32
 +
            MessageBoxA( NULL, e.what(), "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL );
 +
        #else
 +
            stderr << "An exception has occurred: " << e.what() << std::endl;
 +
        #endif
 +
        }
 +
 +
 +
        catch (...)
 +
        {
 +
        #if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32
 +
            MessageBoxA( NULL, "Unknows exception thrown!", "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL );
 +
        #else
 +
            stderr << "An exception has occurred: " << e.what() << std::endl;
 +
        #endif
 +
        }
 +
 +
 +
        return EXIT_SUCCESS;
 +
    }
 +
 +
//-----------------------------------------------------------------------------
 +
//
 +
// ...end main function
 +
//=============================================================================
 +
</pre>
===MyGUI===
===MyGUI===
Line 35: Line 569:
* BetaGUI
* BetaGUI
* Navi - uses the Gecko engine to render HTML and XML into OGRE. Very powerful (supports JavaScript and AJAX, but might be slow and very, very overkill. Also not necessarily easier to design game interfaces in HTML)
* Navi - uses the Gecko engine to render HTML and XML into OGRE. Very powerful (supports JavaScript and AJAX, but might be slow and very, very overkill. Also not necessarily easier to design game interfaces in HTML)
 +
 +
==Conclusions==
 +
CEGUI seems the most well-designed framework. In initial configuration and event bindings QuickGUI feels somewhat messier, and this can be suspected to permeate the entire framework. The function-identical CEGUI code is actually shorter than QuickGUI's (except that it only reacts to the left mouse button). CEGUI binds events to functions rather than methods, which is greatly to its advantage as if simplifies syntax without in practice losing flexibility. QuickGUI's widgets are all dragabble by default. If this is an advantage or not I haven't decided yet.

Revision as of 02:16, 11 March 2009

This page contains temporary information. It does not reflect current or future WARTBED state

Contents

Currently evaluated GUI frameworks

GUI systems are relatively complex beasts (which I know having designed a few!) and are good candidates for 3rd party libraries. Requirements are

  • Sufficiently feature-complete (no half-complete or starting frameworks)
  • Stable
  • Maintained
  • OGRE-integrated

Note that the screenshots below are not necessarily representative of the appearance of the frameworks since they all support skinning.

CEGUI

http://www.cegui.org.uk/wiki/index.php/Main_Page
4.jpg
CEGUI is the default GUI framework under OGRE. I had considerable problems getting it to work, though it was reasonably simple once everything was described (a situation of files all over the place without a meaningfuil structure in OGRE - would need some cleaning up). Also, the available support and guides are scarce. It is also rather clumsy to initialise, if perhaps not to work with.

  • It seems the most powerful GUI library by far.
  • It has bindings for Irrlicht and OpenSceneGraph so it might be considered a relatively inter-API-portable framework.
/************************************************************************/
/* EVALUATION OF CEGUI                                                  */
/*                                                                      */
/* > Includes are in OGRE_HOME/Samples, which must be added to paths(!) */
/*                                                                      */
/************************************************************************/

#include "../source/wartbed/Wartbed.h"

#include <CEGUI/CEGUI.h>
#include <CEGUI/CEGUIDefaultResourceProvider.h>
#include <OgreCEGUIRenderer.h>


CEGUI::System               *g_pSystem      = 0;
CEGUI::OgreCEGUIRenderer    *g_pRenderer    = 0;
CEGUI::WindowManager        *g_pWinMngr     = 0;
CEGUI::Window               *g_pSheet       = 0;
CEGUI::Window               *g_pButton      = 0;


struct FrameListener : wb::FrameListener
{
    bool frameStarted(const Ogre::FrameEvent& evt) 
    {
        using namespace wb::ogre;

        if (pKeyboard->isKeyDown(OIS::KC_ESCAPE)) 
        {
            Stop();
            return false; 
        }

        else
            wb::FrameListener::frameStarted( evt );
    }
};


struct KeyListener : wb::KeyListener
{
    bool keyPressed( OIS::KeyEvent const &e ) 
    { 
        g_pSystem->injectKeyDown( e.key );
        g_pSystem->injectChar( e.text );
        return true; 
    }

    bool keyReleased( OIS::KeyEvent const &e ) 
    { 
        g_pSystem->injectKeyUp( e.key );
        return true; 
    }
};


struct MouseListener : wb::MouseListener
{
    CEGUI::MouseButton convert( OIS::MouseButtonID buttonID )
    {
        switch (buttonID)
        {
            case OIS::MB_Left: return CEGUI::LeftButton;
            case OIS::MB_Right: return CEGUI::RightButton;
            case OIS::MB_Middle: return CEGUI::MiddleButton;
            default: return CEGUI::LeftButton;
        }
    }

    bool mouseMoved( OIS::MouseEvent const &e )
    {
        g_pSystem->injectMouseMove( e.state.X.rel, e.state.Y.rel );

        if(e.state.Z.rel != 0) 
            g_pSystem->injectMouseWheelChange( e.state.Z.rel );

        return true;
    }

    bool mousePressed( OIS::MouseEvent const &e, OIS::MouseButtonID id )
    {
        g_pSystem->injectMouseButtonDown( convert(id) );
        return true;
    }

    bool mouseReleased( OIS::MouseEvent const &e, OIS::MouseButtonID id )
    {
        g_pSystem->injectMouseButtonUp( convert(id) );
        return true;
    }
};


bool OnClick( CEGUI::EventArgs const &args ) 
{  
    MessageBeep( MB_OK ); 
    return true;
}



//=============================================================================
// Main function...
//
//-----------------------------------------------------------------------------

    std::string app_name;
    std::string app_path;

#if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32

    //---------------------------------------------------------------------
    // Windows main signature
    //---------------------------------------------------------------------

    #define WIN32_LEAN_AND_MEAN
    #include "windows.h"

    INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT ) 
    {
        app_name.resize( _MAX_PATH );
        GetModuleFileNameA( NULL, &app_name[0], _MAX_PATH );

        STARTUPINFO startupInfo;
        GetStartupInfo( &startupInfo );


#else

    //---------------------------------------------------------------------
    // POSIX main signature
    //---------------------------------------------------------------------

    int main(int argc, char **argv) 
    {
        app_name = argv[0];

#endif


        utils::tokeniser<char> t( app_name, "\\" );
        app_path = t.collate( 0, t.size()-3, "/" );

    //---------------------------------------------------------------------
    // Common main body
    //---------------------------------------------------------------------

        // The entire game is initialised, started and run in the FCom()
        // function. 
        //
        try 
        { 
            Wartbed::getInstance( "CEGUI Test" ).setFrameListener( new FrameListener );
            Wartbed::getInstance().setKeyListener( new KeyListener );
            Wartbed::getInstance().setMouseListener( new MouseListener );

            Ogre::ResourceGroupManager::getSingleton().addResourceLocation( "./Fonts", "FileSystem" );
            Ogre::ResourceGroupManager::getSingleton().addResourceLocation( "./CEGUI", "FileSystem" );

            // Instruct Ogre to go through all paths set by addResourceLocation 
            // and add any comptible resources.
            //
            Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();

            using namespace wb::ogre;

            g_pRenderer = new CEGUI::OgreCEGUIRenderer( pWindow, Ogre::RENDER_QUEUE_OVERLAY, false, 3000, pSceneManager );
            g_pSystem = new CEGUI::System( g_pRenderer );


            // initialise the required dirs for the DefaultResourceProvider
            CEGUI::DefaultResourceProvider *rp = 
                static_cast<CEGUI::DefaultResourceProvider *>
                    (CEGUI::System::getSingleton().getResourceProvider());


            // Load GUI styles
            //
            CEGUI::SchemeManager::getSingleton().loadScheme( (CEGUI::utf8 *) "TaharezLookSkin.scheme" );
            g_pSystem->setDefaultMouseCursor( (CEGUI::utf8*)"TaharezLook", (CEGUI::utf8 *) "MouseArrow" );
            g_pSystem->setDefaultFont( (CEGUI::utf8 *) "BlueHighway-12" );

            // Create a sheet to work on
            //
            g_pWinMngr  = CEGUI::WindowManager::getSingletonPtr();
            g_pSheet    = g_pWinMngr->createWindow( "DefaultGUISheet", "CEGUIDemo/Sheet" );
            g_pButton   = g_pWinMngr->createWindow( "TaharezLook/Button", "CEGUIDemo/QuitButton" );

            // Create and activate a clickable button
            //
            g_pButton->setText( "Click me" );
            g_pButton->setPosition( CEGUI::UVector2(CEGUI::UDim(0, 10), CEGUI::UDim(0, 5)) );
            g_pButton->setSize( CEGUI::UVector2(CEGUI::UDim(0.15, 0), CEGUI::UDim(0.05, 0)) );
            g_pSheet->addChildWindow( g_pButton );
            g_pSystem->setGUISheet( g_pSheet );

            g_pButton->subscribeEvent
                ( 
                    CEGUI::PushButton::EventClicked,
                    CEGUI::Event::Subscriber( &OnClick ) 
                );

            // Show the mouse using the default mouse cursor image
            //
            CEGUI::MouseCursor::getSingleton().setImage( g_pSystem->getDefaultMouseCursor() );


            Wartbed::getInstance().mainLoop(); 
        }


    //---------------------------------------------------------------------
    // Last-ditch exception handling
    //---------------------------------------------------------------------

        catch (Ogre::Exception &e)
        {
        #if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32
            MessageBoxA( NULL, e.what(), "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL );
        #else
            stderr << "An exception has occurred: " << e.what() << std::endl;
        #endif
        }


        catch (std::exception &e)
        {
        #if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32
            MessageBoxA( NULL, e.what(), "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL );
        #else
            stderr << "An exception has occurred: " << e.what() << std::endl;
        #endif
        }


        catch (...)
        {
        #if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32
            MessageBoxA( NULL, "Unknows exception thrown!", "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL );
        #else
            stderr << "An exception has occurred: " << e.what() << std::endl;
        #endif
        }


        return EXIT_SUCCESS;
    } 

//-----------------------------------------------------------------------------
//
// ...end main function
//=============================================================================

QuickGUI

http://www.ogre3d.org/wiki/index.php/QuickGUI
qgui_9_3.jpg
Made for OGRE, inspired by BetGUI and CEGUI. It seems reasonably complete and is the framework I've gotten furthest with so far.

/************************************************************************/
/* EVALUATION OF QuickGUI                                               */
/*                                                                      */
/*                                                                      */
/************************************************************************/

#include "../source/wartbed/Wartbed.h"
#include <QuickGUI.h>


#pragma comment(lib, "D:/( C++ )/QuickGUI_9_03/bin/QuickGUI_d.lib")


QuickGUI::GUIManager    *g_pGUIManager  = 0;
QuickGUI::Sheet         *g_pSheet       = 0;
QuickGUI::Button        *g_pButton      = 0;


struct FrameListener : wb::FrameListener
{
    bool frameStarted(const Ogre::FrameEvent& evt) 
    {
        using namespace wb::ogre;

        if (pKeyboard->isKeyDown(OIS::KC_ESCAPE)) 
        {
            Stop();
            return false; 
        }

        else
            wb::FrameListener::frameStarted( evt );
    }
};


struct KeyListener : wb::KeyListener
{
    bool keyPressed(const OIS::KeyEvent& e) 
    { 
        g_pGUIManager->injectChar( static_cast<Ogre::UTFString::unicode_char>(e.text) );
        g_pGUIManager->injectKeyDown( static_cast<QuickGUI::KeyCode>(e.key) );
        return true; 
    }

    bool keyReleased(const OIS::KeyEvent& e) 
    { 
        g_pGUIManager->injectKeyUp( static_cast<QuickGUI::KeyCode>(e.key) );
        return true; 
    }
};


struct MouseListener : wb::MouseListener
{
    bool mouseMoved( OIS::MouseEvent const &e )
    {
        g_pGUIManager->injectMousePosition( e.state.X.abs, e.state.Y.abs );

        if(e.state.Z.rel != 0) 
            g_pGUIManager->injectMouseWheelChange( e.state.Z.rel );

        return true;
    }

    bool mousePressed( OIS::MouseEvent const &e, OIS::MouseButtonID id)
    {
        g_pGUIManager->injectMouseButtonDown( static_cast<QuickGUI::MouseButtonID>(id) );
        return true;
    }

    bool mouseReleased( OIS::MouseEvent const &e, OIS::MouseButtonID id)
    {
        g_pGUIManager->injectMouseButtonUp( static_cast<QuickGUI::MouseButtonID>(id) );
        return true;
    }
};


struct GUIEventHandler
{
    GUIEventHandler()
    {
        g_pButton->addWidgetEventHandler
            ( 
                QuickGUI::WIDGET_EVENT_MOUSE_BUTTON_UP, 
                &GUIEventHandler::onClick, 
                this 
            );
    }

    // Note that this must be declared virtual because QuickGUI required a
    // polymorphic class or its dynamic_cast calls will throw
    //
    virtual ~GUIEventHandler() {}

    void onClick( QuickGUI::EventArgs const &args) 
    {  
        QuickGUI::MouseEventArgs const &mea = 
            static_cast<const QuickGUI::MouseEventArgs &>( args );

        if (mea.button == QuickGUI::MB_Left)
        {
	        MessageBeep( MB_OK ); 
        }

        if (mea.button == QuickGUI::MB_Right)
        {
	        MessageBeep( MB_ICONEXCLAMATION ); 
        }
    }
};


//=============================================================================
// Main function...
//
//-----------------------------------------------------------------------------

    std::string app_name;
    std::string app_path;

#if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32

    //---------------------------------------------------------------------
    // Windows main signature
    //---------------------------------------------------------------------

    #define WIN32_LEAN_AND_MEAN
    #include "windows.h"

    INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT ) 
    {
        app_name.resize( _MAX_PATH );
        GetModuleFileNameA( NULL, &app_name[0], _MAX_PATH );

        STARTUPINFO startupInfo;
        GetStartupInfo( &startupInfo );


#else

    //---------------------------------------------------------------------
    // POSIX main signature
    //---------------------------------------------------------------------

    int main(int argc, char **argv) 
    {
        app_name = argv[0];

#endif


//         utils::tokeniser<char> t( app_name, "//" );
//         app_path = t.collate( 0, t.size()-3, "/" );

    //---------------------------------------------------------------------
    // Common main body
    //---------------------------------------------------------------------

        // The entire game is initialised, started and run in the FCom()
        // function. 
        //
        try 
        { 
            Wartbed::getInstance( "QuickGUI Test" ).setFrameListener( new FrameListener );
            Wartbed::getInstance().setKeyListener( new KeyListener );
            Wartbed::getInstance().setMouseListener( new MouseListener );

            // Must be done before OGRE's initialiseAllResourceGroups()
            //
            QuickGUI::registerScriptReader();

            // QuickGUI needs at least one font to start, or it will throw 
            // an exception. Also, we need to add a folder containing 
            // QuickGUI .skinTypes (etc) files.
            //
            Ogre::ResourceGroupManager::getSingleton().addResourceLocation( "./Fonts", "FileSystem" );
            Ogre::ResourceGroupManager::getSingleton().addResourceLocation( "./QuickGUI", "FileSystem" );
            Ogre::ResourceGroupManager::getSingleton().addResourceLocation( "./QuickGUI/qgui.textures.zip", "Zip" );

            // Instruct Ogre to go through all paths set by addResourceLocation 
            // and add any comptible resources.
            //
            Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();

            // Apparently, QuickGUI must be dynamically created. The normal way
            // of interaction is even through a "getSingletonPtr()" method...
            //
            utils::shared_ptr<QuickGUI::Root> pQGUIRoot( new QuickGUI::Root() );

            // These are the steps that must done to set up and prepare
            // QuickGUI for use:
            // * Load the types detected by Ogre's resource initialisation
            // * Creating a GUI manager object
            // * Creating a sheet
            // * Setting the active sheet
            //
            QuickGUI::SkinTypeManager::getSingleton().loadTypes();
            QuickGUI::GUIManagerDesc d;
            d.sceneManager = wb::ogre::pSceneManager;
            d.viewport = wb::ogre::pViewport;
            //d.queueID = Ogre::RENDER_QUEUE_OVERLAY;
            g_pGUIManager = pQGUIRoot->createGUIManager( d );
            g_pSheet = QuickGUI::SheetManager::getSingleton().createSheet( QuickGUI::Size(800,600) );
            g_pGUIManager->setActiveSheet( g_pSheet );

            // Creating widgets:
            //
//             QuickGUI::Sheet* defaultSheet = mGUIManager->getActiveSheet();
//             QuickGUI::FactoryManager::getSingleton().getDescFactory();
//             QuickGUI::FactoryManager::getSingleton().getWidgetFactory();
//             QuickGUI::FactoryManager::getSingleton().getDescFactory()->getInstance("MyButtonDescObject");
            QuickGUI::ButtonDesc* bd = 
                dynamic_cast<QuickGUI::ButtonDesc*>(
                    QuickGUI::FactoryManager::getSingleton().
                        getDescFactory()->
                            getInstance<QuickGUI::ButtonDesc>("DefaultButtonDesc"));

            bd->widget_name = "MyButton";
            bd->textDesc.segments.push_back( QuickGUI::TextSegment("micross.12",Ogre::ColourValue::Red,"Click Me!") );
            bd->widget_dimensions.size = QuickGUI::Size(100,25);
            bd->widget_dimensions.position = QuickGUI::Point(50,50);
            g_pButton = g_pSheet->createButton(bd);


            // Registering events with a widget. Since the event handlers 
            // use a pointer-to-member-function signature we need to wrap
            // them in classes, which however could be useful...
            //
            GUIEventHandler handler;

    
            Wartbed::getInstance().mainLoop(); 
        }


    //---------------------------------------------------------------------
    // Last-ditch exception handling
    //---------------------------------------------------------------------

        catch (Ogre::Exception &e)
        {
        #if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32
            MessageBoxA( NULL, e.what(), "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL );
        #else
            stderr << "An exception has occurred: " << e.what() << std::endl;
        #endif
        }


        catch (std::exception &e)
        {
        #if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32
            MessageBoxA( NULL, e.what(), "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL );
        #else
            stderr << "An exception has occurred: " << e.what() << std::endl;
        #endif
        }


        catch (...)
        {
        #if OGRE_PLATFORM == PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_WIN32
            MessageBoxA( NULL, "Unknows exception thrown!", "An exception has occurred!", MB_OK | MB_ICONERROR | MB_TASKMODAL );
        #else
            stderr << "An exception has occurred: " << e.what() << std::endl;
        #endif
        }


        return EXIT_SUCCESS;
    } 

//-----------------------------------------------------------------------------
//
// ...end main function
//=============================================================================

MyGUI

http://www.ohloh.net/p/my-gui
1702687_1024x768.png
Last updated in June 2008. MyGUI is a sleek and sufficiently feature-complete framework that is well prepared for integration into OGRE. However, it myst be compiled from source (which is a one-time occurrence, though) and depends in turn on FreeType2, which also must be compiled. This meant initial only hassle, but since the current version seems to be written to a pre-Shoggoth OGRE version I've yet to get it to compile (some invalid signatures and a bunch of unresolved externals).

OpenGUI

http://opengui.rightbracket.com/
Screenshots
OpenGUI seems like a nice GUI library. However, it seems not to be updated anymore (last official optade was in 2007), which might mean severe integration issues with OGRE.

GUIs to be checked and perhaps evalutated

  • BetaGUI
  • Navi - uses the Gecko engine to render HTML and XML into OGRE. Very powerful (supports JavaScript and AJAX, but might be slow and very, very overkill. Also not necessarily easier to design game interfaces in HTML)

Conclusions

CEGUI seems the most well-designed framework. In initial configuration and event bindings QuickGUI feels somewhat messier, and this can be suspected to permeate the entire framework. The function-identical CEGUI code is actually shorter than QuickGUI's (except that it only reacts to the left mouse button). CEGUI binds events to functions rather than methods, which is greatly to its advantage as if simplifies syntax without in practice losing flexibility. QuickGUI's widgets are all dragabble by default. If this is an advantage or not I haven't decided yet.

Personal tools
communication