Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/netp5/src/core/input/InputManager.cc @ 3212

Last change on this file since 3212 was 3196, checked in by rgrieder, 15 years ago

Merged pch branch back to trunk.

  • Property svn:eol-style set to native
File size: 54.2 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 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30@file
31@brief
32    Implementation of the InputManager that captures all the input from OIS
33    and redirects it to handlers.
34 */
35
36#include "InputManager.h"
37
38#include <climits>
39#include <cassert>
40#include <ois/OISException.h>
41#include <ois/OISInputManager.h>
42
43#include "util/Convert.h"
44#include "util/Exception.h"
45#include "util/Debug.h"
46#include "core/Clock.h"
47#include "core/CoreIncludes.h"
48#include "core/ConfigValueIncludes.h"
49#include "core/ConsoleCommand.h"
50#include "core/CommandLine.h"
51
52#include "InputBuffer.h"
53#include "KeyDetector.h"
54#include "InputState.h"
55#include "SimpleInputState.h"
56#include "ExtendedInputState.h"
57#include "JoyStickDeviceNumberListener.h"
58
59// HACK (include this as last, X11 seems to define some macros...)
60#ifdef ORXONOX_PLATFORM_LINUX
61#  include <ois/linux/LinuxMouse.h>
62#endif
63
64namespace orxonox
65{
66    SetConsoleCommand(InputManager, calibrate, true);
67    SetConsoleCommand(InputManager, reload, false);
68#ifdef ORXONOX_PLATFORM_LINUX
69    SetConsoleCommand(InputManager, grabMouse, true);
70    SetConsoleCommand(InputManager, ungrabMouse, true);
71#endif
72    SetCommandLineSwitch(keyboard_no_grab);
73
74    EmptyHandler InputManager::EMPTY_HANDLER;
75    InputManager* InputManager::singletonRef_s = 0;
76
77    using namespace InputDevice;
78
79    /**
80    @brief
81        Defines the |= operator for easier use.
82    */
83    inline InputManager::InputManagerState operator|=(InputManager::InputManagerState& lval,
84                                                      InputManager::InputManagerState rval)
85    {
86        return (lval = (InputManager::InputManagerState)(lval | rval));
87    }
88
89    /**
90    @brief
91        Defines the &= operator for easier use.
92    */
93    inline InputManager::InputManagerState operator&=(InputManager::InputManagerState& lval, int rval)
94    {
95        return (lval = (InputManager::InputManagerState)(lval & rval));
96    }
97
98    // ############################################################
99    // #####                  Initialisation                  #####
100    // ##########                                        ##########
101    // ############################################################
102
103    /**
104    @brief
105        Constructor only sets member fields to initial zero values
106        and registers the class in the class hierarchy.
107    */
108    InputManager::InputManager()
109        : inputSystem_(0)
110        , keyboard_(0)
111        , mouse_(0)
112        , joySticksSize_(0)
113        , devicesNum_(0)
114        , windowHnd_(0)
115        , internalState_(Uninitialised)
116        , stateEmpty_(0)
117        , keyDetector_(0)
118        , calibratorCallbackBuffer_(0)
119        , keyboardModifiers_(0)
120    {
121        RegisterRootObject(InputManager);
122
123        assert(singletonRef_s == 0);
124        singletonRef_s = this;
125
126        setConfigValues();
127    }
128
129    /**
130    @brief
131        Sets the configurable values.
132    */
133    void InputManager::setConfigValues()
134    {
135        SetConfigValue(calibrationFilename_, "joystick_calibration.ini")
136            .description("Ini filename for the the joy stick calibration data.")
137            .callback(this, &InputManager::_calibrationFileCallback);
138    }
139
140    /**
141    @brief
142        Callback for the joy stick calibration config file. @see setConfigValues.
143    */
144    void InputManager::_calibrationFileCallback()
145    {
146        ConfigFileManager::getInstance().setFilename(ConfigFileType::JoyStickCalibration, calibrationFilename_);
147    }
148
149    /**
150    @brief
151        Creates the OIS::InputMananger, the keyboard, the mouse and
152        the joysticks and assigns the key bindings.
153    @param windowHnd
154        The window handle of the render window
155    @param windowWidth
156        The width of the render window
157    @param windowHeight
158        The height of the render window
159    @param joyStickSupport
160        Whether or not to load the joy sticks as well
161    */
162    void InputManager::initialise(size_t windowHnd, int windowWidth, int windowHeight, bool joyStickSupport)
163    {
164        CCOUT(3) << "Initialising Input System..." << std::endl;
165
166        if (!(internalState_ & OISReady))
167        {
168            CCOUT(4) << "Initialising OIS components..." << std::endl;
169
170            // store handle internally so we can reload OIS
171            windowHnd_ = windowHnd;
172
173            OIS::ParamList paramList;
174            std::ostringstream windowHndStr;
175
176            // Fill parameter list
177            windowHndStr << (unsigned int)windowHnd_;
178            paramList.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
179            //paramList.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_NONEXCLUSIVE")));
180            //paramList.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_FOREGROUND")));
181#if defined ORXONOX_PLATFORM_LINUX
182            paramList.insert(std::make_pair(std::string("XAutoRepeatOn"), std::string("true")));
183            paramList.insert(std::make_pair(std::string("x11_mouse_grab"), "true"));
184            paramList.insert(std::make_pair(std::string("x11_mouse_hide"), "true"));
185            bool kbNoGrab;
186            CommandLine::getValue("keyboard_no_grab", &kbNoGrab);
187            if (kbNoGrab)
188                paramList.insert(std::make_pair(std::string("x11_keyboard_grab"), std::string("false")));
189            else
190                paramList.insert(std::make_pair(std::string("x11_keyboard_grab"), std::string("true")));
191#endif
192
193            inputSystem_ = OIS::InputManager::createInputSystem(paramList);
194            CCOUT(ORX_DEBUG) << "Created OIS input system" << std::endl;
195
196            _initialiseKeyboard();
197
198            _initialiseMouse();
199
200            if (joyStickSupport)
201                _initialiseJoySticks();
202            // Do this anyway to also inform everything when a joystick was detached.
203            _configureJoySticks();
204
205            // Set mouse/joystick region
206            if (mouse_)
207                setWindowExtents(windowWidth, windowHeight);
208
209            // clear all buffers
210            _clearBuffers();
211
212            internalState_ |= OISReady;
213
214            CCOUT(ORX_DEBUG) << "Initialising OIS components done." << std::endl;
215        }
216        else
217        {
218            CCOUT(2) << "Warning: OIS compoments already initialised, skipping" << std::endl;
219        }
220
221        if (!(internalState_ & InternalsReady))
222        {
223            CCOUT(4) << "Initialising InputStates components..." << std::endl;
224
225            // Lowest priority empty InputState
226            stateEmpty_ = createInputState<SimpleInputState>("empty", false, false, InputStatePriority::Empty);
227            stateEmpty_->setHandler(&EMPTY_HANDLER);
228            activeStates_[stateEmpty_->getPriority()] = stateEmpty_;
229
230            // KeyDetector to evaluate a pressed key's name
231            SimpleInputState* detector = createInputState<SimpleInputState>("detector", false, false, InputStatePriority::Detector);
232            keyDetector_ = new KeyDetector();
233            detector->setHandler(keyDetector_);
234
235            // Joy stick calibration helper callback
236            SimpleInputState* calibrator = createInputState<SimpleInputState>("calibrator", false, false, InputStatePriority::Calibrator);
237            calibrator->setHandler(&EMPTY_HANDLER);
238            calibratorCallbackBuffer_ = new InputBuffer();
239            calibratorCallbackBuffer_->registerListener(this, &InputManager::_completeCalibration, '\r', true);
240            calibrator->setKeyHandler(calibratorCallbackBuffer_);
241
242            internalState_ |= InternalsReady;
243
244            CCOUT(4) << "Initialising InputStates complete." << std::endl;
245        }
246
247        _updateActiveStates();
248
249        CCOUT(3) << "Initialising complete." << std::endl;
250    }
251
252    /**
253    @brief
254        Creates a keyboard and sets the event handler.
255    @return
256        False if keyboard stays uninitialised, true otherwise.
257    */
258    void InputManager::_initialiseKeyboard()
259    {
260        if (keyboard_ != 0)
261        {
262            CCOUT(2) << "Warning: Keyboard already initialised, skipping." << std::endl;
263            return;
264        }
265        if (inputSystem_->getNumberOfDevices(OIS::OISKeyboard) > 0)
266        {
267            keyboard_ = (OIS::Keyboard*)inputSystem_->createInputObject(OIS::OISKeyboard, true);
268            // register our listener in OIS.
269            keyboard_->setEventCallback(this);
270            // note: OIS will not detect keys that have already been down when the keyboard was created.
271            CCOUT(ORX_DEBUG) << "Created OIS keyboard" << std::endl;
272        }
273        else
274        {
275            ThrowException(InitialisationFailed, "No keyboard found!");
276        }
277    }
278
279    /**
280    @brief
281        Creates a mouse and sets the event handler.
282    @return
283        False if mouse stays uninitialised, true otherwise.
284    */
285    void InputManager::_initialiseMouse()
286    {
287        if (mouse_ != 0)
288        {
289            CCOUT(2) << "Warning: Mouse already initialised, skipping." << std::endl;
290            return;
291        }
292        try
293        {
294            if (inputSystem_->getNumberOfDevices(OIS::OISMouse) > 0)
295            {
296                mouse_ = static_cast<OIS::Mouse*>(inputSystem_->createInputObject(OIS::OISMouse, true));
297                // register our listener in OIS.
298                mouse_->setEventCallback(this);
299                CCOUT(ORX_DEBUG) << "Created OIS mouse" << std::endl;
300            }
301            else
302            {
303                CCOUT(ORX_WARNING) << "Warning: No mouse found!" << std::endl;
304            }
305        }
306        catch (OIS::Exception ex)
307        {
308            CCOUT(ORX_WARNING) << "Warning: Failed to create an OIS mouse\n"
309                << "OIS error message: \"" << ex.eText << "\"" << std::endl;
310            mouse_ = 0;
311        }
312    }
313
314    /**
315    @brief
316        Creates all joy sticks and sets the event handler.
317    @return
318        False joy stick stay uninitialised, true otherwise.
319    */
320    void InputManager::_initialiseJoySticks()
321    {
322        if (joySticksSize_ > 0)
323        {
324            CCOUT(2) << "Warning: Joy sticks already initialised, skipping." << std::endl;
325            return;
326        }
327        if (inputSystem_->getNumberOfDevices(OIS::OISJoyStick) > 0)
328        {
329            for (int i = 0; i < inputSystem_->getNumberOfDevices(OIS::OISJoyStick); i++)
330            {
331                try
332                {
333                    OIS::JoyStick* stig = static_cast<OIS::JoyStick*>
334                        (inputSystem_->createInputObject(OIS::OISJoyStick, true));
335                    CCOUT(ORX_DEBUG) << "Created OIS joy stick with ID " << stig->getID() << std::endl;
336                    joySticks_.push_back(stig);
337                    // register our listener in OIS.
338                    stig->setEventCallback(this);
339                }
340                catch (OIS::Exception ex)
341                {
342                    CCOUT(ORX_WARNING) << "Warning: Failed to create OIS joy number" << i << "\n"
343                        << "OIS error message: \"" << ex.eText << "\"" << std::endl;
344                }
345            }
346        }
347        else
348        {
349            //CCOUT(ORX_WARNING) << "Warning: Joy stick support requested, but no joy stick was found" << std::endl;
350        }
351    }
352
353    /**
354    @brief
355        Helper function that loads the config value vector of one coefficient
356    */
357    void loadCalibration(std::vector<int>& list, const std::string& sectionName, const std::string& valueName, size_t size, int defaultValue)
358    {
359        list.resize(size);
360        unsigned int configValueVectorSize = ConfigFileManager::getInstance().getVectorSize(ConfigFileType::JoyStickCalibration, sectionName, valueName);
361        if (configValueVectorSize > size)
362            configValueVectorSize = size;
363
364        for (unsigned int i = 0; i < configValueVectorSize; ++i)
365        {
366            list[i] = multi_cast<int>(ConfigFileManager::getInstance().getValue(
367                ConfigFileType::JoyStickCalibration, sectionName, valueName, i, multi_cast<std::string>(defaultValue), false));
368        }
369
370        // fill the rest with default values
371        for (unsigned int i = configValueVectorSize; i < size; ++i)
372        {
373            list[i] = defaultValue;
374        }
375    }
376
377    /**
378    @brief
379        Sets the size of all the different lists that are dependent on the number
380        of joy stick devices created and loads the joy stick calibration.
381    @remarks
382        No matter whether there are a mouse and/or keyboard, they will always
383        occupy 2 places in the device number dependent lists.
384    */
385    void InputManager::_configureJoySticks()
386    {
387        joySticksSize_ = joySticks_.size();
388        devicesNum_    = 2 + joySticksSize_;
389        joyStickIDs_         .resize(joySticksSize_);
390        joyStickButtonsDown_ .resize(joySticksSize_);
391        povStates_           .resize(joySticksSize_);
392        sliderStates_        .resize(joySticksSize_);
393        joyStickMinValues_   .resize(joySticksSize_);
394        joyStickMaxValues_   .resize(joySticksSize_);
395        joyStickMiddleValues_.resize(joySticksSize_);
396        joyStickCalibrations_.resize(joySticksSize_);
397
398        for (unsigned int iJoyStick = 0; iJoyStick < joySticksSize_; iJoyStick++)
399        {
400            // Generate some sort of execution unique id per joy stick
401            std::string id = "JoyStick_";
402            id += multi_cast<std::string>(joySticks_[iJoyStick]->getNumberOfComponents(OIS::OIS_Button))  + "_";
403            id += multi_cast<std::string>(joySticks_[iJoyStick]->getNumberOfComponents(OIS::OIS_Axis))    + "_";
404            id += multi_cast<std::string>(joySticks_[iJoyStick]->getNumberOfComponents(OIS::OIS_Slider))  + "_";
405            id += multi_cast<std::string>(joySticks_[iJoyStick]->getNumberOfComponents(OIS::OIS_POV))     + "_";
406            id += multi_cast<std::string>(joySticks_[iJoyStick]->getNumberOfComponents(OIS::OIS_Vector3)) + "_";
407            id += joySticks_[iJoyStick]->vendor();
408            for (unsigned int i = 0; i < iJoyStick; ++i)
409            {
410                if (id == joyStickIDs_[i])
411                {
412                    // Two joysticks are probably equal --> add the index as well
413                    id += "_" + multi_cast<std::string>(iJoyStick);
414                }
415            }
416            joyStickIDs_[iJoyStick] = id;
417
418            size_t axes = sliderAxes + (size_t)this->joySticks_[iJoyStick]->getNumberOfComponents(OIS::OIS_Axis);
419            loadCalibration(joyStickMinValues_[iJoyStick], id, "MinValue", axes, -32768);
420            loadCalibration(joyStickMaxValues_[iJoyStick], id, "MaxValue", axes,  32768);
421            loadCalibration(joyStickMiddleValues_[iJoyStick], id, "MiddleValue", axes,      0);
422        }
423
424        _evaluateCalibration();
425
426        // state management
427        activeStatesTriggered_.resize(devicesNum_);
428
429        // inform all states
430        for (std::map<std::string, InputState*>::const_iterator it = inputStatesByName_.begin();
431            it != inputStatesByName_.end(); ++it)
432        {
433            it->second->setNumOfJoySticks(joySticksSize_);
434        }
435
436        // inform all JoyStick Device Number Listeners
437        for (ObjectList<JoyStickDeviceNumberListener>::iterator it = ObjectList<JoyStickDeviceNumberListener>::begin(); it; ++it)
438            it->JoyStickDeviceNumberChanged(joySticksSize_);
439
440    }
441
442    void InputManager::_evaluateCalibration()
443    {
444        for (unsigned int iJoyStick = 0; iJoyStick < this->joySticksSize_; ++iJoyStick)
445        {
446            for (unsigned int i = 0; i < this->joyStickMinValues_[iJoyStick].size(); i++)
447            {
448                this->joyStickCalibrations_[iJoyStick].middleValue[i] = this->joyStickMiddleValues_[iJoyStick][i];
449                this->joyStickCalibrations_[iJoyStick].negativeCoeff[i] = - 1.0f / (this->joyStickMinValues_[iJoyStick][i] - this->joyStickMiddleValues_[iJoyStick][i]);
450                this->joyStickCalibrations_[iJoyStick].positiveCoeff[i] =   1.0f / (this->joyStickMaxValues_[iJoyStick][i] - this->joyStickMiddleValues_[iJoyStick][i]);
451            }
452        }
453    }
454
455    void InputManager::_startCalibration()
456    {
457        for (unsigned int iJoyStick = 0; iJoyStick < this->joySticksSize_; ++iJoyStick)
458        {
459            // Set initial values
460            for (unsigned int i = 0; i < this->joyStickMinValues_[iJoyStick].size(); ++i)
461                this->joyStickMinValues_[iJoyStick][i] = INT_MAX;
462            for (unsigned int i = 0; i < this->joyStickMaxValues_[iJoyStick].size(); ++i)
463                this->joyStickMaxValues_[iJoyStick][i] = INT_MIN;
464            for (unsigned int i = 0; i < this->joyStickMiddleValues_[iJoyStick].size(); ++i)
465                this->joyStickMiddleValues_[iJoyStick][i] = 0;
466        }
467
468        getInstance().internalState_ |= Calibrating;
469        getInstance().requestEnterState("calibrator");
470    }
471
472    void InputManager::_completeCalibration()
473    {
474        for (unsigned int iJoyStick = 0; iJoyStick < this->joySticksSize_; ++iJoyStick)
475        {
476            // Get the middle positions now
477            unsigned int iAxis = 0;
478            for (unsigned int i = 0; i < sliderAxes/2; ++i)
479            {
480                this->joyStickMiddleValues_[iJoyStick][iAxis++] = this->joySticks_[iJoyStick]->getJoyStickState().mSliders[i].abX;
481                this->joyStickMiddleValues_[iJoyStick][iAxis++] = this->joySticks_[iJoyStick]->getJoyStickState().mSliders[i].abY;
482            }
483            // Note: joyStickMiddleValues_[iJoyStick] was already correctly resized in _configureJoySticks()
484            assert(joySticks_[iJoyStick]->getJoyStickState().mAxes.size() == joyStickMiddleValues_[iJoyStick].size() - sliderAxes);
485            for (unsigned int i = 0; i < joyStickMiddleValues_[iJoyStick].size() - sliderAxes; ++i)
486            {
487                this->joyStickMiddleValues_[iJoyStick][iAxis++] = this->joySticks_[iJoyStick]->getJoyStickState().mAxes[i].abs;
488            }
489
490            for (unsigned int i = 0; i < joyStickMinValues_[iJoyStick].size(); ++i)
491            {
492                // Minimum values
493                if (joyStickMinValues_[iJoyStick][i] == INT_MAX)
494                    joyStickMinValues_[iJoyStick][i] = -32768;
495                ConfigFileManager::getInstance().setValue(ConfigFileType::JoyStickCalibration,
496                    this->joyStickIDs_[iJoyStick], "MinValue", i, multi_cast<std::string>(joyStickMinValues_[iJoyStick][i]), false);
497
498                // Maximum values
499                if (joyStickMaxValues_[iJoyStick][i] == INT_MIN)
500                    joyStickMaxValues_[iJoyStick][i] = 32767;
501                ConfigFileManager::getInstance().setValue(ConfigFileType::JoyStickCalibration,
502                    this->joyStickIDs_[iJoyStick], "MaxValue", i, multi_cast<std::string>(joyStickMaxValues_[iJoyStick][i]), false);
503
504                // Middle values
505                ConfigFileManager::getInstance().setValue(ConfigFileType::JoyStickCalibration,
506                    this->joyStickIDs_[iJoyStick], "MiddleValue", i, multi_cast<std::string>(joyStickMiddleValues_[iJoyStick][i]), false);
507            }
508        }
509
510        _evaluateCalibration();
511
512        // restore old input state
513        requestLeaveState("calibrator");
514        internalState_ &= ~Calibrating;
515    }
516
517    // ############################################################
518    // #####                    Destruction                   #####
519    // ##########                                        ##########
520    // ############################################################
521
522    /**
523    @brief
524        Destroys all the created input devices and states.
525    */
526    InputManager::~InputManager()
527    {
528        if (internalState_ != Uninitialised)
529        {
530            try
531            {
532                CCOUT(3) << "Destroying ..." << std::endl;
533
534                // kick all active states 'nicely'
535                for (std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin();
536                    rit != activeStates_.rend(); ++rit)
537                {
538                    (*rit).second->onLeave();
539                }
540
541                // Destroy calibrator helper handler and state
542                delete keyDetector_;
543                requestDestroyState("calibrator");
544                // Destroy KeyDetector and state
545                delete calibratorCallbackBuffer_;
546                requestDestroyState("detector");
547                // destroy the empty InputState
548                _destroyState(this->stateEmpty_);
549
550                // destroy all user InputStates
551                while (inputStatesByName_.size() > 0)
552                    _destroyState((*inputStatesByName_.rbegin()).second);
553
554                // destroy the devices
555                _destroyKeyboard();
556                _destroyMouse();
557                _destroyJoySticks();
558
559                OIS::InputManager::destroyInputSystem(inputSystem_);
560
561                CCOUT(3) << "Destroying done." << std::endl;
562            }
563            catch (OIS::Exception& ex)
564            {
565                CCOUT(1) << "An exception has occured while destroying:\n" << ex.what()
566                         << "This could lead to a possible memory/resource leak!" << std::endl;
567            }
568        }
569
570        singletonRef_s = 0;
571    }
572
573    /**
574    @brief
575        Destroys the keyboard and sets it to 0.
576    */
577    void InputManager::_destroyKeyboard()
578    {
579        assert(inputSystem_);
580        if (keyboard_)
581            inputSystem_->destroyInputObject(keyboard_);
582        keyboard_ = 0;
583        CCOUT(4) << "Keyboard destroyed." << std::endl;
584    }
585
586    /**
587    @brief
588        Destroys the mouse and sets it to 0.
589    */
590    void InputManager::_destroyMouse()
591    {
592        assert(inputSystem_);
593        if (mouse_)
594            inputSystem_->destroyInputObject(mouse_);
595        mouse_ = 0;
596        CCOUT(4) << "Mouse destroyed." << std::endl;
597    }
598
599    /**
600    @brief
601        Destroys all the joy sticks and resizes the lists to 0.
602    */
603    void InputManager::_destroyJoySticks()
604    {
605        if (joySticksSize_ > 0)
606        {
607            assert(inputSystem_);
608            for (unsigned int i = 0; i < joySticksSize_; i++)
609                if (joySticks_[i] != 0)
610                    inputSystem_->destroyInputObject(joySticks_[i]);
611
612            joySticks_.clear();
613            // don't use _configureNumberOfJoySticks(), might mess with registered handler if
614            // downgrading from 2 to 1 joystick
615            //_configureNumberOfJoySticks();
616            joySticksSize_ = 0;
617        }
618        CCOUT(4) << "Joy sticks destroyed." << std::endl;
619    }
620
621    /**
622    @brief
623        Removes and destroys an InputState.
624    @return
625        True if state was removed immediately, false if postponed.
626    */
627    void InputManager::_destroyState(InputState* state)
628    {
629        assert(state && !(this->internalState_ & Ticking));
630        std::map<int, InputState*>::iterator it = this->activeStates_.find(state->getPriority());
631        if (it != this->activeStates_.end())
632        {
633            this->activeStates_.erase(it);
634            _updateActiveStates();
635        }
636        inputStatesByName_.erase(state->getName());
637        delete state;
638    }
639
640    void InputManager::_clearBuffers()
641    {
642        keysDown_.clear();
643        keyboardModifiers_ = 0;
644        mouseButtonsDown_.clear();
645        for (unsigned int i = 0; i < joySticksSize_; ++i)
646        {
647            joyStickButtonsDown_[i].clear();
648            for (int j = 0; j < 4; ++j)
649            {
650                sliderStates_[i].sliderStates[j].x = 0;
651                sliderStates_[i].sliderStates[j].y = 0;
652                povStates_[i][j] = 0;
653            }
654        }
655    }
656
657
658    // ############################################################
659    // #####                     Reloading                    #####
660    // ##########                                        ##########
661    // ############################################################
662
663    /**
664    @brief
665        Public interface. Only reloads immediately if the call stack doesn't
666        include the update() method.
667    @param joyStickSupport
668        Whether or not to initialise joy sticks as well.
669    */
670    void InputManager::reloadInputSystem(bool joyStickSupport)
671    {
672        if (internalState_ & Ticking)
673        {
674            // We cannot destroy OIS right now, because reload was probably
675            // caused by a user clicking on a GUI item. The backtrace would then
676            // include an OIS method. So it would be a very bad thing to destroy it..
677            internalState_ |= ReloadRequest;
678            // Misuse of internalState_: We can easily store the joyStickSupport bool.
679            // use Uninitialised as 0 value in order to make use of the overloaded |= operator
680            internalState_ |= joyStickSupport ? JoyStickSupport : Uninitialised;
681        }
682        else if (internalState_ & OISReady)
683        {
684            _reload(joyStickSupport);
685        }
686        else
687        {
688            CCOUT(2) << "Warning: Cannot reload OIS. May not yet be initialised or"
689                     << "joy sticks are currently calibrating." << std::endl;
690        }
691    }
692
693    /**
694    @brief
695        Internal reload method. Destroys the OIS devices and loads them again.
696    */
697    void InputManager::_reload(bool joyStickSupport)
698    {
699        try
700        {
701            CCOUT(3) << "Reloading ..." << std::endl;
702
703            // Save mouse clipping size
704            int mouseWidth  = mouse_->getMouseState().width;
705            int mouseHeight = mouse_->getMouseState().height;
706
707            internalState_ &= ~OISReady;
708
709            // destroy the devices
710            _destroyKeyboard();
711            _destroyMouse();
712            _destroyJoySticks();
713
714            OIS::InputManager::destroyInputSystem(inputSystem_);
715            inputSystem_ = 0;
716
717            // clear all buffers containing input information
718            _clearBuffers();
719
720            initialise(windowHnd_, mouseWidth, mouseHeight, joyStickSupport);
721
722            CCOUT(3) << "Reloading done." << std::endl;
723        }
724        catch (OIS::Exception& ex)
725        {
726            CCOUT(1) << "An exception has occured while reloading:\n" << ex.what() << std::endl;
727        }
728    }
729
730    // ############################################################
731    // #####                  Runtime Methods                 #####
732    // ##########                                        ##########
733    // ############################################################
734
735    /**
736    @brief
737        Updates the states and the InputState situation.
738    @param time
739        Clock holding the current time.
740    */
741    void InputManager::update(const Clock& time)
742    {
743        if (internalState_ == Uninitialised)
744            return;
745        else if (internalState_ & ReloadRequest)
746        {
747            _reload(internalState_ & JoyStickSupport);
748            internalState_ &= ~ReloadRequest;
749            internalState_ &= ~JoyStickSupport;
750        }
751
752        // check for states to leave
753        if (!stateLeaveRequests_.empty())
754        {
755            for (std::set<InputState*>::iterator it = stateLeaveRequests_.begin();
756                it != stateLeaveRequests_.end(); ++it)
757            {
758                (*it)->onLeave();
759                // just to be sure that the state actually is registered
760                assert(inputStatesByName_.find((*it)->getName()) != inputStatesByName_.end());
761
762                activeStates_.erase((*it)->getPriority());
763                if ((*it)->getPriority() < InputStatePriority::HighPriority)
764                    (*it)->setPriority(0);
765                _updateActiveStates();
766            }
767            stateLeaveRequests_.clear();
768        }
769
770        // check for states to enter
771        if (!stateEnterRequests_.empty())
772        {
773            for (std::set<InputState*>::const_iterator it = stateEnterRequests_.begin();
774                it != stateEnterRequests_.end(); ++it)
775            {
776                // just to be sure that the state actually is registered
777                assert(inputStatesByName_.find((*it)->getName()) != inputStatesByName_.end());
778
779                if ((*it)->getPriority() == 0)
780                {
781                    // Get smallest possible priority between 1 and maxStateStackSize_s
782#if defined( __MINGW32__ ) // Avoid the strange mingw-stl bug with const_reverse_iterator
783                    for(std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin();
784                        rit != activeStates_.rend(); ++rit)
785#else
786                    for(std::map<int, InputState*>::const_reverse_iterator rit = activeStates_.rbegin();
787                        rit != activeStates_.rend(); ++rit)
788#endif
789                    {
790                        if (rit->first < InputStatePriority::HighPriority)
791                        {
792                            (*it)->setPriority(rit->first + 1);
793                            break;
794                        }
795                    }
796                    // In case no normal handler was on the stack
797                    if ((*it)->getPriority() == 0)
798                        (*it)->setPriority(1);
799                }
800                activeStates_[(*it)->getPriority()] = (*it);
801                _updateActiveStates();
802                (*it)->onEnter();
803            }
804            stateEnterRequests_.clear();
805        }
806
807        // check for states to destroy
808        if (!stateDestroyRequests_.empty())
809        {
810            for (std::set<InputState*>::iterator it = stateDestroyRequests_.begin();
811                it != stateDestroyRequests_.end(); ++it)
812            {
813                _destroyState((*it));
814            }
815            stateDestroyRequests_.clear();
816        }
817
818        // check whether a state has changed its EMPTY_HANDLER situation
819        bool bUpdateRequired = false;
820        for (std::map<int, InputState*>::iterator it = activeStates_.begin(); it != activeStates_.end(); ++it)
821        {
822            if (it->second->handlersChanged())
823            {
824                it->second->resetHandlersChanged();
825                bUpdateRequired = true;
826            }
827        }
828        if (bUpdateRequired)
829            _updateActiveStates();
830
831        // mark that we now start capturing and distributing input
832        internalState_ |= Ticking;
833
834        // Capture all the input. This calls the event handlers in InputManager.
835        if (keyboard_)
836            keyboard_->capture();
837        if (mouse_)
838            mouse_->capture();
839        for (unsigned  int i = 0; i < joySticksSize_; i++)
840            joySticks_[i]->capture();
841
842        if (!(internalState_ & Calibrating))
843        {
844            // call all the handlers for the held key events
845            for (unsigned int iKey = 0; iKey < keysDown_.size(); iKey++)
846            {
847                KeyEvent kEvt(keysDown_[iKey], keyboardModifiers_);
848
849                for (unsigned int iState = 0; iState < activeStatesTriggered_[Keyboard].size(); ++iState)
850                    activeStatesTriggered_[Keyboard][iState]->keyHeld(kEvt);
851            }
852
853            // call all the handlers for the held mouse button events
854            for (unsigned int iButton = 0; iButton < mouseButtonsDown_.size(); iButton++)
855            {
856                for (unsigned int iState = 0; iState < activeStatesTriggered_[Mouse].size(); ++iState)
857                    activeStatesTriggered_[Mouse][iState]->mouseButtonHeld(mouseButtonsDown_[iButton]);
858            }
859
860            // call all the handlers for the held joy stick button events
861            for (unsigned int iJoyStick  = 0; iJoyStick < joySticksSize_; iJoyStick++)
862                for (unsigned int iButton   = 0; iButton   < joyStickButtonsDown_[iJoyStick].size(); iButton++)
863                {
864                    for (unsigned int iState = 0; iState < activeStatesTriggered_[JoyStick0 + iJoyStick].size(); ++iState)
865                        activeStatesTriggered_[JoyStick0 + iJoyStick][iState]->joyStickButtonHeld(iJoyStick, joyStickButtonsDown_[iJoyStick][iButton]);
866                }
867
868            // update the handlers for each active handler
869            for (unsigned int i = 0; i < devicesNum_; ++i)
870            {
871                for (unsigned int iState = 0; iState < activeStatesTriggered_[i].size(); ++iState)
872                    activeStatesTriggered_[i][iState]->updateInput(time.getDeltaTime(), i);
873            }
874
875            // update the handler with a general tick afterwards
876            for (unsigned int i = 0; i < activeStatesTicked_.size(); ++i)
877                activeStatesTicked_[i]->updateInput(time.getDeltaTime());
878        }
879
880        internalState_ &= ~Ticking;
881    }
882
883    /**
884    @brief
885        Updates the currently active states (according to activeStates_) for each device.
886        Also, a list of all active states (no duplicates!) is compiled for the general update().
887    */
888    void InputManager::_updateActiveStates()
889    {
890        for (unsigned int i = 0; i < devicesNum_; ++i)
891        {
892            bool occupied = false;
893            activeStatesTriggered_[i].clear();
894#if defined( __MINGW32__ ) // Avoid the strange mingw-stl bug with const_reverse_iterator
895            for (std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin(); rit != activeStates_.rend(); ++rit)
896            {
897#else
898            for (std::map<int, InputState*>::const_reverse_iterator rit = activeStates_.rbegin(); rit != activeStates_.rend(); ++rit)
899            {
900#endif
901                if (rit->second->isInputDeviceEnabled(i) && (!occupied || rit->second->bAlwaysGetsInput_))
902                {
903                    activeStatesTriggered_[i].push_back(rit->second);
904                    if (!rit->second->bTransparent_)
905                        occupied = true;
906                }
907            }
908        }
909
910        // update tickables (every state will only appear once)
911        // Using a std::set to avoid duplicates
912        std::set<InputState*> tempSet;
913        for (unsigned int i = 0; i < devicesNum_; ++i)
914            for (unsigned int iState = 0; iState < activeStatesTriggered_[i].size(); ++iState)
915                tempSet.insert(activeStatesTriggered_[i][iState]);
916
917        // copy the content of the std::set back to the actual vector
918        activeStatesTicked_.clear();
919        for (std::set<InputState*>::const_iterator it = tempSet.begin();it != tempSet.end(); ++it)
920            activeStatesTicked_.push_back(*it);
921
922        this->mouseButtonsDown_.clear();
923    }
924
925    /**
926    @brief
927        Clears all buffers that store what keys/buttons are being pressed at the moment.
928    */
929    void InputManager::clearBuffers()
930    {
931        this->keysDown_.clear();
932        this->mouseButtonsDown_.clear();
933        for (unsigned int i = 0; i < this->joySticksSize_; ++i)
934            this->joyStickButtonsDown_[i].clear();
935    }
936
937
938    // ############################################################
939    // #####                    OIS events                    #####
940    // ##########                                        ##########
941    // ############################################################
942
943    // ###### Key Events ######
944
945    /**
946    @brief
947        Event handler for the keyPressed Event.
948    @param e
949        Event information
950    */
951    bool InputManager::keyPressed(const OIS::KeyEvent &e)
952    {
953        // check whether the key already is in the list (can happen when focus was lost)
954        unsigned int iKey = 0;
955        while (iKey < keysDown_.size() && keysDown_[iKey].key != (KeyCode::ByEnum)e.key)
956            iKey++;
957        if (iKey == keysDown_.size())
958            keysDown_.push_back(Key(e));
959        else
960        {
961            // This happens when XAutoRepeat is set under linux. The KeyPressed event gets then sent
962            // continuously.
963            return true;
964        }
965
966        // update modifiers
967        if(e.key == OIS::KC_RMENU    || e.key == OIS::KC_LMENU)
968            keyboardModifiers_ |= KeyboardModifier::Alt;   // alt key
969        if(e.key == OIS::KC_RCONTROL || e.key == OIS::KC_LCONTROL)
970            keyboardModifiers_ |= KeyboardModifier::Ctrl;  // ctrl key
971        if(e.key == OIS::KC_RSHIFT   || e.key == OIS::KC_LSHIFT)
972            keyboardModifiers_ |= KeyboardModifier::Shift; // shift key
973
974        KeyEvent kEvt(e, keyboardModifiers_);
975        for (unsigned int iState = 0; iState < activeStatesTriggered_[Keyboard].size(); ++iState)
976            activeStatesTriggered_[Keyboard][iState]->keyPressed(kEvt);
977
978        return true;
979    }
980
981    /**
982    @brief
983        Event handler for the keyReleased Event.
984    @param e
985        Event information
986    */
987    bool InputManager::keyReleased(const OIS::KeyEvent &e)
988    {
989        // remove the key from the keysDown_ list
990        for (unsigned int iKey = 0; iKey < keysDown_.size(); iKey++)
991        {
992            if (keysDown_[iKey].key == (KeyCode::ByEnum)e.key)
993            {
994                keysDown_.erase(keysDown_.begin() + iKey);
995                break;
996            }
997        }
998
999        // update modifiers
1000        if(e.key == OIS::KC_RMENU    || e.key == OIS::KC_LMENU)
1001            keyboardModifiers_ &= ~KeyboardModifier::Alt;   // alt key
1002        if(e.key == OIS::KC_RCONTROL || e.key == OIS::KC_LCONTROL)
1003            keyboardModifiers_ &= ~KeyboardModifier::Ctrl;  // ctrl key
1004        if(e.key == OIS::KC_RSHIFT   || e.key == OIS::KC_LSHIFT)
1005            keyboardModifiers_ &= ~KeyboardModifier::Shift; // shift key
1006
1007        KeyEvent kEvt(e, keyboardModifiers_);
1008        for (unsigned int iState = 0; iState < activeStatesTriggered_[Keyboard].size(); ++iState)
1009            activeStatesTriggered_[Keyboard][iState]->keyReleased(kEvt);
1010
1011        return true;
1012    }
1013
1014
1015    // ###### Mouse Events ######
1016
1017    /**
1018    @brief
1019        Event handler for the mouseMoved Event.
1020    @param e
1021        Event information
1022    */
1023    bool InputManager::mouseMoved(const OIS::MouseEvent &e)
1024    {
1025        // check for actual moved event
1026        if (e.state.X.rel != 0 || e.state.Y.rel != 0)
1027        {
1028            IntVector2 abs(e.state.X.abs, e.state.Y.abs);
1029            IntVector2 rel(e.state.X.rel, e.state.Y.rel);
1030            IntVector2 clippingSize(e.state.width, e.state.height);
1031            for (unsigned int iState = 0; iState < activeStatesTriggered_[Mouse].size(); ++iState)
1032                activeStatesTriggered_[Mouse][iState]->mouseMoved(abs, rel, clippingSize);
1033        }
1034
1035        // check for mouse scrolled event
1036        if (e.state.Z.rel != 0)
1037        {
1038            for (unsigned int iState = 0; iState < activeStatesTriggered_[Mouse].size(); ++iState)
1039                activeStatesTriggered_[Mouse][iState]->mouseScrolled(e.state.Z.abs, e.state.Z.rel);
1040        }
1041
1042        return true;
1043    }
1044
1045    /**
1046    @brief
1047        Event handler for the mousePressed Event.
1048    @param e
1049        Event information
1050    @param id
1051        The ID of the mouse button
1052    */
1053    bool InputManager::mousePressed(const OIS::MouseEvent &e, OIS::MouseButtonID id)
1054    {
1055        // check whether the button already is in the list (can happen when focus was lost)
1056        unsigned int iButton = 0;
1057        while (iButton < mouseButtonsDown_.size() && mouseButtonsDown_[iButton] != (MouseButtonCode::ByEnum)id)
1058            iButton++;
1059        if (iButton == mouseButtonsDown_.size())
1060            mouseButtonsDown_.push_back((MouseButtonCode::ByEnum)id);
1061
1062        for (unsigned int iState = 0; iState < activeStatesTriggered_[Mouse].size(); ++iState)
1063            activeStatesTriggered_[Mouse][iState]->mouseButtonPressed((MouseButtonCode::ByEnum)id);
1064
1065        return true;
1066    }
1067
1068    /**
1069    @brief
1070        Event handler for the mouseReleased Event.
1071    @param e
1072        Event information
1073    @param id
1074        The ID of the mouse button
1075    */
1076    bool InputManager::mouseReleased(const OIS::MouseEvent &e, OIS::MouseButtonID id)
1077    {
1078        // remove the button from the keysDown_ list
1079        for (unsigned int iButton = 0; iButton < mouseButtonsDown_.size(); iButton++)
1080        {
1081            if (mouseButtonsDown_[iButton] == (MouseButtonCode::ByEnum)id)
1082            {
1083                mouseButtonsDown_.erase(mouseButtonsDown_.begin() + iButton);
1084                break;
1085            }
1086        }
1087
1088        for (unsigned int iState = 0; iState < activeStatesTriggered_[Mouse].size(); ++iState)
1089            activeStatesTriggered_[Mouse][iState]->mouseButtonReleased((MouseButtonCode::ByEnum)id);
1090
1091        return true;
1092    }
1093
1094
1095    // ###### Joy Stick Events ######
1096
1097    /**
1098    @brief
1099        Returns the joy stick ID (orxonox) according to a OIS::JoyStickEvent
1100    */
1101    inline unsigned int InputManager::_getJoystick(const OIS::JoyStickEvent& arg)
1102    {
1103        // use the device to identify which one called the method
1104        OIS::JoyStick* joyStick = (OIS::JoyStick*)arg.device;
1105        unsigned int iJoyStick = 0;
1106        while (joySticks_[iJoyStick] != joyStick)
1107            iJoyStick++;
1108        // assert: Unknown joystick fired an event.
1109        assert(iJoyStick != joySticksSize_);
1110        return iJoyStick;
1111    }
1112
1113    bool InputManager::buttonPressed(const OIS::JoyStickEvent &arg, int button)
1114    {
1115        unsigned int iJoyStick = _getJoystick(arg);
1116
1117        // check whether the button already is in the list (can happen when focus was lost)
1118        std::vector<JoyStickButtonCode::ByEnum>& buttonsDown = joyStickButtonsDown_[iJoyStick];
1119        unsigned int iButton = 0;
1120        while (iButton < buttonsDown.size() && buttonsDown[iButton] != button)
1121            iButton++;
1122        if (iButton == buttonsDown.size())
1123            buttonsDown.push_back((JoyStickButtonCode::ByEnum)button);
1124
1125        for (unsigned int iState = 0; iState < activeStatesTriggered_[2 + iJoyStick].size(); ++iState)
1126            activeStatesTriggered_[2 + iJoyStick][iState]->joyStickButtonPressed(iJoyStick, (JoyStickButtonCode::ByEnum)button);
1127
1128        return true;
1129    }
1130
1131    bool InputManager::buttonReleased(const OIS::JoyStickEvent &arg, int button)
1132    {
1133        unsigned int iJoyStick = _getJoystick(arg);
1134
1135        // remove the button from the joyStickButtonsDown_ list
1136        std::vector<JoyStickButtonCode::ByEnum>& buttonsDown = joyStickButtonsDown_[iJoyStick];
1137        for (unsigned int iButton = 0; iButton < buttonsDown.size(); iButton++)
1138        {
1139            if (buttonsDown[iButton] == button)
1140            {
1141                buttonsDown.erase(buttonsDown.begin() + iButton);
1142                break;
1143            }
1144        }
1145
1146        for (unsigned int iState = 0; iState < activeStatesTriggered_[2 + iJoyStick].size(); ++iState)
1147            activeStatesTriggered_[2 + iJoyStick][iState]->joyStickButtonReleased(iJoyStick, (JoyStickButtonCode::ByEnum)button);
1148
1149        return true;
1150    }
1151
1152    /**
1153    @brief
1154        Calls the states for a particular axis with our enumeration.
1155        Used by OIS sliders and OIS axes.
1156    */
1157    void InputManager::_fireAxis(unsigned int iJoyStick, int axis, int value)
1158    {
1159        if (internalState_ & Calibrating)
1160        {
1161            if (value < joyStickMinValues_[iJoyStick][axis])
1162                joyStickMinValues_[iJoyStick][axis] = value;
1163            if (value > joyStickMaxValues_[iJoyStick][axis])
1164                joyStickMaxValues_[iJoyStick][axis] = value;
1165        }
1166        else
1167        {
1168            float fValue = static_cast<float>(value - joyStickCalibrations_[iJoyStick].middleValue[axis]);
1169            if (fValue > 0.0f)
1170                fValue *= joyStickCalibrations_[iJoyStick].positiveCoeff[axis];
1171            else
1172                fValue *= joyStickCalibrations_[iJoyStick].negativeCoeff[axis];
1173
1174            for (unsigned int iState = 0; iState < activeStatesTriggered_[2 + iJoyStick].size(); ++iState)
1175                activeStatesTriggered_[2 + iJoyStick][iState]->joyStickAxisMoved(iJoyStick, axis, fValue);
1176        }
1177    }
1178
1179    bool InputManager::axisMoved(const OIS::JoyStickEvent &arg, int axis)
1180    {
1181        unsigned int iJoyStick = _getJoystick(arg);
1182
1183        // keep in mind that the first 8 axes are reserved for the sliders
1184        _fireAxis(iJoyStick, axis + sliderAxes, arg.state.mAxes[axis].abs);
1185
1186        return true;
1187    }
1188
1189    bool InputManager::sliderMoved(const OIS::JoyStickEvent &arg, int id)
1190    {
1191        unsigned int iJoyStick = _getJoystick(arg);
1192
1193        if (sliderStates_[iJoyStick].sliderStates[id].x != arg.state.mSliders[id].abX)
1194            _fireAxis(iJoyStick, id * 2, arg.state.mSliders[id].abX);
1195        else if (sliderStates_[iJoyStick].sliderStates[id].y != arg.state.mSliders[id].abY)
1196            _fireAxis(iJoyStick, id * 2 + 1, arg.state.mSliders[id].abY);
1197
1198        return true;
1199    }
1200
1201    bool InputManager::povMoved(const OIS::JoyStickEvent &arg, int id)
1202    {
1203        unsigned int iJoyStick = _getJoystick(arg);
1204
1205        // translate the POV into 8 simple buttons
1206
1207        int lastState = povStates_[iJoyStick][id];
1208        if (lastState & OIS::Pov::North)
1209            buttonReleased(arg, 32 + id * 4 + 0);
1210        if (lastState & OIS::Pov::South)
1211            buttonReleased(arg, 32 + id * 4 + 1);
1212        if (lastState & OIS::Pov::East)
1213            buttonReleased(arg, 32 + id * 4 + 2);
1214        if (lastState & OIS::Pov::West)
1215            buttonReleased(arg, 32 + id * 4 + 3);
1216
1217        povStates_[iJoyStick].povStates[id] = arg.state.mPOV[id].direction;
1218
1219        int currentState = povStates_[iJoyStick][id];
1220        if (currentState & OIS::Pov::North)
1221            buttonPressed(arg, 32 + id * 4 + 0);
1222        if (currentState & OIS::Pov::South)
1223            buttonPressed(arg, 32 + id * 4 + 1);
1224        if (currentState & OIS::Pov::East)
1225            buttonPressed(arg, 32 + id * 4 + 2);
1226        if (currentState & OIS::Pov::West)
1227            buttonPressed(arg, 32 + id * 4 + 3);
1228
1229        return true;
1230    }
1231
1232
1233    // ############################################################
1234    // #####         Other Public Interface Methods           #####
1235    // ##########                                        ##########
1236    // ############################################################
1237
1238    /**
1239    @brief
1240        Adjusts the mouse window metrics.
1241        This method has to be called every time the size of the window changes.
1242    @param width
1243        The new width of the render window
1244    @param^height
1245        The new height of the render window
1246    */
1247    void InputManager::setWindowExtents(const int width, const int height)
1248    {
1249        if (mouse_)
1250        {
1251            // Set mouse region (if window resizes, we should alter this to reflect as well)
1252            mouse_->getMouseState().width  = width;
1253            mouse_->getMouseState().height = height;
1254        }
1255    }
1256
1257    /**
1258    @brief
1259        Sets the the name of the command used by the KeyDetector as callback.
1260    @param command
1261        Command name as string
1262    */
1263    void InputManager::setKeyDetectorCallback(const std::string& command)
1264    {
1265        this->keyDetector_->setCallbackCommand(command);
1266    }
1267
1268    // ###### InputStates ######
1269
1270    /**
1271    @brief
1272        Adds a new key handler.
1273    @param handler
1274        Pointer to the handler object.
1275    @param name
1276        Unique name of the handler.
1277    @param priority
1278        Determines which InputState gets the input. Higher is better.
1279        Use 0 to handle it implicitely by the order of activation.
1280        Otherwise numbers larger than maxStateStackSize_s have to be used!
1281    @return
1282        True if added, false if name or priority already existed.
1283    */
1284    bool InputManager::_configureInputState(InputState* state, const std::string& name, bool bAlwaysGetsInput, bool bTransparent, int priority)
1285    {
1286        if (name == "")
1287            return false;
1288        if (!state)
1289            return false;
1290        if (inputStatesByName_.find(name) == inputStatesByName_.end())
1291        {
1292            if (priority >= InputStatePriority::HighPriority || priority == InputStatePriority::Empty)
1293            {
1294                // Make sure we don't add two high priority states with the same priority
1295                for (std::map<std::string, InputState*>::const_iterator it = this->inputStatesByName_.begin();
1296                    it != this->inputStatesByName_.end(); ++it)
1297                {
1298                    if (it->second->getPriority() == priority)
1299                    {
1300                        COUT(2) << "Warning: Could not add an InputState with the same priority '"
1301                            << priority << "' != 0." << std::endl;
1302                        return false;
1303                    }
1304                }
1305            }
1306            inputStatesByName_[name] = state;
1307            state->setNumOfJoySticks(numberOfJoySticks());
1308            state->setName(name);
1309            state->bAlwaysGetsInput_ = bAlwaysGetsInput;
1310            state->bTransparent_ = bTransparent;
1311            if (priority >= InputStatePriority::HighPriority || priority == InputStatePriority::Empty)
1312                state->setPriority(priority);
1313            return true;
1314        }
1315        else
1316        {
1317            COUT(2) << "Warning: Could not add an InputState with the same name '" << name << "'." << std::endl;
1318            return false;
1319        }
1320    }
1321
1322    /**
1323    @brief
1324        Removes and destroys an input state internally.
1325    @param name
1326        Name of the handler.
1327    @return
1328        True if removal was successful, false if name was not found.
1329    @remarks
1330        You can't remove the internal states "empty", "calibrator" and "detector".
1331        The removal process is being postponed if InputManager::update() is currently running.
1332    */
1333    bool InputManager::requestDestroyState(const std::string& name)
1334    {
1335        if (name == "empty")
1336        {
1337            COUT(2) << "InputManager: Removing the empty state is not allowed!" << std::endl;
1338            return false;
1339        }
1340        std::map<std::string, InputState*>::iterator it = inputStatesByName_.find(name);
1341        if (it != inputStatesByName_.end())
1342        {
1343            if (activeStates_.find(it->second->getPriority()) != activeStates_.end())
1344            {
1345                // The state is still active. We have to postpone
1346                stateLeaveRequests_.insert(it->second);
1347                stateDestroyRequests_.insert(it->second);
1348            }
1349            else if (this->internalState_ & Ticking)
1350            {
1351                // cannot remove state while ticking
1352                stateDestroyRequests_.insert(it->second);
1353            }
1354            else
1355                _destroyState(it->second);
1356
1357            return true;
1358        }
1359        return false;
1360    }
1361
1362    /**
1363    @brief
1364        Returns the pointer to the requested InputState.
1365    @param name
1366        Unique name of the state.
1367    @return
1368        Pointer to the instance, 0 if name was not found.
1369    */
1370    InputState* InputManager::getState(const std::string& name)
1371    {
1372        std::map<std::string, InputState*>::iterator it = inputStatesByName_.find(name);
1373        if (it != inputStatesByName_.end())
1374            return it->second;
1375        else
1376            return 0;
1377    }
1378
1379    /**
1380    @brief
1381        Returns the current input state (there might be others active too!)
1382    @return
1383        The current highest prioritised active input state.
1384    */
1385    InputState* InputManager::getCurrentState()
1386    {
1387        return (*activeStates_.rbegin()).second;
1388    }
1389
1390    /**
1391    @brief
1392        Activates a specific input state.
1393        It might not be really activated if the priority is too low!
1394    @param name
1395        Unique name of the state.
1396    @return
1397        False if name was not found, true otherwise.
1398    */
1399    bool InputManager::requestEnterState(const std::string& name)
1400    {
1401        // get pointer from the map with all stored handlers
1402        std::map<std::string, InputState*>::const_iterator it = inputStatesByName_.find(name);
1403        if (it != inputStatesByName_.end())
1404        {
1405            // exists
1406            if (activeStates_.find(it->second->getPriority()) == activeStates_.end())
1407            {
1408                // not active
1409                if (stateDestroyRequests_.find(it->second) == stateDestroyRequests_.end())
1410                {
1411                    // not scheduled for destruction
1412                    // prevents a state being added multiple times
1413                    stateEnterRequests_.insert(it->second);
1414                    return true;
1415                }
1416            }
1417        }
1418        return false;
1419    }
1420
1421    /**
1422    @brief
1423        Deactivates a specific input state.
1424    @param name
1425        Unique name of the state.
1426    @return
1427        False if name was not found, true otherwise.
1428    */
1429    bool InputManager::requestLeaveState(const std::string& name)
1430    {
1431        if (name == "empty")
1432        {
1433            COUT(2) << "InputManager: Leaving the empty state is not allowed!" << std::endl;
1434            return false;
1435        }
1436        // get pointer from the map with all stored handlers
1437        std::map<std::string, InputState*>::const_iterator it = inputStatesByName_.find(name);
1438        if (it != inputStatesByName_.end())
1439        {
1440            // exists
1441            if (activeStates_.find(it->second->getPriority()) != activeStates_.end())
1442            {
1443                // active
1444                stateLeaveRequests_.insert(it->second);
1445                return true;
1446            }
1447        }
1448        return false;
1449    }
1450
1451
1452    // ############################################################
1453    // #####                Console Commands                  #####
1454    // ##########                                        ##########
1455    // ############################################################
1456
1457    /**
1458    @brief
1459        Starts joy stick calibration.
1460    */
1461    void InputManager::calibrate()
1462    {
1463        COUT(0) << "Move all joy stick axes fully in all directions." << std::endl
1464                << "When done, put the axex in the middle position and press enter." << std::endl;
1465
1466        getInstance()._startCalibration();
1467    }
1468
1469    /**
1470    @brief
1471        Reloads the input system
1472    */
1473    void InputManager::reload(bool joyStickSupport)
1474    {
1475        getInstance().reloadInputSystem(joyStickSupport);
1476    }
1477
1478
1479    // ############################################################
1480    // #####                   ugly hacks                     #####
1481    // ##########                                        ##########
1482    // ############################################################
1483
1484#ifdef ORXONOX_PLATFORM_LINUX
1485    void InputManager::grabMouse()
1486    {
1487        OIS::LinuxMouse* linuxMouse = dynamic_cast<OIS::LinuxMouse*>(singletonRef_s->mouse_);
1488        assert(linuxMouse);
1489        linuxMouse->grab(true);
1490    }
1491
1492    void InputManager::ungrabMouse()
1493    {
1494        OIS::LinuxMouse* linuxMouse = dynamic_cast<OIS::LinuxMouse*>(singletonRef_s->mouse_);
1495        assert(linuxMouse);
1496        linuxMouse->grab(false);
1497    }
1498#endif
1499}
Note: See TracBrowser for help on using the repository browser.