1/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
2/* If you are missing that file, acquire a complete release at teeworlds.com. */
3#ifndef ENGINE_CLIENT_INPUT_H
4#define ENGINE_CLIENT_INPUT_H
5
6#include <SDL_events.h>
7#include <SDL_joystick.h>
8#include <engine/console.h>
9
10#include <engine/input.h>
11#include <engine/keys.h>
12
13#include <string>
14#include <vector>
15
16class IEngineGraphics;
17
18class CInput : public IEngineInput
19{
20public:
21 class CJoystick : public IJoystick
22 {
23 friend class CInput;
24
25 CInput *m_pInput;
26 int m_Index;
27 char m_aName[64];
28 char m_aGUID[34];
29 SDL_JoystickID m_InstanceId;
30 int m_NumAxes;
31 int m_NumButtons;
32 int m_NumBalls;
33 int m_NumHats;
34 SDL_Joystick *m_pDelegate;
35
36 CInput *Input() { return m_pInput; }
37
38 public:
39 CJoystick() {}
40 CJoystick(CInput *pInput, int Index, SDL_Joystick *pDelegate);
41 virtual ~CJoystick() = default;
42
43 int GetIndex() const override { return m_Index; }
44 const char *GetName() const override { return m_aName; }
45 const char *GetGUID() const { return m_aGUID; }
46 SDL_JoystickID GetInstanceId() const { return m_InstanceId; }
47 int GetNumAxes() const override { return m_NumAxes; }
48 int GetNumButtons() const override { return m_NumButtons; }
49 int GetNumBalls() const override { return m_NumBalls; }
50 int GetNumHats() const override { return m_NumHats; }
51 float GetAxisValue(int Axis) override;
52 void GetHatValue(int Hat, int (&HatKeys)[2]) override;
53 bool Relative(float *pX, float *pY) override;
54 bool Absolute(float *pX, float *pY) override;
55
56 static void GetJoystickHatKeys(int Hat, int HatValue, int (&HatKeys)[2]);
57 };
58
59private:
60 IEngineGraphics *m_pGraphics;
61 IConsole *m_pConsole;
62
63 IEngineGraphics *Graphics() { return m_pGraphics; }
64 IConsole *Console() { return m_pConsole; }
65
66 // joystick
67 std::vector<CJoystick> m_vJoysticks;
68 CJoystick *m_pActiveJoystick = nullptr;
69 void InitJoysticks();
70 bool OpenJoystick(int JoystickIndex);
71 void CloseJoysticks();
72 void UpdateActiveJoystick();
73 static void ConchainJoystickGuidChanged(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);
74 float GetJoystickDeadzone();
75
76 bool m_InputGrabbed;
77 char *m_pClipboardText;
78
79 bool m_MouseFocus;
80 bool m_MouseDoubleClick;
81#if defined(CONF_PLATFORM_ANDROID) // No relative mouse on Android
82 ivec2 m_LastMousePos = ivec2(0, 0);
83#endif
84
85 // IME support
86 char m_aComposition[MAX_COMPOSITION_ARRAY_SIZE];
87 int m_CompositionCursor;
88 int m_CompositionLength;
89 std::vector<std::string> m_vCandidates;
90 int m_CandidateSelectedIndex;
91
92 void AddEvent(char *pText, int Key, int Flags);
93 void Clear() override;
94 bool IsEventValid(const CEvent &Event) const override { return Event.m_InputCount == m_InputCounter; }
95
96 // quick access to input
97 unsigned short m_aInputCount[g_MaxKeys]; // tw-KEY
98 unsigned char m_aInputState[g_MaxKeys]; // SDL_SCANCODE
99 int m_InputCounter;
100
101 void UpdateMouseState();
102 void UpdateJoystickState();
103 void HandleJoystickAxisMotionEvent(const SDL_JoyAxisEvent &Event);
104 void HandleJoystickButtonEvent(const SDL_JoyButtonEvent &Event);
105 void HandleJoystickHatMotionEvent(const SDL_JoyHatEvent &Event);
106 void HandleJoystickAddedEvent(const SDL_JoyDeviceEvent &Event);
107 void HandleJoystickRemovedEvent(const SDL_JoyDeviceEvent &Event);
108
109 char m_aDropFile[IO_MAX_PATH_LENGTH];
110
111 bool KeyState(int Key) const;
112
113 void ProcessSystemMessage(SDL_SysWMmsg *pMsg);
114
115public:
116 CInput();
117
118 void Init() override;
119 int Update() override;
120 void Shutdown() override;
121
122 bool ModifierIsPressed() const override { return KeyState(Key: KEY_LCTRL) || KeyState(Key: KEY_RCTRL) || KeyState(Key: KEY_LGUI) || KeyState(Key: KEY_RGUI); }
123 bool ShiftIsPressed() const override { return KeyState(Key: KEY_LSHIFT) || KeyState(Key: KEY_RSHIFT); }
124 bool AltIsPressed() const override { return KeyState(Key: KEY_LALT) || KeyState(Key: KEY_RALT); }
125 bool KeyIsPressed(int Key) const override { return KeyState(Key); }
126 bool KeyPress(int Key, bool CheckCounter) const override { return CheckCounter ? (m_aInputCount[Key] == m_InputCounter) : m_aInputCount[Key]; }
127
128 size_t NumJoysticks() const override { return m_vJoysticks.size(); }
129 CJoystick *GetJoystick(size_t Index) override { return &m_vJoysticks[Index]; }
130 CJoystick *GetActiveJoystick() override { return m_pActiveJoystick; }
131 void SetActiveJoystick(size_t Index) override;
132
133 bool MouseRelative(float *pX, float *pY) override;
134 void MouseModeAbsolute() override;
135 void MouseModeRelative() override;
136 void NativeMousePos(int *pX, int *pY) const override;
137 bool NativeMousePressed(int Index) override;
138 bool MouseDoubleClick() override;
139
140 const char *GetClipboardText() override;
141 void SetClipboardText(const char *pText) override;
142
143 void StartTextInput() override;
144 void StopTextInput() override;
145 const char *GetComposition() const override { return m_aComposition; }
146 bool HasComposition() const override { return m_CompositionLength != COMP_LENGTH_INACTIVE; }
147 int GetCompositionCursor() const override { return m_CompositionCursor; }
148 int GetCompositionLength() const override { return m_CompositionLength; }
149 const char *GetCandidate(int Index) const override { return m_vCandidates[Index].c_str(); }
150 int GetCandidateCount() const override { return m_vCandidates.size(); }
151 int GetCandidateSelectedIndex() const override { return m_CandidateSelectedIndex; }
152 void SetCompositionWindowPosition(float X, float Y, float H) override;
153
154 bool GetDropFile(char *aBuf, int Len) override;
155};
156
157#endif
158