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