1 | //************************************ bs::framework - Copyright 2018 Marko Pintera **************************************// |
2 | //*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********// |
3 | #pragma once |
4 | |
5 | #include "BsPrerequisites.h" |
6 | #include "Utility/BsModule.h" |
7 | #include "Input/BsInputConfiguration.h" |
8 | #include "Utility/BsDynArray.h" |
9 | |
10 | namespace bs |
11 | { |
12 | /** @addtogroup Input-Engine |
13 | * @{ |
14 | */ |
15 | |
16 | /** |
17 | * Handles virtual input that allows you to receive virtual input events that hide the actual physical input, allowing |
18 | * you to easily change the input keys while being transparent to the external code. |
19 | */ |
20 | class BS_EXPORT VirtualInput : public Module<VirtualInput> |
21 | { |
22 | /** Possible states of virtual buttons. */ |
23 | enum class ButtonState |
24 | { |
25 | Off, |
26 | On, |
27 | ToggledOn, |
28 | ToggledOff |
29 | }; |
30 | |
31 | /** Data container for a single virtual button. */ |
32 | struct ButtonData |
33 | { |
34 | VirtualButton button; |
35 | ButtonState state; |
36 | UINT64 timestamp; |
37 | UINT64 updateFrameIdx; |
38 | bool allowRepeat; |
39 | }; |
40 | |
41 | /** Contains button data for a specific input device. */ |
42 | struct DeviceData |
43 | { |
44 | Map<UINT32, ButtonData> cachedStates; |
45 | DynArray<UINT32> heldButtons; |
46 | }; |
47 | |
48 | /** Data container for a virtual button event. */ |
49 | struct VirtualButtonEvent |
50 | { |
51 | VirtualButton button; |
52 | ButtonState state; |
53 | UINT32 deviceIdx; |
54 | }; |
55 | |
56 | public: |
57 | VirtualInput(); |
58 | |
59 | /** Creates a new empty input configuration. */ |
60 | static SPtr<InputConfiguration> createConfiguration(); |
61 | |
62 | /** Sets an input configuration that determines how physical keys map to virtual buttons. */ |
63 | void setConfiguration(const SPtr<InputConfiguration>& input); |
64 | |
65 | /** Retrieves the active input configuration that determines how physical keys map to virtual buttons. */ |
66 | SPtr<InputConfiguration> getConfiguration() const { return mInputConfiguration; } |
67 | |
68 | /** |
69 | * Check is the virtual button just getting pressed. This state is only active for one frame. |
70 | * |
71 | * @param[in] button Virtual button identifier. |
72 | * @param[in] deviceIdx Optional device index in case multiple input devices are available. |
73 | */ |
74 | bool isButtonDown(const VirtualButton& button, UINT32 deviceIdx = 0) const; |
75 | |
76 | /** |
77 | * Check is the virtual button just getting released. This state is only active for one frame. |
78 | * |
79 | * @param[in] button Virtual button identifier. |
80 | * @param[in] deviceIdx Optional device index in case multiple input devices are available. |
81 | */ |
82 | bool isButtonUp(const VirtualButton& button, UINT32 deviceIdx = 0) const; |
83 | |
84 | /** |
85 | * Check is the virtual button is being held. This state is active as long as the button is being held down, |
86 | * possibly for multiple frames. |
87 | * |
88 | * @param[in] button Virtual button identifier. |
89 | * @param[in] deviceIdx Optional device index in case multiple input devices are available. |
90 | */ |
91 | bool isButtonHeld(const VirtualButton& button, UINT32 deviceIdx = 0) const; |
92 | |
93 | /** |
94 | * Returns normalized value for the specified input axis. Returned value will usually be in [-1.0, 1.0] range, but |
95 | * can be outside the range for devices with unbound axes (for example mouse). |
96 | * |
97 | * @param[in] axis Virtual axis identifier. |
98 | * @param[in] deviceIdx Optional device index in case multiple input devices are available. |
99 | */ |
100 | float getAxisValue(const VirtualAxis& axis, UINT32 deviceIdx = 0) const; |
101 | |
102 | /** Triggered when a virtual button is pressed. */ |
103 | Event<void(const VirtualButton&, UINT32 deviceIdx)> onButtonDown; |
104 | |
105 | /** Triggered when a virtual button is released. */ |
106 | Event<void(const VirtualButton&, UINT32 deviceIdx)> onButtonUp; |
107 | |
108 | /** Triggered every frame when a virtual button is being held down. */ |
109 | Event<void(const VirtualButton&, UINT32 deviceIdx)> onButtonHeld; |
110 | |
111 | /** @name Internal |
112 | * @{ |
113 | */ |
114 | |
115 | /** Called once every frame. Triggers button callbacks. */ |
116 | void _update(); |
117 | |
118 | /** @} */ |
119 | private: |
120 | friend class VirtualButton; |
121 | |
122 | /** Performs all logic related to a button press. */ |
123 | void buttonDown(const ButtonEvent& event); |
124 | |
125 | /** Performs all logic related to a button release. */ |
126 | void buttonUp(const ButtonEvent& event); |
127 | |
128 | SPtr<InputConfiguration> mInputConfiguration; |
129 | Vector<DeviceData> mDevices; |
130 | Queue<VirtualButtonEvent> mEvents; |
131 | UINT32 mActiveModifiers = (UINT32)ButtonModifier::None; |
132 | |
133 | // Transient |
134 | Vector<VirtualButton> tempButtons; |
135 | Vector<VIRTUAL_BUTTON_DESC> tempBtnDescs; |
136 | }; |
137 | |
138 | /** Provides easier access to VirtualInput. */ |
139 | BS_EXPORT VirtualInput& gVirtualInput(); |
140 | |
141 | /** @} */ |
142 | } |
143 | |