Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentation2/src/libraries/core/input/InputDevice.h @ 6379

Last change on this file since 6379 was 6301, checked in by rgrieder, 15 years ago

Changed an input strategy: When you press a key but don't release it and then clear the input buffer, the release event will not be triggered anymore.

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