Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/consolecommands3/src/libraries/core/input/InputDevice.h @ 7267

Last change on this file since 7267 was 7174, checked in by rgrieder, 14 years ago

Only catch exceptions you actually expect. And rethrow unknown exceptions ("…" can also catch internal Microsoft exceptions like floating point exception).

  • Property svn:eol-style set to native
File size: 9.3 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 InputDevice and InputDeviceTemplated
33*/
34
35#ifndef _InputDevice_H__
36#define _InputDevice_H__
37
38#include "InputPrereqs.h"
39
40#include <vector>
41#include <ois/OISInputManager.h>
42#include <ois/OISException.h>
43
44#include "util/Clock.h"
45#include "util/Debug.h"
46#include "util/Exception.h"
47#include "InputState.h"
48
49namespace orxonox
50{
51    /**
52    @brief
53        Abstract base class for all input devices (mouse, keyboard and joy sticks).
54
55        It provides common virtual functions to be used by the InputManager.
56    */
57    class InputDevice
58    {
59    public:
60        //! Only resets the members
61        InputDevice(unsigned int id) : bCalibrating_(false), deviceID_(id) { }
62        virtual ~InputDevice() { }
63        //! Returns the device class (derived) name as string
64        virtual std::string getClassName() const = 0;
65        //! Updates the device which should in turn distribute events
66        virtual void update(const Clock& time) = 0;
67        //! Clear all button related buffers
68        virtual void clearBuffers() = 0;
69
70        //! Start calibrating (only useful for joy sticks)
71        void startCalibration()
72        {
73            bCalibrating_ = true;
74            this->calibrationStarted();
75        }
76
77        //! Stop calibrating and evaluate the data (only useful for joy sticks)
78        void stopCalibration()
79        {
80            this->calibrationStopped();
81            bCalibrating_ = false;
82        }
83
84        //! Returns a reference to the internal input state vector. Use with care!
85        std::vector<InputState*>& getStateListRef() { return this->inputStates_; }
86        //! Returns the ID of the device (the same as in InputDeviceEnumerator for mouse and keyboard)
87        unsigned int getDeviceID() const { return this->deviceID_; }
88        //! Tells whether the device is in calibration mode
89        bool isCalibrating() const { return bCalibrating_; }
90
91    protected:
92        //! To be ovrridden by the subclass
93        virtual void calibrationStarted() { }
94        //! To be ovrridden by the subclass
95        virtual void calibrationStopped() { }
96
97        //! List of all input states that receive events from this device
98        std::vector<InputState*> inputStates_;
99
100    private:
101        InputDevice(const InputDevice& rhs); //!< Don't use!
102
103        bool bCalibrating_;                  //!< Whether the device is in calibration mode
104        const unsigned int deviceID_;        //!< ID of the device (the same as in InputDeviceEnumerator for mouse and keyboard)
105    };
106
107    /**
108    @brief
109        Heavily templated base class for all three input devices.
110
111        The purpose of this class is not to provide an interface but rather
112        to reduce code redundancy. This concerns device creation and destruction
113        as well as common code for button events (press, release, hold).
114
115        In order to derive from this class you have to supply it with a struct
116        as template parameter that contains the necessary type traits.
117    */
118    template <class Traits>
119    class InputDeviceTemplated : public InputDevice
120    {
121        typedef typename Traits::DeviceClass DeviceClass;
122        typedef typename Traits::OISDeviceClass OISDeviceClass;
123        typedef typename Traits::ButtonType ButtonType;
124        typedef typename Traits::ButtonTypeParam ButtonTypeParam;
125        static const OIS::Type OISDeviceValue = Traits::OISDeviceValue;
126
127    public:
128        //! Creates the OIS device
129        InputDeviceTemplated(unsigned int id, OIS::InputManager* oisInputManager)
130            : InputDevice(id)
131            , oisInputManager_(oisInputManager)
132        {
133            oisDevice_ = static_cast<OISDeviceClass*>(oisInputManager_->createInputObject(OISDeviceValue, true));
134            // Note: after the static_cast here, the casted this pointer becomes
135            //       invalid right until the subclass has been constructed!
136            oisDevice_->setEventCallback(static_cast<DeviceClass*>(this));
137            COUT(4) << "Instantiated a " << this->getClassName() << std::endl;
138        }
139
140        //! Destroys the OIS device
141        virtual ~InputDeviceTemplated()
142        {
143            try
144            {
145                oisInputManager_->destroyInputObject(oisDevice_);
146            }
147            catch (const OIS::Exception& ex)
148            {
149                COUT(1) << this->getClassName() << " destruction failed: " << ex.eText << std::endl
150                        << "    Potential resource leak!" << std::endl;
151            }
152        }
153
154        //! Captures OIS events (which then get distributed to the derived class) and creates the button held events
155        void update(const Clock& time)
156        {
157            oisDevice_->capture();
158
159            // Call all the states with the held button event
160            for (unsigned int iB = 0; iB < pressedButtons_.size(); ++iB)
161                for (unsigned int iS = 0; iS < inputStates_.size(); ++iS)
162                    inputStates_[iS]->buttonEvent<ButtonEvent::THold, typename Traits::ButtonTypeParam>(
163                        this->getDeviceID(), static_cast<DeviceClass*>(this)->getButtonEventArg(pressedButtons_[iB]));
164
165            // Call states with device update events
166            for (unsigned int i = 0; i < inputStates_.size(); ++i)
167                inputStates_[i]->update(time.getDeltaTime(), this->getDeviceID());
168
169            static_cast<DeviceClass*>(this)->updateImpl(time);
170        }
171
172        //! Clears the list of pressed buttons and calls the derived class's method
173        void clearBuffers()
174        {
175            pressedButtons_.clear();
176            static_cast<DeviceClass*>(this)->clearBuffersImpl();
177        }
178
179        // Returns a pointer to the OIS device
180        OISDeviceClass* getOISDevice()   { return this->oisDevice_; }
181        // Returns the name of the derived class as string
182        std::string getClassName() const { return DeviceClass::getClassNameImpl(); }
183
184    protected:
185        //! Common code for all button pressed events (updates pressed buttons list and calls the input states)
186        FORCEINLINE void buttonPressed(ButtonTypeParam button)
187        {
188            // check whether the button already is in the list (can happen when focus was lost)
189            unsigned int iButton = 0;
190            while (iButton < pressedButtons_.size() && pressedButtons_[iButton] != button)
191                iButton++;
192            if (iButton == pressedButtons_.size())
193                pressedButtons_.push_back(button);
194            else
195                return; // Button already pressed
196
197            // Call states
198            for (unsigned int i = 0; i < inputStates_.size(); ++i)
199                inputStates_[i]->buttonEvent<ButtonEvent::TPress, typename Traits::ButtonTypeParam>(this->getDeviceID(), static_cast<DeviceClass*>(this)->getButtonEventArg(button));
200        }
201
202        //! Common code for all button released events (updates pressed buttons list and calls the input states)
203        FORCEINLINE void buttonReleased(ButtonTypeParam button)
204        {
205            // remove the button from the pressedButtons_ list
206            bool found = false;
207            for (unsigned int iButton = 0; iButton < pressedButtons_.size(); iButton++)
208            {
209                if (pressedButtons_[iButton] == button)
210                {
211                    pressedButtons_.erase(pressedButtons_.begin() + iButton);
212                    found = true;
213                    break;
214                }
215            }
216            if (!found)
217                return; // We ignore release strokes when the press was not captured
218
219            // Call states
220            for (unsigned int i = 0; i < inputStates_.size(); ++i)
221                inputStates_[i]->buttonEvent<ButtonEvent::TRelease, typename Traits::ButtonTypeParam>(this->getDeviceID(), static_cast<DeviceClass*>(this)->getButtonEventArg(button));
222        }
223
224        //! Managed pointer to the OIS device
225        OISDeviceClass* oisDevice_;
226
227    private:
228        //!< Fallback dummy function for static polymorphism
229        void clearBuffersImpl() { }
230        //!< Fallback dummy function for static polymorphism
231        void updateImpl(const Clock& time) { }
232        //!< Fallback dummy function for static polymorphism
233        ButtonType& getButtonEventArg(ButtonType& button) { return button; }
234
235        std::vector<ButtonType> pressedButtons_; //!< List of all buttons that are currently pressed down
236        OIS::InputManager* oisInputManager_;     //!< Pointer to the OIS InputManager that can create and destroy devices
237    };
238}
239
240#endif /* _InputDevice_H__ */
Note: See TracBrowser for help on using the repository browser.