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
10namespace 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