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 "Input/BsInputFwd.h"
7
8namespace bs
9{
10 /** @addtogroup Input-Engine
11 * @{
12 */
13
14 /**
15 * Describes a virtual button. Virtual buttons allow you to map custom actions without needing to know about what
16 * physical buttons trigger those actions.
17 */
18 struct BS_EXPORT VIRTUAL_BUTTON_DESC
19 {
20 VIRTUAL_BUTTON_DESC() = default;
21
22 /**
23 * Constructs a virtual button descriptor.
24 *
25 * @param[in] buttonCode Physical button the virtual button is triggered by.
26 * @param[in] modifiers Modifiers required to be pressed with the physical button to trigger the virtual button.
27 * @param[in] repeatable If true, the virtual button events will be sent continually while the physical button
28 * is being held.
29 */
30 VIRTUAL_BUTTON_DESC(ButtonCode buttonCode, ButtonModifier modifiers = ButtonModifier::None, bool repeatable = false);
31
32 ButtonCode buttonCode = BC_0;
33 ButtonModifier modifiers = ButtonModifier::None;
34 bool repeatable = false;
35 };
36
37 /**
38 * Describes a virtual axis. Virtual axes allow you to map custom axes without needing to know the actual physical
39 * device handling those axes.
40 */
41 struct BS_EXPORT VIRTUAL_AXIS_DESC
42 {
43 VIRTUAL_AXIS_DESC() = default;
44
45 /**
46 * Constructs a new virtual axis descriptor.
47 *
48 * @param[in] type @copydoc VIRTUAL_AXIS_DESC::type
49 */
50 VIRTUAL_AXIS_DESC(UINT32 type);
51
52 /** Type of physical axis to map to. See InputAxis type for common types, but you are not limited to those values. */
53 UINT32 type = (UINT32)InputAxis::MouseX;
54
55 /** Value below which to ignore axis value and consider it 0. */
56 float deadZone = 0.0001f;
57
58 /** Higher sensitivity means the axis will more easily reach its maximum values. */
59 float sensitivity = 1.0f;
60
61 /** Should the axis be inverted. */
62 bool invert = false;
63
64 /**
65 * If enabled, axis values will be normalized to [-1, 1] range. Most axes already come in normalized form and this
66 * value will not affect such axes. Some axes, like mouse movement are not normalized by default and will instead
67 * report relative movement. By enabling this you will normalize such axes to [-1, 1] range.
68 */
69 bool normalize = false;
70 };
71
72 /**
73 * Identifier for a virtual button.
74 *
75 * Primary purpose of this class is to avoid expensive string compare, and instead use a unique button identifier for
76 * compare. Generally you want to create one of these using the button name, and then store it for later use.
77 *
78 * @note
79 * This class is not thread safe and should only be used on the sim thread.
80 *
81 * @see VIRTUAL_BUTTON_DESC
82 */
83 class BS_EXPORT VirtualButton
84 {
85 public:
86 VirtualButton() = default;
87 VirtualButton(const String& name);
88
89 bool operator== (const VirtualButton& rhs) const
90 {
91 return (buttonIdentifier == rhs.buttonIdentifier);
92 }
93
94 UINT32 buttonIdentifier = 0;
95 private:
96 /** Returns a static map of all virtual button identifiers and their buttons. */
97 static Map<String, UINT32>& getUniqueButtonIds();
98
99 static UINT32 NextButtonId;
100 };
101
102 /**
103 * Identifier for a virtual axis.
104 *
105 * Primary purpose of this class is to avoid expensive string compare (axis names), and instead use a unique axis
106 * identifier for compare. Generally you want to create one of these using the axis name, and then store it for later
107 * use.
108 *
109 * @note
110 * This class is not thread safe and should only be used on the sim thread.
111 *
112 * @see VIRTUAL_AXIS_DESC
113 */
114 class BS_EXPORT VirtualAxis
115 {
116 public:
117 VirtualAxis() = default;
118 VirtualAxis(const String& name);
119
120 UINT32 axisIdentifier = 0;
121
122 bool operator== (const VirtualAxis& rhs) const
123 {
124 return (axisIdentifier == rhs.axisIdentifier);
125 }
126
127 private:
128 static Map<String, UINT32> UniqueAxisIds;
129 static UINT32 NextAxisId;
130 };
131
132 /** Contains virtual <-> physical key mappings. */
133 class BS_EXPORT InputConfiguration
134 {
135 static const int MAX_NUM_DEVICES_PER_TYPE = 8;
136 static const int MAX_NUM_DEVICES = (UINT32)InputDevice::Count * MAX_NUM_DEVICES_PER_TYPE;
137
138 /** Internal virtual button data container. */
139 struct VirtualButtonData
140 {
141 String name;
142 VirtualButton button;
143 VIRTUAL_BUTTON_DESC desc;
144 };
145
146 /** Internal virtual axis data container. */
147 struct VirtualAxisData
148 {
149 String name;
150 VirtualAxis axis;
151 VIRTUAL_AXIS_DESC desc;
152 };
153
154 /** Internal container for holding axis data for all devices. */
155 struct DeviceAxisData
156 {
157 VirtualAxisData axes[(UINT32)InputAxis::Count];
158 };
159
160 public:
161 InputConfiguration() = default;
162
163 /**
164 * Registers a new virtual button.
165 *
166 * @param[in] name Unique name used to access the virtual button.
167 * @param[in] buttonCode Physical button the virtual button is triggered by.
168 * @param[in] modifiers Modifiers required to be pressed with the physical button to trigger the virtual button.
169 * @param[in] repeatable If true, the virtual button events will be sent continually while the physical button
170 * is being held.
171 */
172 void registerButton(const String& name, ButtonCode buttonCode, ButtonModifier modifiers = ButtonModifier::None, bool repeatable = false);
173
174 /** Unregisters a virtual button with the specified name. Events will no longer be generated for that button. */
175 void unregisterButton(const String& name);
176
177 /**
178 * Registers a new virtual axis.
179 *
180 * @param[in] name Unique name used to access the axis.
181 * @param[in] desc Descriptor structure containing virtual axis creation parameters.
182 */
183 void registerAxis(const String& name, const VIRTUAL_AXIS_DESC& desc);
184
185 /**
186 * Unregisters a virtual axis with the specified name. You will no longer be able to retrieve valid values for that
187 * axis.
188 */
189 void unregisterAxis(const String& name);
190
191 /**
192 * Sets repeat interval for held virtual buttons. Buttons will be continously triggered in interval increments as
193 * long as they button is being held.
194 */
195 void setRepeatInterval(UINT64 milliseconds) { mRepeatInterval = milliseconds; }
196
197 /** Gets the currently set repeat interval for held virtual buttons. */
198 UINT64 getRepeatInterval() const { return mRepeatInterval; }
199
200 /** @name Internal
201 * @{
202 */
203
204 /**
205 * Returns data about virtual buttons that are triggered by the specified physical button code and modifier flags.
206 */
207 bool _getButtons(ButtonCode code, UINT32 modifiers, Vector<VirtualButton>& btns, Vector<VIRTUAL_BUTTON_DESC>& btnDescs) const;
208
209 /** Retrieves virtual axis descriptor for the provided axis. */
210 bool _getAxis(const VirtualAxis& axis, VIRTUAL_AXIS_DESC& axisDesc) const;
211
212 /** @} */
213
214 private:
215 Vector<VirtualButtonData> mButtons[BC_Count];
216 Vector<VirtualAxisData> mAxes;
217
218 UINT64 mRepeatInterval = 300;
219 };
220
221 /** @} */
222}