Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentation/src/libraries/core/GUIManager.cc @ 8740

Last change on this file since 8740 was 8704, checked in by dafrick, 14 years ago

Only escape [] in CEGUI tetx of version is ≥ 0.7

  • Property svn:eol-style set to native
File size: 27.7 KB
Line 
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
24 *      Benjamin Knecht
25 *   Co-authors:
26 *      ...
27 *
28 */
29
30#include "GUIManager.h"
31
32#include <fstream>
33#include <memory>
34#include <boost/bind.hpp>
35#include <OgreRenderQueue.h>
36#include <OgreRenderWindow.h>
37
38#include <CEGUIDefaultLogger.h>
39#include <CEGUIExceptions.h>
40#include <CEGUIFontManager.h>
41#include <CEGUIInputEvent.h>
42#include <CEGUIMouseCursor.h>
43#include <CEGUIResourceProvider.h>
44#include <CEGUISystem.h>
45#include <CEGUIWindow.h>
46#include <CEGUIWindowManager.h>
47#include <CEGUIXMLAttributes.h>
48#include <elements/CEGUIListbox.h>
49#include <elements/CEGUIListboxItem.h>
50
51#ifdef ORXONOX_OLD_CEGUI
52#  include <CEGUILua.h>
53#  include <ogreceguirenderer/OgreCEGUIRenderer.h>
54extern "C" {
55#  include <lauxlib.h>
56}
57#else
58#  include <ScriptingModules/LuaScriptModule/CEGUILua.h>
59#  include <RendererModules/Ogre/CEGUIOgreImageCodec.h>
60#  include <RendererModules/Ogre/CEGUIOgreRenderer.h>
61#  include <RendererModules/Ogre/CEGUIOgreResourceProvider.h>
62#  include <OgreCamera.h>
63#  include <OgreRenderQueueListener.h>
64#  include <OgreRenderSystem.h>
65#  include <OgreRoot.h>
66#  include <OgreSceneManager.h>
67#endif
68
69#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(ORXONOX_COMPILER_MINGW)
70#  include <windows.h>
71#endif
72
73#include "util/Clock.h"
74#include "util/Convert.h"
75#include "util/Debug.h"
76#include "util/Exception.h"
77#include "util/Math.h"
78#include "util/OrxAssert.h"
79#include "ConfigValueIncludes.h"
80#include "Core.h"
81#include "CoreIncludes.h"
82#include "Game.h"
83#include "GraphicsManager.h"
84#include "LuaState.h"
85#include "PathConfig.h"
86#include "Resource.h"
87#include "command/ConsoleCommand.h"
88#include "input/InputManager.h"
89#include "input/InputState.h"
90#include "input/KeyBinderManager.h"
91
92namespace orxonox
93{
94    static void key_esc()
95        { GUIManager::getInstance().keyESC(); }
96    SetConsoleCommand("keyESC", &key_esc);
97
98    class CEGUILogger : public CEGUI::DefaultLogger
99    {
100    public:
101        void logEvent(const CEGUI::String& message, CEGUI::LoggingLevel level = CEGUI::Standard)
102        {
103            int orxonoxLevel = CEGUI::Standard;
104            switch (level)
105            {
106                case CEGUI::Errors:      orxonoxLevel = 1; break;
107                case CEGUI::Warnings:    orxonoxLevel = 2; break;
108                case CEGUI::Standard:    orxonoxLevel = 4; break;
109                case CEGUI::Informative: orxonoxLevel = 5; break;
110                case CEGUI::Insane:      orxonoxLevel = 6; break;
111                default: OrxAssert(false, "CEGUI log level out of range, inspect immediately!");
112            }
113            OutputHandler::getOutStream(orxonoxLevel)
114                << "CEGUI: " << message << std::endl;
115
116            CEGUI::DefaultLogger::logEvent(message, level);
117        }
118
119        /// Carbon copy from CEGUIDefaultLogger.cpp with a bugfix for Windows
120        void setLogFilename(const CEGUI::String& filename, bool append = false)
121        {
122            // Close current log file (if any)
123            if (d_ostream.is_open())
124                d_ostream.close();
125
126#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(ORXONOX_COMPILER_MINGW)
127            // filename.c_str() is UTF-8 encoded, but Windows expects characters
128            // according to the current codepage or UTF-16 (wchar)
129            d_ostream.open(utf8ToUtf16(filename.c_str()).c_str(), std::ios_base::out | (append ? std::ios_base::app : std::ios_base::trunc));
130#else
131            d_ostream.open(filename.c_str(), std::ios_base::out | (append ? std::ios_base::app : std::ios_base::trunc));
132#endif
133            if (!d_ostream)
134                ThrowException(General, "Setting the CEGUI log filename failed");
135
136            // Initialise width for date & time alignment.
137            d_ostream.width(2);
138
139            // Write out cached log strings.
140            if (d_caching)
141            {
142                d_caching = false;
143
144                std::vector<std::pair<CEGUI::String, CEGUI::LoggingLevel> >::iterator it = d_cache.begin();
145
146                while (it != d_cache.end())
147                {
148                    if (d_level >= it->second)
149                    {
150                        d_ostream << it->first;
151                        // Ensure new event is written to the file, rather than just being buffered.
152                        d_ostream.flush();
153                    }
154                    ++it;
155                }
156
157                d_cache.clear();
158            }
159        }
160
161#if defined(ORXONOX_PLATFORM_WINDOWS) && !defined(ORXONOX_COMPILER_MINGW)
162        /// Converts a UTF-8 character sequence to Windows UTF-16
163        static std::wstring utf8ToUtf16(const std::string& utf8text)
164        {
165            const int textLen = MultiByteToWideChar(CP_UTF8, 0, utf8text.c_str(),
166                utf8text.size() + 1, 0, 0);
167
168            if (textLen == 0)
169                ThrowException(General, "Utf8ToUtf16 - MultiByteToWideChar failed");
170
171            std::wstring wideStr(textLen, 0);
172            MultiByteToWideChar(CP_UTF8, 0, utf8text.c_str(), utf8text.size() + 1,
173                &wideStr[0], wideStr.size());
174            return wideStr;
175        }
176#endif
177    };
178
179#ifdef ORXONOX_OLD_CEGUI
180    /** Class with the same memory layout as CEGUI::LuaScriptModule. <br>
181        We need this to fix a problem with an uninitialised member variable
182        in CEGUI < 0.7 <br>
183        Notice the "public" modifier for the otherwise private variables.
184    */
185    class LuaScriptModuleWorkaround : public CEGUI::ScriptModule
186    {
187    public:
188        LuaScriptModuleWorkaround();
189        ~LuaScriptModuleWorkaround();
190
191    public:
192        bool d_ownsState;
193        lua_State* d_state;
194        CEGUI::String d_errFuncName;
195        int d_errFuncIndex;
196        CEGUI::String d_activeErrFuncName;
197        int d_activeErrFuncIndex;
198    };
199#else
200    /// RenderQueueListener based class used to hook into the ogre rendering system
201    class RQListener : public Ogre::RenderQueueListener
202    {
203    public:
204        /// Callback from Ogre invoked before other stuff in our target queue is rendered
205        void renderQueueStarted(Ogre::uint8 id, const Ogre::String& invocation, bool& skipThisQueue)
206        {
207            if (id == Ogre::RENDER_QUEUE_OVERLAY && invocation.empty())
208            {
209                CEGUI::System::getSingleton().renderGUI();
210
211                // Important workaround! (at least required by CEGUI 0.7.5)
212                // If we don't reset the scissor test, OGRE will only render overlays
213                // in the area where CEGUI last drew, which is usually nothing
214                // or a little box where the focused element is.
215                Ogre::Root::getSingleton().getRenderSystem()->setScissorTest(false);
216            }
217        }
218    };
219#endif
220
221    static CEGUI::MouseButton convertButton(MouseButtonCode::ByEnum button);
222
223    GUIManager* GUIManager::singletonPtr_s = 0;
224    /*static*/ const std::string GUIManager::defaultScheme_ = "TaharezGreen";
225
226    SetConsoleCommand("showGUI", &GUIManager::showGUI).defaultValue(1, false).defaultValue(2, false);
227    SetConsoleCommand("hideGUI", &GUIManager::hideGUI);
228    SetConsoleCommand("toggleGUI", &GUIManager::toggleGUI).defaultValue(1, false).defaultValue(2, false);
229
230    /**
231    @brief
232        Constructs the GUIManager by starting up CEGUI
233
234        Creates the interface to Ogre, sets up the CEGUI renderer and the Lua script module together with the Lua engine.
235        The log is set up and connected to the CEGUILogger.
236        After Lua setup tolua++-elements are linked to Lua-state to give Lua access to C++-code.
237        Finally initial Lua code is executed (maybe we can do this with the CEGUI startup script automatically).
238    @return true if success, otherwise false
239    */
240    GUIManager::GUIManager(const std::pair<int, int>& mousePosition)
241        : guiRenderer_(NULL)
242        , resourceProvider_(NULL)
243#ifndef ORXONOX_OLD_CEGUI
244        , rqListener_(NULL)
245        , imageCodec_(NULL)
246#endif
247        , luaState_(NULL)
248        , scriptModule_(NULL)
249        , guiSystem_(NULL)
250        , ceguiLogger_(NULL)
251        , rootWindow_(NULL)
252        , hudRootWindow_(NULL)
253        , menuRootWindow_(NULL)
254        , camera_(NULL)
255        , destructionHelper_(this)
256    {
257        RegisterRootObject(GUIManager);
258        this->setConfigValues();
259
260        using namespace CEGUI;
261
262        COUT(3) << "Initialising CEGUI." << std::endl;
263
264        this->oldCEGUI_ = false;
265       
266        // Note: No SceneManager specified yet
267#ifdef ORXONOX_OLD_CEGUI
268        guiRenderer_ = new OgreCEGUIRenderer(GraphicsManager::getInstance().getRenderWindow(), Ogre::RENDER_QUEUE_OVERLAY, false, 3000);
269        resourceProvider_ = guiRenderer_->createResourceProvider();
270        this->oldCEGUI_ = true;
271#else
272        guiRenderer_ = &OgreRenderer::create(*GraphicsManager::getInstance().getRenderWindow());
273        // We use our own RenderQueueListener so we can draw UNDER overlays
274        guiRenderer_->setFrameControlExecutionEnabled(false);
275        rqListener_ = new RQListener();
276        resourceProvider_ = &OgreRenderer::createOgreResourceProvider();
277        imageCodec_ = &OgreRenderer::createOgreImageCodec();
278#endif
279        resourceProvider_->setDefaultResourceGroup("General");
280
281        // Setup scripting
282        luaState_ = new LuaState();
283        rootFileInfo_ = Resource::getInfo("InitialiseGUI.lua");
284        // This is necessary to ensure that input events also use the right resource info when triggering lua functions
285        luaState_->setDefaultResourceInfo(this->rootFileInfo_);
286#ifdef ORXONOX_OLD_CEGUI
287        scriptModule_ = new LuaScriptModule(luaState_->getInternalLuaState());
288        // Ugly workaround: older CEGUILua versions don't initialise the member
289        // d_activeErrFuncIndex at all. That leads to "error in error handling"
290        // problems when a Lua error occurs.
291        // We fix this by setting the member manually.
292        reinterpret_cast<LuaScriptModuleWorkaround*>(scriptModule_)->d_activeErrFuncIndex = LUA_NOREF;
293        luaState_->doString("ORXONOX_OLD_CEGUI = true");
294#else
295        scriptModule_ = &LuaScriptModule::create(luaState_->getInternalLuaState());
296#endif
297        scriptModule_->setDefaultPCallErrorHandler(LuaState::ERROR_HANDLER_NAME);
298
299        // Create our own logger to specify the filepath
300        std::auto_ptr<CEGUILogger> ceguiLogger(new CEGUILogger());
301        ceguiLogger->setLogFilename(PathConfig::getLogPathString() + "cegui.log");
302        // Set the log level according to ours (translate by subtracting 1)
303        ceguiLogger->setLoggingLevel(
304            static_cast<LoggingLevel>(OutputHandler::getInstance().getSoftDebugLevel("logFile") - 1));
305        this->ceguiLogger_ = ceguiLogger.release();
306
307        // Create the CEGUI system singleton
308#ifdef ORXONOX_OLD_CEGUI
309        guiSystem_ = new System(guiRenderer_, resourceProvider_, 0, scriptModule_);
310        // Add functions that have been renamed in newer versions
311        luaState_->doString("CEGUI.SchemeManager.create = CEGUI.SchemeManager.loadScheme");
312        luaState_->doString("CEGUI.Window.getUnclippedOuterRect = CEGUI.Window.getUnclippedPixelRect");
313#else
314        guiSystem_ = &System::create(*guiRenderer_, resourceProvider_, 0, imageCodec_, scriptModule_);
315#endif
316
317        // Align CEGUI mouse with OIS mouse
318        guiSystem_->injectMousePosition((float)mousePosition.first, (float)mousePosition.second);
319
320        // Initialise the Lua framework and load the schemes
321        this->luaState_->doFile("InitialiseGUI.lua");
322
323        // Create the root nodes
324        this->rootWindow_ = CEGUI::WindowManager::getSingleton().createWindow("MenuWidgets/StaticImage", "AbsoluteRootWindow");
325        this->rootWindow_->setProperty("FrameEnabled", "False");
326        this->hudRootWindow_ = CEGUI::WindowManager::getSingleton().createWindow("DefaultWindow", "HUDRootWindow");
327        this->menuRootWindow_ = CEGUI::WindowManager::getSingleton().createWindow("DefaultWindow", "MenuRootWindow");
328        // And connect them
329        CEGUI::System::getSingleton().setGUISheet(this->rootWindow_);
330        this->rootWindow_->addChildWindow(this->hudRootWindow_);
331        this->rootWindow_->addChildWindow(this->menuRootWindow_);
332
333        // No background to start with (sets the alpha value to 0)
334        this->setBackgroundImage("");
335
336        // Set up the sheet manager in the Lua framework
337        this->luaState_->doFile("SheetManager.lua");
338    }
339
340    void GUIManager::destroy()
341    {
342        using namespace CEGUI;
343
344#ifdef ORXONOX_OLD_CEGUI
345        safeObjectDelete(&guiSystem_);
346        safeObjectDelete(&guiRenderer_);
347        safeObjectDelete(&scriptModule_);
348#else
349        System::destroy();
350        OgreRenderer::destroyOgreResourceProvider(*resourceProvider_);
351        OgreRenderer::destroyOgreImageCodec(*imageCodec_);
352        OgreRenderer::destroy(*guiRenderer_);
353        LuaScriptModule::destroy(*scriptModule_);
354        safeObjectDelete(&ceguiLogger_);
355        safeObjectDelete(&rqListener_);
356#endif
357        safeObjectDelete(&luaState_);
358    }
359
360    void GUIManager::setConfigValues(void)
361    {
362        SetConfigValue(guiScheme_, GUIManager::defaultScheme_) .description("Changes the current GUI scheme.") .callback(this, &GUIManager::changedGUIScheme);
363        SetConfigValue(numScrollLines_, 1).description("How many lines to scroll in a list if the scroll wheel is used");
364    }
365
366    void GUIManager::changedGUIScheme(void)
367    {
368    }
369
370    /**
371    @brief
372        used to tick the GUI
373    @param time
374        clock which provides time value for the GUI System
375
376        Ticking the GUI means updating it with a certain regularity.
377        The elapsed time since the last call is given in the time value provided by the clock.
378        This time value is then used to provide a fluent animation of the GUI.
379    */
380    void GUIManager::preUpdate(const Clock& time)
381    {
382        assert(guiSystem_);
383        this->protectedCall(boost::bind(&CEGUI::System::injectTimePulse, _1, time.getDeltaTime()));
384    }
385
386    /**
387    @brief
388        Tells the GUIManager which SceneManager to use
389    @param camera
390        The current camera on which the GUI should be displayed on.
391
392        In fact the GUIManager needs the SceneManager and not the Camera to display the GUI.
393        This means the GUI is not bound to a camera but rather to the SceneManager.
394        Hiding the GUI when needed can therefore not be resolved by just NOT setting the current camera.
395    */
396    void GUIManager::setCamera(Ogre::Camera* camera)
397    {
398#ifdef ORXONOX_OLD_CEGUI
399        if (camera == NULL)
400            this->guiRenderer_->setTargetSceneManager(0);
401        else
402            this->guiRenderer_->setTargetSceneManager(camera->getSceneManager());
403#else
404        if (camera_ != NULL && camera_->getSceneManager() != NULL)
405            camera_->getSceneManager()->removeRenderQueueListener(rqListener_);
406        if (camera != NULL && camera->getSceneManager() != NULL)
407            camera->getSceneManager()->addRenderQueueListener(rqListener_);
408#endif
409        this->camera_ = camera;
410    }
411
412    /**
413    @brief
414        Executes Lua code
415    @param str
416        reference to string object holding the Lua code which is to be executed
417    */
418    void GUIManager::executeCode(const std::string& str)
419    {
420        this->luaState_->doString(str, rootFileInfo_);
421    }
422
423    /** Loads a GUI sheet by Lua script
424    @param name
425        The name of the GUI (like the script name, but without the extension)
426    */
427    void GUIManager::loadGUI(const std::string& name)
428    {
429        this->executeCode("loadSheet(\"" + name + "\")");
430    }
431
432    /**
433    @brief
434        Displays specified GUI on screen
435    @param name
436        The name of the GUI
437    @param bHidePrevious
438        If true all displayed GUIs on the stack, that are below this GUI are hidden.
439    @param bNoInput
440        If true the GUI is transparent to input.
441
442        The function executes the Lua function with the same name in case the GUIManager is ready.
443    */
444    /*static*/ void GUIManager::showGUI(const std::string& name, bool bHidePrevious, bool bNoInput)
445    {
446        GUIManager::getInstance().executeCode("showMenuSheet(\"" + name + "\", " + multi_cast<std::string>(bHidePrevious) + ", " + multi_cast<std::string>(bNoInput) + ")");
447    }
448
449    /**
450    @brief
451        Hack-ish. Needed for GUIOverlay.
452    */
453    void GUIManager::showGUIExtra(const std::string& name, const std::string& ptr, bool bHidePrevious, bool bNoInput)
454    {
455        this->executeCode("showMenuSheet(\"" + name + "\", " + multi_cast<std::string>(bHidePrevious) + ", " + multi_cast<std::string>(bNoInput) + ", " + ptr + ")");
456    }
457
458    /**
459    @brief
460        Hides specified GUI.
461    @param name
462        The name of the GUI.
463    */
464    /*static*/ void GUIManager::hideGUI(const std::string& name)
465    {
466        GUIManager::getInstance().executeCode("hideMenuSheet(\"" + name + "\")");
467    }
468
469    /**
470    @brief
471        Toggles specified GUI.
472        If the GUI with the input name is already shown and on the top, it is hidden, else it is shown.
473    */
474    /*static*/ void GUIManager::toggleGUI(const std::string& name, bool bHidePrevious, bool bNoInput)
475    {
476        GUIManager::getInstance().executeCode("getGUIFirstActive(\"" + name + "\", " + multi_cast<std::string>(bHidePrevious) + ", " + multi_cast<std::string>(bNoInput) + ")");
477    }
478
479    /**
480    @brief
481        Helper method to toggle a specified GUI.
482        Is called by lua.
483    */
484    void GUIManager::toggleGUIHelper(const std::string& name, bool bHidePrevious, bool bNoInput, bool show)
485    {
486        if(show)
487            GUIManager::showGUI(name, bHidePrevious, bNoInput);
488        else
489            GUIManager::hideGUI(name);
490    }
491
492    const std::string& GUIManager::createInputState(const std::string& name, TriBool::Value showCursor, TriBool::Value useKeyboard, bool bBlockJoyStick)
493    {
494        InputState* state = InputManager::getInstance().createInputState(name);
495        if (!state)
496            return BLANKSTRING;
497
498        /* Table that maps isFullScreen() and showCursor to mouseExclusive
499        isFullscreen / showCursor | True  | False | Dontcare
500        ----------------------------------------------------
501        true                      | True  | True  | Dontcare
502        ----------------------------------------------------
503        false                     | False | True  | Dontcare
504        */
505
506#ifdef ORXONOX_PLATFORM_APPLE
507        // There is no non exclusive mode on OS X yet
508        state->setMouseExclusive(TriBool::True);
509#else
510        if (showCursor == TriBool::Dontcare)
511            state->setMouseExclusive(TriBool::Dontcare);
512        else if (GraphicsManager::getInstance().isFullScreen() || showCursor == TriBool::False)
513            state->setMouseExclusive(TriBool::True);
514        else
515            state->setMouseExclusive(TriBool::False);
516#endif
517
518        if (showCursor == TriBool::True)
519            state->setMouseHandler(this);
520        else if (showCursor == TriBool::False)
521            state->setMouseHandler(&InputHandler::EMPTY);
522
523        if (useKeyboard == TriBool::True)
524            state->setKeyHandler(this);
525        else if (useKeyboard == TriBool::False)
526            state->setKeyHandler(&InputHandler::EMPTY);
527
528        if (bBlockJoyStick)
529            state->setJoyStickHandler(&InputHandler::EMPTY);
530
531        return state->getName();
532    }
533
534    void GUIManager::keyESC()
535    {
536        this->executeCode("keyESC()");
537    }
538
539    void GUIManager::setBackgroundImage(const std::string& imageSet, const std::string imageName)
540    {
541        if (imageSet.empty() || imageName.empty())
542            this->setBackgroundImage("");
543        else
544            this->setBackgroundImage("set: " + imageSet + " image: " + imageName);
545    }
546
547    void GUIManager::setBackgroundImage(const std::string& image)
548    {
549        if (image.empty())
550            this->rootWindow_->setProperty("Alpha", "0.0");
551        else
552            this->rootWindow_->setProperty("Alpha", "1.0");
553        this->rootWindow_->setProperty("Image", image);
554    }
555
556    void GUIManager::buttonPressed(const KeyEvent& evt)
557    {
558        this->protectedCall(boost::bind(&CEGUI::System::injectKeyDown, _1, evt.getKeyCode()));
559        this->protectedCall(boost::bind(&CEGUI::System::injectChar, _1, evt.getText()));
560    }
561
562    void GUIManager::buttonReleased(const KeyEvent& evt)
563    {
564        this->protectedCall(boost::bind(&CEGUI::System::injectKeyUp, _1, evt.getKeyCode()));
565    }
566
567    /**
568    @brief
569        Function receiving a mouse button pressed event.
570    @param id
571        ID of the mouse button which got pressed
572
573        This function is inherited by MouseHandler and injects the event into CEGUI.
574        It is for CEGUI to process the event.
575    */
576    void GUIManager::buttonPressed(MouseButtonCode::ByEnum id)
577    {
578        this->protectedCall(boost::bind(&CEGUI::System::injectMouseButtonDown, _1, convertButton(id)));
579    }
580
581    /**
582    @brief
583        Function receiving a mouse button released event.
584    @param id
585        ID of the mouse button which got released
586
587        This function is inherited by MouseHandler and injects the event into CEGUI.
588        It is for CEGUI to process the event.
589    */
590    void GUIManager::buttonReleased(MouseButtonCode::ByEnum id)
591    {
592        this->protectedCall(boost::bind(&CEGUI::System::injectMouseButtonUp, _1, convertButton(id)));
593    }
594
595    void GUIManager::mouseMoved(IntVector2 abs, IntVector2 rel, IntVector2 clippingSize)
596    {
597        this->protectedCall(boost::bind(&CEGUI::System::injectMousePosition, _1, (float)abs.x, (float)abs.y));
598    }
599
600    void GUIManager::mouseScrolled(int abs, int rel)
601    {
602        this->protectedCall(boost::bind(&CEGUI::System::injectMouseWheelChange, _1, (float)sgn(rel) * this->numScrollLines_));
603    }
604
605    /**
606        @brief Indicates that the mouse left the application's window.
607    */
608    void GUIManager::mouseLeft()
609    {
610        this->protectedCall(boost::bind(&CEGUI::System::injectMouseLeaves, _1));
611    }
612
613    /**
614    @brief
615        converts mouse event code to CEGUI event code
616    @param button
617        code of the mouse button as we use it in Orxonox
618    @return
619        code of the mouse button as it is used by CEGUI
620
621        Simple conversion from mouse event code in Orxonox to the one used in CEGUI.
622     */
623    static inline CEGUI::MouseButton convertButton(MouseButtonCode::ByEnum button)
624    {
625        switch (button)
626        {
627        case MouseButtonCode::Left:
628            return CEGUI::LeftButton;
629
630        case MouseButtonCode::Right:
631            return CEGUI::RightButton;
632
633        case MouseButtonCode::Middle:
634            return CEGUI::MiddleButton;
635
636        case MouseButtonCode::Button3:
637            return CEGUI::X1Button;
638
639        case MouseButtonCode::Button4:
640            return CEGUI::X2Button;
641
642        default:
643            return CEGUI::NoButton;
644        }
645    }
646
647    /** Executes a CEGUI function normally, but catches CEGUI::ScriptException.
648        When a ScriptException occurs, the error message will be displayed and
649        the program carries on.
650    @remarks
651        The exception behaviour may pose problems if the code is not written
652        exception-safe (and you can forget about that in Lua). The program might
653        be left in an undefined state. But otherwise one script error would
654        terminate the whole program...
655    @note
656        Your life gets easier if you use boost::bind to create the object/function.
657    @param function
658        Any callable object/function that takes this->guiSystem_ as its only parameter.
659    @return
660        True if input was handled, false otherwise. A caught exception yields true.
661    */
662    template <typename FunctionType>
663    bool GUIManager::protectedCall(FunctionType function)
664    {
665        try
666        {
667            return function(this->guiSystem_);
668        }
669        catch (CEGUI::ScriptException& ex)
670        {
671            // Display the error and proceed. See @remarks why this can be dangerous.
672            COUT(1) << ex.getMessage() << std::endl;
673            return true;
674        }
675    }
676
677    /**
678    @brief
679        Subscribe the input function to the input event for the input window.
680        This is a helper to be used in lua, because subscribeScriptedEvent() doesn't work in lua.
681    @param window
682        The window for which the event is subscribed.
683    @param event
684        The type of event to which we subscribe.
685    @param function
686        The function that is called when the event occurs.
687    */
688    void GUIManager::subscribeEventHelper(CEGUI::Window* window, const std::string& event, const std::string& function)
689    {
690        window->subscribeScriptedEvent(event, function);
691    }
692
693    /**
694    @brief
695        Set the input tooltip text for the input ListboxItem.
696    @param item
697        The ListboxItem for which the tooltip should be set.
698    @param tooltip
699        The tooltip text that should be set.
700    */
701    void GUIManager::setTooltipTextHelper(CEGUI::ListboxItem* item, const std::string& tooltip)
702    {
703        item->setTooltipText(tooltip);
704    }
705
706    /**
707    @brief
708        Set whether the tooltips for the input Listbox are enabled.
709    @param listbox
710        The Listbox for which to enable (or disable) tooltips.
711    @param enabled
712        Whether to enable or disable the tooltips.
713    */
714    void GUIManager::setItemTooltipsEnabledHelper(CEGUI::Listbox* listbox, bool enabled)
715    {
716        listbox->setItemTooltipsEnabled(enabled);
717    }
718
719    /**
720        @brief Callback of window event listener, called if the window is resized. Sets the display size of CEGUI.
721    */
722    void GUIManager::windowResized(unsigned int newWidth, unsigned int newHeight)
723    {
724        this->guiRenderer_->setDisplaySize(CEGUI::Size((float)newWidth, (float)newHeight));
725    }
726
727    /**
728        @brief Notify CEGUI if the windows loses the focus (stops highlighting of menu items, etc).
729    */
730    void GUIManager::windowFocusChanged(bool bFocus)
731    {
732        if (!bFocus)
733            this->mouseLeft();
734    }
735
736    /**
737    @brief
738        Adds a new freetype font to the CEGUI system.
739    @param name
740        The name of the new font.
741    @param size
742        The font size of the new font in pixels.
743        @param fontName
744        The filename of the font.
745    */
746    /*static*/ void GUIManager::addFontHelper(const std::string& name, int size, const std::string& fontName)
747    {
748#ifdef ORXONOX_OLD_CEGUI
749        if(CEGUI::FontManager::getSingleton().isFontPresent(name)) // If a font with that name already exists.
750            return;
751
752        CEGUI::Font* font = NULL;
753        CEGUI::XMLAttributes xmlAttributes;
754
755        // Attributes specified within CEGUIFont
756        xmlAttributes.add("Name", name);
757        xmlAttributes.add("Filename", fontName);
758        xmlAttributes.add("ResourceGroup", "");
759        xmlAttributes.add("AutoScaled", "true");
760        xmlAttributes.add("NativeHorzRes", "800");
761        xmlAttributes.add("NativeVertRes", "600");
762
763        // Attributes specified within CEGUIXMLAttributes
764        xmlAttributes.add("Size", multi_cast<std::string>(size));
765        xmlAttributes.add("AntiAlias", "true");
766
767        font = CEGUI::FontManager::getSingleton().createFont("FreeType", xmlAttributes);
768        if(font != NULL)
769            font->load();
770#else
771        if(CEGUI::FontManager::getSingleton().isDefined(name)) // If a font with that name already exists.
772            return;
773
774        CEGUI::FontManager::getSingleton().createFreeTypeFont(name, (float)size, true, fontName, "", true, 800.0f, 600.0f);
775#endif
776    }
777
778}
Note: See TracBrowser for help on using the repository browser.