]> git.lizzy.rs Git - minetest.git/blob - src/client/inputhandler.h
Move KeyList & InputHandler from game.h to client/inputhandler.h (#5752)
[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
28 #ifdef HAVE_TOUCHSCREENGUI
29 #include "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                 clearInput();
145 #ifdef HAVE_TOUCHSCREENGUI
146                 m_touchscreengui = NULL;
147 #endif
148         }
149
150         bool leftclicked;
151         bool rightclicked;
152         bool leftreleased;
153         bool rightreleased;
154
155         bool left_active;
156         bool middle_active;
157         bool right_active;
158
159         s32 mouse_wheel;
160
161         JoystickController *joystick;
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() {}
184         virtual ~InputHandler() {}
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(IrrlichtDevice *device, MyEventReceiver *receiver)
224             : m_device(device), m_receiver(receiver), m_mousepos(0, 0)
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 (m_device->getCursorControl()) {
244                         return m_device->getCursorControl()->getPosition();
245                 } else {
246                         return m_mousepos;
247                 }
248         }
249         virtual void setMousePos(s32 x, s32 y)
250         {
251                 if (m_device->getCursorControl()) {
252                         m_device->getCursorControl()->setPosition(x, y);
253                 } else {
254                         m_mousepos = v2s32(x, y);
255                 }
256         }
257
258         virtual bool getLeftState() { return m_receiver->left_active; }
259         virtual bool getRightState() { return m_receiver->right_active; }
260
261         virtual bool getLeftClicked() { return m_receiver->leftclicked; }
262         virtual bool getRightClicked() { return m_receiver->rightclicked; }
263         virtual void resetLeftClicked() { m_receiver->leftclicked = false; }
264         virtual void resetRightClicked() { m_receiver->rightclicked = false; }
265
266         virtual bool getLeftReleased() { return m_receiver->leftreleased; }
267         virtual bool getRightReleased() { return m_receiver->rightreleased; }
268         virtual void resetLeftReleased() { m_receiver->leftreleased = false; }
269         virtual void resetRightReleased() { m_receiver->rightreleased = false; }
270
271         virtual s32 getMouseWheel() { return m_receiver->getMouseWheel(); }
272
273         void clear()
274         {
275                 joystick.clear();
276                 m_receiver->clearInput();
277         }
278
279 private:
280         IrrlichtDevice *m_device;
281         MyEventReceiver *m_receiver;
282         v2s32 m_mousepos;
283 };
284
285 class RandomInputHandler : public InputHandler
286 {
287 public:
288         RandomInputHandler()
289         {
290                 leftdown = false;
291                 rightdown = false;
292                 leftclicked = false;
293                 rightclicked = false;
294                 leftreleased = false;
295                 rightreleased = false;
296                 keydown.clear();
297         }
298         virtual bool isKeyDown(const KeyPress &keyCode) { return keydown[keyCode]; }
299         virtual bool wasKeyDown(const KeyPress &keyCode) { return false; }
300         virtual v2s32 getMousePos() { return mousepos; }
301         virtual void setMousePos(s32 x, s32 y) { mousepos = v2s32(x, y); }
302
303         virtual bool getLeftState() { return leftdown; }
304         virtual bool getRightState() { return rightdown; }
305
306         virtual bool getLeftClicked() { return leftclicked; }
307         virtual bool getRightClicked() { return rightclicked; }
308         virtual void resetLeftClicked() { leftclicked = false; }
309         virtual void resetRightClicked() { rightclicked = false; }
310
311         virtual bool getLeftReleased() { return leftreleased; }
312         virtual bool getRightReleased() { return rightreleased; }
313         virtual void resetLeftReleased() { leftreleased = false; }
314         virtual void resetRightReleased() { rightreleased = false; }
315
316         virtual s32 getMouseWheel() { return 0; }
317
318         virtual void step(float dtime)
319         {
320                 {
321                         static float counter1 = 0;
322                         counter1 -= dtime;
323                         if (counter1 < 0.0) {
324                                 counter1 = 0.1 * Rand(1, 40);
325                                 keydown.toggle(getKeySetting("keymap_jump"));
326                         }
327                 }
328                 {
329                         static float counter1 = 0;
330                         counter1 -= dtime;
331                         if (counter1 < 0.0) {
332                                 counter1 = 0.1 * Rand(1, 40);
333                                 keydown.toggle(getKeySetting("keymap_special1"));
334                         }
335                 }
336                 {
337                         static float counter1 = 0;
338                         counter1 -= dtime;
339                         if (counter1 < 0.0) {
340                                 counter1 = 0.1 * Rand(1, 40);
341                                 keydown.toggle(getKeySetting("keymap_forward"));
342                         }
343                 }
344                 {
345                         static float counter1 = 0;
346                         counter1 -= dtime;
347                         if (counter1 < 0.0) {
348                                 counter1 = 0.1 * Rand(1, 40);
349                                 keydown.toggle(getKeySetting("keymap_left"));
350                         }
351                 }
352                 {
353                         static float counter1 = 0;
354                         counter1 -= dtime;
355                         if (counter1 < 0.0) {
356                                 counter1 = 0.1 * Rand(1, 20);
357                                 mousespeed = v2s32(Rand(-20, 20), Rand(-15, 20));
358                         }
359                 }
360                 {
361                         static float counter1 = 0;
362                         counter1 -= dtime;
363                         if (counter1 < 0.0) {
364                                 counter1 = 0.1 * Rand(1, 30);
365                                 leftdown = !leftdown;
366                                 if (leftdown)
367                                         leftclicked = true;
368                                 if (!leftdown)
369                                         leftreleased = true;
370                         }
371                 }
372                 {
373                         static float counter1 = 0;
374                         counter1 -= dtime;
375                         if (counter1 < 0.0) {
376                                 counter1 = 0.1 * Rand(1, 15);
377                                 rightdown = !rightdown;
378                                 if (rightdown)
379                                         rightclicked = true;
380                                 if (!rightdown)
381                                         rightreleased = true;
382                         }
383                 }
384                 mousepos += mousespeed;
385         }
386
387         s32 Rand(s32 min, s32 max);
388
389 private:
390         KeyList keydown;
391         v2s32 mousepos;
392         v2s32 mousespeed;
393         bool leftdown;
394         bool rightdown;
395         bool leftclicked;
396         bool rightclicked;
397         bool leftreleased;
398         bool rightreleased;
399 };
400
401 #endif