Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/core/input/InputManager.cc @ 3196

Last change on this file since 3196 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
RevLine 
[918]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
[1502]3 *                    > www.orxonox.net <
[918]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:
[934]25 *      ...
[918]26 *
27 */
[973]28
[918]29/**
[1755]30@file
31@brief
32    Implementation of the InputManager that captures all the input from OIS
33    and redirects it to handlers.
[918]34 */
35
[1062]36#include "InputManager.h"
[1519]37
[1755]38#include <climits>
39#include <cassert>
[3196]40#include <ois/OISException.h>
41#include <ois/OISInputManager.h>
[1555]42
[3196]43#include "util/Convert.h"
[1764]44#include "util/Exception.h"
[3196]45#include "util/Debug.h"
[2896]46#include "core/Clock.h"
[1519]47#include "core/CoreIncludes.h"
48#include "core/ConfigValueIncludes.h"
[3196]49#include "core/ConsoleCommand.h"
[1934]50#include "core/CommandLine.h"
[1555]51
[1219]52#include "InputBuffer.h"
[1520]53#include "KeyDetector.h"
[1755]54#include "InputState.h"
55#include "SimpleInputState.h"
56#include "ExtendedInputState.h"
[1887]57#include "JoyStickDeviceNumberListener.h"
[918]58
[3196]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
[918]64namespace orxonox
65{
[1755]66    SetConsoleCommand(InputManager, calibrate, true);
67    SetConsoleCommand(InputManager, reload, false);
[3084]68#ifdef ORXONOX_PLATFORM_LINUX
69    SetConsoleCommand(InputManager, grabMouse, true);
70    SetConsoleCommand(InputManager, ungrabMouse, true);
71#endif
[1934]72    SetCommandLineSwitch(keyboard_no_grab);
[1502]73
[1878]74    EmptyHandler InputManager::EMPTY_HANDLER;
[1755]75    InputManager* InputManager::singletonRef_s = 0;
[1084]76
[1755]77    using namespace InputDevice;
[929]78
[1755]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    }
[919]88
[1755]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    }
[1219]97
[1755]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)
[1881]117        , keyDetector_(0)
118        , calibratorCallbackBuffer_(0)
[1755]119        , keyboardModifiers_(0)
[918]120    {
[1755]121        RegisterRootObject(InputManager);
[1219]122
[1755]123        assert(singletonRef_s == 0);
124        singletonRef_s = this;
[2662]125
126        setConfigValues();
[1755]127    }
[918]128
[1755]129    /**
130    @brief
[2662]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
[1755]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")));
[2896]181#if defined ORXONOX_PLATFORM_LINUX
[1755]182            paramList.insert(std::make_pair(std::string("XAutoRepeatOn"), std::string("true")));
[1934]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")));
[1735]191#endif
[928]192
[1755]193            inputSystem_ = OIS::InputManager::createInputSystem(paramList);
194            CCOUT(ORX_DEBUG) << "Created OIS input system" << std::endl;
[1219]195
[1755]196            _initialiseKeyboard();
[1219]197
[1755]198            _initialiseMouse();
[1219]199
[1755]200            if (joyStickSupport)
201                _initialiseJoySticks();
[2662]202            // Do this anyway to also inform everything when a joystick was detached.
203            _configureJoySticks();
[1219]204
[1755]205            // Set mouse/joystick region
206            if (mouse_)
207                setWindowExtents(windowWidth, windowHeight);
[1219]208
[1755]209            // clear all buffers
210            _clearBuffers();
[1502]211
[1755]212            internalState_ |= OISReady;
[1502]213
[1755]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        }
[1502]220
[1755]221        if (!(internalState_ & InternalsReady))
222        {
223            CCOUT(4) << "Initialising InputStates components..." << std::endl;
[1502]224
[1881]225            // Lowest priority empty InputState
[2896]226            stateEmpty_ = createInputState<SimpleInputState>("empty", false, false, InputStatePriority::Empty);
[1878]227            stateEmpty_->setHandler(&EMPTY_HANDLER);
[1755]228            activeStates_[stateEmpty_->getPriority()] = stateEmpty_;
[1502]229
[1881]230            // KeyDetector to evaluate a pressed key's name
[2896]231            SimpleInputState* detector = createInputState<SimpleInputState>("detector", false, false, InputStatePriority::Detector);
[1881]232            keyDetector_ = new KeyDetector();
233            detector->setHandler(keyDetector_);
234
235            // Joy stick calibration helper callback
[2896]236            SimpleInputState* calibrator = createInputState<SimpleInputState>("calibrator", false, false, InputStatePriority::Calibrator);
[1881]237            calibrator->setHandler(&EMPTY_HANDLER);
238            calibratorCallbackBuffer_ = new InputBuffer();
239            calibratorCallbackBuffer_->registerListener(this, &InputManager::_completeCalibration, '\r', true);
240            calibrator->setKeyHandler(calibratorCallbackBuffer_);
241
[1755]242            internalState_ |= InternalsReady;
243
244            CCOUT(4) << "Initialising InputStates complete." << std::endl;
245        }
246
247        _updateActiveStates();
248
249        CCOUT(3) << "Initialising complete." << std::endl;
[1219]250    }
[928]251
[1755]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()
[1219]259    {
[1755]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        }
[1219]277    }
[1035]278
[1755]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()
[1219]286    {
[1755]287        if (mouse_ != 0)
288        {
289            CCOUT(2) << "Warning: Mouse already initialised, skipping." << std::endl;
290            return;
291        }
[1219]292        try
293        {
[1755]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            }
[1219]305        }
306        catch (OIS::Exception ex)
307        {
[1755]308            CCOUT(ORX_WARNING) << "Warning: Failed to create an OIS mouse\n"
309                << "OIS error message: \"" << ex.eText << "\"" << std::endl;
310            mouse_ = 0;
[1219]311        }
312    }
[1755]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()
[1219]321    {
[1755]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        }
[1219]351    }
[1035]352
[1755]353    /**
354    @brief
[2662]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        {
[3196]366            list[i] = multi_cast<int>(ConfigFileManager::getInstance().getValue(
367                ConfigFileType::JoyStickCalibration, sectionName, valueName, i, multi_cast<std::string>(defaultValue), false));
[2662]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
[1755]379        Sets the size of all the different lists that are dependent on the number
[2662]380        of joy stick devices created and loads the joy stick calibration.
[1755]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    */
[2662]385    void InputManager::_configureJoySticks()
[1505]386    {
[1755]387        joySticksSize_ = joySticks_.size();
[2662]388        devicesNum_    = 2 + joySticksSize_;
389        joyStickIDs_         .resize(joySticksSize_);
[1755]390        joyStickButtonsDown_ .resize(joySticksSize_);
391        povStates_           .resize(joySticksSize_);
392        sliderStates_        .resize(joySticksSize_);
[2662]393        joyStickMinValues_   .resize(joySticksSize_);
394        joyStickMaxValues_   .resize(joySticksSize_);
395        joyStickMiddleValues_.resize(joySticksSize_);
396        joyStickCalibrations_.resize(joySticksSize_);
[1502]397
[1755]398        for (unsigned int iJoyStick = 0; iJoyStick < joySticksSize_; iJoyStick++)
399        {
[2662]400            // Generate some sort of execution unique id per joy stick
401            std::string id = "JoyStick_";
[3196]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)) + "_";
[2662]407            id += joySticks_[iJoyStick]->vendor();
408            for (unsigned int i = 0; i < iJoyStick; ++i)
[1755]409            {
[2662]410                if (id == joyStickIDs_[i])
411                {
412                    // Two joysticks are probably equal --> add the index as well
[3196]413                    id += "_" + multi_cast<std::string>(iJoyStick);
[2662]414                }
[1755]415            }
[2662]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);
[1755]422        }
[1505]423
[2662]424        _evaluateCalibration();
425
[1755]426        // state management
[2896]427        activeStatesTriggered_.resize(devicesNum_);
[1505]428
[1755]429        // inform all states
[2896]430        for (std::map<std::string, InputState*>::const_iterator it = inputStatesByName_.begin();
431            it != inputStatesByName_.end(); ++it)
[1887]432        {
[1755]433            it->second->setNumOfJoySticks(joySticksSize_);
[1887]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
[1505]440    }
[1502]441
[2662]442    void InputManager::_evaluateCalibration()
[1219]443    {
[2662]444        for (unsigned int iJoyStick = 0; iJoyStick < this->joySticksSize_; ++iJoyStick)
[1755]445        {
[2662]446            for (unsigned int i = 0; i < this->joyStickMinValues_[iJoyStick].size(); i++)
[1755]447            {
[2662]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]);
[1755]451            }
[2662]452        }
453    }
[2896]454
[2662]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        }
[1293]467
[2662]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)
[1755]479            {
[2662]480                this->joyStickMiddleValues_[iJoyStick][iAxis++] = this->joySticks_[iJoyStick]->getJoyStickState().mSliders[i].abX;
481                this->joyStickMiddleValues_[iJoyStick][iAxis++] = this->joySticks_[iJoyStick]->getJoyStickState().mSliders[i].abY;
[1755]482            }
[2662]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)
[1755]486            {
[2662]487                this->joyStickMiddleValues_[iJoyStick][iAxis++] = this->joySticks_[iJoyStick]->getJoyStickState().mAxes[i].abs;
[1755]488            }
[1219]489
[2662]490            for (unsigned int i = 0; i < joyStickMinValues_[iJoyStick].size(); ++i)
[1755]491            {
[2662]492                // Minimum values
493                if (joyStickMinValues_[iJoyStick][i] == INT_MAX)
494                    joyStickMinValues_[iJoyStick][i] = -32768;
495                ConfigFileManager::getInstance().setValue(ConfigFileType::JoyStickCalibration,
[3196]496                    this->joyStickIDs_[iJoyStick], "MinValue", i, multi_cast<std::string>(joyStickMinValues_[iJoyStick][i]), false);
[1502]497
[2662]498                // Maximum values
499                if (joyStickMaxValues_[iJoyStick][i] == INT_MIN)
500                    joyStickMaxValues_[iJoyStick][i] = 32767;
501                ConfigFileManager::getInstance().setValue(ConfigFileType::JoyStickCalibration,
[3196]502                    this->joyStickIDs_[iJoyStick], "MaxValue", i, multi_cast<std::string>(joyStickMaxValues_[iJoyStick][i]), false);
[2662]503
504                // Middle values
505                ConfigFileManager::getInstance().setValue(ConfigFileType::JoyStickCalibration,
[3196]506                    this->joyStickIDs_[iJoyStick], "MiddleValue", i, multi_cast<std::string>(joyStickMiddleValues_[iJoyStick][i]), false);
[1755]507            }
508        }
[2662]509
510        _evaluateCalibration();
511
512        // restore old input state
513        requestLeaveState("calibrator");
514        internalState_ &= ~Calibrating;
[1219]515    }
[928]516
[1755]517    // ############################################################
518    // #####                    Destruction                   #####
519    // ##########                                        ##########
520    // ############################################################
[1219]521
[1755]522    /**
523    @brief
524        Destroys all the created input devices and states.
525    */
526    InputManager::~InputManager()
[1219]527    {
[1755]528        if (internalState_ != Uninitialised)
529        {
530            try
531            {
532                CCOUT(3) << "Destroying ..." << std::endl;
[1219]533
[1755]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                }
[1502]540
[1881]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_);
[1788]549
[1881]550                // destroy all user InputStates
[2896]551                while (inputStatesByName_.size() > 0)
552                    _destroyState((*inputStatesByName_.rbegin()).second);
[1881]553
[1755]554                // destroy the devices
555                _destroyKeyboard();
556                _destroyMouse();
557                _destroyJoySticks();
[1219]558
[1755]559                OIS::InputManager::destroyInputSystem(inputSystem_);
[1349]560
[1755]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        }
[2662]569
570        singletonRef_s = 0;
[1755]571    }
[1349]572
[1755]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    }
[1219]585
[1755]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    }
[1219]598
[1755]599    /**
600    @brief
601        Destroys all the joy sticks and resizes the lists to 0.
602    */
603    void InputManager::_destroyJoySticks()
[1022]604    {
[1755]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]);
[1219]611
[1755]612            joySticks_.clear();
[1887]613            // don't use _configureNumberOfJoySticks(), might mess with registered handler if
[1755]614            // downgrading from 2 to 1 joystick
[1887]615            //_configureNumberOfJoySticks();
[1755]616            joySticksSize_ = 0;
617        }
618        CCOUT(4) << "Joy sticks destroyed." << std::endl;
619    }
[1502]620
[1755]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    }
[1502]639
[1755]640    void InputManager::_clearBuffers()
641    {
[1502]642        keysDown_.clear();
[1755]643        keyboardModifiers_ = 0;
[1502]644        mouseButtonsDown_.clear();
[1755]645        for (unsigned int i = 0; i < joySticksSize_; ++i)
[1219]646        {
[1755]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    }
[1219]656
657
[1755]658    // ############################################################
659    // #####                     Reloading                    #####
660    // ##########                                        ##########
661    // ############################################################
[1219]662
[1755]663    /**
664    @brief
665        Public interface. Only reloads immediately if the call stack doesn't
[2896]666        include the update() method.
[1755]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;
[1219]681        }
[1755]682        else if (internalState_ & OISReady)
683        {
684            _reload(joyStickSupport);
685        }
[1502]686        else
687        {
[1755]688            CCOUT(2) << "Warning: Cannot reload OIS. May not yet be initialised or"
689                     << "joy sticks are currently calibrating." << std::endl;
[1502]690        }
[1755]691    }
[1502]692
[1755]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;
[1502]702
[1755]703            // Save mouse clipping size
704            int mouseWidth  = mouse_->getMouseState().width;
705            int mouseHeight = mouse_->getMouseState().height;
[1502]706
[1755]707            internalState_ &= ~OISReady;
[1219]708
[1755]709            // destroy the devices
710            _destroyKeyboard();
711            _destroyMouse();
712            _destroyJoySticks();
[1219]713
[1755]714            OIS::InputManager::destroyInputSystem(inputSystem_);
715            inputSystem_ = 0;
[1219]716
[1755]717            // clear all buffers containing input information
718            _clearBuffers();
[1219]719
[1755]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        }
[1502]728    }
[1219]729
[1755]730    // ############################################################
731    // #####                  Runtime Methods                 #####
732    // ##########                                        ##########
733    // ############################################################
[1555]734
[1755]735    /**
736    @brief
[2662]737        Updates the states and the InputState situation.
[2896]738    @param time
739        Clock holding the current time.
[1755]740    */
[2896]741    void InputManager::update(const Clock& time)
[1502]742    {
[1755]743        if (internalState_ == Uninitialised)
744            return;
745        else if (internalState_ & ReloadRequest)
746        {
747            _reload(internalState_ & JoyStickSupport);
748            internalState_ &= ~ReloadRequest;
749            internalState_ &= ~JoyStickSupport;
750        }
[1349]751
[1755]752        // check for states to leave
[2662]753        if (!stateLeaveRequests_.empty())
[1755]754        {
[2896]755            for (std::set<InputState*>::iterator it = stateLeaveRequests_.begin();
756                it != stateLeaveRequests_.end(); ++it)
[2662]757            {
[2896]758                (*it)->onLeave();
[2662]759                // just to be sure that the state actually is registered
[2896]760                assert(inputStatesByName_.find((*it)->getName()) != inputStatesByName_.end());
[1505]761
[2896]762                activeStates_.erase((*it)->getPriority());
763                if ((*it)->getPriority() < InputStatePriority::HighPriority)
764                    (*it)->setPriority(0);
[2662]765                _updateActiveStates();
766            }
767            stateLeaveRequests_.clear();
[1755]768        }
[1505]769
[1755]770        // check for states to enter
[2662]771        if (!stateEnterRequests_.empty())
[1755]772        {
[2896]773            for (std::set<InputState*>::const_iterator it = stateEnterRequests_.begin();
774                it != stateEnterRequests_.end(); ++it)
[2662]775            {
776                // just to be sure that the state actually is registered
[2896]777                assert(inputStatesByName_.find((*it)->getName()) != inputStatesByName_.end());
[1219]778
[2896]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);
[2662]801                _updateActiveStates();
[2896]802                (*it)->onEnter();
[2662]803            }
804            stateEnterRequests_.clear();
[1755]805        }
[1219]806
[1755]807        // check for states to destroy
[2662]808        if (!stateDestroyRequests_.empty())
[1755]809        {
[2896]810            for (std::set<InputState*>::iterator it = stateDestroyRequests_.begin();
811                it != stateDestroyRequests_.end(); ++it)
[2662]812            {
[2896]813                _destroyState((*it));
[2662]814            }
815            stateDestroyRequests_.clear();
[1755]816        }
[1219]817
[1878]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
[2896]831        // mark that we now start capturing and distributing input
[1755]832        internalState_ |= Ticking;
[1293]833
[1755]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();
[1219]841
[2662]842        if (!(internalState_ & Calibrating))
[1755]843        {
844            // call all the handlers for the held key events
845            for (unsigned int iKey = 0; iKey < keysDown_.size(); iKey++)
[1788]846            {
847                KeyEvent kEvt(keysDown_[iKey], keyboardModifiers_);
[2896]848
849                for (unsigned int iState = 0; iState < activeStatesTriggered_[Keyboard].size(); ++iState)
850                    activeStatesTriggered_[Keyboard][iState]->keyHeld(kEvt);
[1788]851            }
[1219]852
[1755]853            // call all the handlers for the held mouse button events
854            for (unsigned int iButton = 0; iButton < mouseButtonsDown_.size(); iButton++)
[1788]855            {
[2896]856                for (unsigned int iState = 0; iState < activeStatesTriggered_[Mouse].size(); ++iState)
857                    activeStatesTriggered_[Mouse][iState]->mouseButtonHeld(mouseButtonsDown_[iButton]);
[1788]858            }
[1219]859
[1755]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++)
[1788]863                {
[2896]864                    for (unsigned int iState = 0; iState < activeStatesTriggered_[JoyStick0 + iJoyStick].size(); ++iState)
865                        activeStatesTriggered_[JoyStick0 + iJoyStick][iState]->joyStickButtonHeld(iJoyStick, joyStickButtonsDown_[iJoyStick][iButton]);
[1788]866                }
[1293]867
[2896]868            // update the handlers for each active handler
[1755]869            for (unsigned int i = 0; i < devicesNum_; ++i)
[1788]870            {
[2896]871                for (unsigned int iState = 0; iState < activeStatesTriggered_[i].size(); ++iState)
872                    activeStatesTriggered_[i][iState]->updateInput(time.getDeltaTime(), i);
[1788]873            }
[1219]874
[2896]875            // update the handler with a general tick afterwards
[1755]876            for (unsigned int i = 0; i < activeStatesTicked_.size(); ++i)
[2896]877                activeStatesTicked_[i]->updateInput(time.getDeltaTime());
[1755]878        }
[1219]879
[1755]880        internalState_ &= ~Ticking;
[1293]881    }
[1219]882
[1755]883    /**
884    @brief
885        Updates the currently active states (according to activeStates_) for each device.
[2896]886        Also, a list of all active states (no duplicates!) is compiled for the general update().
[1755]887    */
888    void InputManager::_updateActiveStates()
[1293]889    {
[2896]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        }
[1293]909
[1755]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)
[2896]914            for (unsigned int iState = 0; iState < activeStatesTriggered_[i].size(); ++iState)
915                tempSet.insert(activeStatesTriggered_[i][iState]);
[1219]916
[2896]917        // copy the content of the std::set back to the actual vector
[1755]918        activeStatesTicked_.clear();
919        for (std::set<InputState*>::const_iterator it = tempSet.begin();it != tempSet.end(); ++it)
920            activeStatesTicked_.push_back(*it);
[1219]921
[1755]922        this->mouseButtonsDown_.clear();
923    }
[1219]924
[1755]925    /**
926    @brief
[2662]927        Clears all buffers that store what keys/buttons are being pressed at the moment.
[1755]928    */
[1878]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    }
[1502]936
[1878]937
[1755]938    // ############################################################
939    // #####                    OIS events                    #####
940    // ##########                                        ##########
941    // ############################################################
[1219]942
[1755]943    // ###### Key Events ######
[1219]944
[1755]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)
[1219]952    {
[1755]953        // check whether the key already is in the list (can happen when focus was lost)
954        unsigned int iKey = 0;
[1887]955        while (iKey < keysDown_.size() && keysDown_[iKey].key != (KeyCode::ByEnum)e.key)
[1755]956            iKey++;
957        if (iKey == keysDown_.size())
958            keysDown_.push_back(Key(e));
959        else
[1788]960        {
961            // This happens when XAutoRepeat is set under linux. The KeyPressed event gets then sent
962            // continuously.
[1755]963            return true;
[1788]964        }
[1219]965
[1755]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
[1219]973
[1788]974        KeyEvent kEvt(e, keyboardModifiers_);
[2896]975        for (unsigned int iState = 0; iState < activeStatesTriggered_[Keyboard].size(); ++iState)
976            activeStatesTriggered_[Keyboard][iState]->keyPressed(kEvt);
[1219]977
[1755]978        return true;
[1349]979    }
[1755]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)
[1349]988    {
[1755]989        // remove the key from the keysDown_ list
990        for (unsigned int iKey = 0; iKey < keysDown_.size(); iKey++)
991        {
[1887]992            if (keysDown_[iKey].key == (KeyCode::ByEnum)e.key)
[1755]993            {
994                keysDown_.erase(keysDown_.begin() + iKey);
995                break;
996            }
997        }
[1502]998
[1755]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
[1293]1006
[1788]1007        KeyEvent kEvt(e, keyboardModifiers_);
[2896]1008        for (unsigned int iState = 0; iState < activeStatesTriggered_[Keyboard].size(); ++iState)
1009            activeStatesTriggered_[Keyboard][iState]->keyReleased(kEvt);
[1502]1010
[1755]1011        return true;
1012    }
[1502]1013
1014
[1755]1015    // ###### Mouse Events ######
[1502]1016
[1755]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        {
[1788]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);
[2896]1031            for (unsigned int iState = 0; iState < activeStatesTriggered_[Mouse].size(); ++iState)
1032                activeStatesTriggered_[Mouse][iState]->mouseMoved(abs, rel, clippingSize);
[1755]1033        }
[1502]1034
[1755]1035        // check for mouse scrolled event
1036        if (e.state.Z.rel != 0)
1037        {
[2896]1038            for (unsigned int iState = 0; iState < activeStatesTriggered_[Mouse].size(); ++iState)
1039                activeStatesTriggered_[Mouse][iState]->mouseScrolled(e.state.Z.abs, e.state.Z.rel);
[1755]1040        }
[1502]1041
[1755]1042        return true;
1043    }
[1502]1044
[1755]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;
[1887]1057        while (iButton < mouseButtonsDown_.size() && mouseButtonsDown_[iButton] != (MouseButtonCode::ByEnum)id)
[1755]1058            iButton++;
1059        if (iButton == mouseButtonsDown_.size())
[1887]1060            mouseButtonsDown_.push_back((MouseButtonCode::ByEnum)id);
[1502]1061
[2896]1062        for (unsigned int iState = 0; iState < activeStatesTriggered_[Mouse].size(); ++iState)
1063            activeStatesTriggered_[Mouse][iState]->mouseButtonPressed((MouseButtonCode::ByEnum)id);
[1502]1064
[1755]1065        return true;
1066    }
[1502]1067
[1755]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        {
[1887]1081            if (mouseButtonsDown_[iButton] == (MouseButtonCode::ByEnum)id)
[1755]1082            {
1083                mouseButtonsDown_.erase(mouseButtonsDown_.begin() + iButton);
1084                break;
1085            }
1086        }
[1502]1087
[2896]1088        for (unsigned int iState = 0; iState < activeStatesTriggered_[Mouse].size(); ++iState)
1089            activeStatesTriggered_[Mouse][iState]->mouseButtonReleased((MouseButtonCode::ByEnum)id);
[1219]1090
[1755]1091        return true;
1092    }
[1293]1093
[1502]1094
[1755]1095    // ###### Joy Stick Events ######
[1219]1096
[1755]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    }
[1219]1112
[1755]1113    bool InputManager::buttonPressed(const OIS::JoyStickEvent &arg, int button)
1114    {
1115        unsigned int iJoyStick = _getJoystick(arg);
[1502]1116
[1755]1117        // check whether the button already is in the list (can happen when focus was lost)
[1887]1118        std::vector<JoyStickButtonCode::ByEnum>& buttonsDown = joyStickButtonsDown_[iJoyStick];
[1755]1119        unsigned int iButton = 0;
1120        while (iButton < buttonsDown.size() && buttonsDown[iButton] != button)
1121            iButton++;
1122        if (iButton == buttonsDown.size())
[1887]1123            buttonsDown.push_back((JoyStickButtonCode::ByEnum)button);
[1219]1124
[2896]1125        for (unsigned int iState = 0; iState < activeStatesTriggered_[2 + iJoyStick].size(); ++iState)
1126            activeStatesTriggered_[2 + iJoyStick][iState]->joyStickButtonPressed(iJoyStick, (JoyStickButtonCode::ByEnum)button);
[1502]1127
[1755]1128        return true;
1129    }
[1219]1130
[1755]1131    bool InputManager::buttonReleased(const OIS::JoyStickEvent &arg, int button)
1132    {
1133        unsigned int iJoyStick = _getJoystick(arg);
[1219]1134
[1755]1135        // remove the button from the joyStickButtonsDown_ list
[1887]1136        std::vector<JoyStickButtonCode::ByEnum>& buttonsDown = joyStickButtonsDown_[iJoyStick];
[1755]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        }
[1219]1145
[2896]1146        for (unsigned int iState = 0; iState < activeStatesTriggered_[2 + iJoyStick].size(); ++iState)
1147            activeStatesTriggered_[2 + iJoyStick][iState]->joyStickButtonReleased(iJoyStick, (JoyStickButtonCode::ByEnum)button);
[1219]1148
[1755]1149        return true;
1150    }
[1219]1151
[1755]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    {
[2662]1159        if (internalState_ & Calibrating)
[1755]1160        {
[2662]1161            if (value < joyStickMinValues_[iJoyStick][axis])
1162                joyStickMinValues_[iJoyStick][axis] = value;
1163            if (value > joyStickMaxValues_[iJoyStick][axis])
1164                joyStickMaxValues_[iJoyStick][axis] = value;
[1755]1165        }
1166        else
1167        {
[3196]1168            float fValue = static_cast<float>(value - joyStickCalibrations_[iJoyStick].middleValue[axis]);
[1755]1169            if (fValue > 0.0f)
[2662]1170                fValue *= joyStickCalibrations_[iJoyStick].positiveCoeff[axis];
[1755]1171            else
[2662]1172                fValue *= joyStickCalibrations_[iJoyStick].negativeCoeff[axis];
[1219]1173
[2896]1174            for (unsigned int iState = 0; iState < activeStatesTriggered_[2 + iJoyStick].size(); ++iState)
1175                activeStatesTriggered_[2 + iJoyStick][iState]->joyStickAxisMoved(iJoyStick, axis, fValue);
[1755]1176        }
1177    }
[1219]1178
[1755]1179    bool InputManager::axisMoved(const OIS::JoyStickEvent &arg, int axis)
1180    {
1181        unsigned int iJoyStick = _getJoystick(arg);
[1219]1182
[1755]1183        // keep in mind that the first 8 axes are reserved for the sliders
[2662]1184        _fireAxis(iJoyStick, axis + sliderAxes, arg.state.mAxes[axis].abs);
[1293]1185
[1755]1186        return true;
1187    }
[1293]1188
[1755]1189    bool InputManager::sliderMoved(const OIS::JoyStickEvent &arg, int id)
1190    {
1191        unsigned int iJoyStick = _getJoystick(arg);
[1293]1192
[1755]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);
[1219]1197
[1755]1198        return true;
1199    }
[1219]1200
[1755]1201    bool InputManager::povMoved(const OIS::JoyStickEvent &arg, int id)
[1219]1202    {
[1755]1203        unsigned int iJoyStick = _getJoystick(arg);
[918]1204
[1755]1205        // translate the POV into 8 simple buttons
[922]1206
[1755]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);
[918]1216
[1755]1217        povStates_[iJoyStick].povStates[id] = arg.state.mPOV[id].direction;
[1219]1218
[1755]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);
[1502]1228
[1755]1229        return true;
[1219]1230    }
[1066]1231
1232
[1755]1233    // ############################################################
1234    // #####         Other Public Interface Methods           #####
1235    // ##########                                        ##########
1236    // ############################################################
[1219]1237
[1755]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)
[1219]1248    {
[1755]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        }
[1219]1255    }
1256
[1887]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    }
[1219]1267
[1755]1268    // ###### InputStates ######
[1219]1269
[1755]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
[2896]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!
[1755]1281    @return
1282        True if added, false if name or priority already existed.
1283    */
[2896]1284    bool InputManager::_configureInputState(InputState* state, const std::string& name, bool bAlwaysGetsInput, bool bTransparent, int priority)
[1219]1285    {
[1755]1286        if (name == "")
1287            return false;
1288        if (!state)
1289            return false;
1290        if (inputStatesByName_.find(name) == inputStatesByName_.end())
1291        {
[2896]1292            if (priority >= InputStatePriority::HighPriority || priority == InputStatePriority::Empty)
[1755]1293            {
[2896]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)
[1755]1312                state->setPriority(priority);
[2896]1313            return true;
[1755]1314        }
1315        else
1316        {
1317            COUT(2) << "Warning: Could not add an InputState with the same name '" << name << "'." << std::endl;
1318            return false;
1319        }
[1219]1320    }
1321
[1755]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".
[2896]1331        The removal process is being postponed if InputManager::update() is currently running.
[1755]1332    */
1333    bool InputManager::requestDestroyState(const std::string& name)
[1219]1334    {
[1881]1335        if (name == "empty")
[1755]1336        {
[1881]1337            COUT(2) << "InputManager: Removing the empty state is not allowed!" << std::endl;
[1755]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);
[1219]1356
[1755]1357            return true;
1358        }
1359        return false;
[1219]1360    }
1361
[1755]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)
[1219]1371    {
[1755]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;
[1219]1377    }
1378
[1755]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()
[1219]1386    {
[1755]1387        return (*activeStates_.rbegin()).second;
[1219]1388    }
1389
[1755]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)
[1219]1400    {
[1755]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
[2896]1412                    // prevents a state being added multiple times
[1755]1413                    stateEnterRequests_.insert(it->second);
1414                    return true;
1415                }
1416            }
1417        }
1418        return false;
[1219]1419    }
1420
[1755]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)
[1219]1430    {
[2896]1431        if (name == "empty")
1432        {
1433            COUT(2) << "InputManager: Leaving the empty state is not allowed!" << std::endl;
1434            return false;
1435        }
[1755]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;
[1219]1449    }
1450
1451
[1755]1452    // ############################################################
1453    // #####                Console Commands                  #####
1454    // ##########                                        ##########
1455    // ############################################################
[1219]1456
[1755]1457    /**
1458    @brief
1459        Starts joy stick calibration.
1460    */
1461    void InputManager::calibrate()
[1219]1462    {
[2662]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();
[1219]1467    }
1468
[1755]1469    /**
1470    @brief
1471        Reloads the input system
1472    */
1473    void InputManager::reload(bool joyStickSupport)
[1219]1474    {
[1755]1475        getInstance().reloadInputSystem(joyStickSupport);
[1219]1476    }
[3084]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
[918]1499}
Note: See TracBrowser for help on using the repository browser.