Pioneer
Loading...
Searching...
No Matches
Input.h
Go to the documentation of this file.
1// Copyright © 2008-2024 Pioneer Developers. See AUTHORS.txt for details
2// Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
3
4#ifndef INPUT_H
5#define INPUT_H
6
7#include "InputBindings.h"
8
9#include "SDL_joystick.h"
10
11#include <array>
12#include <vector>
13#include <map>
14#include <string>
15
16class IniConfig;
17
18// Macro to simplify registering input bindings in the codebase
19// TODO: evaluate if registering key bindings via lua / json file works better
20#define REGISTER_INPUT_BINDING(name) \
21 namespace name##Input \
22 { \
23 void Register(Input::Manager *input); \
24 bool name##Registered = Input::AddBindingRegistrar(&Register); \
25 } \
26 void name##Input::Register(Input::Manager *input)
27
28namespace Input {
29 class Manager;
30
31 // The Page->Group->Binding system serves as a thin veneer for the UI to make
32 // sane reasonings about how to structure the Options dialog.
33 struct BindingGroup {
34 enum EntryType : uint8_t {
37 };
38
39 std::map<std::string, EntryType> bindings;
40 };
41
42 struct BindingPage {
43 BindingGroup *GetBindingGroup(std::string id) { return &groups[id]; }
44
45 std::map<std::string, BindingGroup> groups;
46 };
47
48 struct InputFrame {
51
52 InputFrame(Input::Manager *man, bool modal = false) :
53 manager(man),
55 {}
56
57 std::vector<Action *> actions;
58 std::vector<Axis *> axes;
59
60 // Must set this to a valid Input::Manager instance before using AddAction / AddAxis
61 Manager *manager = nullptr;
62 bool active = false;
63 bool modal = false;
64
65 // Call this at startup to register all the bindings associated with the frame.
66 virtual void RegisterBindings(){};
67
68 // Called when the frame is added to the stack.
69 sigc::signal<void, InputFrame *> onFrameAdded;
70
71 // Called when the frame is removed from the stack.
72 sigc::signal<void, InputFrame *> onFrameRemoved;
73
74 Action *AddAction(std::string id);
75 Axis *AddAxis(std::string id);
76 };
77
78 struct JoystickInfo {
79 struct Axis {
80 float value = 0.0;
81 float deadzone = 0.1;
82 float curve = 1.0;
83 bool zeroToOne = false;
84 };
85
86 SDL_Joystick *joystick;
87 SDL_JoystickGUID guid;
88 std::string name;
89
90 std::vector<bool> buttons;
91 std::vector<int> hats;
92
93 std::vector<Axis> axes;
94 };
95
96 void InitJoysticks(IniConfig *config);
97 std::vector<JoystickInfo> &GetJoysticks();
98
99 // User display name for the joystick from the API/OS.
100 std::string JoystickName(int joystick);
101 // fetch the GUID for the named joystick
102 SDL_JoystickGUID JoystickGUID(int joystick);
103 std::string JoystickGUIDString(int joystick);
104 // update the joystick's saved configuration
105 void SaveJoystickConfig(uint32_t joystick, IniConfig *config);
106
107 // reverse map a JoystickGUID to the actual internal ID.
108 int JoystickFromGUIDString(const std::string &guid);
109 int JoystickFromGUIDString(const char *guid);
110 int JoystickFromGUID(SDL_JoystickGUID guid);
111
112 int JoystickFromID(SDL_JoystickID id);
113 // map SDL joystick instance ID to internal ID
114 void AddJoystickID(SDL_JoystickID sdl_id, uint32_t internal_id);
115
116 // An adapter to decouple input frame creation from input binding registration.
117 // The functions registered via AddBindingRegistrar should be thread-safe and
118 // should not depend on anything but the manager object being passed in.
119 // The registrars are guaranteed to be called after static initialization has finished.
120 std::vector<sigc::slot<void, Input::Manager *>> &GetBindingRegistration();
121 bool AddBindingRegistrar(sigc::slot<void, Input::Manager *> &&fn);
122} // namespace Input
123
125public:
126 Manager(IniConfig *config, SDL_Window *window);
127 void InitGame();
128
129 // Call this at the start of a frame, before passing SDL events in
130 void NewFrame();
131
132 // Call once per SDL event, handles updating all internal state
133 void HandleSDLEvent(SDL_Event &ev);
134
135 // Call immediately after processing events, dispatches events to Action / Axis bindings.
136 void DispatchEvents();
137
138 // When enable is false, this prevents the input system from writing to the config file.
139 void EnableConfigSaving(bool enable) { m_enableConfigSaving = enable; }
140
141 BindingPage *GetBindingPage(std::string id) { return &bindingPages[id]; }
142 std::map<std::string, BindingPage> GetBindingPages() { return bindingPages; }
143
144 // Pushes an InputFrame onto the input stack.
145 bool AddInputFrame(InputFrame *frame);
146
147 // Get a read-only list of input frames.
148 const std::vector<InputFrame *> &GetInputFrames() { return m_inputFrames; }
149
150 // Check if a specific input frame is currently on the stack.
152 {
153 return std::count(m_inputFrames.begin(), m_inputFrames.end(), frame) > 0;
154 }
155
156 // Remove an arbitrary input frame from the input stack.
157 void RemoveInputFrame(InputFrame *frame);
158
159 // Inform the input system that a binding or frame was changed this frame.
160 void MarkBindingsDirty() { m_frameListChanged = true; }
161
162 // Creates a new action binding, copying the provided binding.
163 // The returned binding pointer points to the actual binding.
166
167 // Creates a new axis binding, copying the provided binding.
168 // The returned binding pointer points to the actual binding.
169 InputBindings::Axis *AddAxisBinding(std::string id, BindingGroup *group, InputBindings::Axis &&binding);
170 InputBindings::Axis *GetAxisBinding(std::string id);
171
172 // Call EnableBindings() to temporarily disable handling input bindings while
173 // you're recording a new input binding or are in a modal window.
174 void EnableBindings(bool enabled) { m_enableBindings = enabled; }
175
176 bool KeyState(SDL_Keycode k) { return IsKeyDown(k); }
177
178 // returns true if key K is currently pressed
179 bool IsKeyDown(SDL_Keycode k) { return keyState[k] & 0x3; }
180
181 // returns true if key K was pressed this frame
182 bool IsKeyPressed(SDL_Keycode k) { return keyState[k] == 1; }
183
184 // returns true if key K was released this frame
185 bool IsKeyReleased(SDL_Keycode k) { return keyState[k] == 4; }
186
187 int KeyModState() { return keyModState; }
188
189 int JoystickButtonState(int joystick, int button);
190 int JoystickHatState(int joystick, int hat);
191 float JoystickAxisState(int joystick, int axis);
192
193 bool IsJoystickEnabled() { return joystickEnabled; }
194 void SetJoystickEnabled(bool state);
195
196 bool IsMouseYInvert() { return mouseYInvert; }
197 void SetMouseYInvert(bool state);
198
199 bool IsMouseButtonPressed(int button) { return mouseButton[button] == 1; }
200 bool IsMouseButtonReleased(int button) { return mouseButton[button] == 4; }
201
202 bool MouseButtonState(int button) { return mouseButton[button] & 3; }
203 void SetMouseButtonState(int button, bool state) { mouseButton[button] = state; }
204
205 void GetMousePosition(int position[2]);
206
207 void GetMouseMotion(int motion[2])
208 {
209 std::copy_n(mouseMotion.data(), mouseMotion.size(), motion);
210 }
211
212 int GetMouseWheel() { return mouseWheel; }
213
214 // Capturing the mouse hides the cursor, puts the mouse into relative mode,
215 // and passes all mouse inputs to the input system, regardless of whether
216 // ImGui is using them or not.
217 bool IsCapturingMouse() const { return m_capturingMouse; }
218
219 // Set whether the application would like to capture the mouse.
220 // To avoid contention between different classes, please only call this when the state
221 // has actually changed.
222 void SetCapturingMouse(bool enabled);
223 void ClearMouse();
224
225 // Get the default speed modifier to apply to movement (scrolling, zooming...), depending on the "shift" keys.
226 // This is a default value only, centralized here to promote uniform user expericience.
228
229 sigc::signal<void, SDL_Keysym *> onKeyPress;
230 sigc::signal<void, SDL_Keysym *> onKeyRelease;
231 sigc::signal<void, int, int, int> onMouseButtonUp;
232 sigc::signal<void, int, int, int> onMouseButtonDown;
233 sigc::signal<void, bool> onMouseWheel;
234
235private:
236 void RebuildInputFrames();
237 bool GetModifierState(InputBindings::KeyChord *key);
238 bool GetBindingState(InputBindings::KeyBinding &key);
239 float GetAxisState(InputBindings::JoyAxis &axis);
240
241 SDL_Window *m_window;
242 IniConfig *m_config;
243 bool m_enableConfigSaving;
244
245 std::map<SDL_Keycode, uint8_t> keyState;
246 int keyModState;
247 std::array<char, 6> mouseButton;
248 std::array<int, 2> mouseMotion;
249 int mouseWheel;
250 bool m_capturingMouse;
251
252 bool joystickEnabled;
253 bool mouseYInvert;
254
255 std::map<std::string, BindingPage> bindingPages;
256 std::map<std::string, InputBindings::Action> actionBindings;
257 std::map<std::string, InputBindings::Axis> axisBindings;
258 bool m_enableBindings;
259
260 std::vector<InputFrame *> m_inputFrames;
261 bool m_frameListChanged;
262
263 std::vector<InputBindings::Action *> m_activeActions;
264 std::vector<InputBindings::Axis *> m_activeAxes;
265
266 std::map<InputBindings::KeyBinding, bool> m_modifiers;
267 std::vector<InputBindings::KeyChord *> m_chords;
268};
269
270#endif
Definition: IniConfig.h:16
Definition: Input.h:124
InputBindings::Action * AddActionBinding(std::string id, BindingGroup *group, InputBindings::Action &&binding)
Definition: Input.cpp:365
void DispatchEvents()
Definition: Input.cpp:781
bool KeyState(SDL_Keycode k)
Definition: Input.h:176
sigc::signal< void, int, int, int > onMouseButtonUp
Definition: Input.h:231
bool AddInputFrame(InputFrame *frame)
Definition: Input.cpp:307
void ClearMouse()
Definition: Input.cpp:846
void GetMousePosition(int position[2])
Definition: Input.cpp:506
bool IsMouseButtonReleased(int button)
Definition: Input.h:200
bool IsKeyPressed(SDL_Keycode k)
Definition: Input.h:182
void SetCapturingMouse(bool enabled)
Definition: Input.cpp:835
bool IsMouseYInvert()
Definition: Input.h:196
int KeyModState()
Definition: Input.h:187
bool IsMouseButtonPressed(int button)
Definition: Input.h:199
float JoystickAxisState(int joystick, int axis)
Definition: Input.cpp:476
sigc::signal< void, bool > onMouseWheel
Definition: Input.h:233
void MarkBindingsDirty()
Definition: Input.h:160
void NewFrame()
Definition: Input.cpp:517
void SetJoystickEnabled(bool state)
Definition: Input.cpp:488
bool IsKeyDown(SDL_Keycode k)
Definition: Input.h:179
bool MouseButtonState(int button)
Definition: Input.h:202
std::map< std::string, BindingPage > GetBindingPages()
Definition: Input.h:142
bool HasInputFrame(InputFrame *frame)
Definition: Input.h:151
void SetMouseYInvert(bool state)
Definition: Input.cpp:497
bool IsJoystickEnabled()
Definition: Input.h:193
sigc::signal< void, SDL_Keysym * > onKeyPress
Definition: Input.h:229
void GetMouseMotion(int motion[2])
Definition: Input.h:207
int GetMouseWheel()
Definition: Input.h:212
InputBindings::Axis * AddAxisBinding(std::string id, BindingGroup *group, InputBindings::Axis &&binding)
Definition: Input.cpp:383
float GetMoveSpeedShiftModifier()
Definition: Input.cpp:852
void RemoveInputFrame(InputFrame *frame)
Definition: Input.cpp:352
void EnableBindings(bool enabled)
Definition: Input.h:174
InputBindings::Axis * GetAxisBinding(std::string id)
Definition: Input.cpp:406
bool IsCapturingMouse() const
Definition: Input.h:217
void EnableConfigSaving(bool enable)
Definition: Input.h:139
void HandleSDLEvent(SDL_Event &ev)
Definition: Input.cpp:629
BindingPage * GetBindingPage(std::string id)
Definition: Input.h:141
sigc::signal< void, SDL_Keysym * > onKeyRelease
Definition: Input.h:230
bool IsKeyReleased(SDL_Keycode k)
Definition: Input.h:185
int JoystickButtonState(int joystick, int button)
Definition: Input.cpp:452
InputBindings::Action * GetActionBinding(std::string id)
Definition: Input.cpp:401
void InitGame()
Definition: Input.cpp:262
const std::vector< InputFrame * > & GetInputFrames()
Definition: Input.h:148
void SetMouseButtonState(int button, bool state)
Definition: Input.h:203
sigc::signal< void, int, int, int > onMouseButtonDown
Definition: Input.h:232
int JoystickHatState(int joystick, int hat)
Definition: Input.cpp:464
Definition: GuiApplication.h:14
std::string JoystickName(int joystick)
Definition: Input.cpp:57
SDL_JoystickGUID JoystickGUID(int joystick)
Definition: Input.cpp:104
void InitJoysticks(IniConfig *config)
Definition: Input.cpp:185
int JoystickFromGUIDString(const std::string &guid)
Definition: Input.cpp:72
bool AddBindingRegistrar(sigc::slot< void, Input::Manager * > &&fn)
Definition: Input.cpp:32
int JoystickFromGUID(SDL_JoystickGUID guid)
Definition: Input.cpp:85
std::vector< JoystickInfo > & GetJoysticks()
Definition: Input.cpp:234
int JoystickFromID(SDL_JoystickID id)
Definition: Input.cpp:97
std::vector< sigc::slot< void, Input::Manager * > > & GetBindingRegistration()
Definition: Input.cpp:27
void AddJoystickID(SDL_JoystickID sdl_id, uint32_t internal_id)
Definition: Input.cpp:176
std::string JoystickGUIDString(int joystick)
Definition: Input.cpp:62
void SaveJoystickConfig(uint32_t joystick, IniConfig *config)
Definition: Input.cpp:157
Definition: InputBindings.h:144
Definition: InputBindings.h:168
Definition: InputBindings.h:89
Definition: InputBindings.h:23
Definition: InputBindings.h:109
Definition: Input.h:33
std::map< std::string, EntryType > bindings
Definition: Input.h:39
EntryType
Definition: Input.h:34
@ ENTRY_ACTION
Definition: Input.h:35
@ ENTRY_AXIS
Definition: Input.h:36
Definition: Input.h:42
BindingGroup * GetBindingGroup(std::string id)
Definition: Input.h:43
std::map< std::string, BindingGroup > groups
Definition: Input.h:45
Definition: Input.h:48
virtual void RegisterBindings()
Definition: Input.h:66
InputFrame(Input::Manager *man, bool modal=false)
Definition: Input.h:52
Manager * manager
Definition: Input.h:61
bool active
Definition: Input.h:62
std::vector< Action * > actions
Definition: Input.h:57
Action * AddAction(std::string id)
Definition: Input.cpp:287
sigc::signal< void, InputFrame * > onFrameRemoved
Definition: Input.h:72
Axis * AddAxis(std::string id)
Definition: Input.cpp:297
bool modal
Definition: Input.h:63
std::vector< Axis * > axes
Definition: Input.h:58
sigc::signal< void, InputFrame * > onFrameAdded
Definition: Input.h:69
Definition: Input.h:79
float deadzone
Definition: Input.h:81
bool zeroToOne
Definition: Input.h:83
float value
Definition: Input.h:80
float curve
Definition: Input.h:82
Definition: Input.h:78
SDL_Joystick * joystick
Definition: Input.h:86
std::vector< bool > buttons
Definition: Input.h:90
std::string name
Definition: Input.h:88
std::vector< Axis > axes
Definition: Input.h:93
SDL_JoystickGUID guid
Definition: Input.h:87
std::vector< int > hats
Definition: Input.h:91