RavEngine
Loading...
Searching...
No Matches
InputManager.hpp
1#pragma once
2#if !RVE_SERVER
3#include "Ref.hpp"
4 #include <SDL3/SDL_scancode.h>
5 #include <SDL3/SDL_mouse.h>
6 #include <SDL3/SDL_events.h>
7 #include <SDL3/SDL_gamepad.h>
8#include "Function.hpp"
9#include "IInputListener.hpp"
10#include "SpinLock.hpp"
11#include "Map.hpp"
12#include "DataStructures.hpp"
13#include <RavEngine/mathtypes.hpp>
14#include "WeakRef.hpp"
15
16namespace RavEngine {
17
18 enum ActionState{
19 Released = 0,
20 Pressed = 1
21 };
22
23 struct Special {
24 enum {
25 MOUSEMOVE_X = -500,
26 MOUSEMOVE_Y = -501,
27 MOUSEMOVE_XVEL = -502,
28 MOUSEMOVE_YVEL = -503,
29 MOUSEWHEEL_X = -504,
30 MOUSEWHEEL_Y = -505,
31 CONTROLLER_AXIS_OFFSET = -8000,
32 CONTROLLER_BUTTON_OFFSET = -10000
33 };
34 };
35
36 //use this when binding controller buttons
38 enum {
39 SDL_CONTROLLER_BUTTON_INVALID = -1,
40 SDL_CONTROLLER_BUTTON_A = Special::CONTROLLER_BUTTON_OFFSET,
41 SDL_CONTROLLER_BUTTON_B,
42 SDL_CONTROLLER_BUTTON_X,
43 SDL_CONTROLLER_BUTTON_Y,
44 SDL_CONTROLLER_BUTTON_BACK,
45 SDL_CONTROLLER_BUTTON_GUIDE,
46 SDL_CONTROLLER_BUTTON_START,
47 SDL_CONTROLLER_BUTTON_LEFTSTICK,
48 SDL_CONTROLLER_BUTTON_RIGHTSTICK,
49 SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
50 SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,
51 SDL_CONTROLLER_BUTTON_DPAD_UP,
52 SDL_CONTROLLER_BUTTON_DPAD_DOWN,
53 SDL_CONTROLLER_BUTTON_DPAD_LEFT,
54 SDL_CONTROLLER_BUTTON_DPAD_RIGHT,
55 SDL_CONTROLLER_BUTTON_MAX
56 };
57 };
58
59 //use this when binding controller axis
61 enum {
62 SDL_CONTROLLER_AXIS_INVALID = -1,
63 SDL_CONTROLLER_AXIS_LEFTX = Special::CONTROLLER_AXIS_OFFSET,
64 SDL_CONTROLLER_AXIS_LEFTY,
65 SDL_CONTROLLER_AXIS_RIGHTX,
66 SDL_CONTROLLER_AXIS_RIGHTY,
67 SDL_CONTROLLER_AXIS_TRIGGERLEFT,
68 SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
69 SDL_CONTROLLER_AXIS_MAX
70 };
71 };
72
73
74 struct Event{
75 int ID;
76 ActionState value;
77 };
78
79 //controller IDs
80 enum class CID{
81 NONE = 0,
82 C0 = 1 << 0,
83 C1 = 1 << 1,
84 C2 = 1 << 2,
85 C3 = 1 << 3,
86 C4 = 1 << 4,
87 C5 = 1 << 5,
88 C6 = 1 << 6,
89 C7 = 1 << 7,
90
91 C8 = 1 << 8,
92 C9 = 1 << 9,
93 C10 = 1 << 10,
94 C11 = 1 << 11,
95 C12 = 1 << 12,
96 C13 = 1 << 13,
97 C14 = 1 << 14,
98 C15 = 1 << 15,
99 ANY = ~0
100 };
101 //bitwise
102 constexpr inline CID operator | (CID lhs, CID rhs)
103 {
104 using T = std::underlying_type_t<CID>;
105 return static_cast<CID>(static_cast<T>(lhs) | static_cast<T>(rhs));
106 }
107
108 constexpr inline CID& operator |= (CID& lhs, CID rhs)
109 {
110 lhs = lhs | rhs;
111 return lhs;
112 }
113 constexpr inline CID operator & (CID lhs, CID rhs)
114 {
115 using T = std::underlying_type_t<CID>;
116 return static_cast<CID>(static_cast<T>(lhs) & static_cast<T>(rhs));
117 }
118
119 constexpr inline CID& operator &= (CID& lhs, CID rhs)
120 {
121 lhs = lhs & rhs;
122 return lhs;
123 }
124
129 constexpr inline static CID Make_CID(int x){
130 return static_cast<CID>(1 << x);
131 }
132
133 typedef Function<void(float)> axisCallback;
134 typedef Function<void()> actionCallback;
135
137 {
138 protected:
140 actionCallback func; //the lambda to invoke
141 void* func_addr = nullptr; //used for equality comparison
142 size_t id; //used for determining validity
143 CID controller;
144 ActionState state;
145
146 public:
155 ActionBinding(decltype(id) id, actionCallback fn, void* addr, CID c, ActionState s) : id(id), func(fn), controller(c), state(s), func_addr(addr){}
161 constexpr inline void operator()(ActionState state_in, CID c_in) const{
162 if (state_in == state && (controller & c_in) != CID::NONE && IsValid()){
163 func();
164 }
165 }
169 inline bool IsValid() const{
170 return true;
171 }
172
176 constexpr inline bool operator==(const ActionBinding& other) const{
177 return controller == other.controller && state == other.state && id == other.id && func_addr == other.func_addr;
178 }
179 };
180
182 protected:
183 axisCallback func; //the lambda to invoke
184 void* func_addr = nullptr; //used for equality comparison
185 size_t id; //used for determining validity
186 CID controller;
187 float deadzone = 0;
188 public:
198 AxisBinding(decltype(id) id, axisCallback fn, void* addr, CID c, float dz): id(id), func(fn), func_addr(addr), controller(c),deadzone(dz){}
199
205 constexpr inline void operator()(float value, CID c_in) const{
206 //check if can run
207 if ((controller & c_in) != CID::NONE && IsValid()){
208 func(std::abs(value) >= deadzone ? value : 0); //pass 0 if in deadzone range
209 }
210 }
211 inline bool IsValid() const{
212 return true;
213 //return ! bound_object.expired();
214 }
215
216 constexpr inline bool operator==(const AxisBinding& other) const{
217 return deadzone == other.deadzone && controller == other.controller && id == other.id && func_addr == other.func_addr;
218 }
219 };
220
221
222 //stores which mappings each event ID is bound to
223 locked_hashmap<int, locked_hashset<std::string,SpinLock>,SpinLock> CodeToAction;
224 //the binding objects, keyed by binding ID
225 locked_hashmap<std::string, LinkedList<ActionBinding>,SpinLock> ActionBindings;
226 //stores which mappings each event ID is bound to
227 struct AxisID{
228 std::string identifier;
229 float scale = 1;
230 };
231
233 inline std::size_t operator()(const AxisID& other) const{
234 std::hash<std::string> hasher;
235 return hasher(other.identifier);
236 }
237 };
238
239 struct aid_eq{
240 inline bool operator()(const AxisID& A, const AxisID& B) const{
241 return A.identifier == B.identifier && A.scale == B.scale;
242 }
243 };
244
246 //the buffered axis inputs for each identifier
247 struct AxisInput{
248 float value;
249 CID source_controller;
250 };
251 struct AxisData{
252 UnorderedMap<int,AxisInput> bufferedInputs;
254 };
256
257 //AnyActions
259
266 void ProcessActionID(int ID, ActionState state_in, CID controller);
267
274 void ProcessAxisID(int ID, float value, CID controller);
275
279 void CleanupBindings();
280 public:
281 InputManager();
282
283 static vector2 GetMousePosPixels(float dpiScaleFactor);
284
285 //process axis maps
286 void TickAxes();
287
291 void ProcessInput(const SDL_Event&, uint32_t windowflags, float scale, int windowWidth, int windowHeight, float dpiScale);
292
298 inline void AddActionMap(const std::string& name, int Id){
299 CodeToAction[Id].insert(name);
300 }
301
308 inline void AddAxisMap(const std::string& name, int Id, float scale = 1){
309 CodeToAxis[Id].insert({name,scale});
310 }
311
317 inline void RemoveActionMap(const std::string& name, int Id){
318 CodeToAction[Id].erase(name);
319 }
320
326 inline void RemoveAxisMap(const std::string& name, int Id, float scale = 1){
327 CodeToAxis[Id].erase({name, scale});
328 }
329
337 template<class U,typename T>
338 inline void BindAction(const std::string& name, T thisptr, void(U::* f)(), ActionState type, CID controllers){
339 auto binding = [=]() mutable{
340 (thisptr.get()->*f)();
341 };
342 ActionBinding ab(thisptr.get_id(),binding,&f,controllers,type);
343
344 ActionBindings[name].push_back(ab);
345 }
346
354 template<typename U, typename T>
355 inline void BindAxis(const std::string& name, T thisptr, void(U::* f)(float), CID controllers, float deadZone = 0) {
356 auto func = [=](float amt) mutable{
357 (thisptr.get()->*f)(amt);
358 };
359 AxisBinding ab(thisptr.get_id(), func, &f, controllers, deadZone);
360
361 AxisBindings[name].bindings.push_back(ab);
362 }
363
371 template<typename U, typename T>
372 inline void UnbindAction(const std::string& name, T thisptr, void(U::* f)(), ActionState type, CID controllers){
373 auto binding = [=](){
374 (thisptr.get()->*f)();
375 };
376 ActionBinding ab(thisptr.get_id(),binding,&f,controllers,type);
377
378 ActionBindings[name].remove(ab); //remove the first binding that compares equal
379 }
380
387 template<typename U, typename T>
388 inline void UnbindAxis(const std::string& name, T thisptr, void(U::* f)(float), CID controllers, float deadZone){
389 auto func = [=](float amt){
390 (thisptr.get()->*f)(amt);
391 };
392 AxisBinding ab(thisptr.get_id(), func, &f, controllers, deadZone);
393
394 AxisBindings[name].bindings.remove(ab);
395 }
396
401 AnyEventBindings.push_back(listener);
402 }
403
408 AnyEventBindings.remove(listener);
409 }
410 };
411}
412#endif
413
Definition InputManager.hpp:139
bool IsValid() const
Definition InputManager.hpp:169
constexpr bool operator==(const ActionBinding &other) const
Definition InputManager.hpp:176
constexpr void operator()(ActionState state_in, CID c_in) const
Definition InputManager.hpp:161
ActionBinding(decltype(id) id, actionCallback fn, void *addr, CID c, ActionState s)
Definition InputManager.hpp:155
Definition InputManager.hpp:181
constexpr void operator()(float value, CID c_in) const
Definition InputManager.hpp:205
AxisBinding(decltype(id) id, axisCallback fn, void *addr, CID c, float dz)
Definition InputManager.hpp:198
Definition InputManager.hpp:137
void ProcessInput(const SDL_Event &, uint32_t windowflags, float scale, int windowWidth, int windowHeight, float dpiScale)
Definition InputManager.cpp:121
void UnbindAction(const std::string &name, T thisptr, void(U::*f)(), ActionState type, CID controllers)
Definition InputManager.hpp:372
void UnbindAxis(const std::string &name, T thisptr, void(U::*f)(float), CID controllers, float deadZone)
Definition InputManager.hpp:388
void RemoveActionMap(const std::string &name, int Id)
Definition InputManager.hpp:317
void ProcessAxisID(int ID, float value, CID controller)
Definition InputManager.cpp:56
void BindAnyAction(Ref< IInputListener > listener)
Definition InputManager.hpp:400
void BindAction(const std::string &name, T thisptr, void(U::*f)(), ActionState type, CID controllers)
Definition InputManager.hpp:338
void RemoveAxisMap(const std::string &name, int Id, float scale=1)
Definition InputManager.hpp:326
void BindAxis(const std::string &name, T thisptr, void(U::*f)(float), CID controllers, float deadZone=0)
Definition InputManager.hpp:355
void AddAxisMap(const std::string &name, int Id, float scale=1)
Definition InputManager.hpp:308
void UnbindAnyAction(Ref< IInputListener > listener)
Definition InputManager.hpp:407
void AddActionMap(const std::string &name, int Id)
Definition InputManager.hpp:298
void ProcessActionID(int ID, ActionState state_in, CID controller)
Definition InputManager.cpp:30
void CleanupBindings()
Definition InputManager.cpp:99
Definition SpinLock.hpp:9
Definition concurrentqueue.h:747
Definition Animation.hpp:6
Definition InputManager.hpp:60
Definition InputManager.hpp:37
Definition InputManager.hpp:74
Definition InputManager.hpp:251
Definition InputManager.hpp:227
Definition InputManager.hpp:247
Definition InputManager.hpp:239
Definition InputManager.hpp:232
Definition InputManager.hpp:23
Definition qualifier.hpp:35