]> git.lizzy.rs Git - minetest.git/blob - src/client/inputhandler.h
Modernize client code (#6250)
[minetest.git] / src / client / inputhandler.h
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #ifndef INPUT_HANDLER_H
21 #define INPUT_HANDLER_H
22
23 #include "irrlichttypes_extrabloated.h"
24 #include "joystick_controller.h"
25 #include <list>
26 #include "keycode.h"
27 #include "renderingengine.h"
28
29 #ifdef HAVE_TOUCHSCREENGUI
30 #include "touchscreengui.h"
31 #endif
32
33 class KeyList : private std::list<KeyPress>
34 {
35         typedef std::list<KeyPress> super;
36         typedef super::iterator iterator;
37         typedef super::const_iterator const_iterator;
38
39         virtual const_iterator find(const KeyPress &key) const
40         {
41                 const_iterator f(begin());
42                 const_iterator e(end());
43
44                 while (f != e) {
45                         if (*f == key)
46                                 return f;
47
48                         ++f;
49                 }
50
51                 return e;
52         }
53
54         virtual iterator find(const KeyPress &key)
55         {
56                 iterator f(begin());
57                 iterator e(end());
58
59                 while (f != e) {
60                         if (*f == key)
61                                 return f;
62
63                         ++f;
64                 }
65
66                 return e;
67         }
68
69 public:
70         void clear() { super::clear(); }
71
72         void set(const KeyPress &key)
73         {
74                 if (find(key) == end())
75                         push_back(key);
76         }
77
78         void unset(const KeyPress &key)
79         {
80                 iterator p(find(key));
81
82                 if (p != end())
83                         erase(p);
84         }
85
86         void toggle(const KeyPress &key)
87         {
88                 iterator p(this->find(key));
89
90                 if (p != end())
91                         erase(p);
92                 else
93                         push_back(key);
94         }
95
96         bool operator[](const KeyPress &key) const { return find(key) != end(); }
97 };
98
99 class MyEventReceiver : public IEventReceiver
100 {
101 public:
102         // This is the one method that we have to implement
103         virtual bool OnEvent(const SEvent &event);
104
105         bool IsKeyDown(const KeyPress &keyCode) const { return keyIsDown[keyCode]; }
106
107         // Checks whether a key was down and resets the state
108         bool WasKeyDown(const KeyPress &keyCode)
109         {
110                 bool b = keyWasDown[keyCode];
111                 if (b)
112                         keyWasDown.unset(keyCode);
113                 return b;
114         }
115
116         void listenForKey(const KeyPress &keyCode) { keysListenedFor.set(keyCode); }
117         void dontListenForKeys() { keysListenedFor.clear(); }
118
119         s32 getMouseWheel()
120         {
121                 s32 a = mouse_wheel;
122                 mouse_wheel = 0;
123                 return a;
124         }
125
126         void clearInput()
127         {
128                 keyIsDown.clear();
129                 keyWasDown.clear();
130
131                 leftclicked = false;
132                 rightclicked = false;
133                 leftreleased = false;
134                 rightreleased = false;
135
136                 left_active = false;
137                 middle_active = false;
138                 right_active = false;
139
140                 mouse_wheel = 0;
141         }
142
143         MyEventReceiver()
144         {
145 #ifdef HAVE_TOUCHSCREENGUI
146                 m_touchscreengui = NULL;
147 #endif
148         }
149
150         bool leftclicked = false;
151         bool rightclicked = false;
152         bool leftreleased = false;
153         bool rightreleased = false;
154
155         bool left_active = false;
156         bool middle_active = false;
157         bool right_active = false;
158
159         s32 mouse_wheel = 0;
160
161         JoystickController *joystick = nullptr;
162
163 #ifdef HAVE_TOUCHSCREENGUI
164         TouchScreenGUI *m_touchscreengui;
165 #endif
166
167 private:
168         // The current state of keys
169         KeyList keyIsDown;
170         // Whether a key has been pressed or not
171         KeyList keyWasDown;
172         // List of keys we listen for
173         // TODO perhaps the type of this is not really
174         // performant as KeyList is designed for few but
175         // often changing keys, and keysListenedFor is expected
176         // to change seldomly but contain lots of keys.
177         KeyList keysListenedFor;
178 };
179
180 class InputHandler
181 {
182 public:
183         InputHandler() = default;
184
185         virtual ~InputHandler() = default;
186
187         virtual bool isKeyDown(const KeyPress &keyCode) = 0;
188         virtual bool wasKeyDown(const KeyPress &keyCode) = 0;
189
190         virtual void listenForKey(const KeyPress &keyCode) {}
191         virtual void dontListenForKeys() {}
192
193         virtual v2s32 getMousePos() = 0;
194         virtual void setMousePos(s32 x, s32 y) = 0;
195
196         virtual bool getLeftState() = 0;
197         virtual bool getRightState() = 0;
198
199         virtual bool getLeftClicked() = 0;
200         virtual bool getRightClicked() = 0;
201         virtual void resetLeftClicked() = 0;
202         virtual void resetRightClicked() = 0;
203
204         virtual bool getLeftReleased() = 0;
205         virtual bool getRightReleased() = 0;
206         virtual void resetLeftReleased() = 0;
207         virtual void resetRightReleased() = 0;
208
209         virtual s32 getMouseWheel() = 0;
210
211         virtual void step(float dtime) {}
212
213         virtual void clear() {}
214
215         JoystickController joystick;
216 };
217 /*
218         Separated input handler
219 */
220
221 class RealInputHandler : public InputHandler
222 {
223 public:
224         RealInputHandler(MyEventReceiver *receiver) : m_receiver(receiver)
225         {
226                 m_receiver->joystick = &joystick;
227         }
228         virtual bool isKeyDown(const KeyPress &keyCode)
229         {
230                 return m_receiver->IsKeyDown(keyCode);
231         }
232         virtual bool wasKeyDown(const KeyPress &keyCode)
233         {
234                 return m_receiver->WasKeyDown(keyCode);
235         }
236         virtual void listenForKey(const KeyPress &keyCode)
237         {
238                 m_receiver->listenForKey(keyCode);
239         }
240         virtual void dontListenForKeys() { m_receiver->dontListenForKeys(); }
241         virtual v2s32 getMousePos()
242         {
243                 if (RenderingEngine::get_raw_device()->getCursorControl()) {
244                         return RenderingEngine::get_raw_device()
245                                         ->getCursorControl()
246                                         ->getPosition();
247                 }
248
249                 return m_mousepos;
250
251         }
252         virtual void setMousePos(s32 x, s32 y)
253         {
254                 if (RenderingEngine::get_raw_device()->getCursorControl()) {
255                         RenderingEngine::get_raw_device()
256                                         ->getCursorControl()
257                                         ->setPosition(x, y);
258                 } else {
259                         m_mousepos = v2s32(x, y);
260                 }
261         }
262
263         virtual bool getLeftState() { return m_receiver->left_active; }
264         virtual bool getRightState() { return m_receiver->right_active; }
265
266         virtual bool getLeftClicked() { return m_receiver->leftclicked; }
267         virtual bool getRightClicked() { return m_receiver->rightclicked; }
268         virtual void resetLeftClicked() { m_receiver->leftclicked = false; }
269         virtual void resetRightClicked() { m_receiver->rightclicked = false; }
270
271         virtual bool getLeftReleased() { return m_receiver->leftreleased; }
272         virtual bool getRightReleased() { return m_receiver->rightreleased; }
273         virtual void resetLeftReleased() { m_receiver->leftreleased = false; }
274         virtual void resetRightReleased() { m_receiver->rightreleased = false; }
275
276         virtual s32 getMouseWheel() { return m_receiver->getMouseWheel(); }
277
278         void clear()
279         {
280                 joystick.clear();
281                 m_receiver->clearInput();
282         }
283
284 private:
285         MyEventReceiver *m_receiver = nullptr;
286         v2s32 m_mousepos;
287 };
288
289 class RandomInputHandler : public InputHandler
290 {
291 public:
292         RandomInputHandler() = default;
293
294         virtual bool isKeyDown(const KeyPress &keyCode) { return keydown[keyCode]; }
295         virtual bool wasKeyDown(const KeyPress &keyCode) { return false; }
296         virtual v2s32 getMousePos() { return mousepos; }
297         virtual void setMousePos(s32 x, s32 y) { mousepos = v2s32(x, y); }
298
299         virtual bool getLeftState() { return leftdown; }
300         virtual bool getRightState() { return rightdown; }
301
302         virtual bool getLeftClicked() { return leftclicked; }
303         virtual bool getRightClicked() { return rightclicked; }
304         virtual void resetLeftClicked() { leftclicked = false; }
305         virtual void resetRightClicked() { rightclicked = false; }
306
307         virtual bool getLeftReleased() { return leftreleased; }
308         virtual bool getRightReleased() { return rightreleased; }
309         virtual void resetLeftReleased() { leftreleased = false; }
310         virtual void resetRightReleased() { rightreleased = false; }
311
312         virtual s32 getMouseWheel() { return 0; }
313
314         virtual void step(float dtime)
315         {
316                 {
317                         static float counter1 = 0;
318                         counter1 -= dtime;
319                         if (counter1 < 0.0) {
320                                 counter1 = 0.1 * Rand(1, 40);
321                                 keydown.toggle(getKeySetting("keymap_jump"));
322                         }
323                 }
324                 {
325                         static float counter1 = 0;
326                         counter1 -= dtime;
327                         if (counter1 < 0.0) {
328                                 counter1 = 0.1 * Rand(1, 40);
329                                 keydown.toggle(getKeySetting("keymap_special1"));
330                         }
331                 }
332                 {
333                         static float counter1 = 0;
334                         counter1 -= dtime;
335                         if (counter1 < 0.0) {
336                                 counter1 = 0.1 * Rand(1, 40);
337                                 keydown.toggle(getKeySetting("keymap_forward"));
338                         }
339                 }
340                 {
341                         static float counter1 = 0;
342                         counter1 -= dtime;
343                         if (counter1 < 0.0) {
344                                 counter1 = 0.1 * Rand(1, 40);
345                                 keydown.toggle(getKeySetting("keymap_left"));
346                         }
347                 }
348                 {
349                         static float counter1 = 0;
350                         counter1 -= dtime;
351                         if (counter1 < 0.0) {
352                                 counter1 = 0.1 * Rand(1, 20);
353                                 mousespeed = v2s32(Rand(-20, 20), Rand(-15, 20));
354                         }
355                 }
356                 {
357                         static float counter1 = 0;
358                         counter1 -= dtime;
359                         if (counter1 < 0.0) {
360                                 counter1 = 0.1 * Rand(1, 30);
361                                 leftdown = !leftdown;
362                                 if (leftdown)
363                                         leftclicked = true;
364                                 if (!leftdown)
365                                         leftreleased = true;
366                         }
367                 }
368                 {
369                         static float counter1 = 0;
370                         counter1 -= dtime;
371                         if (counter1 < 0.0) {
372                                 counter1 = 0.1 * Rand(1, 15);
373                                 rightdown = !rightdown;
374                                 if (rightdown)
375                                         rightclicked = true;
376                                 if (!rightdown)
377                                         rightreleased = true;
378                         }
379                 }
380                 mousepos += mousespeed;
381         }
382
383         s32 Rand(s32 min, s32 max);
384
385 private:
386         KeyList keydown;
387         v2s32 mousepos;
388         v2s32 mousespeed;
389         bool leftdown = false;
390         bool rightdown = false;
391         bool leftclicked = false;
392         bool rightclicked = false;
393         bool leftreleased = false;
394         bool rightreleased = false;
395 };
396
397 #endif