Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/toonshader/src/core/input/InputManager.cc @ 3825

Last change on this file since 3825 was 2896, checked in by landauf, 16 years ago

Merged gui branch back to trunk.

I did 2 small changes in IngameManager.cc on line 777 and 888 (yes, really), because const_reverse_iterator strangely doesn't work on MinGW.

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