Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/core/input/InputDevice.h @ 4157

Last change on this file since 4157 was 3327, checked in by rgrieder, 15 years ago

Merged all remaining revisions from core4 back to the trunk.

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