Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Finally! The InputManager is now working like I imagined it to. And it's even easier to use it as well.
A little explanation: Every time you change something about the input distribution, it is a change of 'state' represented by the class 'InputState'.
That can be for instance: "console", "game", "gui", etc. Every state has a name and a priority which describes who comes first. Now if one state doesn't handle mouse input or instance, then the one with the next lower priority gets it. To prevent that, you can add the 'EmptyHandler' to the state with setMouseHandler.
InputState is just an abstract base class. There are two classes implementing it: SimpleInputState and ExtendedInputState. The latter allows for multiple input handlers for one single device.

Basically, what you need to know is what you see in Orxonox.cc, InGameConsole.cc and Shell.cc.

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