73e507fdc8567b0bf7776ea20fb9ecbf35a4af43
[oweals/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
25 class MyEventReceiver : public IEventReceiver
26 {
27 public:
28         // This is the one method that we have to implement
29         virtual bool OnEvent(const SEvent& event)
30         {
31                 /*
32                         React to nothing here if a menu is active
33                 */
34                 if (noMenuActive() == false) {
35 #ifdef HAVE_TOUCHSCREENGUI
36                         if (m_touchscreengui != 0) {
37                                 m_touchscreengui->Toggle(false);
38                         }
39 #endif
40                         return g_menumgr.preprocessEvent(event);
41                 }
42
43                 // Remember whether each key is down or up
44                 if (event.EventType == irr::EET_KEY_INPUT_EVENT) {
45                         const KeyPress &keyCode = event.KeyInput;
46                         if (keysListenedFor[keyCode]) {
47                                 if (event.KeyInput.PressedDown) {
48                                         keyIsDown.set(keyCode);
49                                         keyWasDown.set(keyCode);
50                                 } else {
51                                         keyIsDown.unset(keyCode);
52                                 }
53                                 return true;
54                         }
55                 }
56
57 #ifdef HAVE_TOUCHSCREENGUI
58                 // case of touchscreengui we have to handle different events
59                 if ((m_touchscreengui != 0) &&
60                                 (event.EventType == irr::EET_TOUCH_INPUT_EVENT)) {
61                         m_touchscreengui->translateEvent(event);
62                         return true;
63                 }
64 #endif
65                 // handle mouse events
66                 if (event.EventType == irr::EET_MOUSE_INPUT_EVENT) {
67                         if (noMenuActive() == false) {
68                                 left_active = false;
69                                 middle_active = false;
70                                 right_active = false;
71                         } else {
72                                 left_active = event.MouseInput.isLeftPressed();
73                                 middle_active = event.MouseInput.isMiddlePressed();
74                                 right_active = event.MouseInput.isRightPressed();
75
76                                 if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) {
77                                         leftclicked = true;
78                                 }
79                                 if (event.MouseInput.Event == EMIE_RMOUSE_PRESSED_DOWN) {
80                                         rightclicked = true;
81                                 }
82                                 if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP) {
83                                         leftreleased = true;
84                                 }
85                                 if (event.MouseInput.Event == EMIE_RMOUSE_LEFT_UP) {
86                                         rightreleased = true;
87                                 }
88                                 if (event.MouseInput.Event == EMIE_MOUSE_WHEEL) {
89                                         mouse_wheel += event.MouseInput.Wheel;
90                                 }
91                         }
92                 } else if (event.EventType == irr::EET_LOG_TEXT_EVENT) {
93                         static const LogLevel irr_loglev_conv[] = {
94                                 LL_VERBOSE, // ELL_DEBUG
95                                 LL_INFO,    // ELL_INFORMATION
96                                 LL_WARNING, // ELL_WARNING
97                                 LL_ERROR,   // ELL_ERROR
98                                 LL_NONE,    // ELL_NONE
99                         };
100                         assert(event.LogEvent.Level < ARRLEN(irr_loglev_conv));
101                         g_logger.log(irr_loglev_conv[event.LogEvent.Level],
102                                 std::string("Irrlicht: ") + (const char*) event.LogEvent.Text);
103                         return true;
104                 }
105                 /* always return false in order to continue processing events */
106                 return false;
107         }
108
109         bool IsKeyDown(const KeyPress &keyCode) const
110         {
111                 return keyIsDown[keyCode];
112         }
113
114         // Checks whether a key was down and resets the state
115         bool WasKeyDown(const KeyPress &keyCode)
116         {
117                 bool b = keyWasDown[keyCode];
118                 if (b)
119                         keyWasDown.unset(keyCode);
120                 return b;
121         }
122
123         void listenForKey(const KeyPress &keyCode)
124         {
125                 keysListenedFor.set(keyCode);
126         }
127         void dontListenForKeys()
128         {
129                 keysListenedFor.clear();
130         }
131
132         s32 getMouseWheel()
133         {
134                 s32 a = mouse_wheel;
135                 mouse_wheel = 0;
136                 return a;
137         }
138
139         void clearInput()
140         {
141                 keyIsDown.clear();
142                 keyWasDown.clear();
143
144                 leftclicked = false;
145                 rightclicked = false;
146                 leftreleased = false;
147                 rightreleased = false;
148
149                 left_active = false;
150                 middle_active = false;
151                 right_active = false;
152
153                 mouse_wheel = 0;
154         }
155
156         MyEventReceiver()
157         {
158                 clearInput();
159 #ifdef HAVE_TOUCHSCREENGUI
160                 m_touchscreengui = NULL;
161 #endif
162         }
163
164         bool leftclicked;
165         bool rightclicked;
166         bool leftreleased;
167         bool rightreleased;
168
169         bool left_active;
170         bool middle_active;
171         bool right_active;
172
173         s32 mouse_wheel;
174
175 #ifdef HAVE_TOUCHSCREENGUI
176         TouchScreenGUI* m_touchscreengui;
177 #endif
178
179 private:
180         // The current state of keys
181         KeyList keyIsDown;
182         // Whether a key has been pressed or not
183         KeyList keyWasDown;
184         // List of keys we listen for
185         // TODO perhaps the type of this is not really
186         // performant as KeyList is designed for few but
187         // often changing keys, and keysListenedFor is expected
188         // to change seldomly but contain lots of keys.
189         KeyList keysListenedFor;
190 };
191
192
193 /*
194         Separated input handler
195 */
196
197 class RealInputHandler : public InputHandler
198 {
199 public:
200         RealInputHandler(IrrlichtDevice *device, MyEventReceiver *receiver):
201                 m_device(device),
202                 m_receiver(receiver),
203                 m_mousepos(0,0)
204         {
205         }
206         virtual bool isKeyDown(const KeyPress &keyCode)
207         {
208                 return m_receiver->IsKeyDown(keyCode);
209         }
210         virtual bool wasKeyDown(const KeyPress &keyCode)
211         {
212                 return m_receiver->WasKeyDown(keyCode);
213         }
214         virtual void listenForKey(const KeyPress &keyCode)
215         {
216                 m_receiver->listenForKey(keyCode);
217         }
218         virtual void dontListenForKeys()
219         {
220                 m_receiver->dontListenForKeys();
221         }
222         virtual v2s32 getMousePos()
223         {
224                 if (m_device->getCursorControl()) {
225                         return m_device->getCursorControl()->getPosition();
226                 }
227                 else {
228                         return m_mousepos;
229                 }
230         }
231         virtual void setMousePos(s32 x, s32 y)
232         {
233                 if (m_device->getCursorControl()) {
234                         m_device->getCursorControl()->setPosition(x, y);
235                 }
236                 else {
237                         m_mousepos = v2s32(x,y);
238                 }
239         }
240
241         virtual bool getLeftState()
242         {
243                 return m_receiver->left_active;
244         }
245         virtual bool getRightState()
246         {
247                 return m_receiver->right_active;
248         }
249
250         virtual bool getLeftClicked()
251         {
252                 return m_receiver->leftclicked;
253         }
254         virtual bool getRightClicked()
255         {
256                 return m_receiver->rightclicked;
257         }
258         virtual void resetLeftClicked()
259         {
260                 m_receiver->leftclicked = false;
261         }
262         virtual void resetRightClicked()
263         {
264                 m_receiver->rightclicked = false;
265         }
266
267         virtual bool getLeftReleased()
268         {
269                 return m_receiver->leftreleased;
270         }
271         virtual bool getRightReleased()
272         {
273                 return m_receiver->rightreleased;
274         }
275         virtual void resetLeftReleased()
276         {
277                 m_receiver->leftreleased = false;
278         }
279         virtual void resetRightReleased()
280         {
281                 m_receiver->rightreleased = false;
282         }
283
284         virtual s32 getMouseWheel()
285         {
286                 return m_receiver->getMouseWheel();
287         }
288
289         void clear()
290         {
291                 m_receiver->clearInput();
292         }
293 private:
294         IrrlichtDevice  *m_device;
295         MyEventReceiver *m_receiver;
296         v2s32           m_mousepos;
297 };
298
299 class RandomInputHandler : public InputHandler
300 {
301 public:
302         RandomInputHandler()
303         {
304                 leftdown = false;
305                 rightdown = false;
306                 leftclicked = false;
307                 rightclicked = false;
308                 leftreleased = false;
309                 rightreleased = false;
310                 keydown.clear();
311         }
312         virtual bool isKeyDown(const KeyPress &keyCode)
313         {
314                 return keydown[keyCode];
315         }
316         virtual bool wasKeyDown(const KeyPress &keyCode)
317         {
318                 return false;
319         }
320         virtual v2s32 getMousePos()
321         {
322                 return mousepos;
323         }
324         virtual void setMousePos(s32 x, s32 y)
325         {
326                 mousepos = v2s32(x, y);
327         }
328
329         virtual bool getLeftState()
330         {
331                 return leftdown;
332         }
333         virtual bool getRightState()
334         {
335                 return rightdown;
336         }
337
338         virtual bool getLeftClicked()
339         {
340                 return leftclicked;
341         }
342         virtual bool getRightClicked()
343         {
344                 return rightclicked;
345         }
346         virtual void resetLeftClicked()
347         {
348                 leftclicked = false;
349         }
350         virtual void resetRightClicked()
351         {
352                 rightclicked = false;
353         }
354
355         virtual bool getLeftReleased()
356         {
357                 return leftreleased;
358         }
359         virtual bool getRightReleased()
360         {
361                 return rightreleased;
362         }
363         virtual void resetLeftReleased()
364         {
365                 leftreleased = false;
366         }
367         virtual void resetRightReleased()
368         {
369                 rightreleased = false;
370         }
371
372         virtual s32 getMouseWheel()
373         {
374                 return 0;
375         }
376
377         virtual void step(float dtime)
378         {
379                 {
380                         static float counter1 = 0;
381                         counter1 -= dtime;
382                         if (counter1 < 0.0) {
383                                 counter1 = 0.1 * Rand(1, 40);
384                                 keydown.toggle(getKeySetting("keymap_jump"));
385                         }
386                 }
387                 {
388                         static float counter1 = 0;
389                         counter1 -= dtime;
390                         if (counter1 < 0.0) {
391                                 counter1 = 0.1 * Rand(1, 40);
392                                 keydown.toggle(getKeySetting("keymap_special1"));
393                         }
394                 }
395                 {
396                         static float counter1 = 0;
397                         counter1 -= dtime;
398                         if (counter1 < 0.0) {
399                                 counter1 = 0.1 * Rand(1, 40);
400                                 keydown.toggle(getKeySetting("keymap_forward"));
401                         }
402                 }
403                 {
404                         static float counter1 = 0;
405                         counter1 -= dtime;
406                         if (counter1 < 0.0) {
407                                 counter1 = 0.1 * Rand(1, 40);
408                                 keydown.toggle(getKeySetting("keymap_left"));
409                         }
410                 }
411                 {
412                         static float counter1 = 0;
413                         counter1 -= dtime;
414                         if (counter1 < 0.0) {
415                                 counter1 = 0.1 * Rand(1, 20);
416                                 mousespeed = v2s32(Rand(-20, 20), Rand(-15, 20));
417                         }
418                 }
419                 {
420                         static float counter1 = 0;
421                         counter1 -= dtime;
422                         if (counter1 < 0.0) {
423                                 counter1 = 0.1 * Rand(1, 30);
424                                 leftdown = !leftdown;
425                                 if (leftdown)
426                                         leftclicked = true;
427                                 if (!leftdown)
428                                         leftreleased = true;
429                         }
430                 }
431                 {
432                         static float counter1 = 0;
433                         counter1 -= dtime;
434                         if (counter1 < 0.0) {
435                                 counter1 = 0.1 * Rand(1, 15);
436                                 rightdown = !rightdown;
437                                 if (rightdown)
438                                         rightclicked = true;
439                                 if (!rightdown)
440                                         rightreleased = true;
441                         }
442                 }
443                 mousepos += mousespeed;
444         }
445
446         s32 Rand(s32 min, s32 max)
447         {
448                 return (myrand()%(max-min+1))+min;
449         }
450 private:
451         KeyList keydown;
452         v2s32 mousepos;
453         v2s32 mousespeed;
454         bool leftdown;
455         bool rightdown;
456         bool leftclicked;
457         bool rightclicked;
458         bool leftreleased;
459         bool rightreleased;
460 };
461
462 #endif