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