Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/gamestates2/src/libraries/core/GUIManager.cc @ 6670

Last change on this file since 6670 was 6662, checked in by rgrieder, 14 years ago

Merged revisions 6621-6661 to gamestates2.

  • Property svn:eol-style set to native
File size: 13.4 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 <memory>
33extern "C" {
34#include <lua.h>
35}
36#include <CEGUIDefaultLogger.h>
37#include <CEGUIExceptions.h>
38#include <CEGUIInputEvent.h>
39#include <CEGUIMouseCursor.h>
40#include <CEGUIResourceProvider.h>
41#include <CEGUISystem.h>
42#include <CEGUIWindow.h>
43#include <ogreceguirenderer/OgreCEGUIRenderer.h>
44
45#include "SpecialConfig.h" // Configures the macro below
46#ifdef CEGUILUA_USE_INTERNAL_LIBRARY
47#   include <ceguilua/CEGUILua.h>
48#else
49#   include <CEGUILua.h>
50#endif
51
52#include "util/Clock.h"
53#include "util/Convert.h"
54#include "util/Debug.h"
55#include "util/Exception.h"
56#include "util/OrxAssert.h"
57#include "ConsoleCommand.h"
58#include "Core.h"
59#include "GraphicsManager.h"
60#include "LuaState.h"
61#include "PathConfig.h"
62#include "Resource.h"
63#include "input/InputManager.h"
64#include "input/InputState.h"
65#include "input/KeyBinderManager.h"
66
67namespace orxonox
68{
69    static void key_esc()
70        { GUIManager::getInstance().keyESC(); }
71    SetConsoleCommandShortcutExternAlias(key_esc, "keyESC");
72
73    class CEGUILogger : public CEGUI::DefaultLogger
74    {
75    public:
76        void logEvent(const CEGUI::String& message, CEGUI::LoggingLevel level = CEGUI::Standard)
77        {
78            int orxonoxLevel = CEGUI::Standard;
79            switch (level)
80            {
81                case CEGUI::Errors:      orxonoxLevel = 1; break;
82                case CEGUI::Warnings:    orxonoxLevel = 2; break;
83                case CEGUI::Standard:    orxonoxLevel = 4; break;
84                case CEGUI::Informative: orxonoxLevel = 5; break;
85                case CEGUI::Insane:      orxonoxLevel = 6; break;
86                default: OrxAssert(false, "CEGUI log level out of range, inpect immediately!");
87            }
88            OutputHandler::getOutStream(orxonoxLevel)
89                << "CEGUI: " << message << std::endl;
90
91            CEGUI::DefaultLogger::logEvent(message, level);
92        }
93    };
94
95    static CEGUI::MouseButton convertButton(MouseButtonCode::ByEnum button);
96
97    GUIManager* GUIManager::singletonPtr_s = 0;
98
99    SetConsoleCommandShortcut(GUIManager, showGUI).accessLevel(AccessLevel::User).defaultValue(1, false).defaultValue(2, true);
100    SetConsoleCommandShortcut(GUIManager, hideGUI).accessLevel(AccessLevel::User);
101
102    /**
103    @brief
104        Constructs the GUIManager by starting up CEGUI
105
106        Creates the interface to Ogre, sets up the CEGUI renderer and the Lua script module together with the Lua engine.
107        The log is set up and connected to the CEGUILogger.
108        After Lua setup tolua++-elements are linked to Lua-state to give Lua access to C++-code.
109        Finally initial Lua code is executed (maybe we can do this with the CEGUI startup script automatically).
110    @param renderWindow
111        Ogre's render window. Without this, the GUI cannot be displayed.
112    @return true if success, otherwise false
113    */
114    GUIManager::GUIManager(const std::pair<int, int>& mousePosition)
115        : resourceProvider_(NULL)
116        , camera_(NULL)
117    {
118        using namespace CEGUI;
119
120        COUT(3) << "Initialising CEGUI." << std::endl;
121
122        // Note: No SceneManager specified yet
123        guiRenderer_.reset(new OgreCEGUIRenderer(GraphicsManager::getInstance().getRenderWindow(), Ogre::RENDER_QUEUE_OVERLAY, false, 3000));
124        resourceProvider_ = guiRenderer_->createResourceProvider();
125        resourceProvider_->setDefaultResourceGroup("GUI");
126
127        // setup scripting
128        luaState_.reset(new LuaState());
129        rootFileInfo_ = Resource::getInfo("InitialiseGUI.lua");
130        // This is necessary to ensure that input events also use the right resource info when triggering lua functions
131        luaState_->setDefaultResourceInfo(this->rootFileInfo_);
132        scriptModule_.reset(new LuaScriptModule(luaState_->getInternalLuaState()));
133
134        // Create our own logger to specify the filepath
135        std::auto_ptr<CEGUILogger> ceguiLogger(new CEGUILogger());
136        ceguiLogger->setLogFilename(PathConfig::getLogPathString() + "cegui.log");
137        // set the log level according to ours (translate by subtracting 1)
138        ceguiLogger->setLoggingLevel(
139            static_cast<LoggingLevel>(OutputHandler::getInstance().getSoftDebugLevel("logFile") - 1));
140        this->ceguiLogger_ = ceguiLogger.release();
141
142        // create the CEGUI system singleton
143        guiSystem_.reset(new System(guiRenderer_.get(), resourceProvider_, 0, scriptModule_.get()));
144
145        // Align CEGUI mouse with OIS mouse
146        guiSystem_->injectMousePosition((float)mousePosition.first, (float)mousePosition.second);
147
148        // Hide the mouse cursor unless playing in full screen mode
149        if (!GraphicsManager::getInstance().isFullScreen())
150            CEGUI::MouseCursor::getSingleton().hide();
151
152        // Initialise the basic Lua code
153        this->luaState_->doFile("InitialiseGUI.lua");
154    }
155
156    /**
157    @brief
158        Basically shuts down CEGUI (member smart pointers) but first unloads our Tolua modules.
159    */
160    GUIManager::~GUIManager()
161    {
162    }
163
164    /**
165    @brief
166        used to tick the GUI
167    @param time
168        clock which provides time value for the GUI System
169
170        Ticking the GUI means updating it with a certain regularity.
171        The elapsed time since the last call is given in the time value provided by the clock.
172        This time value is then used to provide a fluent animation of the GUI.
173    */
174    void GUIManager::preUpdate(const Clock& time)
175    {
176        assert(guiSystem_);
177        guiSystem_->injectTimePulse(time.getDeltaTime());
178    }
179
180    /**
181    @brief
182        Tells the GUIManager which SceneManager to use
183    @param camera
184        The current camera on which the GUI should be displayed on.
185
186        In fact the GUIManager needs the SceneManager and not the Camera to display the GUI.
187        This means the GUI is not bound to a camera but rather to the SceneManager.
188        Hiding the GUI when needed can therefore not be resolved by just NOT setting the current camera.
189    */
190    void GUIManager::setCamera(Ogre::Camera* camera)
191    {
192        this->camera_ = camera;
193        if (camera == NULL)
194            this->guiRenderer_->setTargetSceneManager(0);
195        else
196            this->guiRenderer_->setTargetSceneManager(camera->getSceneManager());
197    }
198
199    /**
200    @brief
201        Executes Lua code
202    @param str
203        reference to string object holding the Lua code which is to be executed
204
205        This function gives total access to the GUI. You can execute ANY Lua code here.
206    */
207    void GUIManager::executeCode(const std::string& str)
208    {
209        this->luaState_->doString(str, rootFileInfo_);
210    }
211
212    /** Loads a GUI sheet by Lua script
213    @param name
214        The name of the GUI (like the script name, but without the extension)
215    */
216    void GUIManager::loadGUI(const std::string& name)
217    {
218        this->executeCode("loadGUI(\"" + name + "\")");
219    }
220
221    /**
222    @brief
223        Displays specified GUI on screen
224    @param name
225        The name of the GUI
226
227        The function executes the Lua function with the same name in case the GUIManager is ready.
228        For more details check out loadGUI_2.lua where the function presides.
229    */
230    /*static*/ void GUIManager::showGUI(const std::string& name, bool hidePrevious, bool showCursor)
231    {
232        GUIManager::getInstance().executeCode("showGUI(\"" + name + "\", " + multi_cast<std::string>(hidePrevious) + ", " + multi_cast<std::string>(showCursor) + ")");
233    }
234
235    /**
236    @brief
237        Hack-ish. Needed for GUIOverlay.
238    */
239    void GUIManager::showGUIExtra(const std::string& name, const std::string& ptr, bool hidePrevious, bool showCursor)
240    {
241        this->executeCode("showGUI(\"" + name + "\", " + multi_cast<std::string>(hidePrevious) + ", " + multi_cast<std::string>(showCursor) + ", " + ptr + ")");
242    }
243
244    /**
245    @brief
246        Hides specified GUI.
247    @param name
248        The name of the GUI.
249    */
250    /*static*/ void GUIManager::hideGUI(const std::string& name)
251    {
252        GUIManager::getInstance().executeCode("hideGUI(\"" + name + "\")");
253    }
254
255    const std::string& GUIManager::createInputState(const std::string& name, TriBool::Value showCursor, TriBool::Value useKeyboard, bool bBlockJoyStick)
256    {
257        InputState* state = InputManager::getInstance().createInputState(name);
258
259        /* Table that maps isFullScreen() and showCursor to mouseExclusive
260        isFullscreen / showCursor | True  | False | Dontcare
261        ----------------------------------------------------
262        true                      | True  | True  | Dontcare
263        ----------------------------------------------------
264        false                     | False | True  | Dontcare
265        */
266        if (showCursor == TriBool::Dontcare)
267            state->setMouseExclusive(TriBool::Dontcare);
268        else if (GraphicsManager::getInstance().isFullScreen() || showCursor == TriBool::False)
269            state->setMouseExclusive(TriBool::True);
270        else
271            state->setMouseExclusive(TriBool::False);
272
273        if (showCursor == TriBool::True)
274            state->setMouseHandler(this);
275        else if (showCursor == TriBool::False)
276            state->setMouseHandler(&InputHandler::EMPTY);
277
278        if (useKeyboard == TriBool::True)
279            state->setKeyHandler(this);
280        else if (useKeyboard == TriBool::False)
281            state->setKeyHandler(&InputHandler::EMPTY);
282
283        if (bBlockJoyStick)
284            state->setJoyStickHandler(&InputHandler::EMPTY);
285
286        return state->getName();
287    }
288
289    void GUIManager::keyESC()
290    {
291        this->executeCode("keyESC()");
292    }
293
294    void GUIManager::setBackground(const std::string& name)
295    {
296        this->executeCode("setBackground(\"" + name + "\")");
297    }
298
299    void GUIManager::keyPressed(const KeyEvent& evt)
300    {
301        guiSystem_->injectKeyDown(evt.getKeyCode());
302        guiSystem_->injectChar(evt.getText());
303    }
304    void GUIManager::keyReleased(const KeyEvent& evt)
305    {
306        guiSystem_->injectKeyUp(evt.getKeyCode());
307    }
308
309    /**
310    @brief
311        Function receiving a mouse button pressed event.
312    @param id
313        ID of the mouse button which got pressed
314
315        This function is inherited by MouseHandler and injects the event into CEGUI.
316        It is for CEGUI to process the event.
317    */
318    void GUIManager::buttonPressed(MouseButtonCode::ByEnum id)
319    {
320        try
321        {
322            guiSystem_->injectMouseButtonDown(convertButton(id));
323        }
324        catch (CEGUI::ScriptException& ex)
325        {
326            // We simply ignore the exception and proceed
327            COUT(1) << ex.getMessage() << std::endl;
328        }
329    }
330
331    /**
332    @brief
333        Function receiving a mouse button released event.
334    @param id
335        ID of the mouse button which got released
336
337        This function is inherited by MouseHandler and injects the event into CEGUI.
338        It is for CEGUI to process the event.
339    */
340    void GUIManager::buttonReleased(MouseButtonCode::ByEnum id)
341    {
342        try
343        {
344            guiSystem_->injectMouseButtonUp(convertButton(id));
345        }
346        catch (CEGUI::ScriptException& ex)
347        {
348            // We simply ignore the exception and proceed
349            COUT(1) << ex.getMessage() << std::endl;
350        }
351    }
352
353    void GUIManager::mouseMoved(IntVector2 abs, IntVector2 rel, IntVector2 clippingSize)
354    {
355        guiSystem_->injectMousePosition(static_cast<float>(abs.x), static_cast<float>(abs.y));
356    }
357    void GUIManager::mouseScrolled(int abs, int rel)
358    {
359        guiSystem_->injectMouseWheelChange(static_cast<float>(rel));
360    }
361
362    /**
363    @brief
364        converts mouse event code to CEGUI event code
365    @param button
366        code of the mouse button as we use it in Orxonox
367    @return
368        code of the mouse button as it is used by CEGUI
369
370        Simple conversion from mouse event code in Orxonox to the one used in CEGUI.
371     */
372    static inline CEGUI::MouseButton convertButton(MouseButtonCode::ByEnum button)
373    {
374        switch (button)
375        {
376        case MouseButtonCode::Left:
377            return CEGUI::LeftButton;
378
379        case MouseButtonCode::Right:
380            return CEGUI::RightButton;
381
382        case MouseButtonCode::Middle:
383            return CEGUI::MiddleButton;
384
385        case MouseButtonCode::Button3:
386            return CEGUI::X1Button;
387
388        case MouseButtonCode::Button4:
389            return CEGUI::X2Button;
390
391        default:
392            return CEGUI::NoButton;
393        }
394    }
395
396    void GUIManager::subscribeEventHelper(CEGUI::Window* window, const std::string& event, const std::string& function)
397    {
398        window->subscribeScriptedEvent(event, function);
399    }
400}
Note: See TracBrowser for help on using the repository browser.