Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/kicklib/src/libraries/core/GUIManager.cc @ 7960

Last change on this file since 7960 was 7960, checked in by rgrieder, 14 years ago

Applied C++ code changes to compile Orxonox with CEGUI 0.7 (does not run yet).

  • Property svn:eol-style set to native
File size: 19.7 KB
RevLine 
[1638]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Reto Grieder
[2896]24 *      Benjamin Knecht
[1638]25 *   Co-authors:
[3196]26 *      ...
[1638]27 *
28 */
29
30#include "GUIManager.h"
31
[7941]32#include <memory>
[6746]33#include <boost/bind.hpp>
[7960]34#include <OgreRenderQueue.h>
35#include <OgreRenderWindow.h>
[7939]36
[2710]37#include <CEGUIDefaultLogger.h>
[3196]38#include <CEGUIExceptions.h>
39#include <CEGUIInputEvent.h>
[5695]40#include <CEGUIMouseCursor.h>
[3196]41#include <CEGUIResourceProvider.h>
42#include <CEGUISystem.h>
[6417]43#include <CEGUIWindow.h>
[6746]44#include <CEGUIWindowManager.h>
[7648]45#include <elements/CEGUIListbox.h>
46#include <elements/CEGUIListboxItem.h>
[7941]47
[7960]48#if CEGUI_VERSION_MAJOR < 1 && CEGUI_VERSION_MINOR < 7
49#  include <CEGUILua.h>
50#  include <ogreceguirenderer/OgreCEGUIRenderer.h>
51#else
52#  include <ScriptingModules/LuaScriptModule/CEGUILua.h>
53#  include <RendererModules/Ogre/CEGUIOgreImageCodec.h>
54#  include <RendererModules/Ogre/CEGUIOgreRenderer.h>
55#  include <RendererModules/Ogre/CEGUIOgreResourceProvider.h>
56#endif
[3196]57
[5929]58#include "util/Clock.h"
[6417]59#include "util/Convert.h"
[3280]60#include "util/Debug.h"
[1764]61#include "util/Exception.h"
[3280]62#include "util/OrxAssert.h"
[7801]63#include "ConfigValueIncludes.h"
[6417]64#include "Core.h"
[7801]65#include "CoreIncludes.h"
[7876]66#include "Game.h"
[6746]67#include "GraphicsManager.h"
[5695]68#include "LuaState.h"
[5929]69#include "PathConfig.h"
[5695]70#include "Resource.h"
[7284]71#include "command/ConsoleCommand.h"
[6746]72#include "input/InputManager.h"
73#include "input/InputState.h"
74#include "input/KeyBinderManager.h"
[1638]75
76namespace orxonox
77{
[6417]78    static void key_esc()
79        { GUIManager::getInstance().keyESC(); }
[7284]80    SetConsoleCommand("keyESC", &key_esc);
[6417]81
[3280]82    class CEGUILogger : public CEGUI::DefaultLogger
83    {
84    public:
[5929]85        void logEvent(const CEGUI::String& message, CEGUI::LoggingLevel level = CEGUI::Standard)
[3280]86        {
[3327]87            int orxonoxLevel = CEGUI::Standard;
[3280]88            switch (level)
89            {
90                case CEGUI::Errors:      orxonoxLevel = 1; break;
91                case CEGUI::Warnings:    orxonoxLevel = 2; break;
92                case CEGUI::Standard:    orxonoxLevel = 4; break;
93                case CEGUI::Informative: orxonoxLevel = 5; break;
94                case CEGUI::Insane:      orxonoxLevel = 6; break;
95                default: OrxAssert(false, "CEGUI log level out of range, inpect immediately!");
96            }
[6105]97            OutputHandler::getOutStream(orxonoxLevel)
[3280]98                << "CEGUI: " << message << std::endl;
99
100            CEGUI::DefaultLogger::logEvent(message, level);
101        }
102    };
103
[3196]104    static CEGUI::MouseButton convertButton(MouseButtonCode::ByEnum button);
[3339]105
[3366]106    GUIManager* GUIManager::singletonPtr_s = 0;
[7801]107    /*static*/ const std::string GUIManager::defaultScheme_ = "TaharezGreen";
[1646]108
[7403]109    SetConsoleCommand("showGUI", &GUIManager::showGUI).defaultValue(1, false).defaultValue(2, false);
[7284]110    SetConsoleCommand("hideGUI", &GUIManager::hideGUI);
[6417]111
[2896]112    /**
113    @brief
[3338]114        Constructs the GUIManager by starting up CEGUI
[2896]115
116        Creates the interface to Ogre, sets up the CEGUI renderer and the Lua script module together with the Lua engine.
117        The log is set up and connected to the CEGUILogger.
118        After Lua setup tolua++-elements are linked to Lua-state to give Lua access to C++-code.
119        Finally initial Lua code is executed (maybe we can do this with the CEGUI startup script automatically).
[3338]120    @return true if success, otherwise false
[2896]121    */
[6746]122    GUIManager::GUIManager(const std::pair<int, int>& mousePosition)
[7957]123        : destroyer_(*this, &GUIManager::cleanup)
124        , guiRenderer_(NULL)
125        , luaState_(NULL)
126        , scriptModule_(NULL)
127        , guiSystem_(NULL)
128        , resourceProvider_(NULL)
[7960]129#if CEGUI_VERSION_MAJOR >= 1 || CEGUI_VERSION_MINOR >= 7
130        , imageCodec_(NULL)
131#endif
[5929]132        , camera_(NULL)
[1638]133    {
[7801]134        RegisterRootObject(GUIManager);
135        this->setConfigValues();
136
[1638]137        using namespace CEGUI;
138
[3338]139        COUT(3) << "Initialising CEGUI." << std::endl;
[1638]140
[5695]141        // Note: No SceneManager specified yet
[7960]142#if CEGUI_VERSION_MAJOR < 1 && CEGUI_VERSION_MINOR < 7
[7957]143        guiRenderer_ = new OgreCEGUIRenderer(GraphicsManager::getInstance().getRenderWindow(), Ogre::RENDER_QUEUE_OVERLAY, false, 3000);
[5695]144        resourceProvider_ = guiRenderer_->createResourceProvider();
[7960]145#else
146        guiRenderer_ = &OgreRenderer::create(*GraphicsManager::getInstance().getRenderWindow());
147        resourceProvider_ = &OgreRenderer::createOgreResourceProvider();
148        imageCodec_ = &OgreRenderer::createOgreImageCodec();
149#endif
[7709]150        resourceProvider_->setDefaultResourceGroup("General");
[1776]151
[6749]152        // Setup scripting
[7957]153        luaState_ = new LuaState();
[6417]154        rootFileInfo_ = Resource::getInfo("InitialiseGUI.lua");
155        // This is necessary to ensure that input events also use the right resource info when triggering lua functions
156        luaState_->setDefaultResourceInfo(this->rootFileInfo_);
[7960]157#if CEGUI_VERSION_MAJOR < 1 && CEGUI_VERSION_MINOR < 7
[7957]158        scriptModule_ = new LuaScriptModule(luaState_->getInternalLuaState());
[7960]159#else
160        scriptModule_ = &LuaScriptModule::create(luaState_->getInternalLuaState());
161#endif
[6763]162        scriptModule_->setDefaultPCallErrorHandler(LuaState::ERROR_HANDLER_NAME);
[1638]163
[5695]164        // Create our own logger to specify the filepath
165        std::auto_ptr<CEGUILogger> ceguiLogger(new CEGUILogger());
[5929]166        ceguiLogger->setLogFilename(PathConfig::getLogPathString() + "cegui.log");
[7957]167        // Set the log level according to ours (translate by subtracting 1)
[5695]168        ceguiLogger->setLoggingLevel(
[6105]169            static_cast<LoggingLevel>(OutputHandler::getInstance().getSoftDebugLevel("logFile") - 1));
[5695]170        this->ceguiLogger_ = ceguiLogger.release();
[2710]171
[6749]172        // Create the CEGUI system singleton
[7960]173#if CEGUI_VERSION_MAJOR < 1 && CEGUI_VERSION_MINOR < 7
[7957]174        guiSystem_ = new System(guiRenderer_, resourceProvider_, 0, scriptModule_);
[7960]175#else
176        guiSystem_ = &System::create(*guiRenderer_, resourceProvider_, 0, imageCodec_, scriptModule_);
177#endif
[1776]178
[5695]179        // Align CEGUI mouse with OIS mouse
[6502]180        guiSystem_->injectMousePosition((float)mousePosition.first, (float)mousePosition.second);
[5695]181
[6746]182        // Initialise the Lua framework and load the schemes
183        this->luaState_->doFile("InitialiseGUI.lua");
184
185        // Create the root nodes
186        this->rootWindow_ = CEGUI::WindowManager::getSingleton().createWindow("MenuWidgets/StaticImage", "AbsoluteRootWindow");
187        this->rootWindow_->setProperty("FrameEnabled", "False");
188        this->hudRootWindow_ = CEGUI::WindowManager::getSingleton().createWindow("DefaultWindow", "HUDRootWindow");
189        this->menuRootWindow_ = CEGUI::WindowManager::getSingleton().createWindow("DefaultWindow", "MenuRootWindow");
190        // And connect them
191        CEGUI::System::getSingleton().setGUISheet(this->rootWindow_);
192        this->rootWindow_->addChildWindow(this->hudRootWindow_);
193        this->rootWindow_->addChildWindow(this->menuRootWindow_);
194
[6749]195        // No background to start with (sets the alpha value to 0)
196        this->setBackgroundImage("");
197
[6746]198        // Set up the sheet manager in the Lua framework
199        this->luaState_->doFile("SheetManager.lua");
[3338]200    }
[1776]201
[7957]202    void GUIManager::cleanup()
[3338]203    {
[7957]204        using namespace CEGUI;
205
[7960]206#if CEGUI_VERSION_MAJOR < 1 && CEGUI_VERSION_MINOR < 7
[7957]207        delete guiSystem_;
208        delete guiRenderer_;
209        delete scriptModule_;
[7960]210#else
211        System::destroy();
212        OgreRenderer::destroyOgreResourceProvider(*resourceProvider_);
213        OgreRenderer::destroyOgreImageCodec(*imageCodec_);
214        OgreRenderer::destroy(*guiRenderer_);
215        LuaScriptModule::destroy(*scriptModule_);
216#endif
[7957]217        delete luaState_;
[1638]218    }
219
[7801]220    void GUIManager::setConfigValues(void)
221    {
222        SetConfigValue(guiScheme_, GUIManager::defaultScheme_) .description("Changes the current GUI scheme.") .callback(this, &GUIManager::changedGUIScheme);
223    }
224
225    void GUIManager::changedGUIScheme(void)
226    {
[7873]227
[7801]228    }
229
[2896]230    /**
231    @brief
232        used to tick the GUI
233    @param time
234        clock which provides time value for the GUI System
235
236        Ticking the GUI means updating it with a certain regularity.
237        The elapsed time since the last call is given in the time value provided by the clock.
238        This time value is then used to provide a fluent animation of the GUI.
239    */
[6417]240    void GUIManager::preUpdate(const Clock& time)
[1638]241    {
[2896]242        assert(guiSystem_);
[6746]243        this->protectedCall(boost::bind(&CEGUI::System::injectTimePulse, _1, time.getDeltaTime()));
[2896]244    }
[1638]245
[2896]246    /**
247    @brief
248        Tells the GUIManager which SceneManager to use
249    @param camera
250        The current camera on which the GUI should be displayed on.
251
252        In fact the GUIManager needs the SceneManager and not the Camera to display the GUI.
253        This means the GUI is not bound to a camera but rather to the SceneManager.
[3337]254        Hiding the GUI when needed can therefore not be resolved by just NOT setting the current camera.
[2896]255    */
256    void GUIManager::setCamera(Ogre::Camera* camera)
[1638]257    {
[5929]258        this->camera_ = camera;
[7960]259#if CEGUI_VERSION_MAJOR < 1 && CEGUI_VERSION_MINOR < 7
[2927]260        if (camera == NULL)
261            this->guiRenderer_->setTargetSceneManager(0);
262        else
263            this->guiRenderer_->setTargetSceneManager(camera->getSceneManager());
[7960]264#endif
[2896]265    }
266
267    /**
268    @brief
[3338]269        Executes Lua code
270    @param str
271        reference to string object holding the Lua code which is to be executed
272    */
273    void GUIManager::executeCode(const std::string& str)
274    {
[5695]275        this->luaState_->doString(str, rootFileInfo_);
[3338]276    }
277
[6746]278    /** Loads a GUI sheet by Lua script
279    @param name
280        The name of the GUI (like the script name, but without the extension)
281    */
282    void GUIManager::loadGUI(const std::string& name)
283    {
284        this->executeCode("loadSheet(\"" + name + "\")");
285    }
286
[3338]287    /**
288    @brief
[2896]289        Displays specified GUI on screen
290    @param name
291        The name of the GUI
[7401]292    @param bHidePrevious
293        If true all displayed GUIs on the stack, that are below this GUI are hidden.
[7403]294    @param bNoInput
295        If true the GUI is transparent to input.
[2896]296
297        The function executes the Lua function with the same name in case the GUIManager is ready.
298    */
[7403]299    /*static*/ void GUIManager::showGUI(const std::string& name, bool bHidePrevious, bool bNoInput)
[2896]300    {
[7403]301        GUIManager::getInstance().executeCode("showMenuSheet(\"" + name + "\", " + multi_cast<std::string>(bHidePrevious) + ", " + multi_cast<std::string>(bNoInput) + ")");
[1638]302    }
303
[6417]304    /**
305    @brief
306        Hack-ish. Needed for GUIOverlay.
307    */
[7403]308    void GUIManager::showGUIExtra(const std::string& name, const std::string& ptr, bool bHidePrevious, bool bNoInput)
[6417]309    {
[7403]310        this->executeCode("showMenuSheet(\"" + name + "\", " + multi_cast<std::string>(bHidePrevious) + ", " + multi_cast<std::string>(bNoInput) + ", " + ptr + ")");
[6417]311    }
312
313    /**
314    @brief
315        Hides specified GUI.
316    @param name
317        The name of the GUI.
318    */
319    /*static*/ void GUIManager::hideGUI(const std::string& name)
320    {
[6746]321        GUIManager::getInstance().executeCode("hideMenuSheet(\"" + name + "\")");
[6417]322    }
323
[6746]324    const std::string& GUIManager::createInputState(const std::string& name, TriBool::Value showCursor, TriBool::Value useKeyboard, bool bBlockJoyStick)
325    {
326        InputState* state = InputManager::getInstance().createInputState(name);
[7811]327        if (!state)
328            return BLANKSTRING;
[6746]329
330        /* Table that maps isFullScreen() and showCursor to mouseExclusive
331        isFullscreen / showCursor | True  | False | Dontcare
332        ----------------------------------------------------
333        true                      | True  | True  | Dontcare
334        ----------------------------------------------------
335        false                     | False | True  | Dontcare
336        */
337        if (showCursor == TriBool::Dontcare)
338            state->setMouseExclusive(TriBool::Dontcare);
339        else if (GraphicsManager::getInstance().isFullScreen() || showCursor == TriBool::False)
340            state->setMouseExclusive(TriBool::True);
341        else
342            state->setMouseExclusive(TriBool::False);
343
344        if (showCursor == TriBool::True)
345            state->setMouseHandler(this);
346        else if (showCursor == TriBool::False)
347            state->setMouseHandler(&InputHandler::EMPTY);
348
349        if (useKeyboard == TriBool::True)
350            state->setKeyHandler(this);
351        else if (useKeyboard == TriBool::False)
352            state->setKeyHandler(&InputHandler::EMPTY);
353
354        if (bBlockJoyStick)
355            state->setJoyStickHandler(&InputHandler::EMPTY);
356
357        return state->getName();
358    }
359
[6417]360    void GUIManager::keyESC()
361    {
362        this->executeCode("keyESC()");
363    }
364
[6746]365    void GUIManager::setBackgroundImage(const std::string& imageSet, const std::string imageName)
[6417]366    {
[6746]367        if (imageSet.empty() || imageName.empty())
368            this->setBackgroundImage("");
369        else
370            this->setBackgroundImage("set: " + imageSet + " image: " + imageName);
[6417]371    }
372
[6746]373    void GUIManager::setBackgroundImage(const std::string& image)
374    {
375        if (image.empty())
376            this->rootWindow_->setProperty("Alpha", "0.0");
377        else
378            this->rootWindow_->setProperty("Alpha", "1.0");
379        this->rootWindow_->setProperty("Image", image);
380    }
381
[7163]382    void GUIManager::buttonPressed(const KeyEvent& evt)
[3196]383    {
[6746]384        this->protectedCall(boost::bind(&CEGUI::System::injectKeyDown, _1, evt.getKeyCode()));
385        this->protectedCall(boost::bind(&CEGUI::System::injectChar, _1, evt.getText()));
[3196]386    }
[6746]387
[7163]388    void GUIManager::buttonReleased(const KeyEvent& evt)
[3196]389    {
[6746]390        this->protectedCall(boost::bind(&CEGUI::System::injectKeyUp, _1, evt.getKeyCode()));
[3196]391    }
392
[2896]393    /**
394    @brief
395        Function receiving a mouse button pressed event.
396    @param id
397        ID of the mouse button which got pressed
[1638]398
[2896]399        This function is inherited by MouseHandler and injects the event into CEGUI.
400        It is for CEGUI to process the event.
401    */
[3327]402    void GUIManager::buttonPressed(MouseButtonCode::ByEnum id)
[1638]403    {
[6746]404        this->protectedCall(boost::bind(&CEGUI::System::injectMouseButtonDown, _1, convertButton(id)));
[1638]405    }
406
[2896]407    /**
408    @brief
409        Function receiving a mouse button released event.
410    @param id
411        ID of the mouse button which got released
412
413        This function is inherited by MouseHandler and injects the event into CEGUI.
414        It is for CEGUI to process the event.
415    */
[3327]416    void GUIManager::buttonReleased(MouseButtonCode::ByEnum id)
[1638]417    {
[6746]418        this->protectedCall(boost::bind(&CEGUI::System::injectMouseButtonUp, _1, convertButton(id)));
[1638]419    }
420
[3196]421    void GUIManager::mouseMoved(IntVector2 abs, IntVector2 rel, IntVector2 clippingSize)
422    {
[6746]423        this->protectedCall(boost::bind(&CEGUI::System::injectMousePosition, _1, (float)abs.x, (float)abs.y));
[3196]424    }
[6746]425
[3196]426    void GUIManager::mouseScrolled(int abs, int rel)
427    {
[6746]428        this->protectedCall(boost::bind(&CEGUI::System::injectMouseWheelChange, _1, (float)rel));
[3196]429    }
430
[2896]431    /**
[7874]432        @brief Indicates that the mouse left the application's window.
433    */
434    void GUIManager::mouseLeft()
435    {
436        this->protectedCall(boost::bind(&CEGUI::System::injectMouseLeaves, _1));
437    }
438
439    /**
[2896]440    @brief
441        converts mouse event code to CEGUI event code
442    @param button
443        code of the mouse button as we use it in Orxonox
444    @return
445        code of the mouse button as it is used by CEGUI
[1638]446
[6105]447        Simple conversion from mouse event code in Orxonox to the one used in CEGUI.
[2896]448     */
[3196]449    static inline CEGUI::MouseButton convertButton(MouseButtonCode::ByEnum button)
[1638]450    {
451        switch (button)
452        {
[1887]453        case MouseButtonCode::Left:
[1638]454            return CEGUI::LeftButton;
455
[1887]456        case MouseButtonCode::Right:
[1638]457            return CEGUI::RightButton;
458
[1887]459        case MouseButtonCode::Middle:
[1638]460            return CEGUI::MiddleButton;
461
[1887]462        case MouseButtonCode::Button3:
[1638]463            return CEGUI::X1Button;
464
[1887]465        case MouseButtonCode::Button4:
[1638]466            return CEGUI::X2Button;
467
468        default:
469            return CEGUI::NoButton;
470        }
471    }
[6417]472
[6746]473    /** Executes a CEGUI function normally, but catches CEGUI::ScriptException.
474        When a ScriptException occurs, the error message will be displayed and
475        the program carries on.
476    @remarks
477        The exception behaviour may pose problems if the code is not written
478        exception-safe (and you can forget about that in Lua). The program might
479        be left in an undefined state. But otherwise one script error would
480        terminate the whole program...
481    @note
482        Your life gets easier if you use boost::bind to create the object/function.
483    @param function
484        Any callable object/function that takes this->guiSystem_ as its only parameter.
485    @return
486        True if input was handled, false otherwise. A caught exception yields true.
487    */
488    template <typename FunctionType>
489    bool GUIManager::protectedCall(FunctionType function)
490    {
491        try
492        {
493            return function(this->guiSystem_);
494        }
495        catch (CEGUI::ScriptException& ex)
496        {
497            // Display the error and proceed. See @remarks why this can be dangerous.
498            COUT(1) << ex.getMessage() << std::endl;
499            return true;
500        }
501    }
502
[7648]503    /**
504    @brief
505        Subscribe the input function to the input event for the input window.
506        This is a helper to be used in lua, because subscribeScriptedEvent() doesn't work in lua.
507    @param window
508        The window for which the event is subscribed.
509    @param event
510        The type of event to which we subscribe.
511    @param function
512        The function that is called when the event occurs.
513    */
[6417]514    void GUIManager::subscribeEventHelper(CEGUI::Window* window, const std::string& event, const std::string& function)
515    {
516        window->subscribeScriptedEvent(event, function);
517    }
[7648]518
519    /**
520    @brief
521        Set the input tooltip text for the input ListboxItem.
522    @param item
523        The ListboxItem for which the tooltip should be set.
524    @param tooltip
525        The tooltip text that should be set.
526    */
527    void GUIManager::setTooltipTextHelper(CEGUI::ListboxItem* item, const std::string& tooltip)
528    {
529        item->setTooltipText(tooltip);
530    }
531
532    /**
533    @brief
534        Set whether the tooltips for the input Listbox are enabled.
535    @param listbox
536        The Listbox for which to enable (or disable) tooltips.
537    @param enabled
538        Whether to enable or disabel the tooltips.
539    */
540    void GUIManager::setItemTooltipsEnabledHelper(CEGUI::Listbox* listbox, bool enabled)
541    {
542        listbox->setItemTooltipsEnabled(enabled);
543    }
544
[7873]545    /**
546        @brief Callback of window event listener, called if the window is resized. Sets the display size of CEGUI.
547    */
548    void GUIManager::windowResized(unsigned int newWidth, unsigned int newHeight)
549    {
[7960]550#if CEGUI_VERSION_MAJOR < 1 && CEGUI_VERSION_MINOR < 7
[7873]551        this->guiRenderer_->setDisplaySize(CEGUI::Size(newWidth, newHeight));
[7960]552#else
553        this->guiRenderer_->setDisplaySize(CEGUI::Size((float)newWidth, (float)newHeight));
554#endif
[7873]555    }
[7874]556
557    /**
558        @brief Notify CEGUI if the windows loses the focus (stops higlight of menu items, etc).
559    */
560    void GUIManager::windowFocusChanged(bool bFocus)
561    {
562        if (!bFocus)
563            this->mouseLeft();
564    }
[7876]565
[1638]566}
Note: See TracBrowser for help on using the repository browser.