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