Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/cpp11_v2/src/libraries/core/GUIManager.cc @ 10772

Last change on this file since 10772 was 10769, checked in by landauf, 9 years ago

no space needed anymore between closing template brackets ('> >' → '>>')

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