]> git.lizzy.rs Git - dragonfireclient.git/blob - src/touchscreengui.cpp
Fix flipped textures for drawtype "glasslike"
[dragonfireclient.git] / src / touchscreengui.cpp
1 /*
2 Copyright (C) 2014 sapier
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 #include "touchscreengui.h"
20 #include "irrlichttypes.h"
21 #include "irr_v2d.h"
22 #include "log.h"
23 #include "keycode.h"
24 #include "settings.h"
25 #include "gettime.h"
26 #include "util/numeric.h"
27 #include "porting.h"
28
29 #include <iostream>
30 #include <algorithm>
31
32 #include <ISceneCollisionManager.h>
33
34 using namespace irr::core;
35
36 extern Settings *g_settings;
37
38 const char** touchgui_button_imagenames = (const char*[]) {
39         "up_arrow.png",
40         "down_arrow.png",
41         "left_arrow.png",
42         "right_arrow.png",
43         "jump_btn.png",
44         "down.png",
45         "inventory_btn.png",
46         "chat_btn.png"
47 };
48
49 static irr::EKEY_CODE id2keycode(touch_gui_button_id id)
50 {
51         std::string key = "";
52         switch (id) {
53                 case forward_id:
54                         key = "forward";
55                         break;
56                 case left_id:
57                         key = "left";
58                         break;
59                 case right_id:
60                         key = "right";
61                         break;
62                 case backward_id:
63                         key = "backward";
64                         break;
65                 case jump_id:
66                         key = "jump";
67                         break;
68                 case inventory_id:
69                         key = "inventory";
70                         break;
71                 case chat_id:
72                         key = "chat";
73                         break;
74                 case crunch_id:
75                         key = "sneak";
76                         break;
77         }
78         assert(key != "");
79         return keyname_to_keycode(g_settings->get("keymap_" + key).c_str());
80 }
81
82 TouchScreenGUI *g_touchscreengui;
83
84 TouchScreenGUI::TouchScreenGUI(IrrlichtDevice *device, IEventReceiver* receiver):
85         m_device(device),
86         m_guienv(device->getGUIEnvironment()),
87         m_camera_yaw(0.0),
88         m_camera_pitch(0.0),
89         m_visible(false),
90         m_move_id(-1),
91         m_receiver(receiver)
92 {
93         for (unsigned int i=0; i < after_last_element_id; i++) {
94                 m_buttons[i].guibutton     =  0;
95                 m_buttons[i].repeatcounter = -1;
96         }
97
98         m_screensize = m_device->getVideoDriver()->getScreenSize();
99 }
100
101 void TouchScreenGUI::loadButtonTexture(button_info* btn, const char* path)
102 {
103         unsigned int tid;
104         video::ITexture *texture = m_texturesource->getTexture(path,&tid);
105         if (texture) {
106                 btn->guibutton->setUseAlphaChannel(true);
107                 btn->guibutton->setImage(texture);
108                 btn->guibutton->setPressedImage(texture);
109                 btn->guibutton->setScaleImage(true);
110                 btn->guibutton->setDrawBorder(false);
111                 btn->guibutton->setText(L"");
112                 }
113 }
114
115 void TouchScreenGUI::initButton(touch_gui_button_id id, rect<s32> button_rect,
116                 std::wstring caption, bool immediate_release )
117 {
118
119         button_info* btn       = &m_buttons[id];
120         btn->guibutton         = m_guienv->addButton(button_rect, 0, id, caption.c_str());
121         btn->guibutton->grab();
122         btn->repeatcounter     = -1;
123         btn->keycode           = id2keycode(id);
124         btn->immediate_release = immediate_release;
125         btn->ids.clear();
126
127         loadButtonTexture(btn,touchgui_button_imagenames[id]);
128 }
129
130 static int getMaxControlPadSize(float density) {
131         return 200 * density * g_settings->getFloat("gui_scaling");
132 }
133
134 void TouchScreenGUI::init(ISimpleTextureSource* tsrc, float density)
135 {
136         assert(tsrc != 0);
137
138         u32 control_pad_size =
139                         MYMIN((2 * m_screensize.Y) / 3,getMaxControlPadSize(density));
140
141         u32 button_size      = control_pad_size / 3;
142         m_visible            = true;
143         m_texturesource      = tsrc;
144         m_control_pad_rect   = rect<s32>(0, m_screensize.Y - 3 * button_size,
145                         3 * button_size, m_screensize.Y);
146         /*
147         draw control pad
148         0 1 2
149         3 4 5
150         for now only 0, 1, 2, and 4 are used
151         */
152         int number = 0;
153         for (int y = 0; y < 2; ++y)
154                 for (int x = 0; x < 3; ++x, ++number) {
155                         rect<s32> button_rect(
156                                         x * button_size, m_screensize.Y - button_size * (2 - y),
157                                         (x + 1) * button_size, m_screensize.Y - button_size * (1 - y)
158                         );
159                         touch_gui_button_id id = after_last_element_id;
160                         std::wstring caption;
161                         switch (number) {
162                         case 0:
163                                 id = left_id;
164                                 caption = L"<";
165                                 break;
166                         case 1:
167                                 id = forward_id;
168                                 caption = L"^";
169                                 break;
170                         case 2:
171                                 id = right_id;
172                                 caption = L">";
173                                 break;
174                         case 4:
175                                 id = backward_id;
176                                 caption = L"v";
177                                 break;
178                         }
179                         if (id != after_last_element_id) {
180                                 initButton(id, button_rect, caption, false);
181                                 }
182                 }
183
184         /* init inventory button */
185         initButton(inventory_id,
186                         rect<s32>(0, m_screensize.Y - (button_size/2),
187                                         (button_size/2), m_screensize.Y), L"inv", true);
188
189         /* init jump button */
190         initButton(jump_id,
191                         rect<s32>(m_screensize.X-(1.75*button_size),
192                                         m_screensize.Y - (0.5*button_size),
193                                         m_screensize.X-(0.25*button_size),
194                                         m_screensize.Y),
195                         L"x",false);
196
197         /* init crunch button */
198         initButton(crunch_id,
199                         rect<s32>(m_screensize.X-(3.25*button_size),
200                                         m_screensize.Y - (0.5*button_size),
201                                         m_screensize.X-(1.75*button_size),
202                                         m_screensize.Y),
203                         L"H",false);
204
205         /* init chat button */
206         initButton(chat_id,
207                         rect<s32>(m_screensize.X-(1.5*button_size), 0,
208                                         m_screensize.X, button_size),
209                         L"Chat", true);
210 }
211
212 touch_gui_button_id TouchScreenGUI::getButtonID(s32 x, s32 y)
213 {
214         IGUIElement* rootguielement = m_guienv->getRootGUIElement();
215
216         if (rootguielement != NULL) {
217                 gui::IGUIElement *element =
218                                 rootguielement->getElementFromPoint(core::position2d<s32>(x,y));
219
220                 if (element) {
221                         for (unsigned int i=0; i < after_last_element_id; i++) {
222                                 if (element == m_buttons[i].guibutton) {
223                                         return (touch_gui_button_id) i;
224                                 }
225                         }
226                 }
227         }
228         return after_last_element_id;
229 }
230
231 touch_gui_button_id TouchScreenGUI::getButtonID(int eventID)
232 {
233         for (unsigned int i=0; i < after_last_element_id; i++) {
234                 button_info* btn = &m_buttons[i];
235
236                 std::vector<int>::iterator id =
237                                 std::find(btn->ids.begin(),btn->ids.end(), eventID);
238
239                 if (id != btn->ids.end())
240                         return (touch_gui_button_id) i;
241         }
242
243         return after_last_element_id;
244 }
245
246 bool TouchScreenGUI::isHUDButton(const SEvent &event)
247 {
248         // check if hud item is pressed
249         for (std::map<int,rect<s32> >::iterator iter = m_hud_rects.begin();
250                         iter != m_hud_rects.end(); iter++) {
251                 if (iter->second.isPointInside(
252                                 v2s32(event.TouchInput.X,
253                                                 event.TouchInput.Y)
254                         )) {
255                         if ( iter->first < 8) {
256                                 SEvent* translated = new SEvent();
257                                 memset(translated,0,sizeof(SEvent));
258                                 translated->EventType = irr::EET_KEY_INPUT_EVENT;
259                                 translated->KeyInput.Key         = (irr::EKEY_CODE) (KEY_KEY_1 + iter->first);
260                                 translated->KeyInput.Control     = false;
261                                 translated->KeyInput.Shift       = false;
262                                 translated->KeyInput.PressedDown = true;
263                                 m_receiver->OnEvent(*translated);
264                                 m_hud_ids[event.TouchInput.ID]   = translated->KeyInput.Key;
265                                 delete translated;
266                                 return true;
267                         }
268                 }
269         }
270         return false;
271 }
272
273 bool TouchScreenGUI::isReleaseHUDButton(int eventID)
274 {
275         std::map<int,irr::EKEY_CODE>::iterator iter = m_hud_ids.find(eventID);
276
277         if (iter != m_hud_ids.end()) {
278                 SEvent* translated = new SEvent();
279                 memset(translated,0,sizeof(SEvent));
280                 translated->EventType            = irr::EET_KEY_INPUT_EVENT;
281                 translated->KeyInput.Key         = iter->second;
282                 translated->KeyInput.PressedDown = false;
283                 translated->KeyInput.Control     = false;
284                 translated->KeyInput.Shift       = false;
285                 m_receiver->OnEvent(*translated);
286                 m_hud_ids.erase(iter);
287                 delete translated;
288                 return true;
289         }
290         return false;
291 }
292
293 void TouchScreenGUI::ButtonEvent(touch_gui_button_id button,
294                 int eventID, bool action)
295 {
296         button_info* btn = &m_buttons[button];
297         SEvent* translated = new SEvent();
298         memset(translated,0,sizeof(SEvent));
299         translated->EventType            = irr::EET_KEY_INPUT_EVENT;
300         translated->KeyInput.Key         = btn->keycode;
301         translated->KeyInput.Control     = false;
302         translated->KeyInput.Shift       = false;
303         translated->KeyInput.Char        = 0;
304
305         /* add this event */
306         if (action) {
307                 assert(std::find(btn->ids.begin(),btn->ids.end(), eventID) == btn->ids.end());
308
309                 btn->ids.push_back(eventID);
310
311                 if (btn->ids.size() > 1) return;
312
313                 btn->repeatcounter = 0;
314                 translated->KeyInput.PressedDown = true;
315                 translated->KeyInput.Key = btn->keycode;
316                 m_receiver->OnEvent(*translated);
317         }
318         /* remove event */
319         if ((!action) || (btn->immediate_release)) {
320
321                 std::vector<int>::iterator pos =
322                                 std::find(btn->ids.begin(),btn->ids.end(), eventID);
323                 /* has to be in touch list */
324                 assert(pos != btn->ids.end());
325                 btn->ids.erase(pos);
326
327                 if (btn->ids.size() > 0)  { return; }
328
329                 translated->KeyInput.PressedDown = false;
330                 btn->repeatcounter               = -1;
331                 m_receiver->OnEvent(*translated);
332         }
333         delete translated;
334 }
335
336 void TouchScreenGUI::translateEvent(const SEvent &event)
337 {
338         if (!m_visible) {
339                 infostream << "TouchScreenGUI::translateEvent got event but not visible?!" << std::endl;
340                 return;
341         }
342
343         if (event.EventType != EET_TOUCH_INPUT_EVENT) {
344                 return;
345         }
346
347         if (event.TouchInput.Event == ETIE_PRESSED_DOWN) {
348
349                 /* add to own copy of eventlist ...
350                  * android would provide this information but irrlicht guys don't
351                  * wanna design a efficient interface
352                  */
353                 id_status toadd;
354                 toadd.id = event.TouchInput.ID;
355                 toadd.X  = event.TouchInput.X;
356                 toadd.Y  = event.TouchInput.Y;
357                 m_known_ids.push_back(toadd);
358
359                 int eventID = event.TouchInput.ID;
360
361                 touch_gui_button_id button =
362                                 getButtonID(event.TouchInput.X, event.TouchInput.Y);
363
364                 /* handle button events */
365                 if (button != after_last_element_id) {
366                         ButtonEvent(button,eventID,true);
367                 }
368                 else if (isHUDButton(event))
369                 {
370                         /* already handled in isHUDButton() */
371                 }
372                 /* handle non button events */
373                 else {
374                         /* if we don't already have a moving point make this the moving one */
375                         if (m_move_id == -1) {
376                                 m_move_id                  = event.TouchInput.ID;
377                                 m_move_has_really_moved    = false;
378                                 m_move_downtime            = getTimeMs();
379                                 m_move_downlocation        = v2s32(event.TouchInput.X, event.TouchInput.Y);
380                                 m_move_sent_as_mouse_event = false;
381                         }
382                 }
383
384                 m_pointerpos[event.TouchInput.ID] = v2s32(event.TouchInput.X, event.TouchInput.Y);
385         }
386         else if (event.TouchInput.Event == ETIE_LEFT_UP) {
387                 verbosestream << "Up event for pointerid: " << event.TouchInput.ID << std::endl;
388
389                 touch_gui_button_id button = getButtonID(event.TouchInput.ID);
390
391                 /* handle button events */
392                 if (button != after_last_element_id) {
393                         ButtonEvent(button,event.TouchInput.ID,false);
394                 }
395                 /* handle hud button events */
396                 else if (isReleaseHUDButton(event.TouchInput.ID)) {
397                         /* nothing to do here */
398                 }
399                 /* handle the point used for moving view */
400                 else if (event.TouchInput.ID == m_move_id) {
401                         m_move_id = -1;
402
403                         /* if this pointer issued a mouse event issue symmetric release here */
404                         if (m_move_sent_as_mouse_event) {
405                                 SEvent* translated = new SEvent;
406                                 memset(translated,0,sizeof(SEvent));
407                                 translated->EventType               = EET_MOUSE_INPUT_EVENT;
408                                 translated->MouseInput.X            = m_move_downlocation.X;
409                                 translated->MouseInput.Y            = m_move_downlocation.Y;
410                                 translated->MouseInput.Shift        = false;
411                                 translated->MouseInput.Control      = false;
412                                 translated->MouseInput.ButtonStates = 0;
413                                 translated->MouseInput.Event        = EMIE_LMOUSE_LEFT_UP;
414                                 m_receiver->OnEvent(*translated);
415                                 delete translated;
416                         }
417                         else {
418                                 /* do double tap detection */
419                                 doubleTapDetection();
420                         }
421                 }
422                 else {
423                         infostream
424                                 << "TouchScreenGUI::translateEvent released unknown button: "
425                                 << event.TouchInput.ID << std::endl;
426                 }
427
428                 for (std::vector<id_status>::iterator iter = m_known_ids.begin();
429                                 iter != m_known_ids.end(); iter++) {
430                         if (iter->id == event.TouchInput.ID) {
431                                 m_known_ids.erase(iter);
432                                 break;
433                         }
434                 }
435         }
436         else {
437                 assert(event.TouchInput.Event == ETIE_MOVED);
438                 int move_idx = event.TouchInput.ID;
439
440                 if (m_pointerpos[event.TouchInput.ID] ==
441                                 v2s32(event.TouchInput.X, event.TouchInput.Y)) {
442                         return;
443                 }
444
445                 if (m_move_id != -1) {
446                         if ((event.TouchInput.ID == m_move_id) &&
447                                 (!m_move_sent_as_mouse_event)) {
448
449                                 double distance = sqrt(
450                                                 (m_pointerpos[event.TouchInput.ID].X - event.TouchInput.X) *
451                                                 (m_pointerpos[event.TouchInput.ID].X - event.TouchInput.X) +
452                                                 (m_pointerpos[event.TouchInput.ID].Y - event.TouchInput.Y) *
453                                                 (m_pointerpos[event.TouchInput.ID].Y - event.TouchInput.Y));
454
455                                 if ((distance > g_settings->getU16("touchscreen_threshold")) ||
456                                                 (m_move_has_really_moved)) {
457                                         m_move_has_really_moved = true;
458                                         s32 X = event.TouchInput.X;
459                                         s32 Y = event.TouchInput.Y;
460
461                                         // update camera_yaw and camera_pitch
462                                         s32 dx = X - m_pointerpos[event.TouchInput.ID].X;
463                                         s32 dy = Y - m_pointerpos[event.TouchInput.ID].Y;
464
465                                         /* adapt to similar behaviour as pc screen */
466                                         double d         = g_settings->getFloat("mouse_sensitivity") *4;
467                                         double old_yaw   = m_camera_yaw;
468                                         double old_pitch = m_camera_pitch;
469
470                                         m_camera_yaw   -= dx * d;
471                                         m_camera_pitch  = MYMIN(MYMAX( m_camera_pitch + (dy * d),-180),180);
472
473                                         while (m_camera_yaw < 0)
474                                                 m_camera_yaw += 360;
475
476                                         while (m_camera_yaw > 360)
477                                                 m_camera_yaw -= 360;
478
479                                         // update shootline
480                                         m_shootline = m_device
481                                                         ->getSceneManager()
482                                                         ->getSceneCollisionManager()
483                                                         ->getRayFromScreenCoordinates(v2s32(X, Y));
484                                         m_pointerpos[event.TouchInput.ID] = v2s32(X, Y);
485                                 }
486                         }
487                         else if ((event.TouchInput.ID == m_move_id) &&
488                                         (m_move_sent_as_mouse_event)) {
489                                 m_shootline = m_device
490                                                 ->getSceneManager()
491                                                 ->getSceneCollisionManager()
492                                                 ->getRayFromScreenCoordinates(
493                                                                 v2s32(event.TouchInput.X,event.TouchInput.Y));
494                         }
495                 }
496                 else {
497                         handleChangedButton(event);
498                 }
499         }
500 }
501
502 void TouchScreenGUI::handleChangedButton(const SEvent &event)
503 {
504         for (unsigned int i = 0; i < after_last_element_id; i++) {
505
506                 if (m_buttons[i].ids.empty()) {
507                         continue;
508                 }
509                 for(std::vector<int>::iterator iter = m_buttons[i].ids.begin();
510                                 iter != m_buttons[i].ids.end(); iter++) {
511
512                         if (event.TouchInput.ID == *iter) {
513
514                                 int current_button_id =
515                                                 getButtonID(event.TouchInput.X, event.TouchInput.Y);
516
517                                 if (current_button_id == i) {
518                                         continue;
519                                 }
520
521                                 /* remove old button */
522                                 ButtonEvent((touch_gui_button_id) i,*iter,false);
523
524                                 if (current_button_id == after_last_element_id) {
525                                         return;
526                                 }
527                                 ButtonEvent((touch_gui_button_id) current_button_id,*iter,true);
528                                 return;
529
530                         }
531                 }
532         }
533
534         int current_button_id = getButtonID(event.TouchInput.X, event.TouchInput.Y);
535
536         if (current_button_id == after_last_element_id) {
537                 return;
538         }
539
540         button_info* btn = &m_buttons[current_button_id];
541         if (std::find(btn->ids.begin(),btn->ids.end(), event.TouchInput.ID) == btn->ids.end()) {
542                 ButtonEvent((touch_gui_button_id) current_button_id,event.TouchInput.ID,true);
543         }
544
545 }
546
547 bool TouchScreenGUI::doubleTapDetection()
548 {
549         m_key_events[0].down_time = m_key_events[1].down_time;
550         m_key_events[0].x         = m_key_events[1].x;
551         m_key_events[0].y         = m_key_events[1].y;
552         m_key_events[1].down_time = m_move_downtime;
553         m_key_events[1].x         = m_move_downlocation.X;
554         m_key_events[1].y         = m_move_downlocation.Y;
555
556         u32 delta = porting::getDeltaMs(m_key_events[0].down_time,getTimeMs());
557         if (delta > 400)
558                 return false;
559
560         double distance = sqrt(
561                         (m_key_events[0].x - m_key_events[1].x) * (m_key_events[0].x - m_key_events[1].x) +
562                         (m_key_events[0].y - m_key_events[1].y) * (m_key_events[0].y - m_key_events[1].y));
563
564
565         if (distance >(20 + g_settings->getU16("touchscreen_threshold")))
566                 return false;
567
568         SEvent* translated = new SEvent();
569         memset(translated,0,sizeof(SEvent));
570         translated->EventType               = EET_MOUSE_INPUT_EVENT;
571         translated->MouseInput.X            = m_key_events[0].x;
572         translated->MouseInput.Y            = m_key_events[0].y;
573         translated->MouseInput.Shift        = false;
574         translated->MouseInput.Control      = false;
575         translated->MouseInput.ButtonStates = EMBSM_RIGHT;
576
577         // update shootline
578         m_shootline = m_device
579                         ->getSceneManager()
580                         ->getSceneCollisionManager()
581                         ->getRayFromScreenCoordinates(v2s32(m_key_events[0].x, m_key_events[0].y));
582
583         translated->MouseInput.Event = EMIE_RMOUSE_PRESSED_DOWN;
584         verbosestream << "TouchScreenGUI::translateEvent right click press" << std::endl;
585         m_receiver->OnEvent(*translated);
586
587         translated->MouseInput.ButtonStates = 0;
588         translated->MouseInput.Event        = EMIE_RMOUSE_LEFT_UP;
589         verbosestream << "TouchScreenGUI::translateEvent right click release" << std::endl;
590         m_receiver->OnEvent(*translated);
591         delete translated;
592         return true;
593
594 }
595
596 TouchScreenGUI::~TouchScreenGUI()
597 {
598         for (unsigned int i=0; i < after_last_element_id; i++) {
599                 button_info* btn = &m_buttons[i];
600                 if (btn->guibutton != 0) {
601                         btn->guibutton->drop();
602                         btn->guibutton = NULL;
603                 }
604         }
605 }
606
607 void TouchScreenGUI::step(float dtime)
608 {
609         /* simulate keyboard repeats */
610         for (unsigned int i=0; i < after_last_element_id; i++) {
611                 button_info* btn = &m_buttons[i];
612
613                 if (btn->ids.size() > 0) {
614                         btn->repeatcounter += dtime;
615
616                         if (btn->repeatcounter < 0.2) continue;
617
618                         btn->repeatcounter              = 0;
619                         SEvent translated;
620                         memset(&translated,0,sizeof(SEvent));
621                         translated.EventType            = irr::EET_KEY_INPUT_EVENT;
622                         translated.KeyInput.Key         = btn->keycode;
623                         translated.KeyInput.PressedDown = false;
624                         m_receiver->OnEvent(translated);
625
626                         translated.KeyInput.PressedDown = true;
627                         m_receiver->OnEvent(translated);
628                 }
629         }
630
631         /* if a new placed pointer isn't moved for some time start digging */
632         if ((m_move_id != -1) &&
633                         (!m_move_has_really_moved) &&
634                         (!m_move_sent_as_mouse_event)) {
635
636                 u32 delta = porting::getDeltaMs(m_move_downtime,getTimeMs());
637
638                 if (delta > MIN_DIG_TIME_MS) {
639                         m_shootline = m_device
640                                         ->getSceneManager()
641                                         ->getSceneCollisionManager()
642                                         ->getRayFromScreenCoordinates(
643                                                         v2s32(m_move_downlocation.X,m_move_downlocation.Y));
644
645                         SEvent translated;
646                         memset(&translated,0,sizeof(SEvent));
647                         translated.EventType               = EET_MOUSE_INPUT_EVENT;
648                         translated.MouseInput.X            = m_move_downlocation.X;
649                         translated.MouseInput.Y            = m_move_downlocation.Y;
650                         translated.MouseInput.Shift        = false;
651                         translated.MouseInput.Control      = false;
652                         translated.MouseInput.ButtonStates = EMBSM_LEFT;
653                         translated.MouseInput.Event        = EMIE_LMOUSE_PRESSED_DOWN;
654                         verbosestream << "TouchScreenGUI::step left click press" << std::endl;
655                         m_receiver->OnEvent(translated);
656                         m_move_sent_as_mouse_event         = true;
657                 }
658         }
659 }
660
661 void TouchScreenGUI::resetHud()
662 {
663         m_hud_rects.clear();
664 }
665
666 void TouchScreenGUI::registerHudItem(int index, const rect<s32> &rect)
667 {
668         m_hud_rects[index] = rect;
669 }
670
671 void TouchScreenGUI::Toggle(bool visible)
672 {
673         m_visible = visible;
674         for (unsigned int i=0; i < after_last_element_id; i++) {
675                 button_info* btn = &m_buttons[i];
676                 if (btn->guibutton != 0) {
677                         btn->guibutton->setVisible(visible);
678                 }
679         }
680 }
681
682 void TouchScreenGUI::Hide()
683 {
684         Toggle(false);
685 }
686
687 void TouchScreenGUI::Show()
688 {
689         Toggle(true);
690 }