Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/core/GUIManager.cc @ 9575

Last change on this file since 9575 was 9575, checked in by fmauro, 11 years ago

Force CEGUI to use Xerces parser instead of TinyXML with versions 0.7.5 and up

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