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
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Reto Grieder
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30@file
31@brief
32    Implementation of the InputManager that captures all the input from OIS
33    and redirects it to handlers.
34 */
35
36#include "InputManager.h"
37
38#include <limits.h>
39
40#include "ois/OISException.h"
41#include "ois/OISInputManager.h"
42
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"
48
49#include "InputBuffer.h"
50#include "KeyBinder.h"
51#include "KeyDetector.h"
52#include "CalibratorCallback.h"
53#include "InputState.h"
54#include "SimpleInputState.h"
55#include "ExtendedInputState.h"
56
57namespace orxonox
58{
59    SetConsoleCommandShortcut(InputManager, keyBind);
60    SetConsoleCommandShortcut(InputManager, storeKeyStroke);
61    SetConsoleCommandShortcut(InputManager, calibrate);
62
63    using namespace InputDevice;
64
65    // ###############################
66    // ###    Internal Methods     ###
67    // ###############################
68    // ###############################
69
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)
80        , devicesNum_(0)
81        , stateDetector_(0)
82        , stateCalibrator_(0)
83        , stateEmpty_(0)
84        , keyboardModifiers_(0)
85        , bCalibrating_(false)
86    {
87        RegisterRootObject(InputManager);
88    }
89
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    */
96    InputManager& InputManager::_getInstance()
97    {
98        static InputManager theOnlyInstance;
99        return theOnlyInstance;
100    }
101
102    /**
103    @brief
104        Destructor only called at the end of the program, after main.
105    */
106    InputManager::~InputManager()
107    {
108        _destroy();
109    }
110
111
112    // ############################################################
113    // #####                  Initialisation                  #####
114    // ##########                                        ##########
115    // ############################################################
116
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)
130    {
131        if (inputSystem_ == 0)
132        {
133            CCOUT(3) << "Initialising Input System..." << std::endl;
134            CCOUT(ORX_DEBUG) << "Initialising OIS components..." << std::endl;
135
136            OIS::ParamList paramList;
137            std::ostringstream windowHndStr;
138
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")));
144//#if defined OIS_LINUX_PLATFORM
145            //paramList.insert(std::make_pair(std::string("XAutoRepeatOn"), std::string("true")));
146//#endif
147
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            }
160
161            if (createKeyboard)
162                _initialiseKeyboard();
163
164            if (createMouse)
165                _initialiseMouse();
166
167            if (createJoySticks)
168                _initialiseJoySticks();
169
170            // set all the std::vector list sizes now that the devices have been created
171            _redimensionLists();
172
173            // Set mouse/joystick region
174            if (mouse_)
175            {
176                setWindowExtents(windowWidth, windowHeight);
177            }
178
179            CCOUT(ORX_DEBUG) << "Initialising OIS components done." << std::endl;
180
181            // InputManager holds the input buffer --> create one and add it.
182            //buffer_ = new InputBuffer();
183            //addKeyHandler(buffer_, "buffer");
184            //Shell::getInstance().setInputBuffer(buffer_);
185
186            setConfigValues();
187
188            stateEmpty_ = createSimpleInputState("empty", -1);
189            stateEmpty_->setHandler(new EmptyHandler());
190            activeStates_[stateEmpty_->getPriority()] = stateEmpty_;
191
192            stateDetector_ = createSimpleInputState("detector", 101);
193            KeyDetector* temp = new KeyDetector();
194            temp->loadBindings("storeKeyStroke");
195            stateDetector_->setHandler(temp);
196
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);
202
203            _updateActiveStates();
204
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        }
211        return true;
212    }
213
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()
221    {
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        }
251    }
252
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()
260    {
261        if (mouse_ != 0)
262        {
263            CCOUT(2) << "Warning: Mouse already initialised, skipping." << std::endl;
264            return true;
265        }
266        try
267        {
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            }
281        }
282        catch (OIS::Exception ex)
283        {
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;
288        }
289    }
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()
298    {
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));
313                    CCOUT(ORX_DEBUG) << "Created OIS joy stick with ID " << stig->getID() << std::endl;
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        }
331        return success;
332    }
333
334    void InputManager::_redimensionLists()
335    {
336        joySticksSize_ = joySticks_.size();
337        devicesNum_ = 2 + joySticksSize_;
338        joyStickButtonsDown_ .resize(joySticksSize_);
339        povStates_           .resize(joySticksSize_);
340        sliderStates_        .resize(joySticksSize_);
341        joySticksCalibration_.resize(joySticksSize_);
342
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        }
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_);
361    }
362
363    /**
364    @brief
365        Sets the configurable values. Use keybindings.ini as file..
366    */
367    void InputManager::setConfigValues()
368    {
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            }
383
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);
391
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);
399
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);
407
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        }
416    }
417
418
419    // ############################################################
420    // #####                    Destruction                   #####
421    // ##########                                        ##########
422    // ############################################################
423
424    /**
425    @brief
426        Destroys all the created input devices and sets the InputManager to construction state.
427    */
428    void InputManager::_destroy()
429    {
430        if (inputSystem_)
431        {
432            CCOUT(ORX_DEBUG) << "Destroying ..." << std::endl;
433
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();
439
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;
450
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();
455
456            // destroy the devices
457            _destroyKeyboard();
458            _destroyMouse();
459            _destroyJoySticks();
460
461            _redimensionLists();
462
463            OIS::InputManager::destroyInputSystem(inputSystem_);
464            inputSystem_ = 0;
465
466            CCOUT(ORX_DEBUG) << "Destroying done." << std::endl;
467        }
468    }
469
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    }
482
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    }
495
496    /**
497    @brief
498        Destroys all the joy sticks and resizes the lists to 0.
499    */
500    void InputManager::_destroyJoySticks()
501    {
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]);
508
509            joySticks_.clear();
510        }
511        CCOUT(ORX_DEBUG) << "Joy sticks destroyed." << std::endl;
512    }
513
514    void InputManager::_destroyState(InputState* state)
515    {
516        assert(state);
517        inputStatesByPriority_.erase(state->getPriority());
518        inputStatesByName_.erase(state->getName());
519        delete state;
520    }
521
522
523    // ############################################################
524    // #####                  Runtime Methods                 #####
525    // ##########                                        ##########
526    // ############################################################
527
528    /**
529    @brief
530        Updates the InputManager. Tick is called by the Core class.
531    @param dt
532        Delta time
533    */
534    void InputManager::_tick(float dt)
535    {
536        if (inputSystem_ == 0)
537            return;
538
539        // check for states to leave (don't use unsigned int!)
540        for (int i = stateLeaveRequests_.size() - 1; i >= 0; --i)
541        {
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        }
550
551
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();
562        }
563
564        // Capture all the input. This calls the event handlers in InputManager.
565        if (keyboard_)
566            keyboard_->capture();
567        if (mouse_)
568            mouse_->capture();
569        for (unsigned  int i = 0; i < joySticksSize_; i++)
570            joySticks_[i]->capture();
571
572        if (!bCalibrating_)
573        {
574            // call all the handlers for the held key events
575            for (unsigned int iKey = 0; iKey < keysDown_.size(); iKey++)
576                activeStatesTop_[Keyboard]->keyHeld(KeyEvent(keysDown_[iKey], keyboardModifiers_));
577
578            // call all the handlers for the held mouse button events
579            for (unsigned int iButton = 0; iButton < mouseButtonsDown_.size(); iButton++)
580                activeStatesTop_[Mouse]->mouseButtonHeld(mouseButtonsDown_[iButton]);
581
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++)
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);
595        }
596    }
597
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);
615    }
616
617    void InputManager::_completeCalibration()
618    {
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;
632
633            // config value
634            ConfigValueContainer* cont = getIdentifier()->getConfigValueContainer("CoeffPos");
635            assert(cont);
636            cont->set(i, joySticksCalibration_[0].positiveCoeff[i]);
637
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        }
674
675        // restore old input state
676        requestLeaveState("calibrator");
677    }
678
679
680    // ############################################################
681    // #####                    OIS events                    #####
682    // ##########                                        ##########
683    // ############################################################
684
685    // ###### Key Events ######
686
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)
694    {
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));
701
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
709
710        activeStatesTop_[Keyboard]->keyPressed(KeyEvent(e, keyboardModifiers_));
711
712        return true;
713    }
714
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        }
732
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
740
741        activeStatesTop_[Keyboard]->keyReleased(KeyEvent(e, keyboardModifiers_));
742
743        return true;
744    }
745
746
747    // ###### Mouse Events ######
748
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        {
760            activeStatesTop_[Mouse]->mouseMoved(IntVector2(e.state.X.abs, e.state.Y.abs),
761                    IntVector2(e.state.X.rel, e.state.Y.rel), IntVector2(e.state.width, e.state.height));
762        }
763
764        // check for mouse scrolled event
765        if (e.state.Z.rel != 0)
766        {
767            activeStatesTop_[Mouse]->mouseScrolled(e.state.Z.abs, e.state.Z.rel);
768        }
769
770        return true;
771    }
772
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)
782    {
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);
789
790        activeStatesTop_[Mouse]->mouseButtonPressed((MouseButton::Enum)id);
791
792        return true;
793    }
794
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        }
814
815        activeStatesTop_[Mouse]->mouseButtonReleased((MouseButton::Enum)id);
816
817        return true;
818    }
819
820
821    // ###### Joy Stick Events ######
822
823    inline unsigned int InputManager::_getJoystick(const OIS::JoyStickEvent& arg)
824    {
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++;
830        // assert: Unknown joystick fired an event.
831        assert(iJoyStick != joySticksSize_);
832        return iJoyStick;
833    }
834
835    bool InputManager::buttonPressed(const OIS::JoyStickEvent &arg, int button)
836    {
837        unsigned int iJoyStick = _getJoystick(arg);
838
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);
846
847        activeStatesTop_[2 + iJoyStick]->joyStickButtonPressed(iJoyStick, button);
848
849        return true;
850    }
851
852    bool InputManager::buttonReleased(const OIS::JoyStickEvent &arg, int button)
853    {
854        unsigned int iJoyStick = _getJoystick(arg);
855
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        }
866
867        activeStatesTop_[2 + iJoyStick]->joyStickButtonReleased(iJoyStick, button);
868
869        return true;
870    }
871
872    void InputManager::_fireAxis(unsigned int iJoyStick, int axis, int value)
873    {
874        if (bCalibrating_)
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];
888
889            activeStatesTop_[2 + iJoyStick]->joyStickAxisMoved(iJoyStick, axis, fValue);
890        }
891    }
892
893    bool InputManager::axisMoved(const OIS::JoyStickEvent &arg, int axis)
894    {
895        unsigned int iJoyStick = _getJoystick(arg);
896
897        // keep in mind that the first 8 axes are reserved for the sliders
898        _fireAxis(iJoyStick, axis + 8, arg.state.mAxes[axis].abs);
899
900        return true;
901    }
902
903    bool InputManager::sliderMoved(const OIS::JoyStickEvent &arg, int id)
904    {
905        unsigned int iJoyStick = _getJoystick(arg);
906
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);
911
912        return true;
913    }
914
915    bool InputManager::povMoved(const OIS::JoyStickEvent &arg, int id)
916    {
917        unsigned int iJoyStick = _getJoystick(arg);
918
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);
929
930        povStates_[iJoyStick].povStates[id] = arg.state.mPOV[id].direction;
931
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);
941
942        return true;
943    }
944
945
946    // ############################################################
947    // #####            Static Interface Methods              #####
948    // ##########                                        ##########
949    // ############################################################
950
951    std::string InputManager::bindingCommmandString_s = "";
952
953    bool InputManager::initialise(const size_t windowHnd, int windowWidth, int windowHeight,
954        bool createKeyboard, bool createMouse, bool createJoySticks)
955    {
956        return _getInstance()._initialise(windowHnd, windowWidth, windowHeight,
957            createKeyboard, createMouse, createJoySticks);
958    }
959
960    bool InputManager::initialiseKeyboard()
961    {
962        return _getInstance()._initialiseKeyboard();
963    }
964
965    bool InputManager::initialiseMouse()
966    {
967        return _getInstance()._initialiseMouse();
968    }
969
970    bool InputManager::initialiseJoySticks()
971    {
972        return _getInstance()._initialiseJoySticks();
973    }
974
975    int InputManager::numberOfKeyboards()
976    {
977        if (_getInstance().keyboard_ != 0)
978            return 1;
979        else
980            return 0;
981    }
982
983    int InputManager::numberOfMice()
984    {
985        if (_getInstance().mouse_ != 0)
986            return 1;
987        else
988            return 0;
989    }
990
991    int InputManager::numberOfJoySticks()
992    {
993        return _getInstance().joySticksSize_;
994    }
995
996    /*bool InputManager::isKeyDown(KeyCode::Enum key)
997    {
998    if (_getInstance().keyboard_)
999        return _getInstance().keyboard_->isKeyDown((OIS::KeyCode)key);
1000    else
1001        return false;
1002    }*/
1003
1004    /*bool InputManager::isModifierDown(KeyboardModifier::Enum modifier)
1005    {
1006    if (_getInstance().keyboard_)
1007        return isModifierDown(modifier);
1008    else
1009        return false;
1010    }*/
1011
1012    /*const MouseState InputManager::getMouseState()
1013    {
1014    if (_getInstance().mouse_)
1015        return _getInstance().mouse_->getMouseState();
1016    else
1017        return MouseState();
1018    }*/
1019
1020    /*const JoyStickState InputManager::getJoyStickState(unsigned int ID)
1021    {
1022    if (ID < _getInstance().joySticksSize_)
1023        return JoyStickState(_getInstance().joySticks_[ID]->getJoyStickState(), ID);
1024    else
1025        return JoyStickState();
1026    }*/
1027
1028    void InputManager::destroy()
1029    {
1030        _getInstance()._destroy();
1031    }
1032
1033    void InputManager::destroyKeyboard()
1034    {
1035        return _getInstance()._destroyKeyboard();
1036    }
1037
1038    void InputManager::destroyMouse()
1039    {
1040        return _getInstance()._destroyMouse();
1041    }
1042
1043    void InputManager::destroyJoySticks()
1044    {
1045        return _getInstance()._destroyJoySticks();
1046    }
1047
1048
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)
1059    {
1060        if (_getInstance().mouse_)
1061        {
1062            // Set mouse region (if window resizes, we should alter this to reflect as well)
1063            const OIS::MouseState &mouseState = _getInstance().mouse_->getMouseState();
1064            mouseState.width  = width;
1065            mouseState.height = height;
1066        }
1067    }
1068
1069    void InputManager::storeKeyStroke(const std::string& name)
1070    {
1071        requestLeaveState("detector");
1072        COUT(0) << "Binding string \"" << bindingCommmandString_s << "\" on key '" << name << "'" << std::endl;
1073        CommandExecutor::execute("config KeyBinder " + name + " " + bindingCommmandString_s, false);
1074    }
1075
1076    void InputManager::keyBind(const std::string& command)
1077    {
1078        bindingCommmandString_s = command;
1079        requestEnterState("detector");
1080        COUT(0) << "Press any button/key or move a mouse/joystick axis" << std::endl;
1081    }
1082
1083    void InputManager::calibrate()
1084    {
1085        requestEnterState("calibrator");
1086    }
1087
1088    void InputManager::tick(float dt)
1089    {
1090        _getInstance()._tick(dt);
1091    }
1092
1093    // ###### InputStates ######
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    */
1105    bool InputManager::_configureInputState(InputState* state, const std::string& name, int priority)
1106    {
1107        if (name == "")
1108            return false;
1109        if (_getInstance().inputStatesByName_.find(name) == _getInstance().inputStatesByName_.end())
1110        {
1111            if (_getInstance().inputStatesByPriority_.find(priority)
1112                == _getInstance().inputStatesByPriority_.end())
1113            {
1114                _getInstance().inputStatesByName_[name] = state;
1115                _getInstance().inputStatesByPriority_[priority] = state;
1116                state->setNumOfJoySticks(numberOfJoySticks());
1117                state->setName(name);
1118                state->setPriority(priority);
1119                return true;
1120            }
1121            else
1122            {
1123                COUT(2) << "Warning: Could not add an InputState with the same priority '"
1124                    << priority << "'." << std::endl;
1125                return false;
1126            }
1127        }
1128        else
1129        {
1130            COUT(2) << "Warning: Could not add an InputState with the same name '" << name << "'." << std::endl;
1131            return false;
1132        }
1133    }
1134
1135    SimpleInputState* InputManager::createSimpleInputState(const std::string &name, int priority)
1136    {
1137        SimpleInputState* state = new SimpleInputState();
1138        if (_getInstance()._configureInputState(state, name, priority))
1139            return state;
1140        else
1141        {
1142            delete state;
1143            return 0;
1144        }
1145    }
1146
1147    ExtendedInputState* InputManager::createExtendedInputState(const std::string &name, int priority)
1148    {
1149        ExtendedInputState* state = new ExtendedInputState();
1150        if (_getInstance()._configureInputState(state, name, priority))
1151            return state;
1152        else
1153        {
1154            delete state;
1155            return 0;
1156        }
1157    }
1158
1159    /**
1160    @brief
1161        Removes a Key handler from the list.
1162    @param name
1163        Unique name of the handler.
1164    @return
1165        True if removal was successful, false if name was not found.
1166    */
1167    bool InputManager::destroyState(const std::string& name)
1168    {
1169        if (name == "empty" || name == "calibrator" || name == "detector")
1170        {
1171            COUT(2) << "InputManager: Removing the '" << name << "' state is not allowed!" << std::endl;
1172            return false;
1173        }
1174        std::map<std::string, InputState*>::iterator it = _getInstance().inputStatesByName_.find(name);
1175        if (it != _getInstance().inputStatesByName_.end())
1176        {
1177            _getInstance()._destroyState((*it).second);
1178            return true;
1179        }
1180        return false;
1181    }
1182
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    */
1191    InputState* InputManager::getState(const std::string& name)
1192    {
1193        std::map<std::string, InputState*>::iterator it = _getInstance().inputStatesByName_.find(name);
1194        if (it != _getInstance().inputStatesByName_.end())
1195            return (*it).second;
1196        else
1197            return 0;
1198    }
1199
1200    /**
1201    @brief
1202        Returns the current input handling method
1203    @return
1204        The current input mode.
1205    */
1206    InputState* InputManager::getCurrentState()
1207    {
1208        return (*_getInstance().activeStates_.rbegin()).second;
1209    }
1210
1211    /**
1212    @brief
1213        Enables a specific key handler that has already been added.
1214    @param name
1215        Unique name of the handler.
1216    @return
1217        False if name was not found, true otherwise.
1218    */
1219    bool InputManager::requestEnterState(const std::string& name)
1220    {
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())
1224        {
1225            _getInstance().stateEnterRequests_.push_back((*it).second);
1226            return true;
1227        }
1228        return false;
1229    }
1230
1231    bool InputManager::requestLeaveState(const std::string& name)
1232    {
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())
1236        {
1237            _getInstance().stateLeaveRequests_.push_back((*it).second);
1238            return true;
1239        }
1240        return false;
1241    }
1242}
Note: See TracBrowser for help on using the repository browser.