Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/core/input/InputState.h @ 12123

Last change on this file since 12123 was 11071, checked in by landauf, 9 years ago

merged branch cpp11_v3 back to trunk

  • Property svn:eol-style set to native
File size: 10.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#ifndef _InputState_H__
30#define _InputState_H__
31
32#include "InputPrereqs.h"
33
34#include <cassert>
35#include <string>
36#include <vector>
37#include <functional>
38
39#include "util/tribool.h"
40#include "InputHandler.h"
41#include "InputManager.h"
42#include "JoyStickQuantityListener.h"
43
44#define INPUT_STATE_PUSH_CALL(deviceIndex, functionName, ...) \
45    InputManager::getInstance().pushCall(std::function<void ()>(std::bind(&InputHandler::functionName, handlers_[deviceIndex], __VA_ARGS__)))
46
47namespace orxonox
48{
49    /**
50    @brief
51        InputStates allow you to customise the input event targets at runtime.
52
53        The general idea is a stack: Every activated InputState will be pushed on
54        that stack and only the top one gets the input events. This is done for
55        every device (keyboard, mouse, all joy sticks) separately to allow
56        for instance keyboard input capturing for the console while you can still
57        steer a ship with the mouse.
58        There are two exceptions to this behaviour though:
59        - If an InputState is created with the 'Transparent' parameter on, the
60          state will not prevent input from getting to the state below it on the stack.
61          This can be useful for instance if you need to deploy input to multiple
62          handlers: Simply create two InputStates and make the high priority one transparent.
63        - If an InputState is created with the 'AlwaysGetsInput' parameter on, then
64          the state will always receive input as long as it is activated.
65        - Note: If you mark an InputState with both parameters on, then it will
66          not influence only other InputState at all.
67
68    @par Priorities
69        Every InputState has a priority when on the stack, but mostly this
70        priority is dynamic (InputStatePriority::Dynamic) which means that a state
71        pushed onto the stack will simply have a higher priority than the top one.
72        This behaviour really only applies to normal states that don't have
73        a high priority (InputStatePriority::HighPriority). These 'special' ones
74        are used for features like the KeyDetector or the console. Use with care!
75
76    @par Exclusive/Non-Exclusive mouse Mode
77        You can select a specific mouse mode that tells whether the application
78        should have exclusive access to it or not.
79        When in non-exclusive mode, you can move the mouse out of the window
80        like with any other normal window (only for windowed mode!).
81        The setting is dictated by the topmost InputState that gets mouse events.
82    */
83    class _CoreExport InputState : public JoyStickQuantityListener
84    {
85        friend class InputManager;
86
87        //! Marks the index in the handler vector for the keyboard handler
88        static const InputDeviceEnumerator::Value keyboardIndex_s = InputDeviceEnumerator::Keyboard;
89        //! Marks the index in the handler vector for the mouse handler
90        static const InputDeviceEnumerator::Value mouseIndex_s = InputDeviceEnumerator::Mouse;
91        //! Marks the index in the handler vector for the first joy stick handler
92        static const InputDeviceEnumerator::Value firstJoyStickIndex_s = InputDeviceEnumerator::FirstJoyStick;
93
94    public:
95        //! Sets the keyboard event handler (overwrites if there already was one!)
96        void setKeyHandler     (InputHandler* handler)
97            { handlers_[keyboardIndex_s] = handler; bExpired_ = true; }
98        //! Sets the mouse event handler (overwrites if there already was one!)
99        void setMouseHandler   (InputHandler* handler)
100            { handlers_[mouseIndex_s]    = handler; bExpired_ = true; }
101        /**
102        @brief
103            Sets the joy stick event handler for one specific joy stick (overwrites if there already was one!)
104        @return
105            Returns false if the specified device was not found
106        */
107        bool setJoyStickHandler(InputHandler* handler, unsigned int joyStick);
108        //! Sets the joy stick event handler for all joy sticks (overwrites if there already was one!)
109        void setJoyStickHandler(InputHandler* handler);
110        //! Sets an InputHandler to be used for all devices
111        void setHandler        (InputHandler* handler);
112
113        void setMouseExclusive(tribool value) { exclusiveMouse_ = value; this->bExpired_ = true; }
114        tribool getMouseExclusive() const { return exclusiveMouse_; }
115
116        //! Returns the name of the state (which is unique!)
117        const std::string& getName() const { return name_; }
118        //! Returns the priority of the state (which is unique if != 0)
119        int getPriority()            const { return priority_; }
120
121        //! Tells whether there a handler installed for a specific device
122        bool isInputDeviceEnabled(unsigned int device);
123
124        //! Returns true if the handler situation has changed
125        bool hasExpired()      { return this->bExpired_; }
126        //! Call this if you have applied the changes resulting from changed handlers
127        void resetExpiration() { bExpired_ = false; }
128
129        //! Updates one specific device handler with deviceUpdated
130        void update(float dt, unsigned int device);
131        //! Updates all handlers with allDevicesUpdated
132        void update(float dt);
133
134        //! Generic function that distributes all 9 button events
135        template <typename EventType, class ButtonTypeParam>
136        void buttonEvent(unsigned int device, ButtonTypeParam button);
137
138        //! Event handler
139        void mouseMoved(IntVector2 abs, IntVector2 rel, IntVector2 clippingSize);
140        //! Event handler
141        void mouseScrolled(int abs, int rel);
142        //! Event handler
143        void joyStickAxisMoved(unsigned int device, unsigned int axis, float value);
144
145        // Functors
146        //! Called when the state is being activated (even if it doesn't get any events afterwards!)
147        void entered();
148        //! Called upon deactivation of the state
149        void left();
150        //! Sets a functor to be called upon activation of the state
151        void setEnterFunctor(const FunctorPtr& functor) { this->enterFunctor_ = functor; }
152        //! Sets a functor to be called upon deactivation of the state
153        void setLeaveFunctor(const FunctorPtr& functor) { this->leaveFunctor_ = functor; }
154
155    private:
156        InputState(const std::string& name, bool bAlwaysGetsInput, bool bTransparent, InputStatePriority priority);
157        ~InputState() = default;
158
159        virtual void JoyStickQuantityChanged(const std::vector<JoyStick*>& joyStickList) override;
160
161        //! Sets the priority (only to be used by the InputManager!)
162        void setPriority(int priority) { priority_ = priority; }
163
164        const std::string           name_;                  //!< Name of the state
165        const bool                  bAlwaysGetsInput_;      //!< See class declaration for explanation
166        const bool                  bTransparent_;          //!< See class declaration for explanation
167        tribool                     exclusiveMouse_;        //!< See class declaration for explanation
168        int                         priority_;              //!< Current priority (might change)
169        bool                        bExpired_;              //!< See hasExpired()
170        std::vector<InputHandler*>  handlers_;              //!< Vector with all handlers where the index is the device ID
171        //! Handler to be used for all joy sticks (needs to be saved in case another joy stick gets attached)
172        InputHandler*               joyStickHandlerAll_;
173        FunctorPtr                  enterFunctor_;          //!< Functor to be executed on enter
174        FunctorPtr                  leaveFunctor_;          //!< Functor to be executed on leave
175    };
176
177    ORX_FORCEINLINE void InputState::update(float dt)
178    {
179        for (unsigned int i = 0; i < handlers_.size(); ++i)
180            if (handlers_[i] != nullptr)
181                INPUT_STATE_PUSH_CALL(i, allDevicesUpdated, dt);
182    }
183
184    ORX_FORCEINLINE void InputState::update(float dt, unsigned int device)
185    {
186        switch (device)
187        {
188        case InputDeviceEnumerator::Keyboard:
189            if (handlers_[keyboardIndex_s] != nullptr)
190                INPUT_STATE_PUSH_CALL(keyboardIndex_s, keyboardUpdated, dt);
191            break;
192
193        case InputDeviceEnumerator::Mouse:
194            if (handlers_[mouseIndex_s] != nullptr)
195                INPUT_STATE_PUSH_CALL(mouseIndex_s, mouseUpdated, dt);
196            break;
197
198        default: // joy sticks
199            if (handlers_[device] != nullptr)
200                INPUT_STATE_PUSH_CALL(device, joyStickUpdated, device - firstJoyStickIndex_s, dt);
201            break;
202        }
203    }
204
205    template <typename EventType, class ButtonTypeParam>
206    ORX_FORCEINLINE void InputState::buttonEvent(unsigned int device, ButtonTypeParam button)
207    {
208        assert(device < handlers_.size());
209        if (handlers_[device] != nullptr)
210        {
211            // We have to store the function pointer to tell the compiler about its actual type because of overloading
212            void (InputHandler::*function)(unsigned int, ButtonTypeParam, EventType) = &InputHandler::buttonEvent<ButtonTypeParam>;
213            InputManager::getInstance().pushCall(std::function<void ()>(std::bind(function, handlers_[device], device, button, EventType())));
214        }
215    }
216
217    ORX_FORCEINLINE void InputState::mouseMoved(IntVector2 abs, IntVector2 rel, IntVector2 clippingSize)
218    {
219        if (handlers_[mouseIndex_s] != nullptr)
220            INPUT_STATE_PUSH_CALL(mouseIndex_s, mouseMoved, abs, rel, clippingSize);
221    }
222
223    ORX_FORCEINLINE void InputState::mouseScrolled(int abs, int rel)
224    {
225        if (handlers_[mouseIndex_s] != nullptr)
226            INPUT_STATE_PUSH_CALL(mouseIndex_s, mouseScrolled, abs, rel);
227    }
228
229    ORX_FORCEINLINE void InputState::joyStickAxisMoved(unsigned int device, unsigned int axis, float value)
230    {
231        assert(device < handlers_.size());
232        if (handlers_[device] != nullptr)
233            INPUT_STATE_PUSH_CALL(device, axisMoved, device - firstJoyStickIndex_s, axis, value);
234    }
235}
236
237#endif /* _InputState_H__ */
Note: See TracBrowser for help on using the repository browser.