Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/formationupdate/src/libraries/core/GUIManager.cc @ 10169

Last change on this file since 10169 was 9576, checked in by landauf, 12 years ago

fall back to default parser if CEGUI cannot load XercesParser

  • Property svn:eol-style set to native
File size: 29.5 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        CEGUI::String defaultXMLParserName = CEGUI::System::getSingleton().getDefaultXMLParserName();
321        try
322        {
323            // Force Xerces parser (CEGUI 0.7.5+)
324            CEGUI::System::getSingleton().setXMLParser("XercesParser");
325        }
326        catch (const CEGUI::GenericException& e)
327        {
328            // Fall back to default parser
329            orxout(internal_warning) << "Cannot use XercesParser for CEGUI - using " << defaultXMLParserName << " instead" << endl;
330            CEGUI::System::getSingleton().setXMLParser(defaultXMLParserName);
331        }
332
333        // Align CEGUI mouse with OIS mouse
334        guiSystem_->injectMousePosition((float)mousePosition.first, (float)mousePosition.second);
335
336        // Initialise the Lua framework and load the schemes
337        orxout(user_info) << "Loading user interface..." << endl;
338        this->luaState_->doFile("InitialiseGUI.lua");
339
340        // Create the root nodes
341        this->rootWindow_ = CEGUI::WindowManager::getSingleton().createWindow("MenuWidgets/StaticImage", "AbsoluteRootWindow");
342        this->rootWindow_->setProperty("FrameEnabled", "False");
343        this->hudRootWindow_ = CEGUI::WindowManager::getSingleton().createWindow("DefaultWindow", "HUDRootWindow");
344        this->menuRootWindow_ = CEGUI::WindowManager::getSingleton().createWindow("DefaultWindow", "MenuRootWindow");
345        // And connect them
346        CEGUI::System::getSingleton().setGUISheet(this->rootWindow_);
347        this->rootWindow_->addChildWindow(this->hudRootWindow_);
348        this->rootWindow_->addChildWindow(this->menuRootWindow_);
349
350        // No background to start with (sets the alpha value to 0)
351        this->setBackgroundImage("");
352
353        // Set up the sheet manager in the Lua framework
354        this->luaState_->doFile("SheetManager.lua");
355
356        orxout(internal_status) << "finished initializing GUIManager" << endl;
357    }
358
359    void GUIManager::destroy()
360    {
361        orxout(internal_status) << "destroying GUIManager..." << endl;
362
363        using namespace CEGUI;
364
365#ifdef ORXONOX_OLD_CEGUI
366        safeObjectDelete(&guiSystem_);
367        safeObjectDelete(&guiRenderer_);
368        safeObjectDelete(&scriptModule_);
369#else
370        System::destroy();
371        OgreRenderer::destroyOgreResourceProvider(*resourceProvider_);
372        OgreRenderer::destroyOgreImageCodec(*imageCodec_);
373        OgreRenderer::destroy(*guiRenderer_);
374        LuaScriptModule::destroy(*scriptModule_);
375        safeObjectDelete(&ceguiLogger_);
376        safeObjectDelete(&rqListener_);
377#endif
378        safeObjectDelete(&luaState_);
379
380        orxout(internal_status) << "finished destroying GUIManager" << endl;
381    }
382
383    void GUIManager::setConfigValues(void)
384    {
385        SetConfigValue(guiScheme_, GUIManager::defaultScheme_).description("Changes the current GUI scheme.").callback(this, &GUIManager::changedGUIScheme);
386        SetConfigValue(numScrollLines_, 1).description("How many lines to scroll in a list if the scroll wheel is used");
387        SetConfigValue(bPreloadMenuSheets_, false).description("Pre-load menu sheets during startup");
388
389        SetConfigValueExternal(outputLevelCeguiLog_, BaseWriter::getConfigurableSectionName(), "outputLevelCeguiLog", CEGUI::Standard).description("The log level of the CEGUI log file").callback(this, &GUIManager::changedCeguiOutputLevel);
390    }
391
392    void GUIManager::changedGUIScheme(void)
393    {
394    }
395
396    void GUIManager::changedCeguiOutputLevel()
397    {
398        if (this->ceguiLogger_)
399            this->ceguiLogger_->setLoggingLevel(static_cast<CEGUI::LoggingLevel>(this->outputLevelCeguiLog_));
400    }
401
402    /**
403    @brief
404        used to tick the GUI
405    @param time
406        clock which provides time value for the GUI System
407
408        Ticking the GUI means updating it with a certain regularity.
409        The elapsed time since the last call is given in the time value provided by the clock.
410        This time value is then used to provide a fluent animation of the GUI.
411    */
412    void GUIManager::preUpdate(const Clock& time)
413    {
414        assert(guiSystem_);
415        this->protectedCall(boost::bind(&CEGUI::System::injectTimePulse, _1, time.getDeltaTime()));
416    }
417
418    /**
419    @brief
420        Tells the GUIManager which SceneManager to use
421    @param camera
422        The current camera on which the GUI should be displayed on.
423
424        In fact the GUIManager needs the SceneManager and not the Camera to display the GUI.
425        This means the GUI is not bound to a camera but rather to the SceneManager.
426        Hiding the GUI when needed can therefore not be resolved by just NOT setting the current camera.
427    */
428    void GUIManager::setCamera(Ogre::Camera* camera)
429    {
430#ifdef ORXONOX_OLD_CEGUI
431        if (camera == NULL)
432            this->guiRenderer_->setTargetSceneManager(0);
433        else
434            this->guiRenderer_->setTargetSceneManager(camera->getSceneManager());
435#else
436        if (camera_ != NULL && camera_->getSceneManager() != NULL)
437            camera_->getSceneManager()->removeRenderQueueListener(rqListener_);
438        if (camera != NULL && camera->getSceneManager() != NULL)
439            camera->getSceneManager()->addRenderQueueListener(rqListener_);
440#endif
441        this->camera_ = camera;
442    }
443
444    /**
445    @brief
446        Executes Lua code
447    @param str
448        reference to string object holding the Lua code which is to be executed
449    */
450    void GUIManager::executeCode(const std::string& str)
451    {
452        this->luaState_->doString(str, rootFileInfo_);
453    }
454
455    /** Loads a GUI sheet by Lua script
456    @param name
457        The name of the GUI (like the script name, but without the extension)
458    */
459    void GUIManager::loadGUI(const std::string& name)
460    {
461        this->executeCode("loadSheet(\"" + name + "\")");
462    }
463
464    /**
465    @brief
466        Displays specified GUI on screen
467    @param name
468        The name of the GUI
469    @param bHidePrevious
470        If true all displayed GUIs on the stack, that are below this GUI are hidden.
471    @param bNoInput
472        If true the GUI is transparent to input.
473
474        The function executes the Lua function with the same name in case the GUIManager is ready.
475    */
476    /*static*/ void GUIManager::showGUI(const std::string& name, bool bHidePrevious, bool bNoInput)
477    {
478        GUIManager::getInstance().executeCode("showMenuSheet(\"" + name + "\", " + multi_cast<std::string>(bHidePrevious) + ", " + multi_cast<std::string>(bNoInput) + ")");
479    }
480
481    /**
482    @brief
483        Hack-ish. Needed for GUIOverlay.
484    */
485    void GUIManager::showGUIExtra(const std::string& name, const std::string& ptr, bool bHidePrevious, bool bNoInput)
486    {
487        this->executeCode("showMenuSheet(\"" + name + "\", " + multi_cast<std::string>(bHidePrevious) + ", " + multi_cast<std::string>(bNoInput) + ", " + ptr + ")");
488    }
489
490    /**
491    @brief
492        Hides specified GUI.
493    @param name
494        The name of the GUI.
495    */
496    /*static*/ void GUIManager::hideGUI(const std::string& name)
497    {
498        GUIManager::getInstance().executeCode("hideMenuSheet(\"" + name + "\")");
499    }
500
501    /**
502    @brief
503        Toggles specified GUI.
504        If the GUI with the input name is already shown and on the top, it is hidden, else it is shown.
505    */
506    /*static*/ void GUIManager::toggleGUI(const std::string& name, bool bHidePrevious, bool bNoInput)
507    {
508        GUIManager::getInstance().executeCode("getGUIFirstActive(\"" + name + "\", " + multi_cast<std::string>(bHidePrevious) + ", " + multi_cast<std::string>(bNoInput) + ")");
509    }
510
511    /**
512    @brief
513        Helper method to toggle a specified GUI.
514        Is called by lua.
515    */
516    void GUIManager::toggleGUIHelper(const std::string& name, bool bHidePrevious, bool bNoInput, bool show)
517    {
518        if(show)
519            GUIManager::showGUI(name, bHidePrevious, bNoInput);
520        else
521            GUIManager::hideGUI(name);
522    }
523
524    const std::string& GUIManager::createInputState(const std::string& name, tribool showCursor, tribool useKeyboard, bool bBlockJoyStick)
525    {
526        InputState* state = InputManager::getInstance().createInputState(name);
527        if (!state)
528            return BLANKSTRING;
529
530        /* Table that maps isFullScreen() and showCursor to mouseExclusive
531        isFullscreen / showCursor | True  | False | Dontcare
532        ----------------------------------------------------
533        true                      | True  | True  | Dontcare
534        ----------------------------------------------------
535        false                     | False | True  | Dontcare
536        */
537
538#ifdef ORXONOX_PLATFORM_APPLE
539        // There is no non exclusive mode on OS X yet
540        state->setMouseExclusive(true);
541#else
542        if (showCursor == dontcare)
543            state->setMouseExclusive(dontcare);
544        else if (GraphicsManager::getInstance().isFullScreen() || showCursor == false)
545            state->setMouseExclusive(true);
546        else
547            state->setMouseExclusive(false);
548#endif
549
550        if (showCursor == true)
551            state->setMouseHandler(this);
552        else if (showCursor == false)
553            state->setMouseHandler(&InputHandler::EMPTY);
554
555        if (useKeyboard == true)
556            state->setKeyHandler(this);
557        else if (useKeyboard == false)
558            state->setKeyHandler(&InputHandler::EMPTY);
559
560        if (bBlockJoyStick)
561            state->setJoyStickHandler(&InputHandler::EMPTY);
562
563        return state->getName();
564    }
565
566    void GUIManager::keyESC()
567    {
568        this->executeCode("keyESC()");
569    }
570
571    void GUIManager::setBackgroundImage(const std::string& imageSet, const std::string imageName)
572    {
573        if (imageSet.empty() || imageName.empty())
574            this->setBackgroundImage("");
575        else
576            this->setBackgroundImage("set: " + imageSet + " image: " + imageName);
577    }
578
579    void GUIManager::setBackgroundImage(const std::string& image)
580    {
581        if (image.empty())
582            this->rootWindow_->setProperty("Alpha", "0.0");
583        else
584            this->rootWindow_->setProperty("Alpha", "1.0");
585        this->rootWindow_->setProperty("Image", image);
586    }
587
588    void GUIManager::buttonPressed(const KeyEvent& evt)
589    {
590        this->protectedCall(boost::bind(&CEGUI::System::injectKeyDown, _1, evt.getKeyCode()));
591        this->protectedCall(boost::bind(&CEGUI::System::injectChar, _1, evt.getText()));
592    }
593
594    void GUIManager::buttonReleased(const KeyEvent& evt)
595    {
596        this->protectedCall(boost::bind(&CEGUI::System::injectKeyUp, _1, evt.getKeyCode()));
597    }
598
599    /**
600    @brief
601        Function receiving a mouse button pressed event.
602    @param id
603        ID of the mouse button which got pressed
604
605        This function is inherited by MouseHandler and injects the event into CEGUI.
606        It is for CEGUI to process the event.
607    */
608    void GUIManager::buttonPressed(MouseButtonCode::ByEnum id)
609    {
610        this->protectedCall(boost::bind(&CEGUI::System::injectMouseButtonDown, _1, convertButton(id)));
611    }
612
613    /**
614    @brief
615        Function receiving a mouse button released event.
616    @param id
617        ID of the mouse button which got released
618
619        This function is inherited by MouseHandler and injects the event into CEGUI.
620        It is for CEGUI to process the event.
621    */
622    void GUIManager::buttonReleased(MouseButtonCode::ByEnum id)
623    {
624        this->protectedCall(boost::bind(&CEGUI::System::injectMouseButtonUp, _1, convertButton(id)));
625    }
626
627    void GUIManager::mouseMoved(IntVector2 abs, IntVector2 rel, IntVector2 clippingSize)
628    {
629        this->protectedCall(boost::bind(&CEGUI::System::injectMousePosition, _1, (float)abs.x, (float)abs.y));
630    }
631
632    void GUIManager::mouseScrolled(int abs, int rel)
633    {
634        this->protectedCall(boost::bind(&CEGUI::System::injectMouseWheelChange, _1, (float)sgn(rel) * this->numScrollLines_));
635    }
636
637    /**
638        @brief Indicates that the mouse left the application's window.
639    */
640    void GUIManager::mouseLeft()
641    {
642        this->protectedCall(boost::bind(&CEGUI::System::injectMouseLeaves, _1));
643    }
644
645    /**
646    @brief
647        converts mouse event code to CEGUI event code
648    @param button
649        code of the mouse button as we use it in Orxonox
650    @return
651        code of the mouse button as it is used by CEGUI
652
653        Simple conversion from mouse event code in Orxonox to the one used in CEGUI.
654     */
655    static inline CEGUI::MouseButton convertButton(MouseButtonCode::ByEnum button)
656    {
657        switch (button)
658        {
659        case MouseButtonCode::Left:
660            return CEGUI::LeftButton;
661
662        case MouseButtonCode::Right:
663            return CEGUI::RightButton;
664
665        case MouseButtonCode::Middle:
666            return CEGUI::MiddleButton;
667
668        case MouseButtonCode::Button3:
669            return CEGUI::X1Button;
670
671        case MouseButtonCode::Button4:
672            return CEGUI::X2Button;
673
674        default:
675            return CEGUI::NoButton;
676        }
677    }
678
679    /** Executes a CEGUI function normally, but catches CEGUI::ScriptException.
680        When a ScriptException occurs, the error message will be displayed and
681        the program carries on.
682    @remarks
683        The exception behaviour may pose problems if the code is not written
684        exception-safe (and you can forget about that in Lua). The program might
685        be left in an undefined state. But otherwise one script error would
686        terminate the whole program...
687    @note
688        Your life gets easier if you use boost::bind to create the object/function.
689    @param function
690        Any callable object/function that takes this->guiSystem_ as its only parameter.
691    @return
692        True if input was handled, false otherwise. A caught exception yields true.
693    */
694    template <typename FunctionType>
695    bool GUIManager::protectedCall(FunctionType function)
696    {
697        try
698        {
699            return function(this->guiSystem_);
700        }
701        catch (CEGUI::ScriptException& ex)
702        {
703            // Display the error and proceed. See @remarks why this can be dangerous.
704            orxout(internal_error) << ex.getMessage() << endl;
705            return true;
706        }
707    }
708
709    /**
710    @brief
711        Subscribe the input function to the input event for the input window.
712        This is a helper to be used in lua, because subscribeScriptedEvent() doesn't work in lua.
713    @param window
714        The window for which the event is subscribed.
715    @param event
716        The type of event to which we subscribe.
717    @param function
718        The function that is called when the event occurs.
719    */
720    void GUIManager::subscribeEventHelper(CEGUI::Window* window, const std::string& event, const std::string& function)
721    {
722        window->subscribeScriptedEvent(event, function);
723    }
724
725    /**
726    @brief
727        Set the input tooltip text for the input ListboxItem.
728    @param item
729        The ListboxItem for which the tooltip should be set.
730    @param tooltip
731        The tooltip text that should be set.
732    */
733    void GUIManager::setTooltipTextHelper(CEGUI::ListboxItem* item, const std::string& tooltip)
734    {
735        item->setTooltipText(tooltip);
736    }
737
738    /**
739    @brief
740        Set whether the tooltips for the input Listbox are enabled.
741    @param listbox
742        The Listbox for which to enable (or disable) tooltips.
743    @param enabled
744        Whether to enable or disable the tooltips.
745    */
746    void GUIManager::setItemTooltipsEnabledHelper(CEGUI::Listbox* listbox, bool enabled)
747    {
748        listbox->setItemTooltipsEnabled(enabled);
749    }
750
751    /** Helper method to get the developer's mode without having to export Core.h.
752    @see Core::inDevMode
753    */
754    /*static*/ bool GUIManager::inDevMode()
755    {
756         return Core::getInstance().inDevMode();
757    }
758
759    /**
760        @brief Callback of window event listener, called if the window is resized. Sets the display size of CEGUI.
761    */
762    void GUIManager::windowResized(unsigned int newWidth, unsigned int newHeight)
763    {
764        this->guiRenderer_->setDisplaySize(CEGUI::Size((float)newWidth, (float)newHeight));
765    }
766
767    /**
768        @brief Notify CEGUI if the windows loses the focus (stops highlighting of menu items, etc).
769    */
770    void GUIManager::windowFocusChanged(bool bFocus)
771    {
772        if (!bFocus)
773            this->mouseLeft();
774    }
775
776    /**
777    @brief
778        Adds a new freetype font to the CEGUI system.
779    @param name
780        The name of the new font.
781    @param size
782        The font size of the new font in pixels.
783        @param fontName
784        The filename of the font.
785    */
786    /*static*/ void GUIManager::addFontHelper(const std::string& name, int size, const std::string& fontName)
787    {
788#ifdef ORXONOX_OLD_CEGUI
789        if(CEGUI::FontManager::getSingleton().isFontPresent(name)) // If a font with that name already exists.
790            return;
791
792        CEGUI::Font* font = NULL;
793        CEGUI::XMLAttributes xmlAttributes;
794
795        // Attributes specified within CEGUIFont
796        xmlAttributes.add("Name", name);
797        xmlAttributes.add("Filename", fontName);
798        xmlAttributes.add("ResourceGroup", "");
799        xmlAttributes.add("AutoScaled", "true");
800        xmlAttributes.add("NativeHorzRes", "800");
801        xmlAttributes.add("NativeVertRes", "600");
802
803        // Attributes specified within CEGUIXMLAttributes
804        xmlAttributes.add("Size", multi_cast<std::string>(size));
805        xmlAttributes.add("AntiAlias", "true");
806
807        font = CEGUI::FontManager::getSingleton().createFont("FreeType", xmlAttributes);
808        if(font != NULL)
809            font->load();
810#else
811        if(CEGUI::FontManager::getSingleton().isDefined(name)) // If a font with that name already exists.
812            return;
813
814        CEGUI::FontManager::getSingleton().createFreeTypeFont(name, (float)size, true, fontName, "", true, 800.0f, 600.0f);
815#endif
816    }
817
818}
Note: See TracBrowser for help on using the repository browser.