Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/gui/src/core/input/InputManager.cc @ 1641

Last change on this file since 1641 was 1641, checked in by rgrieder, 16 years ago

some de-bugging
added enum for joy stick buttons
some more little fixes

  • Property svn:eol-style set to native
File size: 42.6 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/**
[1638]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
[1638]38#include <climits>
39#include <cassert>
[1555]40
[1638]41#include "ois/OISException.h"
42#include "ois/OISInputManager.h"
43
[1519]44#include "core/CoreIncludes.h"
45#include "core/ConfigValueIncludes.h"
46#include "core/Debug.h"
47#include "core/CommandExecutor.h"
48#include "core/ConsoleCommand.h"
[1555]49
[1219]50#include "InputBuffer.h"
[1502]51#include "KeyBinder.h"
[1520]52#include "KeyDetector.h"
53#include "CalibratorCallback.h"
[1638]54#include "InputState.h"
55#include "SimpleInputState.h"
56#include "ExtendedInputState.h"
[918]57
58namespace orxonox
59{
[1638]60    SetConsoleCommandShortcut(InputManager, keyBind);
61    SetConsoleCommandShortcut(InputManager, storeKeyStroke);
62    SetConsoleCommandShortcut(InputManager, calibrate);
[1502]63
[1638]64    using namespace InputDevice;
[1084]65
[1638]66    // ###############################
67    // ###    Internal Methods     ###
68    // ###############################
69    // ###############################
[929]70
[1638]71    /**
72    @brief
73        Constructor only sets member fields to initial zero values
74        and registers the class in the class hierarchy.
75    */
76    InputManager::InputManager()
77        : inputSystem_(0)
78        , keyboard_(0)
79        , mouse_(0)
80        , joySticksSize_(0)
81        , devicesNum_(0)
82        , stateDetector_(0)
83        , stateCalibrator_(0)
84        , stateEmpty_(0)
85        , keyboardModifiers_(0)
86        , bCalibrating_(false)
87    {
88        RegisterRootObject(InputManager);
89    }
[919]90
[1638]91    /**
92    @brief
[1641]93        Destructor itself only called at the end of the program, after main.
94        Instance gets registered for destruction with atexit(.).
95    */
96    InputManager::~InputManager()
97    {
98        _destroy();
99    }
100
101    /**
102    @brief
[1638]103        The one instance of the InputManager is stored in this function.
[1641]104        Only for internal use. Public Interface ist static.
[1638]105    @return
106        A reference to the only instance of the InputManager
107    */
108    InputManager& InputManager::_getInstance()
109    {
110        static InputManager theOnlyInstance;
111        return theOnlyInstance;
112    }
[1219]113
114
[1638]115    // ############################################################
116    // #####                  Initialisation                  #####
117    // ##########                                        ##########
118    // ############################################################
119
120    /**
121    @brief
122        Creates the OIS::InputMananger, the keyboard, the mouse and
123        the joysticks and assigns the key bindings.
124    @param windowHnd
125        The window handle of the render window
126    @param windowWidth
127        The width of the render window
128    @param windowHeight
129        The height of the render window
130    */
131    bool InputManager::_initialise(const size_t windowHnd, int windowWidth, int windowHeight,
132                                   bool createKeyboard, bool createMouse, bool createJoySticks)
133    {
134        if (inputSystem_ == 0)
135        {
136            CCOUT(3) << "Initialising Input System..." << std::endl;
[1641]137            CCOUT(4) << "Initialising OIS components..." << std::endl;
[1638]138
139            OIS::ParamList paramList;
140            std::ostringstream windowHndStr;
141
142            // Fill parameter list
143            windowHndStr << (unsigned int)windowHnd;
144            paramList.insert(std::make_pair(std::string("WINDOW"), windowHndStr.str()));
145            //paramList.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_NONEXCLUSIVE")));
146            //paramList.insert(std::make_pair(std::string("w32_mouse"), std::string("DISCL_FOREGROUND")));
[1219]147//#if defined OIS_LINUX_PLATFORM
[1638]148            //paramList.insert(std::make_pair(std::string("XAutoRepeatOn"), std::string("true")));
[1219]149//#endif
[928]150
[1638]151            try
152            {
153                inputSystem_ = OIS::InputManager::createInputSystem(paramList);
154                CCOUT(ORX_DEBUG) << "Created OIS input system" << std::endl;
155            }
156            catch (OIS::Exception ex)
157            {
158                CCOUT(ORX_ERROR) << "Error: Failed creating an OIS input system."
159                    << "OIS message: \"" << ex.eText << "\"" << std::endl;
160                inputSystem_ = 0;
161                return false;
162            }
[1219]163
[1638]164            if (createKeyboard)
165                _initialiseKeyboard();
[1219]166
[1638]167            if (createMouse)
168                _initialiseMouse();
[1219]169
[1638]170            if (createJoySticks)
171                _initialiseJoySticks();
[1219]172
[1638]173            // set all the std::vector list sizes now that the devices have been created
174            _redimensionLists();
[1219]175
[1638]176            // Set mouse/joystick region
177            if (mouse_)
178            {
179                setWindowExtents(windowWidth, windowHeight);
180            }
[1502]181
[1638]182            CCOUT(ORX_DEBUG) << "Initialising OIS components done." << std::endl;
[1502]183
[1638]184            setConfigValues();
[1502]185
[1638]186            stateEmpty_ = createSimpleInputState("empty", -1);
187            stateEmpty_->setHandler(new EmptyHandler());
188            activeStates_[stateEmpty_->getPriority()] = stateEmpty_;
[1502]189
[1638]190            stateDetector_ = createSimpleInputState("detector", 101);
191            KeyDetector* temp = new KeyDetector();
192            temp->loadBindings("storeKeyStroke");
193            stateDetector_->setHandler(temp);
[1502]194
[1638]195            stateCalibrator_ = createSimpleInputState("calibrator", 100);
196            stateCalibrator_->setHandler(new EmptyHandler());
197            InputBuffer* buffer = new InputBuffer();
198            buffer->registerListener(this, &InputManager::_completeCalibration, '\r', true);
199            stateCalibrator_->setKeyHandler(buffer);
[918]200
[1638]201            _updateActiveStates();
202
[1641]203            CCOUT(3) << "Initialising complete." << std::endl;
[1638]204        }
205        else
206        {
[1641]207            CCOUT(2) << "Warning: OIS compoments already initialised, skipping" << std::endl;
[1638]208        }
[1219]209        return true;
210    }
[928]211
[1638]212    /**
213    @brief
214        Creates a keyboard and sets the event handler.
215    @return
216        False if keyboard stays uninitialised, true otherwise.
217    */
218    bool InputManager::_initialiseKeyboard()
[1219]219    {
[1638]220        if (keyboard_ != 0)
221        {
222            CCOUT(2) << "Warning: Keyboard already initialised, skipping." << std::endl;
223            return true;
224        }
225        try
226        {
227            if (inputSystem_->getNumberOfDevices(OIS::OISKeyboard) > 0)
228            {
229                keyboard_ = (OIS::Keyboard*)inputSystem_->createInputObject(OIS::OISKeyboard, true);
230                // register our listener in OIS.
231                keyboard_->setEventCallback(this);
232                // note: OIS will not detect keys that have already been down when the keyboard was created.
233                CCOUT(ORX_DEBUG) << "Created OIS keyboard" << std::endl;
234                return true;
235            }
236            else
237            {
238                CCOUT(ORX_WARNING) << "Warning: No keyboard found!" << std::endl;
239                return false;
240            }
241        }
242        catch (OIS::Exception ex)
243        {
244            CCOUT(ORX_WARNING) << "Warning: Failed to create an OIS keyboard\n"
245                << "OIS error message: \"" << ex.eText << "\"" << std::endl;
246            keyboard_ = 0;
247            return false;
248        }
[1219]249    }
[1035]250
[1638]251    /**
252    @brief
253        Creates a mouse and sets the event handler.
254    @return
255        False if mouse stays uninitialised, true otherwise.
256    */
257    bool InputManager::_initialiseMouse()
[1219]258    {
[1638]259        if (mouse_ != 0)
260        {
261            CCOUT(2) << "Warning: Mouse already initialised, skipping." << std::endl;
262            return true;
263        }
[1219]264        try
265        {
[1638]266            if (inputSystem_->getNumberOfDevices(OIS::OISMouse) > 0)
267            {
268                mouse_ = static_cast<OIS::Mouse*>(inputSystem_->createInputObject(OIS::OISMouse, true));
269                // register our listener in OIS.
270                mouse_->setEventCallback(this);
271                CCOUT(ORX_DEBUG) << "Created OIS mouse" << std::endl;
272                return true;
273            }
274            else
275            {
276                CCOUT(ORX_WARNING) << "Warning: No mouse found!" << std::endl;
277                return false;
278            }
[1219]279        }
280        catch (OIS::Exception ex)
281        {
[1638]282            CCOUT(ORX_WARNING) << "Warning: Failed to create an OIS mouse\n"
283                << "OIS error message: \"" << ex.eText << "\"" << std::endl;
284            mouse_ = 0;
285            return false;
[1219]286        }
287    }
[1638]288
289    /**
290    @brief
291        Creates all joy sticks and sets the event handler.
292    @return
293        False joy stick stay uninitialised, true otherwise.
294    */
295    bool InputManager::_initialiseJoySticks()
[1219]296    {
[1638]297        if (joySticksSize_ > 0)
298        {
299            CCOUT(2) << "Warning: Joy sticks already initialised, skipping." << std::endl;
300            return true;
301        }
302        bool success = false;
303        if (inputSystem_->getNumberOfDevices(OIS::OISJoyStick) > 0)
304        {
305            for (int i = 0; i < inputSystem_->getNumberOfDevices(OIS::OISJoyStick); i++)
306            {
307                try
308                {
309                    OIS::JoyStick* stig = static_cast<OIS::JoyStick*>
310                        (inputSystem_->createInputObject(OIS::OISJoyStick, true));
311                    CCOUT(ORX_DEBUG) << "Created OIS joy stick with ID " << stig->getID() << std::endl;
312                    joySticks_.push_back(stig);
313                    // register our listener in OIS.
314                    stig->setEventCallback(this);
315                    success = true;
316                }
317                catch (OIS::Exception ex)
318                {
319                    CCOUT(ORX_WARNING) << "Warning: Failed to create OIS joy number" << i << "\n"
320                        << "OIS error message: \"" << ex.eText << "\"" << std::endl;
321                }
322            }
323        }
324        else
325        {
326            CCOUT(ORX_WARNING) << "Warning: Joy stick support requested, but no joy stick was found" << std::endl;
327            return false;
328        }
329        return success;
[1219]330    }
[1035]331
[1641]332    /**
333    @brief
334        Sets the size of all the different lists that are dependent on the number
335        of joy stick devices created.
336    @remarks
337        No matter whether there are a mouse and/or keyboard, they will always
338        occupy 2 places in the device number dependent lists.
339    */
[1638]340    void InputManager::_redimensionLists()
[1505]341    {
[1638]342        joySticksSize_ = joySticks_.size();
343        devicesNum_ = 2 + joySticksSize_;
344        joyStickButtonsDown_ .resize(joySticksSize_);
345        povStates_           .resize(joySticksSize_);
346        sliderStates_        .resize(joySticksSize_);
347        joySticksCalibration_.resize(joySticksSize_);
[1502]348
[1638]349        for (unsigned int iJoyStick = 0; iJoyStick < joySticksSize_; iJoyStick++)
350        {
351            // reset the calibration with default values
352            for (unsigned int i = 0; i < 24; i++)
353            {
354                joySticksCalibration_[iJoyStick].negativeCoeff[i] = 1.0f/32767.0f;
355                joySticksCalibration_[iJoyStick].positiveCoeff[i] = 1.0f/32768.0f;
356                joySticksCalibration_[iJoyStick].zeroStates[i] = 0;
357            }
358        }
[1505]359
[1638]360        // state management
361        activeStatesTop_.resize(devicesNum_);
[1505]362
[1641]363        // inform all states
[1638]364        for (std::map<int, InputState*>::const_iterator it = inputStatesByPriority_.begin();
365            it != inputStatesByPriority_.end(); ++it)
366            (*it).second->setNumOfJoySticks(joySticksSize_);
[1505]367    }
[1502]368
[1638]369    /**
370    @brief
[1641]371        Sets the configurable values.
372        This mainly concerns joy stick calibrations.
[1638]373    */
374    void InputManager::setConfigValues()
[1219]375    {
[1641]376        if (joySticksSize_ > 0)
[1638]377        {
378            std::vector<MultiTypeMath> coeffPos;
379            std::vector<MultiTypeMath> coeffNeg;
380            std::vector<MultiTypeMath> zero;
381            coeffPos.resize(24);
382            coeffNeg.resize(24);
383            zero.resize(24);
384            for (unsigned int i = 0; i < 24; i++)
385            {
386                coeffPos[i] =  1.0f/32767.0f;
387                coeffNeg[i] =  1.0f/32768.0f;
388                zero[i]     =  0;
389            }
[1293]390
[1638]391            ConfigValueContainer* cont = getIdentifier()->getConfigValueContainer("CoeffPos");
392            if (!cont)
393            {
[1641]394                cont = new ConfigValueContainer(CFT_Settings, getIdentifier(), "CoeffPos", coeffPos);
[1638]395                getIdentifier()->addConfigValueContainer("CoeffPos", cont);
396            }
397            cont->getValue(&coeffPos);
[1219]398
[1638]399            cont = getIdentifier()->getConfigValueContainer("CoeffNeg");
400            if (!cont)
401            {
[1641]402                cont = new ConfigValueContainer(CFT_Settings, getIdentifier(), "CoeffNeg", coeffNeg);
[1638]403                getIdentifier()->addConfigValueContainer("CoeffNeg", cont);
404            }
405            cont->getValue(&coeffNeg);
[1219]406
[1638]407            cont = getIdentifier()->getConfigValueContainer("Zero");
408            if (!cont)
409            {
[1641]410                cont = new ConfigValueContainer(CFT_Settings, getIdentifier(), "Zero", zero);
[1638]411                getIdentifier()->addConfigValueContainer("Zero", cont);
412            }
413            cont->getValue(&zero);
[1502]414
[1638]415            // copy values to our own variables
416            for (unsigned int i = 0; i < 24; i++)
417            {
418                joySticksCalibration_[0].positiveCoeff[i] = coeffPos[i];
419                joySticksCalibration_[0].negativeCoeff[i] = coeffNeg[i];
420                joySticksCalibration_[0].zeroStates[i]    = zero[i];
421            }
422        }
[1219]423    }
[928]424
[1219]425
[1638]426    // ############################################################
427    // #####                    Destruction                   #####
428    // ##########                                        ##########
429    // ############################################################
[1219]430
[1638]431    /**
432    @brief
[1641]433        Destroys all the created input devices. InputManager will be ready for a
434        new initialisation.
[1638]435    */
436    void InputManager::_destroy()
[1219]437    {
[1638]438        if (inputSystem_)
439        {
[1641]440            try
441            {
442                CCOUT(3) << "Destroying ..." << std::endl;
[1219]443
[1641]444                // clear our own states
445                stateEmpty_->removeAndDestroyAllHandlers();
446                stateCalibrator_->removeAndDestroyAllHandlers();
447                stateDetector_->removeAndDestroyAllHandlers();
[1219]448
[1641]449                // kick all active states 'nicely'
450                for (std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin();
451                    rit != activeStates_.rend(); ++rit)
452                {
453                    (*rit).second->onLeave();
454                }
455                activeStates_.clear();
456                _updateActiveStates();
[1502]457
[1641]458                // destroy all input states
459                while (inputStatesByPriority_.size() > 0)
460                {
461                    _destroyState((*inputStatesByPriority_.rbegin()).second);
462                }
[1502]463
[1641]464                stateEmpty_ = 0;
465                stateCalibrator_ = 0;
466                stateDetector_ = 0;
[1219]467
[1641]468                // destroy the devices
469                _destroyKeyboard();
470                _destroyMouse();
471                _destroyJoySticks();
[1349]472
[1641]473                // 0 joy sticks now
474                _redimensionLists();
[1349]475
[1641]476                OIS::InputManager::destroyInputSystem(inputSystem_);
477                inputSystem_ = 0;
478
479                CCOUT(3) << "Destroying done." << std::endl;
480            }
481            catch (OIS::Exception& ex)
482            {
483                CCOUT(1) << "An exception has occured while destroying:\n" << ex.what() << std::endl;
484            }
[1638]485        }
486    }
[1219]487
[1638]488    /**
489    @brief
490        Destroys the keyboard and sets it to 0.
491    */
492    void InputManager::_destroyKeyboard()
493    {
494        if (keyboard_)
495            inputSystem_->destroyInputObject(keyboard_);
496        keyboard_ = 0;
497        keysDown_.clear();
[1641]498        CCOUT(4) << "Keyboard destroyed." << std::endl;
[1638]499    }
[1219]500
[1638]501    /**
502    @brief
503        Destroys the mouse and sets it to 0.
504    */
505    void InputManager::_destroyMouse()
[1022]506    {
[1638]507        if (mouse_)
508            inputSystem_->destroyInputObject(mouse_);
509        mouse_ = 0;
510        mouseButtonsDown_.clear();
[1641]511        CCOUT(4) << "Mouse destroyed." << std::endl;
[1638]512    }
[1219]513
[1638]514    /**
515    @brief
516        Destroys all the joy sticks and resizes the lists to 0.
517    */
518    void InputManager::_destroyJoySticks()
519    {
520        if (joySticksSize_ > 0)
521        {
522            // note: inputSystem_ can never be 0, or else the code is mistaken
523            for (unsigned int i = 0; i < joySticksSize_; i++)
524                if (joySticks_[i] != 0)
525                    inputSystem_->destroyInputObject(joySticks_[i]);
[1502]526
[1638]527            joySticks_.clear();
528        }
[1641]529        CCOUT(4) << "Joy sticks destroyed." << std::endl;
[1638]530    }
[1502]531
[1638]532    void InputManager::_destroyState(InputState* state)
533    {
534        assert(state);
535        inputStatesByPriority_.erase(state->getPriority());
536        inputStatesByName_.erase(state->getName());
537        delete state;
538    }
[1502]539
540
[1638]541    // ############################################################
542    // #####                  Runtime Methods                 #####
543    // ##########                                        ##########
544    // ############################################################
[1502]545
[1638]546    /**
547    @brief
548        Updates the InputManager. Tick is called by the Core class.
549    @param dt
550        Delta time
551    */
552    void InputManager::_tick(float dt)
553    {
554        if (inputSystem_ == 0)
555            return;
[1502]556
[1638]557        // check for states to leave (don't use unsigned int!)
558        for (int i = stateLeaveRequests_.size() - 1; i >= 0; --i)
559        {
560            stateLeaveRequests_[i]->onLeave();
561            // just to be sure that the state actually is registered
562            assert(inputStatesByName_.find(stateLeaveRequests_[i]->getName()) != inputStatesByName_.end());
563           
564            activeStates_.erase(stateLeaveRequests_[i]->getPriority());
565            _updateActiveStates();
566            stateLeaveRequests_.pop_back();
567        }
[1502]568
569
[1638]570        // check for states to enter (don't use unsigned int!)
571        for (int i = stateEnterRequests_.size() - 1; i >= 0; --i)
[1219]572        {
[1638]573            // just to be sure that the state actually is registered
574            assert(inputStatesByName_.find(stateEnterRequests_[i]->getName()) != inputStatesByName_.end());
575           
576            activeStates_[stateEnterRequests_[i]->getPriority()] = stateEnterRequests_[i];
577            _updateActiveStates();
578            stateEnterRequests_[i]->onEnter();
579            stateEnterRequests_.pop_back();
580        }
[1219]581
[1638]582        // Capture all the input. This calls the event handlers in InputManager.
583        if (keyboard_)
584            keyboard_->capture();
585        if (mouse_)
586            mouse_->capture();
587        for (unsigned  int i = 0; i < joySticksSize_; i++)
588            joySticks_[i]->capture();
[1219]589
[1638]590        if (!bCalibrating_)
[1502]591        {
[1638]592            // call all the handlers for the held key events
593            for (unsigned int iKey = 0; iKey < keysDown_.size(); iKey++)
594                activeStatesTop_[Keyboard]->keyHeld(KeyEvent(keysDown_[iKey], keyboardModifiers_));
[1502]595
[1638]596            // call all the handlers for the held mouse button events
597            for (unsigned int iButton = 0; iButton < mouseButtonsDown_.size(); iButton++)
598                activeStatesTop_[Mouse]->mouseButtonHeld(mouseButtonsDown_[iButton]);
[1502]599
[1638]600            // call all the handlers for the held joy stick button events
601            for (unsigned int iJoyStick  = 0; iJoyStick < joySticksSize_; iJoyStick++)
602                for (unsigned int iButton   = 0; iButton   < joyStickButtonsDown_[iJoyStick].size(); iButton++)
603                    activeStatesTop_[JoyStick0 + iJoyStick]
604                        ->joyStickButtonHeld(iJoyStick, joyStickButtonsDown_[iJoyStick][iButton]);
[1502]605
[1638]606            // tick the handlers for each active handler
607            for (unsigned int i = 0; i < devicesNum_; ++i)
608                activeStatesTop_[i]->tickInput(dt, i);
609
610            // tick the handler with a general tick afterwards
611            for (unsigned int i = 0; i < activeStatesTicked_.size(); ++i)
612                activeStatesTicked_[i]->tickInput(dt);
613        }
[1219]614    }
615
[1641]616    /**
617    @brief
618        Updates the currently active states (according to activeStates_) for each device.
619        Also, a list of all active states (no duplicates!) is compiled for the general tick.
620    */
[1638]621    void InputManager::_updateActiveStates()
[1502]622    {
[1638]623        for (std::map<int, InputState*>::const_iterator it = activeStates_.begin(); it != activeStates_.end(); ++it)
624            for (unsigned int i = 0; i < devicesNum_; ++i)
625                if ((*it).second->isInputDeviceEnabled(i))
626                    activeStatesTop_[i] = (*it).second;
[1219]627
[1638]628        // update tickables (every state will only appear once)
629        // Using a std::set to avoid duplicates
630        std::set<InputState*> tempSet;
631        for (unsigned int i = 0; i < devicesNum_; ++i)
632            tempSet.insert(activeStatesTop_[i]);
[1219]633
[1638]634        // copy the content of the set back to the actual vector
635        activeStatesTicked_.clear();
636        for (std::set<InputState*>::const_iterator it = tempSet.begin();it != tempSet.end(); ++it)
637            activeStatesTicked_.push_back(*it);
[1502]638    }
[1219]639
[1641]640    /**
641    @brief
642        Processes the accumultated data for the joy stick calibration.
643    */
[1638]644    void InputManager::_completeCalibration()
[1502]645    {
[1638]646        for (unsigned int i = 0; i < 24; i++)
647        {
648            // positive coefficient
649            if (marginalsMax_[i] == INT_MIN)
650                marginalsMax_[i] =  32767;
651            // coefficients
652            if (marginalsMax_[i] - joySticksCalibration_[0].zeroStates[i])
653            {
654                joySticksCalibration_[0].positiveCoeff[i]
655                    = 1.0f/(marginalsMax_[i] - joySticksCalibration_[0].zeroStates[i]);
656            }
657            else
658                joySticksCalibration_[0].positiveCoeff[i] =  1.0f;
[1349]659
[1638]660            // config value
661            ConfigValueContainer* cont = getIdentifier()->getConfigValueContainer("CoeffPos");
662            assert(cont);
663            cont->set(i, joySticksCalibration_[0].positiveCoeff[i]);
[1505]664
[1638]665            // negative coefficient
666            if (marginalsMin_[i] == INT_MAX)
667                marginalsMin_[i] = -32768;
668            // coefficients
669            if (marginalsMin_[i] - joySticksCalibration_[0].zeroStates[i])
670            {
671                joySticksCalibration_[0].negativeCoeff[i] = -1.0f
672                    / (marginalsMin_[i] - joySticksCalibration_[0].zeroStates[i]);
673            }
674            else
675                joySticksCalibration_[0].negativeCoeff[i] =  1.0f;
676            // config value
677            cont = getIdentifier()->getConfigValueContainer("CoeffNeg");
678            assert(cont);
679            cont->set(i, joySticksCalibration_[0].negativeCoeff[i]);
[1505]680
[1638]681            // zero states
682            if (i < 8)
683            {
684                if (!(i & 1))
685                    joySticksCalibration_[0].zeroStates[i] = joySticks_[0]->getJoyStickState().mSliders[i/2].abX;
686                else
687                    joySticksCalibration_[0].zeroStates[i] = joySticks_[0]->getJoyStickState().mSliders[i/2].abY;
688            }
689            else
690            {
691                if (i - 8 < joySticks_[0]->getJoyStickState().mAxes.size())
692                    joySticksCalibration_[0].zeroStates[i] = joySticks_[0]->getJoyStickState().mAxes[i - 8].abs;
693                else
694                    joySticksCalibration_[0].zeroStates[i] = 0;
695            }
696            // config value
697            cont = getIdentifier()->getConfigValueContainer("Zero");
698            assert(cont);
699            cont->set(i, joySticksCalibration_[0].zeroStates[i]);
700        }
701
702        // restore old input state
703        requestLeaveState("calibrator");
[1641]704        bCalibrating_ = false;
[1502]705    }
[1219]706
707
[1638]708    // ############################################################
709    // #####                    OIS events                    #####
710    // ##########                                        ##########
711    // ############################################################
[1219]712
[1638]713    // ###### Key Events ######
[1293]714
[1638]715    /**
716    @brief
717        Event handler for the keyPressed Event.
718    @param e
719        Event information
720    */
721    bool InputManager::keyPressed(const OIS::KeyEvent &e)
[1219]722    {
[1638]723        // check whether the key already is in the list (can happen when focus was lost)
724        unsigned int iKey = 0;
725        while (iKey < keysDown_.size() && keysDown_[iKey].key != (KeyCode::Enum)e.key)
726            iKey++;
727        if (iKey == keysDown_.size())
728            keysDown_.push_back(Key(e));
[1219]729
[1638]730        // update modifiers
731        if(e.key == OIS::KC_RMENU    || e.key == OIS::KC_LMENU)
732            keyboardModifiers_ |= KeyboardModifier::Alt;   // alt key
733        if(e.key == OIS::KC_RCONTROL || e.key == OIS::KC_LCONTROL)
734            keyboardModifiers_ |= KeyboardModifier::Ctrl;  // ctrl key
735        if(e.key == OIS::KC_RSHIFT   || e.key == OIS::KC_LSHIFT)
736            keyboardModifiers_ |= KeyboardModifier::Shift; // shift key
[1293]737
[1638]738        activeStatesTop_[Keyboard]->keyPressed(KeyEvent(e, keyboardModifiers_));
[1219]739
[1638]740        return true;
[1293]741    }
[1219]742
[1638]743    /**
744    @brief
745        Event handler for the keyReleased Event.
746    @param e
747        Event information
748    */
749    bool InputManager::keyReleased(const OIS::KeyEvent &e)
[1293]750    {
[1638]751        // remove the key from the keysDown_ list
752        for (unsigned int iKey = 0; iKey < keysDown_.size(); iKey++)
753        {
754            if (keysDown_[iKey].key == (KeyCode::Enum)e.key)
755            {
756                keysDown_.erase(keysDown_.begin() + iKey);
757                break;
758            }
759        }
[1293]760
[1638]761        // update modifiers
762        if(e.key == OIS::KC_RMENU    || e.key == OIS::KC_LMENU)
763            keyboardModifiers_ &= ~KeyboardModifier::Alt;   // alt key
764        if(e.key == OIS::KC_RCONTROL || e.key == OIS::KC_LCONTROL)
765            keyboardModifiers_ &= ~KeyboardModifier::Ctrl;  // ctrl key
766        if(e.key == OIS::KC_RSHIFT   || e.key == OIS::KC_LSHIFT)
767            keyboardModifiers_ &= ~KeyboardModifier::Shift; // shift key
[1219]768
[1638]769        activeStatesTop_[Keyboard]->keyReleased(KeyEvent(e, keyboardModifiers_));
[1219]770
[1638]771        return true;
[1022]772    }
773
[918]774
[1638]775    // ###### Mouse Events ######
[918]776
[1638]777    /**
778    @brief
779        Event handler for the mouseMoved Event.
780    @param e
781        Event information
782    */
783    bool InputManager::mouseMoved(const OIS::MouseEvent &e)
784    {
785        // check for actual moved event
786        if (e.state.X.rel != 0 || e.state.Y.rel != 0)
787        {
788            activeStatesTop_[Mouse]->mouseMoved(IntVector2(e.state.X.abs, e.state.Y.abs),
789                    IntVector2(e.state.X.rel, e.state.Y.rel), IntVector2(e.state.width, e.state.height));
790        }
[1219]791
[1638]792        // check for mouse scrolled event
793        if (e.state.Z.rel != 0)
794        {
795            activeStatesTop_[Mouse]->mouseScrolled(e.state.Z.abs, e.state.Z.rel);
796        }
[1219]797
[1638]798        return true;
[1502]799    }
800
[1638]801    /**
802    @brief
803        Event handler for the mousePressed Event.
804    @param e
805        Event information
806    @param id
807        The ID of the mouse button
808    */
809    bool InputManager::mousePressed(const OIS::MouseEvent &e, OIS::MouseButtonID id)
810    {
811        // check whether the button already is in the list (can happen when focus was lost)
812        unsigned int iButton = 0;
813        while (iButton < mouseButtonsDown_.size() && mouseButtonsDown_[iButton] != (MouseButton::Enum)id)
814            iButton++;
815        if (iButton == mouseButtonsDown_.size())
816            mouseButtonsDown_.push_back((MouseButton::Enum)id);
[1502]817
[1638]818        activeStatesTop_[Mouse]->mouseButtonPressed((MouseButton::Enum)id);
[1219]819
[1638]820        return true;
821    }
[1219]822
[1638]823    /**
824    @brief
825        Event handler for the mouseReleased Event.
826    @param e
827        Event information
828    @param id
829        The ID of the mouse button
830    */
831    bool InputManager::mouseReleased(const OIS::MouseEvent &e, OIS::MouseButtonID id)
832    {
833        // remove the button from the keysDown_ list
834        for (unsigned int iButton = 0; iButton < mouseButtonsDown_.size(); iButton++)
835        {
836            if (mouseButtonsDown_[iButton] == (MouseButton::Enum)id)
837            {
838                mouseButtonsDown_.erase(mouseButtonsDown_.begin() + iButton);
839                break;
840            }
841        }
[1502]842
[1638]843        activeStatesTop_[Mouse]->mouseButtonReleased((MouseButton::Enum)id);
[1502]844
[1638]845        return true;
[1219]846    }
847
848
[1638]849    // ###### Joy Stick Events ######
[1219]850
[1641]851    /**
852    @brief
853        Returns the joy stick ID (orxonox) according to a OIS::JoyStickEvent
854    */
[1638]855    inline unsigned int InputManager::_getJoystick(const OIS::JoyStickEvent& arg)
[1349]856    {
[1638]857        // use the device to identify which one called the method
858        OIS::JoyStick* joyStick = (OIS::JoyStick*)arg.device;
859        unsigned int iJoyStick = 0;
860        while (joySticks_[iJoyStick] != joyStick)
861            iJoyStick++;
862        // assert: Unknown joystick fired an event.
863        assert(iJoyStick != joySticksSize_);
864        return iJoyStick;
[1349]865    }
[1638]866
867    bool InputManager::buttonPressed(const OIS::JoyStickEvent &arg, int button)
[1349]868    {
[1638]869        unsigned int iJoyStick = _getJoystick(arg);
[1502]870
[1638]871        // check whether the button already is in the list (can happen when focus was lost)
[1641]872        std::vector<JoyStickButton::Enum>& buttonsDown = joyStickButtonsDown_[iJoyStick];
[1638]873        unsigned int iButton = 0;
874        while (iButton < buttonsDown.size() && buttonsDown[iButton] != button)
875            iButton++;
876        if (iButton == buttonsDown.size())
[1641]877            buttonsDown.push_back((JoyStickButton::Enum)button);
[1293]878
[1641]879        activeStatesTop_[2 + iJoyStick]->joyStickButtonPressed(iJoyStick, (JoyStickButton::Enum)button);
[1502]880
[1638]881        return true;
882    }
[1502]883
[1638]884    bool InputManager::buttonReleased(const OIS::JoyStickEvent &arg, int button)
885    {
886        unsigned int iJoyStick = _getJoystick(arg);
[1502]887
[1638]888        // remove the button from the joyStickButtonsDown_ list
[1641]889        std::vector<JoyStickButton::Enum>& buttonsDown = joyStickButtonsDown_[iJoyStick];
[1638]890        for (unsigned int iButton = 0; iButton < buttonsDown.size(); iButton++)
891        {
892            if (buttonsDown[iButton] == button)
893            {
894                buttonsDown.erase(buttonsDown.begin() + iButton);
895                break;
896            }
897        }
[1502]898
[1641]899        activeStatesTop_[2 + iJoyStick]->joyStickButtonReleased(iJoyStick, (JoyStickButton::Enum)button);
[1502]900
[1638]901        return true;
902    }
[1502]903
[1641]904    /**
905    @brief
906        Calls the states for a particular axis with our enumeration.
907        Used by OIS sliders and OIS axes.
908    */
[1638]909    void InputManager::_fireAxis(unsigned int iJoyStick, int axis, int value)
910    {
911        if (bCalibrating_)
912        {
913            if (value > marginalsMax_[axis])
914                marginalsMax_[axis] = value;
915            if (value < marginalsMin_[axis])
916                marginalsMin_[axis] = value;
917        }
918        else
919        {
920            float fValue = value - joySticksCalibration_[iJoyStick].zeroStates[axis];
921            if (fValue > 0.0f)
922                fValue *= joySticksCalibration_[iJoyStick].positiveCoeff[axis];
923            else
924                fValue *= joySticksCalibration_[iJoyStick].negativeCoeff[axis];
[1502]925
[1638]926            activeStatesTop_[2 + iJoyStick]->joyStickAxisMoved(iJoyStick, axis, fValue);
927        }
928    }
[1502]929
[1638]930    bool InputManager::axisMoved(const OIS::JoyStickEvent &arg, int axis)
931    {
932        unsigned int iJoyStick = _getJoystick(arg);
[1502]933
[1638]934        // keep in mind that the first 8 axes are reserved for the sliders
935        _fireAxis(iJoyStick, axis + 8, arg.state.mAxes[axis].abs);
[1502]936
[1638]937        return true;
938    }
[1502]939
[1638]940    bool InputManager::sliderMoved(const OIS::JoyStickEvent &arg, int id)
941    {
942        unsigned int iJoyStick = _getJoystick(arg);
[1219]943
[1638]944        if (sliderStates_[iJoyStick].sliderStates[id].x != arg.state.mSliders[id].abX)
945            _fireAxis(iJoyStick, id * 2, arg.state.mSliders[id].abX);
946        else if (sliderStates_[iJoyStick].sliderStates[id].y != arg.state.mSliders[id].abY)
947            _fireAxis(iJoyStick, id * 2 + 1, arg.state.mSliders[id].abY);
[1293]948
[1638]949        return true;
950    }
[1502]951
[1638]952    bool InputManager::povMoved(const OIS::JoyStickEvent &arg, int id)
953    {
954        unsigned int iJoyStick = _getJoystick(arg);
[1219]955
[1638]956        // translate the POV into 8 simple buttons
[1641]957
[1638]958        int lastState = povStates_[iJoyStick][id];
959        if (lastState & OIS::Pov::North)
960            buttonReleased(arg, 32 + id * 4 + 0);
961        if (lastState & OIS::Pov::South)
962            buttonReleased(arg, 32 + id * 4 + 1);
963        if (lastState & OIS::Pov::East)
964            buttonReleased(arg, 32 + id * 4 + 2);
965        if (lastState & OIS::Pov::West)
966            buttonReleased(arg, 32 + id * 4 + 3);
[1219]967
[1638]968        povStates_[iJoyStick].povStates[id] = arg.state.mPOV[id].direction;
[1502]969
[1638]970        int currentState = povStates_[iJoyStick][id];
971        if (currentState & OIS::Pov::North)
972            buttonPressed(arg, 32 + id * 4 + 0);
973        if (currentState & OIS::Pov::South)
974            buttonPressed(arg, 32 + id * 4 + 1);
975        if (currentState & OIS::Pov::East)
976            buttonPressed(arg, 32 + id * 4 + 2);
977        if (currentState & OIS::Pov::West)
978            buttonPressed(arg, 32 + id * 4 + 3);
[1219]979
[1638]980        return true;
981    }
[1502]982
[1219]983
[1638]984    // ############################################################
985    // #####            Static Interface Methods              #####
986    // ##########                                        ##########
987    // ############################################################
[1219]988
[1638]989    std::string InputManager::bindingCommmandString_s = "";
[1219]990
[1638]991    bool InputManager::initialise(const size_t windowHnd, int windowWidth, int windowHeight,
992        bool createKeyboard, bool createMouse, bool createJoySticks)
[1219]993    {
[1638]994        return _getInstance()._initialise(windowHnd, windowWidth, windowHeight,
995            createKeyboard, createMouse, createJoySticks);
[1219]996    }
[918]997
[1638]998    int InputManager::numberOfKeyboards()
[1219]999    {
[1638]1000        if (_getInstance().keyboard_ != 0)
1001            return 1;
1002        else
1003            return 0;
[1219]1004    }
1005
[1638]1006    int InputManager::numberOfMice()
[1219]1007    {
[1638]1008        if (_getInstance().mouse_ != 0)
1009            return 1;
1010        else
1011            return 0;
[1219]1012    }
1013
[1638]1014    int InputManager::numberOfJoySticks()
[1219]1015    {
[1638]1016        return _getInstance().joySticksSize_;
[1219]1017    }
1018
[1638]1019    /*bool InputManager::isKeyDown(KeyCode::Enum key)
1020    {
1021    if (_getInstance().keyboard_)
1022        return _getInstance().keyboard_->isKeyDown((OIS::KeyCode)key);
1023    else
1024        return false;
1025    }*/
[1219]1026
[1638]1027    /*bool InputManager::isModifierDown(KeyboardModifier::Enum modifier)
[1219]1028    {
[1638]1029    if (_getInstance().keyboard_)
1030        return isModifierDown(modifier);
[1219]1031    else
[1638]1032        return false;
1033    }*/
[1219]1034
[1638]1035    /*const MouseState InputManager::getMouseState()
[1219]1036    {
[1638]1037    if (_getInstance().mouse_)
1038        return _getInstance().mouse_->getMouseState();
[1219]1039    else
[1638]1040        return MouseState();
1041    }*/
[1219]1042
[1638]1043    /*const JoyStickState InputManager::getJoyStickState(unsigned int ID)
[1219]1044    {
[1638]1045    if (ID < _getInstance().joySticksSize_)
1046        return JoyStickState(_getInstance().joySticks_[ID]->getJoyStickState(), ID);
[1219]1047    else
[1638]1048        return JoyStickState();
1049    }*/
[1219]1050
[1638]1051    void InputManager::destroy()
[1219]1052    {
[1638]1053        _getInstance()._destroy();
[1219]1054    }
1055
1056
[1638]1057    /**
1058    @brief
1059        Adjusts the mouse window metrics.
1060        This method has to be called every time the size of the window changes.
1061    @param width
1062        The new width of the render window
1063    @param^height
1064        The new height of the render window
1065    */
1066    void InputManager::setWindowExtents(const int width, const int height)
[1219]1067    {
[1638]1068        if (_getInstance().mouse_)
1069        {
1070            // Set mouse region (if window resizes, we should alter this to reflect as well)
1071            const OIS::MouseState &mouseState = _getInstance().mouse_->getMouseState();
1072            mouseState.width  = width;
1073            mouseState.height = height;
1074        }
[1219]1075    }
1076
[1641]1077    /**
1078    @brief
1079        Method for easily storing a string with the command executor. It is used by the
1080        KeyDetector to get assign commands. The KeyDetector simply executes
1081        the command 'storeKeyStroke myName' for each button/axis.
1082    @remarks
1083        This is only a temporary hack until we thourouhgly support multiple KeyBinders.
1084    @param name
1085        The name of the button/axis.
1086    */
[1638]1087    void InputManager::storeKeyStroke(const std::string& name)
1088    {
1089        requestLeaveState("detector");
1090        COUT(0) << "Binding string \"" << bindingCommmandString_s << "\" on key '" << name << "'" << std::endl;
1091        CommandExecutor::execute("config KeyBinder " + name + " " + bindingCommmandString_s, false);
1092    }
[1219]1093
[1641]1094    /**
1095    @brief
1096        Assigns a command string to a key/button/axis. The name is determined via KeyDetector
1097        and InputManager::storeKeyStroke(.).
1098    @param command
1099        Command string that can be executed by the CommandExecutor
1100    */
[1638]1101    void InputManager::keyBind(const std::string& command)
[1219]1102    {
[1638]1103        bindingCommmandString_s = command;
1104        requestEnterState("detector");
1105        COUT(0) << "Press any button/key or move a mouse/joystick axis" << std::endl;
[1219]1106    }
1107
[1641]1108    /**
1109    @brief
1110        Starts joy stick calibration.
1111    */
[1638]1112    void InputManager::calibrate()
[1219]1113    {
[1641]1114        _getInstance().bCalibrating_ = true;
[1638]1115        requestEnterState("calibrator");
[1219]1116    }
1117
[1638]1118    void InputManager::tick(float dt)
1119    {
1120        _getInstance()._tick(dt);
1121    }
[1219]1122
[1638]1123    // ###### InputStates ######
[1219]1124
[1638]1125    /**
1126    @brief
1127        Adds a new key handler.
1128    @param handler
1129        Pointer to the handler object.
1130    @param name
1131        Unique name of the handler.
[1641]1132    @param priority
1133        Unique integer number. Higher means more prioritised.
[1638]1134    @return
[1641]1135        True if added, false if name or priority already existed.
[1638]1136    */
1137    bool InputManager::_configureInputState(InputState* state, const std::string& name, int priority)
[1219]1138    {
[1638]1139        if (name == "")
1140            return false;
1141        if (_getInstance().inputStatesByName_.find(name) == _getInstance().inputStatesByName_.end())
1142        {
1143            if (_getInstance().inputStatesByPriority_.find(priority)
1144                == _getInstance().inputStatesByPriority_.end())
1145            {
1146                _getInstance().inputStatesByName_[name] = state;
1147                _getInstance().inputStatesByPriority_[priority] = state;
1148                state->setNumOfJoySticks(numberOfJoySticks());
1149                state->setName(name);
1150                state->setPriority(priority);
1151                return true;
1152            }
1153            else
1154            {
1155                COUT(2) << "Warning: Could not add an InputState with the same priority '"
1156                    << priority << "'." << std::endl;
1157                return false;
1158            }
1159        }
1160        else
1161        {
1162            COUT(2) << "Warning: Could not add an InputState with the same name '" << name << "'." << std::endl;
1163            return false;
1164        }
[1219]1165    }
1166
[1641]1167    /**
1168    @brief
1169        Returns a new SimpleInputState and configures it first.
1170    */
[1638]1171    SimpleInputState* InputManager::createSimpleInputState(const std::string &name, int priority)
1172    {
1173        SimpleInputState* state = new SimpleInputState();
1174        if (_getInstance()._configureInputState(state, name, priority))
1175            return state;
1176        else
1177        {
1178            delete state;
1179            return 0;
1180        }
1181    }
[1219]1182
[1641]1183    /**
1184    @brief
1185        Returns a new ExtendedInputState and configures it first.
1186    */
[1638]1187    ExtendedInputState* InputManager::createExtendedInputState(const std::string &name, int priority)
1188    {
1189        ExtendedInputState* state = new ExtendedInputState();
1190        if (_getInstance()._configureInputState(state, name, priority))
1191            return state;
1192        else
1193        {
1194            delete state;
1195            return 0;
1196        }
1197    }
[1219]1198
[1638]1199    /**
1200    @brief
[1641]1201        Removes an input state internally.
[1638]1202    @param name
[1641]1203        Name of the handler.
[1638]1204    @return
1205        True if removal was successful, false if name was not found.
[1641]1206    @remarks
1207        You can't remove the internal states "empty", "calibrator" and "detector".
[1638]1208    */
1209    bool InputManager::destroyState(const std::string& name)
[1219]1210    {
[1638]1211        if (name == "empty" || name == "calibrator" || name == "detector")
1212        {
1213            COUT(2) << "InputManager: Removing the '" << name << "' state is not allowed!" << std::endl;
1214            return false;
1215        }
1216        std::map<std::string, InputState*>::iterator it = _getInstance().inputStatesByName_.find(name);
1217        if (it != _getInstance().inputStatesByName_.end())
1218        {
1219            _getInstance()._destroyState((*it).second);
1220            return true;
1221        }
1222        return false;
[1219]1223    }
1224
[1638]1225    /**
1226    @brief
[1641]1227        Returns the pointer to the requested InputState.
[1638]1228    @param name
[1641]1229        Unique name of the state.
[1638]1230    @return
1231        Pointer to the instance, 0 if name was not found.
1232    */
1233    InputState* InputManager::getState(const std::string& name)
1234    {
1235        std::map<std::string, InputState*>::iterator it = _getInstance().inputStatesByName_.find(name);
1236        if (it != _getInstance().inputStatesByName_.end())
1237            return (*it).second;
1238        else
1239            return 0;
1240    }
[1219]1241
[1638]1242    /**
1243    @brief
[1641]1244        Returns the current input state (there might be others active too!)
[1638]1245    @return
[1641]1246        The current highest prioritised active input state.
[1638]1247    */
1248    InputState* InputManager::getCurrentState()
1249    {
1250        return (*_getInstance().activeStates_.rbegin()).second;
1251    }
[1219]1252
[1638]1253    /**
1254    @brief
[1641]1255        Activates a specific input state.
1256        It might not be really activated if the priority is too low!
[1638]1257    @param name
[1641]1258        Unique name of the state.
[1638]1259    @return
1260        False if name was not found, true otherwise.
1261    */
1262    bool InputManager::requestEnterState(const std::string& name)
[1219]1263    {
[1638]1264        // get pointer from the map with all stored handlers
1265        std::map<std::string, InputState*>::const_iterator it = _getInstance().inputStatesByName_.find(name);
1266        if (it != _getInstance().inputStatesByName_.end())
1267        {
1268            _getInstance().stateEnterRequests_.push_back((*it).second);
1269            return true;
1270        }
1271        return false;
[1219]1272    }
1273
[1641]1274    /**
1275    @brief
1276        Deactivates a specific input state.
1277    @param name
1278        Unique name of the state.
1279    @return
1280        False if name was not found, true otherwise.
1281    */
[1638]1282    bool InputManager::requestLeaveState(const std::string& name)
1283    {
1284        // get pointer from the map with all stored handlers
1285        std::map<std::string, InputState*>::const_iterator it = _getInstance().inputStatesByName_.find(name);
1286        if (it != _getInstance().inputStatesByName_.end())
1287        {
1288            _getInstance().stateLeaveRequests_.push_back((*it).second);
1289            return true;
1290        }
1291        return false;
1292    }
[918]1293}
Note: See TracBrowser for help on using the repository browser.