Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 11083 was 11083, checked in by muemart, 8 years ago

Fix some clang-tidy warnings.
Also, Serialise.h was doing some C-style casts that ended up being const casts. I moved those const casts as close to the source as possible and changed the loadAndIncrease functions to not do that.

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