Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

merged input branch into gui test branch (was about time)
svn save (it's still a mess and CMLs haven't been updated)
I'll have to create a special project to create the tolua_bind files for tolua itself anyway..

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