Create main menu tab "Settings" for client settings
[oweals/minetest.git] / src / guiMainMenu.cpp
1 /*
2 Minetest-c55
3 Copyright (C) 2010-12 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 General Public License as published by
7 the Free Software Foundation; either version 2 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 General Public License for more details.
14
15 You should have received a copy of the GNU 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 #include "guiMainMenu.h"
21 #include "guiKeyChangeMenu.h"
22 #include "guiCreateWorld.h"
23 #include "guiMessageMenu.h"
24 #include "guiConfirmMenu.h"
25 #include "debug.h"
26 #include "serialization.h"
27 #include <string>
28 #include <IGUICheckBox.h>
29 #include <IGUIEditBox.h>
30 #include <IGUIButton.h>
31 #include <IGUIStaticText.h>
32 #include <IGUIFont.h>
33 #include <IGUIListBox.h>
34 #include <IGUITabControl.h>
35 #include <IGUIImage.h>
36 // For IGameCallback
37 #include "guiPauseMenu.h"
38 #include "gettext.h"
39 #include "utility.h"
40 #include "tile.h" // getTexturePath
41
42 struct CreateWorldDestMainMenu : public CreateWorldDest
43 {
44         CreateWorldDestMainMenu(GUIMainMenu *menu):
45                 m_menu(menu)
46         {}
47         void accepted(std::wstring name, std::string gameid)
48         {
49                 m_menu->createNewWorld(name, gameid);
50         }
51         GUIMainMenu *m_menu;
52 };
53
54 struct ConfirmDestDeleteWorld : public ConfirmDest
55 {
56         ConfirmDestDeleteWorld(WorldSpec spec, GUIMainMenu *menu):
57                 m_spec(spec),
58                 m_menu(menu)
59         {}
60         void answer(bool answer)
61         {
62                 if(answer == false)
63                         return;
64                 m_menu->deleteWorld(m_spec);
65         }
66         WorldSpec m_spec;
67         GUIMainMenu *m_menu;
68 };
69
70 enum
71 {
72         GUI_ID_QUIT_BUTTON = 101,
73         GUI_ID_NAME_INPUT,
74         GUI_ID_ADDRESS_INPUT,
75         GUI_ID_PORT_INPUT,
76         GUI_ID_FANCYTREE_CB,
77         GUI_ID_SMOOTH_LIGHTING_CB,
78         GUI_ID_3D_CLOUDS_CB,
79         GUI_ID_OPAQUE_WATER_CB,
80         GUI_ID_DAMAGE_CB,
81         GUI_ID_CREATIVE_CB,
82         GUI_ID_JOIN_GAME_BUTTON,
83         GUI_ID_CHANGE_KEYS_BUTTON,
84         GUI_ID_DELETE_WORLD_BUTTON,
85         GUI_ID_CREATE_WORLD_BUTTON,
86         GUI_ID_CONFIGURE_WORLD_BUTTON,
87         GUI_ID_WORLD_LISTBOX,
88         GUI_ID_TAB_CONTROL,
89 };
90
91 enum
92 {
93         TAB_SINGLEPLAYER=0,
94         TAB_MULTIPLAYER,
95         TAB_ADVANCED,
96         TAB_SETTINGS,
97         TAB_CREDITS
98 };
99
100 GUIMainMenu::GUIMainMenu(gui::IGUIEnvironment* env,
101                 gui::IGUIElement* parent, s32 id,
102                 IMenuManager *menumgr,
103                 MainMenuData *data,
104                 IGameCallback *gamecallback
105 ):
106         GUIModalMenu(env, parent, id, menumgr),
107         m_data(data),
108         m_accepted(false),
109         m_gamecallback(gamecallback),
110         m_is_regenerating(false)
111 {
112         assert(m_data);
113         this->env = env;
114         this->parent = parent;
115         this->id = id;
116         this->menumgr = menumgr;
117 }
118
119 GUIMainMenu::~GUIMainMenu()
120 {
121         removeChildren();
122 }
123
124 void GUIMainMenu::removeChildren()
125 {
126         const core::list<gui::IGUIElement*> &children = getChildren();
127         core::list<gui::IGUIElement*> children_copy;
128         for(core::list<gui::IGUIElement*>::ConstIterator
129                         i = children.begin(); i != children.end(); i++)
130         {
131                 children_copy.push_back(*i);
132         }
133         for(core::list<gui::IGUIElement*>::Iterator
134                         i = children_copy.begin();
135                         i != children_copy.end(); i++)
136         {
137                 (*i)->remove();
138         }
139 }
140
141 void GUIMainMenu::regenerateGui(v2u32 screensize)
142 {
143         m_is_regenerating = true;
144         /*
145                 Read stuff from elements into m_data
146         */
147         readInput(m_data);
148
149         /*
150                 Remove stuff
151         */
152         removeChildren();
153         
154         /*
155                 Calculate new sizes and positions
156         */
157         
158         v2s32 size(screensize.X, screensize.Y);
159
160         core::rect<s32> rect(
161                         screensize.X/2 - size.X/2,
162                         screensize.Y/2 - size.Y/2,
163                         screensize.X/2 + size.X/2,
164                         screensize.Y/2 + size.Y/2
165         );
166
167         DesiredRect = rect;
168         recalculateAbsolutePosition(false);
169
170         //v2s32 size = rect.getSize();
171
172         /*
173                 Add stuff
174         */
175
176         changeCtype("");
177
178         // Version
179         if(m_data->selected_tab != TAB_CREDITS)
180         {
181                 core::rect<s32> rect(0, 0, size.X, 40);
182                 rect += v2s32(4, 0);
183                 Environment->addStaticText(narrow_to_wide(
184                                 "Minetest-c55 " VERSION_STRING).c_str(),
185                                 rect, false, true, this, -1);
186         }
187
188         //v2s32 center(size.X/2, size.Y/2);
189         v2s32 c800(size.X/2-400, size.Y/2-300);
190         
191         m_topleft_client = c800 + v2s32(90, 70+50+30);
192         m_size_client = v2s32(620, 270);
193
194         m_topleft_server = c800 + v2s32(90, 70+30+50+290);
195         m_size_server = v2s32(620, 140);
196         
197         if(m_data->selected_tab == TAB_ADVANCED)
198         {
199                 m_topleft_client = c800 + v2s32(90, 20+50+30);
200                 m_size_client = v2s32(620, 270);
201
202                 m_topleft_server = c800 + v2s32(90, 20+30+50+290);
203                 m_size_server = v2s32(620, 140);
204         }
205
206         // Tabs
207 #if 1
208         {
209                 core::rect<s32> rect(0, 0, m_size_client.X, 30);
210                 rect += m_topleft_client + v2s32(0, -30);
211                 gui::IGUITabControl *e = Environment->addTabControl(
212                                 rect, this, true, true, GUI_ID_TAB_CONTROL);
213                 e->addTab(L"Singleplayer");
214                 e->addTab(L"Multiplayer");
215                 e->addTab(L"Advanced");
216                 e->addTab(L"Settings");
217                 e->addTab(L"Credits");
218                 e->setActiveTab(m_data->selected_tab);
219         }
220 #endif
221         
222         if(m_data->selected_tab == TAB_SINGLEPLAYER)
223         {
224                 // HYBRID
225                 {
226                         /*core::rect<s32> rect(0, 0, 20, 125);
227                         rect += m_topleft_client + v2s32(15, 80);
228                         const wchar_t *text = L"H\nY\nB\nR\nI\nD";*/
229                         core::rect<s32> rect(0, 0, 20, 300);
230                         rect += m_topleft_client + v2s32(15, 15);
231                         const wchar_t *text = L"T\nA\nP\nE\n\nA\nN\nD\n\nG\nL\nU\nE";
232                         //gui::IGUIStaticText *t =
233                         Environment->addStaticText(text, rect, false, true, this, -1);
234                         //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
235                 }
236                 u32 bs = 5;
237                 // World selection listbox
238                 u32 world_sel_h = 160;
239                 u32 world_sel_w = 365;
240                 //s32 world_sel_x = 50;
241                 s32 world_sel_x = m_size_client.X-world_sel_w-30;
242                 s32 world_sel_y = 30;
243                 u32 world_button_count = 3;
244                 u32 world_button_w = (world_sel_w)/world_button_count - bs
245                                 + bs/(world_button_count-1);
246                 {
247                         core::rect<s32> rect(0, 0, world_sel_w-4, 20);
248                         rect += m_topleft_client + v2s32(world_sel_x+4, world_sel_y-20);
249                         /*gui::IGUIStaticText *e =*/ Environment->addStaticText(
250                                         wgettext("Select World:"), 
251                                         rect, false, true, this, -1);
252                         /*e->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);*/
253                 }
254                 {
255                         core::rect<s32> rect(0, 0, world_sel_w, world_sel_h);
256                         rect += m_topleft_client + v2s32(world_sel_x, world_sel_y);
257                         gui::IGUIListBox *e = Environment->addListBox(rect, this,
258                                         GUI_ID_WORLD_LISTBOX);
259                         e->setDrawBackground(true);
260                         for(std::vector<WorldSpec>::const_iterator i = m_data->worlds.begin();
261                                         i != m_data->worlds.end(); i++){
262                                 e->addItem(narrow_to_wide(i->name+" ["+i->gameid+"]").c_str());
263                         }
264                         e->setSelected(m_data->selected_world);
265                         Environment->setFocus(e);
266                 }
267                 // Delete world button
268                 {
269                         core::rect<s32> rect(0, 0, world_button_w, 30);
270                         rect += m_topleft_client + v2s32(world_sel_x, world_sel_y+world_sel_h+0);
271                         Environment->addButton(rect, this, GUI_ID_DELETE_WORLD_BUTTON,
272                                   wgettext("Delete"));
273                 }
274                 // Create world button
275                 {
276                         core::rect<s32> rect(0, 0, world_button_w, 30);
277                         rect += m_topleft_client + v2s32(world_sel_x+world_button_w+bs, world_sel_y+world_sel_h+0);
278                         Environment->addButton(rect, this, GUI_ID_CREATE_WORLD_BUTTON,
279                                   wgettext("New"));
280                 }
281                 // Configure world button
282                 {
283                         core::rect<s32> rect(0, 0, world_button_w, 30);
284                         rect += m_topleft_client + v2s32(world_sel_x+(world_button_w+bs)*2,
285                                         world_sel_y+world_sel_h+0);
286                         Environment->addButton(rect, this, GUI_ID_CONFIGURE_WORLD_BUTTON,
287                                   wgettext("Configure"));
288                 }
289                 // Start game button
290                 {
291                         /*core::rect<s32> rect(0, 0, 120, 30);
292                         rect += m_topleft_client + v2s32(m_size_client.X-120-30,
293                                         m_size_client.Y-30-20-30-5);*/
294                         /*core::rect<s32> rect(0, 0, world_button_w, 30);
295                         rect += m_topleft_client + v2s32(world_sel_x+(world_button_w+bs)*3,
296                                         world_sel_y+world_sel_h+0);*/
297                         u32 bw = 160;
298                         core::rect<s32> rect(0, 0, bw, 30);
299                         rect += m_topleft_client + v2s32(world_sel_x+world_sel_w-bw,
300                                         world_sel_y+world_sel_h+30+bs);
301                         Environment->addButton(rect, this,
302                                         GUI_ID_JOIN_GAME_BUTTON, wgettext("Play"));
303                 }
304                 // Options
305                 s32 option_x = 50;
306                 s32 option_y = 30;
307                 u32 option_w = 150;
308                 {
309                         core::rect<s32> rect(0, 0, option_w, 30);
310                         rect += m_topleft_client + v2s32(option_x, option_y+20*0);
311                         Environment->addCheckBox(m_data->creative_mode, rect, this,
312                                         GUI_ID_CREATIVE_CB, wgettext("Creative Mode"));
313                 }
314                 {
315                         core::rect<s32> rect(0, 0, option_w, 30);
316                         rect += m_topleft_client + v2s32(option_x, option_y+20*1);
317                         Environment->addCheckBox(m_data->enable_damage, rect, this,
318                                         GUI_ID_DAMAGE_CB, wgettext("Enable Damage"));
319                 }
320                 changeCtype("C");
321         }
322         else if(m_data->selected_tab == TAB_MULTIPLAYER)
323         {
324                 changeCtype("");
325                 // CLIENT
326                 {
327                         core::rect<s32> rect(0, 0, 20, 125);
328                         rect += m_topleft_client + v2s32(15, 80);
329                         const wchar_t *text = L"C\nL\nI\nE\nN\nT";
330                         //gui::IGUIStaticText *t =
331                         Environment->addStaticText(text, rect, false, true, this, -1);
332                         //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
333                 }
334                 // Nickname + password
335                 {
336                         core::rect<s32> rect(0, 0, 110, 20);
337                         rect += m_topleft_client + v2s32(35+30, 50+6);
338                         Environment->addStaticText(wgettext("Name/Password"), 
339                                 rect, false, true, this, -1);
340                 }
341                 changeCtype("C");
342                 {
343                         core::rect<s32> rect(0, 0, 230, 30);
344                         rect += m_topleft_client + v2s32(160+30, 50);
345                         gui::IGUIElement *e = 
346                         Environment->addEditBox(m_data->name.c_str(), rect, true, this, GUI_ID_NAME_INPUT);
347                         if(m_data->name == L"")
348                                 Environment->setFocus(e);
349                 }
350                 {
351                         core::rect<s32> rect(0, 0, 120, 30);
352                         rect += m_topleft_client + v2s32(m_size_client.X-60-100, 50);
353                         gui::IGUIEditBox *e =
354                         Environment->addEditBox(L"", rect, true, this, 264);
355                         e->setPasswordBox(true);
356                         if(m_data->name != L"" && m_data->address != L"")
357                                 Environment->setFocus(e);
358
359                 }
360                 changeCtype("");
361                 // Address + port
362                 {
363                         core::rect<s32> rect(0, 0, 110, 20);
364                         rect += m_topleft_client + v2s32(35+30, 100+6);
365                         Environment->addStaticText(wgettext("Address/Port"),
366                                 rect, false, true, this, -1);
367                 }
368                 changeCtype("C");
369                 {
370                         core::rect<s32> rect(0, 0, 230, 30);
371                         rect += m_topleft_client + v2s32(160+30, 100);
372                         gui::IGUIElement *e = 
373                         Environment->addEditBox(m_data->address.c_str(), rect, true,
374                                         this, GUI_ID_ADDRESS_INPUT);
375                         if(m_data->name != L"" && m_data->address == L"")
376                                 Environment->setFocus(e);
377                 }
378                 {
379                         core::rect<s32> rect(0, 0, 120, 30);
380                         rect += m_topleft_client + v2s32(m_size_client.X-60-100, 100);
381                         Environment->addEditBox(m_data->port.c_str(), rect, true,
382                                         this, GUI_ID_PORT_INPUT);
383                 }
384                 changeCtype("");
385                 // Start game button
386                 {
387                         core::rect<s32> rect(0, 0, 180, 30);
388                         rect += m_topleft_client + v2s32(m_size_client.X-180-30,
389                                         m_size_client.Y-30-20);
390                         Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON,
391                                 wgettext("Start Game / Connect"));
392                 }
393                 changeCtype("C");
394         }
395         else if(m_data->selected_tab == TAB_ADVANCED)
396         {
397                 changeCtype("");
398                 // CLIENT
399                 {
400                         core::rect<s32> rect(0, 0, 20, 125);
401                         rect += m_topleft_client + v2s32(15, 80);
402                         const wchar_t *text = L"C\nL\nI\nE\nN\nT";
403                         //gui::IGUIStaticText *t =
404                         Environment->addStaticText(text, rect, false, true, this, -1);
405                         //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
406                 }
407                 // Nickname + password
408                 {
409                         core::rect<s32> rect(0, 0, 110, 20);
410                         rect += m_topleft_client + v2s32(35+30, 50+6);
411                         Environment->addStaticText(wgettext("Name/Password"), 
412                                 rect, false, true, this, -1);
413                 }
414                 changeCtype("C");
415                 {
416                         core::rect<s32> rect(0, 0, 230, 30);
417                         rect += m_topleft_client + v2s32(160+30, 50);
418                         gui::IGUIElement *e = 
419                         Environment->addEditBox(m_data->name.c_str(), rect, true, this, GUI_ID_NAME_INPUT);
420                         if(m_data->name == L"")
421                                 Environment->setFocus(e);
422                 }
423                 {
424                         core::rect<s32> rect(0, 0, 120, 30);
425                         rect += m_topleft_client + v2s32(m_size_client.X-60-100, 50);
426                         gui::IGUIEditBox *e =
427                         Environment->addEditBox(L"", rect, true, this, 264);
428                         e->setPasswordBox(true);
429                         if(m_data->name != L"" && m_data->address != L"")
430                                 Environment->setFocus(e);
431
432                 }
433                 changeCtype("");
434                 // Address + port
435                 {
436                         core::rect<s32> rect(0, 0, 110, 20);
437                         rect += m_topleft_client + v2s32(35+30, 100+6);
438                         Environment->addStaticText(wgettext("Address/Port"),
439                                 rect, false, true, this, -1);
440                 }
441                 changeCtype("C");
442                 {
443                         core::rect<s32> rect(0, 0, 230, 30);
444                         rect += m_topleft_client + v2s32(160+30, 100);
445                         gui::IGUIElement *e = 
446                         Environment->addEditBox(m_data->address.c_str(), rect, true,
447                                         this, GUI_ID_ADDRESS_INPUT);
448                         if(m_data->name != L"" && m_data->address == L"")
449                                 Environment->setFocus(e);
450                 }
451                 {
452                         core::rect<s32> rect(0, 0, 120, 30);
453                         rect += m_topleft_client + v2s32(m_size_client.X-60-100, 100);
454                         Environment->addEditBox(m_data->port.c_str(), rect, true,
455                                         this, GUI_ID_PORT_INPUT);
456                 }
457                 changeCtype("");
458                 {
459                         core::rect<s32> rect(0, 0, 400, 20);
460                         rect += m_topleft_client + v2s32(160+30, 100+35);
461                         Environment->addStaticText(wgettext("Leave address blank to start a local server."),
462                                 rect, false, true, this, -1);
463                 }
464                 // Start game button
465                 {
466                         core::rect<s32> rect(0, 0, 180, 30);
467                         rect += m_topleft_client + v2s32(m_size_client.X-180-30,
468                                         m_size_client.Y-30-20);
469                         Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON,
470                                 wgettext("Start Game / Connect"));
471                 }
472                 /*
473                         Server section
474                 */
475                 // SERVER
476                 {
477                         core::rect<s32> rect(0, 0, 20, 125);
478                         rect += m_topleft_server + v2s32(15, 15);
479                         const wchar_t *text = L"S\nE\nR\nV\nE\nR";
480                         //gui::IGUIStaticText *t =
481                         Environment->addStaticText(text, rect, false, true, this, -1);
482                         //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
483                 }
484                 // Server parameters
485                 {
486                         core::rect<s32> rect(0, 0, 250, 30);
487                         rect += m_topleft_server + v2s32(30+20+250+20, 20);
488                         Environment->addCheckBox(m_data->creative_mode, rect, this, GUI_ID_CREATIVE_CB,
489                                 wgettext("Creative Mode"));
490                 }
491                 {
492                         core::rect<s32> rect(0, 0, 250, 30);
493                         rect += m_topleft_server + v2s32(30+20+250+20, 40);
494                         Environment->addCheckBox(m_data->enable_damage, rect, this, GUI_ID_DAMAGE_CB,
495                                 wgettext("Enable Damage"));
496                 }
497                 // Delete world button
498                 {
499                         core::rect<s32> rect(0, 0, 130, 30);
500                         rect += m_topleft_server + v2s32(30+20+250+20, 90);
501                         Environment->addButton(rect, this, GUI_ID_DELETE_WORLD_BUTTON,
502                                   wgettext("Delete world"));
503                 }
504                 // Create world button
505                 {
506                         core::rect<s32> rect(0, 0, 130, 30);
507                         rect += m_topleft_server + v2s32(30+20+250+20+140, 90);
508                         Environment->addButton(rect, this, GUI_ID_CREATE_WORLD_BUTTON,
509                                   wgettext("Create world"));
510                 }
511                 // World selection listbox
512                 {
513                         core::rect<s32> rect(0, 0, 250, 120);
514                         rect += m_topleft_server + v2s32(30+20, 10);
515                         gui::IGUIListBox *e = Environment->addListBox(rect, this,
516                                         GUI_ID_WORLD_LISTBOX);
517                         e->setDrawBackground(true);
518                         for(std::vector<WorldSpec>::const_iterator i = m_data->worlds.begin();
519                                         i != m_data->worlds.end(); i++){
520                                 e->addItem(narrow_to_wide(i->name+" ["+i->gameid+"]").c_str());
521                         }
522                         e->setSelected(m_data->selected_world);
523                 }
524                 changeCtype("C");
525         }
526         else if(m_data->selected_tab == TAB_SETTINGS)
527         {
528                 {
529                         core::rect<s32> rect(0, 0, 20, 300);
530                         rect += m_topleft_client + v2s32(15, 50);
531                         const wchar_t *text = L"S\nE\nT\nT\nI\nN\nG\nS";
532                         //gui::IGUIStaticText *t =
533                         Environment->addStaticText(text, rect, false, true, this, -1);
534                         //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
535                 }
536                 s32 option_x = 70;
537                 s32 option_y = 50;
538                 u32 option_w = 150;
539                 {
540                         core::rect<s32> rect(0, 0, option_w, 30);
541                         rect += m_topleft_client + v2s32(option_x, option_y);
542                         Environment->addCheckBox(m_data->fancy_trees, rect, this,
543                                         GUI_ID_FANCYTREE_CB, wgettext("Fancy trees")); 
544                 }
545                 {
546                         core::rect<s32> rect(0, 0, option_w, 30);
547                         rect += m_topleft_client + v2s32(option_x, option_y+20);
548                         Environment->addCheckBox(m_data->smooth_lighting, rect, this,
549                                         GUI_ID_SMOOTH_LIGHTING_CB, wgettext("Smooth Lighting"));
550                 }
551                 {
552                         core::rect<s32> rect(0, 0, option_w, 30);
553                         rect += m_topleft_client + v2s32(option_x, option_y+20*2);
554                         Environment->addCheckBox(m_data->clouds_3d, rect, this,
555                                         GUI_ID_3D_CLOUDS_CB, wgettext("3D Clouds"));
556                 }
557                 {
558                         core::rect<s32> rect(0, 0, option_w, 30);
559                         rect += m_topleft_client + v2s32(option_x, option_y+20*3);
560                         Environment->addCheckBox(m_data->opaque_water, rect, this,
561                                         GUI_ID_OPAQUE_WATER_CB, wgettext("Opaque water"));
562                 }
563                 // Key change button
564                 {
565                         core::rect<s32> rect(0, 0, 120, 30);
566                         /*rect += m_topleft_client + v2s32(m_size_client.X-120-30,
567                                         m_size_client.Y-30-20);*/
568                         rect += m_topleft_client + v2s32(option_x, option_y+120);
569                         Environment->addButton(rect, this,
570                                         GUI_ID_CHANGE_KEYS_BUTTON, wgettext("Change keys"));
571                 }
572                 changeCtype("C");
573         }
574         else if(m_data->selected_tab == TAB_CREDITS)
575         {
576                 // CREDITS
577                 {
578                         core::rect<s32> rect(0, 0, 20, 200);
579                         rect += m_topleft_client + v2s32(15, 60);
580                         const wchar_t *text = L"C\nR\nE\nD\nI\nT\nS";
581                         //gui::IGUIStaticText *t =
582                         Environment->addStaticText(text, rect, false, true, this, -1);
583                         //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
584                 }
585                 {
586                         core::rect<s32> rect(0, 0, 620, 250);
587                         rect += m_topleft_client + v2s32(150+14, 50+35);
588                         Environment->addStaticText(narrow_to_wide(
589                         "Minetest-c55 " VERSION_STRING "\n"
590                         "http://c55.me/minetest/\n"
591                         "\n"
592                         "by Perttu Ahola <celeron55@gmail.com>\n"
593                         "and contributors"
594                         ).c_str(), rect, false, true, this, -1);
595                 }
596         }
597
598         m_is_regenerating = false;
599 }
600
601 void GUIMainMenu::drawMenu()
602 {
603         gui::IGUISkin* skin = Environment->getSkin();
604         if (!skin)
605                 return;
606         video::IVideoDriver* driver = Environment->getVideoDriver();
607         
608         /*video::SColor bgcolor(140,0,0,0);
609         driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);*/
610
611         video::SColor bgcolor(140,0,0,0);
612
613         if(getTab() == TAB_SINGLEPLAYER)
614         {
615                 {
616                         core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
617                         rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
618                         driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
619                 }
620         }
621         else if(getTab() == TAB_MULTIPLAYER)
622         {
623                 {
624                         core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
625                         rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
626                         driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
627                 }
628         }
629         else if(getTab() == TAB_ADVANCED)
630         {
631                 {
632                         core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
633                         rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
634                         driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
635                 }
636                 {
637                         core::rect<s32> rect(0, 0, m_size_server.X, m_size_server.Y);
638                         rect += AbsoluteRect.UpperLeftCorner + m_topleft_server;
639                         driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
640                 }
641         }
642         else if(getTab() == TAB_SETTINGS)
643         {
644                 {
645                         core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
646                         rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
647                         driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
648                 }
649         }
650         else if(getTab() == TAB_CREDITS)
651         {
652                 {
653                         core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
654                         rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
655                         driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
656                 }
657                 video::ITexture *logotexture =
658                                 driver->getTexture(getTexturePath("menulogo.png").c_str());
659                 if(logotexture)
660                 {
661                         v2s32 logosize(logotexture->getOriginalSize().Width,
662                                         logotexture->getOriginalSize().Height);
663                         logosize *= 2;
664                         core::rect<s32> rect(0,0,logosize.X,logosize.Y);
665                         rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
666                         rect += v2s32(150, 50);
667                         driver->draw2DImage(logotexture, rect,
668                                 core::rect<s32>(core::position2d<s32>(0,0),
669                                 core::dimension2di(logotexture->getSize())),
670                                 NULL, NULL, true);
671                 }
672         }
673
674         gui::IGUIElement::draw();
675 }
676
677 void GUIMainMenu::readInput(MainMenuData *dst)
678 {
679         {
680                 gui::IGUIElement *e = getElementFromId(GUI_ID_TAB_CONTROL);
681                 if(e != NULL && e->getType() == gui::EGUIET_TAB_CONTROL)
682                         dst->selected_tab = ((gui::IGUITabControl*)e)->getActiveTab();
683         }
684         if(dst->selected_tab == TAB_SINGLEPLAYER)
685         {
686                 dst->simple_singleplayer_mode = true;
687         }
688         else
689         {
690                 dst->simple_singleplayer_mode = false;
691                 {
692                         gui::IGUIElement *e = getElementFromId(GUI_ID_NAME_INPUT);
693                         if(e != NULL)
694                                 dst->name = e->getText();
695                 }
696                 {
697                         gui::IGUIElement *e = getElementFromId(264);
698                         if(e != NULL)
699                                 dst->password = e->getText();
700                 }
701                 {
702                         gui::IGUIElement *e = getElementFromId(GUI_ID_ADDRESS_INPUT);
703                         if(e != NULL)
704                                 dst->address = e->getText();
705                 }
706                 {
707                         gui::IGUIElement *e = getElementFromId(GUI_ID_PORT_INPUT);
708                         if(e != NULL)
709                                 dst->port = e->getText();
710                 }
711         }
712         {
713                 gui::IGUIElement *e = getElementFromId(GUI_ID_CREATIVE_CB);
714                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
715                         dst->creative_mode = ((gui::IGUICheckBox*)e)->isChecked();
716         }
717         {
718                 gui::IGUIElement *e = getElementFromId(GUI_ID_DAMAGE_CB);
719                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
720                         dst->enable_damage = ((gui::IGUICheckBox*)e)->isChecked();
721         }
722         {
723                 gui::IGUIElement *e = getElementFromId(GUI_ID_FANCYTREE_CB);
724                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
725                         dst->fancy_trees = ((gui::IGUICheckBox*)e)->isChecked();
726         }
727         {
728                 gui::IGUIElement *e = getElementFromId(GUI_ID_SMOOTH_LIGHTING_CB);
729                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
730                         dst->smooth_lighting = ((gui::IGUICheckBox*)e)->isChecked();
731         }
732         {
733                 gui::IGUIElement *e = getElementFromId(GUI_ID_3D_CLOUDS_CB);
734                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
735                         dst->clouds_3d = ((gui::IGUICheckBox*)e)->isChecked();
736         }
737         {
738                 gui::IGUIElement *e = getElementFromId(GUI_ID_OPAQUE_WATER_CB);
739                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
740                         dst->opaque_water = ((gui::IGUICheckBox*)e)->isChecked();
741         }
742
743         {
744                 gui::IGUIElement *e = getElementFromId(GUI_ID_WORLD_LISTBOX);
745                 if(e != NULL && e->getType() == gui::EGUIET_LIST_BOX)
746                         dst->selected_world = ((gui::IGUIListBox*)e)->getSelected();
747         }
748 }
749
750 void GUIMainMenu::acceptInput()
751 {
752         readInput(m_data);
753         m_accepted = true;
754 }
755
756 bool GUIMainMenu::OnEvent(const SEvent& event)
757 {
758         if(event.EventType==EET_KEY_INPUT_EVENT)
759         {
760                 if(event.KeyInput.Key==KEY_ESCAPE && event.KeyInput.PressedDown)
761                 {
762                         m_gamecallback->exitToOS();
763                         quitMenu();
764                         return true;
765                 }
766                 if(event.KeyInput.Key==KEY_RETURN && event.KeyInput.PressedDown)
767                 {
768                         acceptInput();
769                         quitMenu();
770                         return true;
771                 }
772         }
773         if(event.EventType==EET_GUI_EVENT)
774         {
775                 if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST
776                                 && isVisible())
777                 {
778                         if(!canTakeFocus(event.GUIEvent.Element))
779                         {
780                                 dstream<<"GUIMainMenu: Not allowing focus change."
781                                                 <<std::endl;
782                                 // Returning true disables focus change
783                                 return true;
784                         }
785                 }
786                 if(event.GUIEvent.EventType==gui::EGET_TAB_CHANGED)
787                 {
788                         if(!m_is_regenerating)
789                                 regenerateGui(m_screensize_old);
790                         return true;
791                 }
792                 if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED)
793                 {
794                         switch(event.GUIEvent.Caller->getID())
795                         {
796                         case GUI_ID_JOIN_GAME_BUTTON: {
797                                 MainMenuData cur;
798                                 readInput(&cur);
799                                 if(cur.address == L"" && getTab() == TAB_MULTIPLAYER){
800                                         (new GUIMessageMenu(env, parent, -1, menumgr,
801                                                         wgettext("Address required."))
802                                                         )->drop();
803                                         return true;
804                                 }
805                                 acceptInput();
806                                 quitMenu();
807                                 return true;
808                         }
809                         case GUI_ID_CHANGE_KEYS_BUTTON: {
810                                 GUIKeyChangeMenu *kmenu = new GUIKeyChangeMenu(env, parent, -1,menumgr);
811                                 kmenu->drop();
812                                 return true;
813                         }
814                         case GUI_ID_DELETE_WORLD_BUTTON: {
815                                 MainMenuData cur;
816                                 readInput(&cur);
817                                 if(cur.selected_world == -1){
818                                         (new GUIMessageMenu(env, parent, -1, menumgr,
819                                                         wgettext("Cannot delete world: Nothing selected"))
820                                                         )->drop();
821                                 } else {
822                                         WorldSpec spec = m_data->worlds[cur.selected_world];
823                                         ConfirmDestDeleteWorld *dest = new
824                                                         ConfirmDestDeleteWorld(spec, this);
825                                         (new GUIConfirmMenu(env, parent, -1, menumgr, dest,
826                                                         (std::wstring(wgettext("Delete world "))
827                                                         +L"\""+narrow_to_wide(spec.name)+L"\"?").c_str()
828                                                         ))->drop();
829                                 }
830                                 return true;
831                         }
832                         case GUI_ID_CREATE_WORLD_BUTTON: {
833                                 std::vector<SubgameSpec> games = getAvailableGames();
834                                 if(games.size() == 0){
835                                         GUIMessageMenu *menu = new GUIMessageMenu(env, parent,
836                                                         -1, menumgr,
837                                                         wgettext("Cannot create world: No games found"));
838                                         menu->drop();
839                                 } else {
840                                         CreateWorldDest *dest = new CreateWorldDestMainMenu(this);
841                                         GUICreateWorld *menu = new GUICreateWorld(env, parent, -1,
842                                                         menumgr, dest, games);
843                                         menu->drop();
844                                 }
845                                 return true;
846                         }
847                         case GUI_ID_CONFIGURE_WORLD_BUTTON: {
848                                 GUIMessageMenu *menu = new GUIMessageMenu(env, parent,
849                                                 -1, menumgr,
850                                                 wgettext("Nothing here"));
851                                 menu->drop();
852                                 return true;
853                         }
854                         }
855                 }
856                 if(event.GUIEvent.EventType==gui::EGET_EDITBOX_ENTER)
857                 {
858                         switch(event.GUIEvent.Caller->getID())
859                         {
860                                 case GUI_ID_ADDRESS_INPUT: case GUI_ID_PORT_INPUT: case GUI_ID_NAME_INPUT: case 264:
861                                 acceptInput();
862                                 quitMenu();
863                                 return true;
864                         }
865                 }
866                 if(event.GUIEvent.EventType==gui::EGET_LISTBOX_SELECTED_AGAIN)
867                 {
868                         switch(event.GUIEvent.Caller->getID())
869                         {
870                                 case GUI_ID_WORLD_LISTBOX:
871                                 acceptInput();
872                                 m_data->address = L""; // Force local game
873                                 quitMenu();
874                                 return true;
875                         }
876                 }
877         }
878
879         return Parent ? Parent->OnEvent(event) : false;
880 }
881
882 void GUIMainMenu::createNewWorld(std::wstring name, std::string gameid)
883 {
884         if(name == L"")
885                 return;
886         acceptInput();
887         m_data->create_world_name = name;
888         m_data->create_world_gameid = gameid;
889         quitMenu();
890 }
891
892 void GUIMainMenu::deleteWorld(WorldSpec spec)
893 {
894         if(!spec.isValid())
895                 return;
896         acceptInput();
897         m_data->delete_world_spec = spec;
898         quitMenu();
899 }
900         
901 int GUIMainMenu::getTab()
902 {
903         gui::IGUIElement *e = getElementFromId(GUI_ID_TAB_CONTROL);
904         if(e != NULL && e->getType() == gui::EGUIET_TAB_CONTROL)
905                 return ((gui::IGUITabControl*)e)->getActiveTab();
906         return TAB_SINGLEPLAYER; // Default
907 }
908