Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/wiimote/src/libraries/core/input/InputManager.cc @ 12067

Last change on this file since 12067 was 9911, checked in by georgr, 11 years ago

watch out for sensitivity! IR input now working, still trying to fix roll

  • Property svn:eol-style set to native
File size: 26.9 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 and a static variable from the InputHandler.
33*/
34
35#include "InputManager.h"
36
37#include <cassert>
38#include <climits>
39#include <ois/OISException.h>
40#include <ois/OISInputManager.h>
41#include <boost/foreach.hpp>
42#include <loki/ScopeGuard.h>
43
44#include "util/Clock.h"
45#include "util/Convert.h"
46#include "util/Exception.h"
47#include "core/CoreIncludes.h"
48#include "core/GraphicsManager.h"
49#include "core/config/ConfigValueIncludes.h"
50#include "core/config/CommandLineParser.h"
51#include "core/command/ConsoleCommand.h"
52#include "core/command/Functor.h"
53
54#include "InputBuffer.h"
55#include "JoyStick.h"
56#include "JoyStickQuantityListener.h"
57#include "Mouse.h"
58#include "Keyboard.h"
59
60#include "WiiMote.h"
61
62
63namespace orxonox
64{
65    SetCommandLineSwitch(keyboard_no_grab).information("Whether not to exclusively grab the keyboard");
66
67    static const std::string __CC_InputManager_name = "InputManager";
68    static const std::string __CC_calibrate_name = "calibrate";
69    static const std::string __CC_reload_name = "reload";
70
71    SetConsoleCommand(__CC_InputManager_name, __CC_calibrate_name, &InputManager::calibrate).addShortcut();
72    SetConsoleCommand(__CC_InputManager_name, __CC_reload_name,    &InputManager::reload   );
73
74    // Abuse of this source file for the InputHandler
75    InputHandler InputHandler::EMPTY;
76
77    InputManager* InputManager::singletonPtr_s = 0;
78
79    //! Defines the |= operator for easier use.
80    inline InputManager::State operator|=(InputManager::State& lval, InputManager::State rval)
81    {
82        return (lval = (InputManager::State)(lval | rval));
83    }
84
85    //! Defines the &= operator for easier use.
86    inline InputManager::State operator&=(InputManager::State& lval, int rval)
87    {
88        return (lval = (InputManager::State)(lval & rval));
89    }
90
91    // ############################################################
92    // #####                  Initialisation                  #####
93    // ##########                                        ##########
94    // ############################################################
95    InputManager::InputManager()
96        : internalState_(Bad)
97        , oisInputManager_(0)
98        , devices_(2)
99        , exclusiveMouse_(false)
100        , emptyState_(0)
101        , calibratorCallbackHandler_(0)
102    {
103        RegisterObject(InputManager);
104
105        orxout(internal_status, context::input) << "InputManager: Constructing..." << endl;
106
107        // Allocate space for the function call buffer
108        this->callBuffer_.reserve(16);
109
110        this->setConfigValues();
111
112        if (GraphicsManager::getInstance().isFullScreen())
113            exclusiveMouse_ = true;
114        this->loadDevices();
115
116        // Lowest priority empty InputState
117        emptyState_ = createInputState("empty", false, false, InputStatePriority::Empty);
118        emptyState_->setHandler(&InputHandler::EMPTY);
119        activeStates_[emptyState_->getPriority()] = emptyState_;
120
121        // Joy stick calibration helper callback
122        InputState* calibrator = createInputState("calibrator", false, false, InputStatePriority::Calibrator);
123        calibrator->setHandler(&InputHandler::EMPTY);
124        calibratorCallbackHandler_ = new InputBuffer();
125        calibratorCallbackHandler_->registerListener(this, &InputManager::stopCalibration, '\r', true);
126        calibrator->setKeyHandler(calibratorCallbackHandler_);
127
128        this->updateActiveStates();
129
130        ModifyConsoleCommand(__CC_InputManager_name, __CC_calibrate_name).setObject(this);
131        ModifyConsoleCommand(__CC_InputManager_name, __CC_reload_name).setObject(this);
132
133        orxout(internal_status, context::input) << "InputManager: Construction complete." << endl;
134        internalState_ = Nothing;
135    }
136
137    void InputManager::setConfigValues()
138    {
139    }
140
141    /**
142    @brief
143        Creates the OIS::InputMananger, the keyboard, the mouse and
144        the joys ticks. If either of the first two fail, this method throws an exception.
145    */
146    void InputManager::loadDevices()
147    {
148        orxout(verbose, context::input) << "InputManager: Loading input devices..." << endl;
149
150        // When loading the devices they should not already be loaded
151        assert(internalState_ & Bad);
152        assert(devices_[InputDeviceEnumerator::Mouse] == 0);
153        assert(devices_[InputDeviceEnumerator::Keyboard] == 0);
154        assert(devices_.size() == InputDeviceEnumerator::FirstJoyStick);
155
156        typedef std::pair<std::string, std::string> StringPair;
157
158        // Fill parameter list
159        OIS::ParamList paramList;
160        size_t windowHnd = GraphicsManager::getInstance().getRenderWindowHandle();
161        paramList.insert(StringPair("WINDOW", multi_cast<std::string>(windowHnd)));
162#if defined(ORXONOX_PLATFORM_WINDOWS)
163        paramList.insert(StringPair("w32_keyboard", "DISCL_NONEXCLUSIVE"));
164        paramList.insert(StringPair("w32_keyboard", "DISCL_FOREGROUND"));
165        paramList.insert(StringPair("w32_mouse", "DISCL_FOREGROUND"));
166        if (exclusiveMouse_ || GraphicsManager::getInstance().isFullScreen())
167        {
168            // Disable Windows key plus special keys (like play, stop, next, etc.)
169            paramList.insert(StringPair("w32_keyboard", "DISCL_NOWINKEY"));
170            paramList.insert(StringPair("w32_mouse", "DISCL_EXCLUSIVE"));
171        }
172        else
173            paramList.insert(StringPair("w32_mouse", "DISCL_NONEXCLUSIVE"));
174#elif defined(ORXONOX_PLATFORM_LINUX)
175        // Enabling this is probably a bad idea, but whenever orxonox crashes, the setting stays on
176        // Trouble might be that the Pressed event occurs a bit too often...
177        paramList.insert(StringPair("XAutoRepeatOn", "true"));
178
179        if (exclusiveMouse_ || GraphicsManager::getInstance().isFullScreen())
180        {
181            if (CommandLineParser::getValue("keyboard_no_grab").get<bool>())
182                paramList.insert(StringPair("x11_keyboard_grab", "false"));
183            else
184                paramList.insert(StringPair("x11_keyboard_grab", "true"));
185            paramList.insert(StringPair("x11_mouse_grab",  "true"));
186            paramList.insert(StringPair("x11_mouse_hide", "true"));
187        }
188        else
189        {
190            paramList.insert(StringPair("x11_keyboard_grab", "false"));
191            paramList.insert(StringPair("x11_mouse_grab",  "false"));
192            paramList.insert(StringPair("x11_mouse_hide", "false"));
193        }
194#endif
195
196        try
197        {
198            oisInputManager_ = OIS::InputManager::createInputSystem(paramList);
199            // Exception-safety
200            Loki::ScopeGuard guard = Loki::MakeGuard(OIS::InputManager::destroyInputSystem, oisInputManager_);
201            orxout(verbose, context::input) << "Created OIS input manager." << endl;
202
203            if (oisInputManager_->getNumberOfDevices(OIS::OISKeyboard) > 0)
204                devices_[InputDeviceEnumerator::Keyboard] = new Keyboard(InputDeviceEnumerator::Keyboard, oisInputManager_);
205            else
206                ThrowException(InitialisationFailed, "InputManager: No keyboard found, cannot proceed!");
207
208            // Successful initialisation
209            guard.Dismiss();
210        }
211        catch (const std::exception& ex)
212        {
213            oisInputManager_ = NULL;
214            internalState_ |= Bad;
215            ThrowException(InitialisationFailed, "Could not initialise the input system: " << ex.what());
216        }
217
218        this->loadMouse();
219        this->loadJoySticks();
220        this->loadWiiMote();
221        // Reorder states in case some joy sticks were added/removed
222        this->updateActiveStates();
223
224        orxout(verbose, context::input) << "Input devices loaded." << endl;
225    }
226
227    void InputManager::loadWiiMote()
228    {
229
230
231
232        static CWii wii; // Defaults to 4 remotes; static because else it will get deleted during InternalReload
233        std::vector< ::CWiimote>::iterator i;
234        int reloadWiimotes = 0;
235        int index;
236
237        // Find and connect to the wiimotes
238        static std::vector<CWiimote>& wiimotes = wii.FindAndConnect(10); //CWiimotes are kept in here in case of InternalReload calls
239        if (!wiimotes.size())
240        {
241                cout << "No wiimotes found." << endl;
242                return;
243                }
244
245            // Setup the wiimotes
246            for(index = 0, i = wiimotes.begin(); i != wiimotes.end(); ++i, ++index)
247            {
248                // Use a reference to make working with the iterator handy.
249            CWiimote & wiimote = *i;
250
251            //Set Leds
252            int LED_MAP[4] =
253              {CWiimote::LED_1, CWiimote::LED_2,
254               CWiimote::LED_3, CWiimote::LED_4};
255            wiimote.SetLEDs(LED_MAP[index]);
256            wiimote.IR.SetMode(CIR::ON);
257            wiimote.IR.SetAspectRatio(CIR::ASPECT_16_9);
258            wiimote.IR.SetBarPosition(CIR::BAR_ABOVE);
259            wiimote.IR.SetVres(1920,1080);
260            try
261                   {
262                         orxout()<< "Size of devices vector before wiimote insertion:" << devices_.size() << std::endl;
263                         devices_.push_back(new WiiMote((unsigned int)devices_.size(), *i, wii));
264                         //devices_[2] = new WiiMote(devices_.size(), *(new CWiimote()));
265                         orxout()<< "Size of devices vector after wiimote insertion:" << devices_.size() << std::endl;
266                         wiimote.SetMotionSensingMode(CWiimote::ON);
267
268                   }
269                   catch(std::exception& e)  //gotta catch em all
270                   {
271                         orxout()<<"Exception loading WiiMote!!!1!11!";
272                   }
273            }
274
275
276    }
277    //! Creates a new orxonox::Mouse
278    void InputManager::loadMouse()
279    {
280        if (oisInputManager_->getNumberOfDevices(OIS::OISMouse) > 0)
281        {
282            try
283            {
284                devices_[InputDeviceEnumerator::Mouse] = new Mouse(InputDeviceEnumerator::Mouse, oisInputManager_);
285            }
286            catch (const std::exception& ex)
287            {
288                orxout(user_warning, context::input) << "Failed to create Mouse:" << ex.what() << '\n'
289                                                     << "Proceeding without mouse support." << endl;
290            }
291        }
292        else
293            orxout(user_warning, context::input) << "No mouse found! Proceeding without mouse support." << endl;
294    }
295
296    //! Creates as many joy sticks as are available.
297    void InputManager::loadJoySticks()
298    {
299        for (int i = 0; i < oisInputManager_->getNumberOfDevices(OIS::OISJoyStick); i++)
300        {
301            try
302            {
303                devices_.push_back(new JoyStick(InputDeviceEnumerator::FirstJoyStick + i, oisInputManager_));
304            }
305            catch (const std::exception& ex)
306            {
307                orxout(user_warning, context::input) << "Failed to create joy stick: " << ex.what() << endl;
308            }
309        }
310
311        // inform all JoyStick Device Number Listeners
312        std::vector<JoyStick*> joyStickList;
313        for (unsigned int i = InputDeviceEnumerator::FirstJoyStick; i < devices_.size(); ++i)
314            joyStickList.push_back(static_cast<JoyStick*>(devices_[i]));
315        JoyStickQuantityListener::changeJoyStickQuantity(joyStickList);
316    }
317
318    // ############################################################
319    // #####                    Destruction                   #####
320    // ##########                                        ##########
321    // ############################################################
322
323    InputManager::~InputManager()
324    {
325        orxout(internal_status, context::input) << "InputManager: Destroying..." << endl;
326
327        // Leave all active InputStates (except "empty")
328        while (this->activeStates_.size() > 1)
329            this->leaveState(this->activeStates_.rbegin()->second->getName());
330        this->activeStates_.clear();
331
332        // Destroy calibrator helper handler and state
333        this->destroyState("calibrator");
334        // Destroy KeyDetector and state
335        delete calibratorCallbackHandler_;
336        // Destroy the empty InputState
337        this->destroyStateInternal(this->emptyState_);
338
339        // Destroy all user InputStates
340        while (statesByName_.size() > 0)
341            this->destroyStateInternal(statesByName_.rbegin()->second);
342
343        if (!(internalState_ & Bad))
344            this->destroyDevices();
345
346        // Reset console commands
347        ModifyConsoleCommand(__CC_InputManager_name, __CC_calibrate_name).setObject(0);
348        ModifyConsoleCommand(__CC_InputManager_name, __CC_reload_name).setObject(0);
349
350        orxout(internal_status, context::input) << "InputManager: Destruction complete." << endl;
351    }
352
353    /**
354    @brief
355        Destoys all input devices (joy sticks, mouse, keyboard and OIS::InputManager)
356    @throw
357        Method does not throw
358    */
359    void InputManager::destroyDevices()
360    {
361        orxout(verbose, context::input) << "InputManager: Destroying devices..." << endl;
362
363        BOOST_FOREACH(InputDevice*& device, devices_)
364        {
365            if (device == NULL)
366                continue;
367            const std::string& className = device->getClassName();
368            delete device;
369            device = 0;
370            orxout(verbose, context::input) << className << " destroyed." << endl;
371        }
372        devices_.resize(InputDeviceEnumerator::FirstJoyStick);
373
374        assert(oisInputManager_ != NULL);
375        try
376        {
377            OIS::InputManager::destroyInputSystem(oisInputManager_);
378        }
379        catch (const OIS::Exception& ex)
380        {
381            orxout(internal_error, context::input) << "OIS::InputManager destruction failed" << ex.eText << '\n'
382                                                   << "Potential resource leak!" << endl;
383        }
384        oisInputManager_ = NULL;
385
386        internalState_ |= Bad;
387        orxout(verbose, context::input) << "Destroyed devices." << endl;
388    }
389
390    // ############################################################
391    // #####                     Reloading                    #####
392    // ##########                                        ##########
393    // ############################################################
394
395    void InputManager::reload()
396    {
397        if (internalState_ & Calibrating)
398            orxout(internal_warning, context::input) << "Cannot reload input system. Joy sticks are currently being calibrated." << endl;
399        else
400            reloadInternal();
401    }
402
403    //! Internal reload method. Destroys the OIS devices and loads them again.
404    void InputManager::reloadInternal()
405    {
406        orxout(verbose, context::input) << "InputManager: Reloading ..." << endl;
407
408        this->destroyDevices();
409        this->loadDevices();
410
411        internalState_ &= ~Bad;
412        orxout(verbose, context::input) << "InputManager: Reloading complete." << endl;
413    }
414
415    // ############################################################
416    // #####                  Runtime Methods                 #####
417    // ##########                                        ##########
418    // ############################################################
419
420    void InputManager::preUpdate(const Clock& time)
421    {
422        if (internalState_ & Bad)
423            ThrowException(General, "InputManager was not correctly reloaded.");
424
425        // check whether a state has changed its EMPTY situation
426        bool bUpdateRequired = false;
427        for (std::map<int, InputState*>::iterator it = activeStates_.begin(); it != activeStates_.end(); ++it)
428        {
429            if (it->second->hasExpired())
430            {
431                it->second->resetExpiration();
432                bUpdateRequired = true;
433            }
434        }
435
436        if (bUpdateRequired)
437            updateActiveStates();
438
439        // Capture all the input and collect the function calls
440        // No event gets triggered here yet!
441
442        BOOST_FOREACH(InputDevice* device, devices_)
443            if (device != NULL)
444                device->update(time);
445
446
447
448        // Collect function calls for the update
449        for (unsigned int i = 0; i < activeStatesTicked_.size(); ++i)
450            activeStatesTicked_[i]->update(time.getDeltaTime());
451
452        // Execute all cached function calls in order
453        // Why so complicated? The problem is that an InputHandler could trigger
454        // a reload that would destroy the OIS devices or it could even leave and
455        // then destroy its own InputState. That would of course lead to access
456        // violations.
457        // If we delay the calls, then OIS and and the InputStates are not anymore
458        // in the call stack and can therefore be edited.
459        for (size_t i = 0; i < this->callBuffer_.size(); ++i)
460            this->callBuffer_[i]();
461
462        this->callBuffer_.clear();
463    }
464
465    /**
466    @brief
467        Updates the currently active states (according to activeStates_) for each device.
468        Also, a list of all active states (no duplicates!) is compiled for the general preUpdate().
469    */
470    void InputManager::updateActiveStates()
471    {
472        // Calculate the stack of input states
473        // and assign it to the corresponding device
474        for (unsigned int i = 0; i < devices_.size(); ++i)
475        {
476            if (devices_[i] == NULL)
477                continue;
478            std::vector<InputState*>& states = devices_[i]->getStateListRef();
479            bool occupied = false;
480            states.clear();
481            for (std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin(); rit != activeStates_.rend(); ++rit)
482            {
483                orxout() << "Checking ID " << i <<std::endl;
484                orxout() << "Checking condition 1: " << rit->second->isInputDeviceEnabled(i) <<std::endl;
485                orxout() << "Checking condition 2: " << rit->second->bAlwaysGetsInput_ <<std::endl;
486                orxout() << "Checking condition 3: " << !occupied <<std::endl;
487                if (rit->second->isInputDeviceEnabled(i) && (!occupied || rit->second->bAlwaysGetsInput_))
488                {
489                    orxout() << "Success with ID " << i <<std::endl;
490                    states.push_back(rit->second);
491                    if (!rit->second->bTransparent_)
492                        occupied = true;
493                }
494            }
495        }
496
497        // See that we only update each InputState once for each device
498        // Using an std::set to avoid duplicates
499        std::set<InputState*> tempSet;
500        for (unsigned int i = 0; i < devices_.size(); ++i)
501            if (devices_[i] != NULL)
502                for (unsigned int iState = 0; iState < devices_[i]->getStateListRef().size(); ++iState)
503                    tempSet.insert(devices_[i]->getStateListRef()[iState]);
504
505        // Copy the content of the std::set back to the actual vector
506        activeStatesTicked_.clear();
507        for (std::set<InputState*>::const_iterator it = tempSet.begin();it != tempSet.end(); ++it)
508            activeStatesTicked_.push_back(*it);
509
510        // Check whether we have to change the mouse mode
511        tribool requestedMode = dontcare;
512        std::vector<InputState*>& mouseStates = devices_[InputDeviceEnumerator::Mouse]->getStateListRef();
513        if (mouseStates.empty())
514            requestedMode = false;
515        else
516            requestedMode = mouseStates.front()->getMouseExclusive();
517        if (requestedMode != dontcare && exclusiveMouse_ != requestedMode)
518        {
519            assert(requestedMode != dontcare);
520            exclusiveMouse_ = (requestedMode == true);
521            if (!GraphicsManager::getInstance().isFullScreen())
522                this->reloadInternal();
523        }
524    }
525
526    void InputManager::clearBuffers()
527    {
528        BOOST_FOREACH(InputDevice* device, devices_)
529            if (device != NULL)
530                device->clearBuffers();
531    }
532
533    void InputManager::calibrate()
534    {
535        orxout(message) << "Move all joy stick axes fully in all directions." << '\n'
536                        << "When done, put the axex in the middle position and press enter." << endl;
537
538        BOOST_FOREACH(InputDevice* device, devices_)
539            if (device != NULL)
540                device->startCalibration();
541
542        internalState_ |= Calibrating;
543        enterState("calibrator");
544    }
545
546    //! Tells all devices to stop the calibration and evaluate it. Buffers are being cleared as well!
547    void InputManager::stopCalibration()
548    {
549        BOOST_FOREACH(InputDevice* device, devices_)
550            if (device != NULL)
551                device->stopCalibration();
552
553        // restore old input state
554        leaveState("calibrator");
555        internalState_ &= ~Calibrating;
556        // Clear buffers to prevent button hold events
557        this->clearBuffers();
558
559        orxout(message) << "Calibration has been stored." << endl;
560    }
561
562    //! Gets called by WindowEventListener upon focus change --> clear buffers
563    void InputManager::windowFocusChanged(bool bFocus)
564    {
565        this->clearBuffers();
566    }
567
568    std::pair<int, int> InputManager::getMousePosition() const
569    {
570        Mouse* mouse = static_cast<Mouse*>(devices_[InputDeviceEnumerator::Mouse]);
571        if (mouse != NULL)
572        {
573            const OIS::MouseState state = mouse->getOISDevice()->getMouseState();
574            return std::make_pair(state.X.abs, state.Y.abs);
575        }
576        else
577            return std::make_pair(0, 0);
578    }
579
580    // ############################################################
581    // #####                    Input States                  #####
582    // ##########                                        ##########
583    // ############################################################
584
585    InputState* InputManager::createInputState(const std::string& name, bool bAlwaysGetsInput, bool bTransparent, InputStatePriority priority)
586    {
587        if (name.empty())
588            return 0;
589        if (statesByName_.find(name) == statesByName_.end())
590        {
591            if (priority >= InputStatePriority::HighPriority || priority == InputStatePriority::Empty)
592            {
593                // Make sure we don't add two high priority states with the same priority
594                for (std::map<std::string, InputState*>::const_iterator it = this->statesByName_.begin();
595                    it != this->statesByName_.end(); ++it)
596                {
597                    if (it->second->getPriority() == priority)
598                    {
599                        orxout(internal_warning, context::input) << "Could not add an InputState with the same priority '"
600                            << static_cast<int>(priority) << "' != 0." << endl;
601                        return 0;
602                    }
603                }
604            }
605            InputState* state = new InputState(name, bAlwaysGetsInput, bTransparent, priority);
606            statesByName_[name] = state;
607
608            return state;
609        }
610        else
611        {
612            orxout(internal_warning, context::input) << "Could not add an InputState with the same name '" << name << "'." << endl;
613            return 0;
614        }
615    }
616
617    InputState* InputManager::getState(const std::string& name)
618    {
619        std::map<std::string, InputState*>::iterator it = statesByName_.find(name);
620        if (it != statesByName_.end())
621            return it->second;
622        else
623            return 0;
624    }
625
626    bool InputManager::enterState(const std::string& name)
627    {
628        // get pointer from the map with all stored handlers
629        std::map<std::string, InputState*>::const_iterator it = statesByName_.find(name);
630        if (it != statesByName_.end() && activeStates_.find(it->second->getPriority()) == activeStates_.end())
631        {
632            // exists and not active
633            if (it->second->getPriority() == 0)
634            {
635                // Get smallest possible priority between 1 and maxStateStackSize_s
636                for (std::map<int, InputState*>::reverse_iterator rit = activeStates_.rbegin();
637                    rit != activeStates_.rend(); ++rit)
638                {
639                    if (rit->first < InputStatePriority::HighPriority)
640                    {
641                        it->second->setPriority(rit->first + 1);
642                        break;
643                    }
644                }
645                // In case no normal handler was on the stack
646                if (it->second->getPriority() == 0)
647                    it->second->setPriority(1);
648            }
649            activeStates_[it->second->getPriority()] = it->second;
650            updateActiveStates();
651            it->second->entered();
652
653            return true;
654        }
655        return false;
656    }
657
658    bool InputManager::leaveState(const std::string& name)
659    {
660        if (name == "empty")
661        {
662            orxout(internal_warning, context::input) << "InputManager: Leaving the empty state is not allowed!" << endl;
663            return false;
664        }
665        // get pointer from the map with all stored handlers
666        std::map<std::string, InputState*>::const_iterator it = statesByName_.find(name);
667        if (it != statesByName_.end() && activeStates_.find(it->second->getPriority()) != activeStates_.end())
668        {
669            // exists and active
670
671            it->second->left();
672
673            activeStates_.erase(it->second->getPriority());
674            if (it->second->getPriority() < InputStatePriority::HighPriority)
675                it->second->setPriority(0);
676            updateActiveStates();
677
678            return true;
679        }
680        return false;
681    }
682
683    bool InputManager::destroyState(const std::string& name)
684    {
685        if (name == "empty")
686        {
687            orxout(internal_warning, context::input) << "InputManager: Removing the empty state is not allowed!" << endl;
688            return false;
689        }
690        std::map<std::string, InputState*>::iterator it = statesByName_.find(name);
691        if (it != statesByName_.end())
692        {
693            this->leaveState(name);
694            destroyStateInternal(it->second);
695
696            return true;
697        }
698        return false;
699    }
700
701    //! Destroys an InputState internally.
702    void InputManager::destroyStateInternal(InputState* state)
703    {
704        assert(state && this->activeStates_.find(state->getPriority()) == this->activeStates_.end());
705        statesByName_.erase(state->getName());
706        delete state;
707    }
708
709    bool InputManager::setMouseExclusive(const std::string& name, tribool value)
710    {
711        if (name == "empty")
712        {
713            orxout(internal_warning, context::input) << "InputManager: Changing the empty state is not allowed!" << endl;
714            return false;
715        }
716        std::map<std::string, InputState*>::iterator it = statesByName_.find(name);
717        if (it != statesByName_.end())
718        {
719            it->second->setMouseExclusive(value);
720            return true;
721        }
722        return false;
723    }
724}
Note: See TracBrowser for help on using the repository browser.