Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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