]> git.lizzy.rs Git - dragonfireclient.git/blob - src/guiMainMenu.cpp
Do not clear address in main menu if starting a singleplayer game by double clicking...
[dragonfireclient.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_size_server = v2s32(620, 140);
195
196         if(m_data->selected_tab == TAB_ADVANCED)
197         {
198                 m_topleft_client = c800 + v2s32(90, 70+50+30);
199                 m_size_client = v2s32(620, 200);
200
201                 m_size_server = v2s32(620, 140);
202         }
203
204         m_topleft_server = m_topleft_client + v2s32(0, m_size_client.Y+20);
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, 10, m_size_client.Y);
227                         rect += m_topleft_client + v2s32(15, 0);
228                         //const wchar_t *text = L"H\nY\nB\nR\nI\nD";
229                         const wchar_t *text = L"T\nA\nP\nE\n\nA\nN\nD\n\nG\nL\nU\nE";
230                         gui::IGUIStaticText *t =
231                         Environment->addStaticText(text, rect, false, true, this, -1);
232                         t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
233                 }
234                 u32 bs = 5;
235                 // World selection listbox
236                 u32 world_sel_h = 160;
237                 u32 world_sel_w = 365;
238                 //s32 world_sel_x = 50;
239                 s32 world_sel_x = m_size_client.X-world_sel_w-30;
240                 s32 world_sel_y = 30;
241                 u32 world_button_count = 3;
242                 u32 world_button_w = (world_sel_w)/world_button_count - bs
243                                 + bs/(world_button_count-1);
244                 {
245                         core::rect<s32> rect(0, 0, world_sel_w-4, 20);
246                         rect += m_topleft_client + v2s32(world_sel_x+4, world_sel_y-20);
247                         /*gui::IGUIStaticText *e =*/ Environment->addStaticText(
248                                         wgettext("Select World:"), 
249                                         rect, false, true, this, -1);
250                         /*e->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);*/
251                 }
252                 {
253                         core::rect<s32> rect(0, 0, world_sel_w, world_sel_h);
254                         rect += m_topleft_client + v2s32(world_sel_x, world_sel_y);
255                         gui::IGUIListBox *e = Environment->addListBox(rect, this,
256                                         GUI_ID_WORLD_LISTBOX);
257                         e->setDrawBackground(true);
258                         for(std::vector<WorldSpec>::const_iterator i = m_data->worlds.begin();
259                                         i != m_data->worlds.end(); i++){
260                                 e->addItem(narrow_to_wide(i->name+" ["+i->gameid+"]").c_str());
261                         }
262                         e->setSelected(m_data->selected_world);
263                         Environment->setFocus(e);
264                 }
265                 // Delete world button
266                 {
267                         core::rect<s32> rect(0, 0, world_button_w, 30);
268                         rect += m_topleft_client + v2s32(world_sel_x, world_sel_y+world_sel_h+0);
269                         Environment->addButton(rect, this, GUI_ID_DELETE_WORLD_BUTTON,
270                                   wgettext("Delete"));
271                 }
272                 // Create world button
273                 {
274                         core::rect<s32> rect(0, 0, world_button_w, 30);
275                         rect += m_topleft_client + v2s32(world_sel_x+world_button_w+bs, world_sel_y+world_sel_h+0);
276                         Environment->addButton(rect, this, GUI_ID_CREATE_WORLD_BUTTON,
277                                   wgettext("New"));
278                 }
279                 // Configure world button
280                 {
281                         core::rect<s32> rect(0, 0, world_button_w, 30);
282                         rect += m_topleft_client + v2s32(world_sel_x+(world_button_w+bs)*2,
283                                         world_sel_y+world_sel_h+0);
284                         Environment->addButton(rect, this, GUI_ID_CONFIGURE_WORLD_BUTTON,
285                                   wgettext("Configure"));
286                 }
287                 // Start game button
288                 {
289                         /*core::rect<s32> rect(0, 0, world_button_w, 30);
290                         rect += m_topleft_client + v2s32(world_sel_x+(world_button_w+bs)*3,
291                                         world_sel_y+world_sel_h+0);*/
292                         u32 bw = 160;
293                         /*core::rect<s32> rect(0, 0, bw, 30);
294                         rect += m_topleft_client + v2s32(m_size_client.X-bw-30,
295                                         m_size_client.Y-30-15);*/
296                         core::rect<s32> rect(0, 0, bw, 30);
297                         rect += m_topleft_client + v2s32(world_sel_x+world_sel_w-bw,
298                                         world_sel_y+world_sel_h+30+bs);
299                         Environment->addButton(rect, this,
300                                         GUI_ID_JOIN_GAME_BUTTON, wgettext("Play"));
301                 }
302                 // Options
303                 s32 option_x = 50;
304                 //s32 option_x = 50+world_sel_w+20;
305                 s32 option_y = 30;
306                 u32 option_w = 150;
307                 {
308                         core::rect<s32> rect(0, 0, option_w, 30);
309                         rect += m_topleft_client + v2s32(option_x, option_y+20*0);
310                         Environment->addCheckBox(m_data->creative_mode, rect, this,
311                                         GUI_ID_CREATIVE_CB, wgettext("Creative Mode"));
312                 }
313                 {
314                         core::rect<s32> rect(0, 0, option_w, 30);
315                         rect += m_topleft_client + v2s32(option_x, option_y+20*1);
316                         Environment->addCheckBox(m_data->enable_damage, rect, this,
317                                         GUI_ID_DAMAGE_CB, wgettext("Enable Damage"));
318                 }
319                 changeCtype("C");
320         }
321         else if(m_data->selected_tab == TAB_MULTIPLAYER)
322         {
323                 changeCtype("");
324                 // CLIENT
325                 {
326                         core::rect<s32> rect(0, 0, 10, m_size_client.Y);
327                         rect += m_topleft_client + v2s32(15, 0);
328                         const wchar_t *text = L"C\nL\nI\nE\nN\nT";
329                         gui::IGUIStaticText *t =
330                         Environment->addStaticText(text, rect, false, true, this, -1);
331                         t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
332                 }
333                 // Nickname + password
334                 {
335                         core::rect<s32> rect(0, 0, 110, 20);
336                         rect += m_topleft_client + v2s32(35+30, 50+6);
337                         Environment->addStaticText(wgettext("Name/Password"), 
338                                 rect, false, true, this, -1);
339                 }
340                 changeCtype("C");
341                 {
342                         core::rect<s32> rect(0, 0, 230, 30);
343                         rect += m_topleft_client + v2s32(160+30, 50);
344                         gui::IGUIElement *e = 
345                         Environment->addEditBox(m_data->name.c_str(), rect, true, this, GUI_ID_NAME_INPUT);
346                         if(m_data->name == L"")
347                                 Environment->setFocus(e);
348                 }
349                 {
350                         core::rect<s32> rect(0, 0, 120, 30);
351                         rect += m_topleft_client + v2s32(m_size_client.X-60-100, 50);
352                         gui::IGUIEditBox *e =
353                         Environment->addEditBox(L"", rect, true, this, 264);
354                         e->setPasswordBox(true);
355                         if(m_data->name != L"" && m_data->address != L"")
356                                 Environment->setFocus(e);
357
358                 }
359                 changeCtype("");
360                 // Address + port
361                 {
362                         core::rect<s32> rect(0, 0, 110, 20);
363                         rect += m_topleft_client + v2s32(35+30, 100+6);
364                         Environment->addStaticText(wgettext("Address/Port"),
365                                 rect, false, true, this, -1);
366                 }
367                 changeCtype("C");
368                 {
369                         core::rect<s32> rect(0, 0, 230, 30);
370                         rect += m_topleft_client + v2s32(160+30, 100);
371                         gui::IGUIElement *e = 
372                         Environment->addEditBox(m_data->address.c_str(), rect, true,
373                                         this, GUI_ID_ADDRESS_INPUT);
374                         if(m_data->name != L"" && m_data->address == L"")
375                                 Environment->setFocus(e);
376                 }
377                 {
378                         core::rect<s32> rect(0, 0, 120, 30);
379                         rect += m_topleft_client + v2s32(m_size_client.X-60-100, 100);
380                         Environment->addEditBox(m_data->port.c_str(), rect, true,
381                                         this, GUI_ID_PORT_INPUT);
382                 }
383                 changeCtype("");
384                 // Start game button
385                 {
386                         core::rect<s32> rect(0, 0, 180, 30);
387                         rect += m_topleft_client + v2s32(m_size_client.X-180-30,
388                                         m_size_client.Y-30-15);
389                         Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON,
390                                 wgettext("Start Game / Connect"));
391                 }
392                 changeCtype("C");
393         }
394         else if(m_data->selected_tab == TAB_ADVANCED)
395         {
396                 changeCtype("");
397                 // CLIENT
398                 {
399                         core::rect<s32> rect(0, 0, 10, m_size_client.Y);
400                         rect += m_topleft_client + v2s32(15, 0);
401                         const wchar_t *text = L"C\nL\nI\nE\nN\nT";
402                         gui::IGUIStaticText *t =
403                         Environment->addStaticText(text, rect, false, true, this, -1);
404                         t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
405                 }
406                 // Nickname + password
407                 {
408                         core::rect<s32> rect(0, 0, 110, 20);
409                         rect += m_topleft_client + v2s32(35+30, 35+6);
410                         Environment->addStaticText(wgettext("Name/Password"), 
411                                 rect, false, true, this, -1);
412                 }
413                 changeCtype("C");
414                 {
415                         core::rect<s32> rect(0, 0, 230, 30);
416                         rect += m_topleft_client + v2s32(160+30, 35);
417                         gui::IGUIElement *e = 
418                         Environment->addEditBox(m_data->name.c_str(), rect, true, this, GUI_ID_NAME_INPUT);
419                         if(m_data->name == L"")
420                                 Environment->setFocus(e);
421                 }
422                 {
423                         core::rect<s32> rect(0, 0, 120, 30);
424                         rect += m_topleft_client + v2s32(m_size_client.X-60-100, 35);
425                         gui::IGUIEditBox *e =
426                         Environment->addEditBox(L"", rect, true, this, 264);
427                         e->setPasswordBox(true);
428                         if(m_data->name != L"" && m_data->address != L"")
429                                 Environment->setFocus(e);
430
431                 }
432                 changeCtype("");
433                 // Address + port
434                 {
435                         core::rect<s32> rect(0, 0, 110, 20);
436                         rect += m_topleft_client + v2s32(35+30, 75+6);
437                         Environment->addStaticText(wgettext("Address/Port"),
438                                 rect, false, true, this, -1);
439                 }
440                 changeCtype("C");
441                 {
442                         core::rect<s32> rect(0, 0, 230, 30);
443                         rect += m_topleft_client + v2s32(160+30, 75);
444                         gui::IGUIElement *e = 
445                         Environment->addEditBox(m_data->address.c_str(), rect, true,
446                                         this, GUI_ID_ADDRESS_INPUT);
447                         if(m_data->name != L"" && m_data->address == L"")
448                                 Environment->setFocus(e);
449                 }
450                 {
451                         core::rect<s32> rect(0, 0, 120, 30);
452                         rect += m_topleft_client + v2s32(m_size_client.X-60-100, 75);
453                         Environment->addEditBox(m_data->port.c_str(), rect, true,
454                                         this, GUI_ID_PORT_INPUT);
455                 }
456                 changeCtype("");
457                 {
458                         core::rect<s32> rect(0, 0, 400, 20);
459                         rect += m_topleft_client + v2s32(160+30, 75+35);
460                         Environment->addStaticText(wgettext("Leave address blank to start a local server."),
461                                 rect, false, true, this, -1);
462                 }
463                 // Start game button
464                 {
465                         core::rect<s32> rect(0, 0, 180, 30);
466                         rect += m_topleft_client + v2s32(m_size_client.X-180-30,
467                                         m_size_client.Y-30-20);
468                         Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON,
469                                 wgettext("Start Game / Connect"));
470                 }
471                 /*
472                         Server section
473                 */
474                 // SERVER
475                 {
476                         core::rect<s32> rect(0, 0, 10, m_size_server.Y);
477                         rect += m_topleft_server + v2s32(15, 0);
478                         const wchar_t *text = L"S\nE\nR\nV\nE\nR";
479                         gui::IGUIStaticText *t =
480                         Environment->addStaticText(text, rect, false, true, this, -1);
481                         t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
482                 }
483                 // Server parameters
484                 {
485                         core::rect<s32> rect(0, 0, 250, 30);
486                         rect += m_topleft_server + v2s32(30+20+250+20, 20);
487                         Environment->addCheckBox(m_data->creative_mode, rect, this, GUI_ID_CREATIVE_CB,
488                                 wgettext("Creative Mode"));
489                 }
490                 {
491                         core::rect<s32> rect(0, 0, 250, 30);
492                         rect += m_topleft_server + v2s32(30+20+250+20, 40);
493                         Environment->addCheckBox(m_data->enable_damage, rect, this, GUI_ID_DAMAGE_CB,
494                                 wgettext("Enable Damage"));
495                 }
496                 // Delete world button
497                 {
498                         core::rect<s32> rect(0, 0, 130, 30);
499                         rect += m_topleft_server + v2s32(30+20+250+20, 90);
500                         Environment->addButton(rect, this, GUI_ID_DELETE_WORLD_BUTTON,
501                                   wgettext("Delete world"));
502                 }
503                 // Create world button
504                 {
505                         core::rect<s32> rect(0, 0, 130, 30);
506                         rect += m_topleft_server + v2s32(30+20+250+20+140, 90);
507                         Environment->addButton(rect, this, GUI_ID_CREATE_WORLD_BUTTON,
508                                   wgettext("Create world"));
509                 }
510                 // World selection listbox
511                 {
512                         core::rect<s32> rect(0, 0, 250, 120);
513                         rect += m_topleft_server + v2s32(30+20, 10);
514                         gui::IGUIListBox *e = Environment->addListBox(rect, this,
515                                         GUI_ID_WORLD_LISTBOX);
516                         e->setDrawBackground(true);
517                         for(std::vector<WorldSpec>::const_iterator i = m_data->worlds.begin();
518                                         i != m_data->worlds.end(); i++){
519                                 e->addItem(narrow_to_wide(i->name+" ["+i->gameid+"]").c_str());
520                         }
521                         e->setSelected(m_data->selected_world);
522                 }
523                 changeCtype("C");
524         }
525         else if(m_data->selected_tab == TAB_SETTINGS)
526         {
527                 {
528                         core::rect<s32> rect(0, 0, 10, m_size_client.Y);
529                         rect += m_topleft_client + v2s32(15, 0);
530                         const wchar_t *text = L"S\nE\nT\nT\nI\nN\nG\nS";
531                         gui::IGUIStaticText *t =
532                         Environment->addStaticText(text, rect, false, true, this, -1);
533                         t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
534                 }
535                 s32 option_x = 70;
536                 s32 option_y = 50;
537                 u32 option_w = 150;
538                 {
539                         core::rect<s32> rect(0, 0, option_w, 30);
540                         rect += m_topleft_client + v2s32(option_x, option_y);
541                         Environment->addCheckBox(m_data->fancy_trees, rect, this,
542                                         GUI_ID_FANCYTREE_CB, wgettext("Fancy trees")); 
543                 }
544                 {
545                         core::rect<s32> rect(0, 0, option_w, 30);
546                         rect += m_topleft_client + v2s32(option_x, option_y+20);
547                         Environment->addCheckBox(m_data->smooth_lighting, rect, this,
548                                         GUI_ID_SMOOTH_LIGHTING_CB, wgettext("Smooth Lighting"));
549                 }
550                 {
551                         core::rect<s32> rect(0, 0, option_w, 30);
552                         rect += m_topleft_client + v2s32(option_x, option_y+20*2);
553                         Environment->addCheckBox(m_data->clouds_3d, rect, this,
554                                         GUI_ID_3D_CLOUDS_CB, wgettext("3D Clouds"));
555                 }
556                 {
557                         core::rect<s32> rect(0, 0, option_w, 30);
558                         rect += m_topleft_client + v2s32(option_x, option_y+20*3);
559                         Environment->addCheckBox(m_data->opaque_water, rect, this,
560                                         GUI_ID_OPAQUE_WATER_CB, wgettext("Opaque water"));
561                 }
562                 // Key change button
563                 {
564                         core::rect<s32> rect(0, 0, 120, 30);
565                         /*rect += m_topleft_client + v2s32(m_size_client.X-120-30,
566                                         m_size_client.Y-30-20);*/
567                         rect += m_topleft_client + v2s32(option_x, option_y+120);
568                         Environment->addButton(rect, this,
569                                         GUI_ID_CHANGE_KEYS_BUTTON, wgettext("Change keys"));
570                 }
571                 changeCtype("C");
572         }
573         else if(m_data->selected_tab == TAB_CREDITS)
574         {
575                 // CREDITS
576                 {
577                         core::rect<s32> rect(0, 0, 10, m_size_client.Y);
578                         rect += m_topleft_client + v2s32(15, 0);
579                         const wchar_t *text = L"C\nR\nE\nD\nI\nT\nS";
580                         gui::IGUIStaticText *t =
581                         Environment->addStaticText(text, rect, false, true, this, -1);
582                         t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
583                 }
584                 {
585                         core::rect<s32> rect(0, 0, 620, 250);
586                         rect += m_topleft_client + v2s32(130+14, 50+35);
587                         Environment->addStaticText(narrow_to_wide(
588                         "Minetest-c55 " VERSION_STRING "\n"
589                         "http://c55.me/minetest/\n"
590                         "\n"
591                         "by Perttu Ahola <celeron55@gmail.com>\n"
592                         "and contributors"
593                         ).c_str(), rect, false, true, this, -1);
594                 }
595         }
596
597         m_is_regenerating = false;
598 }
599
600 void GUIMainMenu::drawMenu()
601 {
602         gui::IGUISkin* skin = Environment->getSkin();
603         if (!skin)
604                 return;
605         video::IVideoDriver* driver = Environment->getVideoDriver();
606         
607         /*video::SColor bgcolor(140,0,0,0);
608         driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);*/
609
610         video::SColor bgcolor(140,0,0,0);
611
612         if(getTab() == TAB_SINGLEPLAYER)
613         {
614                 {
615                         core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
616                         rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
617                         driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
618                 }
619         }
620         else if(getTab() == TAB_MULTIPLAYER)
621         {
622                 {
623                         core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
624                         rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
625                         driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
626                 }
627         }
628         else if(getTab() == TAB_ADVANCED)
629         {
630                 {
631                         core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
632                         rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
633                         driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
634                 }
635                 {
636                         core::rect<s32> rect(0, 0, m_size_server.X, m_size_server.Y);
637                         rect += AbsoluteRect.UpperLeftCorner + m_topleft_server;
638                         driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
639                 }
640         }
641         else if(getTab() == TAB_SETTINGS)
642         {
643                 {
644                         core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
645                         rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
646                         driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
647                 }
648         }
649         else if(getTab() == TAB_CREDITS)
650         {
651                 {
652                         core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
653                         rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
654                         driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
655                 }
656                 video::ITexture *logotexture =
657                                 driver->getTexture(getTexturePath("menulogo.png").c_str());
658                 if(logotexture)
659                 {
660                         v2s32 logosize(logotexture->getOriginalSize().Width,
661                                         logotexture->getOriginalSize().Height);
662                         logosize *= 2;
663                         core::rect<s32> rect(0,0,logosize.X,logosize.Y);
664                         rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
665                         rect += v2s32(130, 50);
666                         driver->draw2DImage(logotexture, rect,
667                                 core::rect<s32>(core::position2d<s32>(0,0),
668                                 core::dimension2di(logotexture->getSize())),
669                                 NULL, NULL, true);
670                 }
671         }
672
673         gui::IGUIElement::draw();
674 }
675
676 void GUIMainMenu::readInput(MainMenuData *dst)
677 {
678         {
679                 gui::IGUIElement *e = getElementFromId(GUI_ID_TAB_CONTROL);
680                 if(e != NULL && e->getType() == gui::EGUIET_TAB_CONTROL)
681                         dst->selected_tab = ((gui::IGUITabControl*)e)->getActiveTab();
682         }
683         if(dst->selected_tab == TAB_SINGLEPLAYER)
684         {
685                 dst->simple_singleplayer_mode = true;
686         }
687         else
688         {
689                 dst->simple_singleplayer_mode = false;
690                 {
691                         gui::IGUIElement *e = getElementFromId(GUI_ID_NAME_INPUT);
692                         if(e != NULL)
693                                 dst->name = e->getText();
694                 }
695                 {
696                         gui::IGUIElement *e = getElementFromId(264);
697                         if(e != NULL)
698                                 dst->password = e->getText();
699                 }
700                 {
701                         gui::IGUIElement *e = getElementFromId(GUI_ID_ADDRESS_INPUT);
702                         if(e != NULL)
703                                 dst->address = e->getText();
704                 }
705                 {
706                         gui::IGUIElement *e = getElementFromId(GUI_ID_PORT_INPUT);
707                         if(e != NULL)
708                                 dst->port = e->getText();
709                 }
710         }
711         {
712                 gui::IGUIElement *e = getElementFromId(GUI_ID_CREATIVE_CB);
713                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
714                         dst->creative_mode = ((gui::IGUICheckBox*)e)->isChecked();
715         }
716         {
717                 gui::IGUIElement *e = getElementFromId(GUI_ID_DAMAGE_CB);
718                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
719                         dst->enable_damage = ((gui::IGUICheckBox*)e)->isChecked();
720         }
721         {
722                 gui::IGUIElement *e = getElementFromId(GUI_ID_FANCYTREE_CB);
723                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
724                         dst->fancy_trees = ((gui::IGUICheckBox*)e)->isChecked();
725         }
726         {
727                 gui::IGUIElement *e = getElementFromId(GUI_ID_SMOOTH_LIGHTING_CB);
728                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
729                         dst->smooth_lighting = ((gui::IGUICheckBox*)e)->isChecked();
730         }
731         {
732                 gui::IGUIElement *e = getElementFromId(GUI_ID_3D_CLOUDS_CB);
733                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
734                         dst->clouds_3d = ((gui::IGUICheckBox*)e)->isChecked();
735         }
736         {
737                 gui::IGUIElement *e = getElementFromId(GUI_ID_OPAQUE_WATER_CB);
738                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
739                         dst->opaque_water = ((gui::IGUICheckBox*)e)->isChecked();
740         }
741
742         {
743                 gui::IGUIElement *e = getElementFromId(GUI_ID_WORLD_LISTBOX);
744                 if(e != NULL && e->getType() == gui::EGUIET_LIST_BOX)
745                         dst->selected_world = ((gui::IGUIListBox*)e)->getSelected();
746         }
747 }
748
749 void GUIMainMenu::acceptInput()
750 {
751         readInput(m_data);
752         m_accepted = true;
753 }
754
755 bool GUIMainMenu::OnEvent(const SEvent& event)
756 {
757         if(event.EventType==EET_KEY_INPUT_EVENT)
758         {
759                 if(event.KeyInput.Key==KEY_ESCAPE && event.KeyInput.PressedDown)
760                 {
761                         m_gamecallback->exitToOS();
762                         quitMenu();
763                         return true;
764                 }
765                 if(event.KeyInput.Key==KEY_RETURN && event.KeyInput.PressedDown)
766                 {
767                         acceptInput();
768                         quitMenu();
769                         return true;
770                 }
771         }
772         if(event.EventType==EET_GUI_EVENT)
773         {
774                 if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST
775                                 && isVisible())
776                 {
777                         if(!canTakeFocus(event.GUIEvent.Element))
778                         {
779                                 dstream<<"GUIMainMenu: Not allowing focus change."
780                                                 <<std::endl;
781                                 // Returning true disables focus change
782                                 return true;
783                         }
784                 }
785                 if(event.GUIEvent.EventType==gui::EGET_TAB_CHANGED)
786                 {
787                         if(!m_is_regenerating)
788                                 regenerateGui(m_screensize_old);
789                         return true;
790                 }
791                 if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED)
792                 {
793                         switch(event.GUIEvent.Caller->getID())
794                         {
795                         case GUI_ID_JOIN_GAME_BUTTON: {
796                                 MainMenuData cur;
797                                 readInput(&cur);
798                                 if(cur.address == L"" && getTab() == TAB_MULTIPLAYER){
799                                         (new GUIMessageMenu(env, parent, -1, menumgr,
800                                                         wgettext("Address required."))
801                                                         )->drop();
802                                         return true;
803                                 }
804                                 acceptInput();
805                                 quitMenu();
806                                 return true;
807                         }
808                         case GUI_ID_CHANGE_KEYS_BUTTON: {
809                                 GUIKeyChangeMenu *kmenu = new GUIKeyChangeMenu(env, parent, -1,menumgr);
810                                 kmenu->drop();
811                                 return true;
812                         }
813                         case GUI_ID_DELETE_WORLD_BUTTON: {
814                                 MainMenuData cur;
815                                 readInput(&cur);
816                                 if(cur.selected_world == -1){
817                                         (new GUIMessageMenu(env, parent, -1, menumgr,
818                                                         wgettext("Cannot delete world: Nothing selected"))
819                                                         )->drop();
820                                 } else {
821                                         WorldSpec spec = m_data->worlds[cur.selected_world];
822                                         ConfirmDestDeleteWorld *dest = new
823                                                         ConfirmDestDeleteWorld(spec, this);
824                                         (new GUIConfirmMenu(env, parent, -1, menumgr, dest,
825                                                         (std::wstring(wgettext("Delete world "))
826                                                         +L"\""+narrow_to_wide(spec.name)+L"\"?").c_str()
827                                                         ))->drop();
828                                 }
829                                 return true;
830                         }
831                         case GUI_ID_CREATE_WORLD_BUTTON: {
832                                 std::vector<SubgameSpec> games = getAvailableGames();
833                                 if(games.size() == 0){
834                                         GUIMessageMenu *menu = new GUIMessageMenu(env, parent,
835                                                         -1, menumgr,
836                                                         wgettext("Cannot create world: No games found"));
837                                         menu->drop();
838                                 } else {
839                                         CreateWorldDest *dest = new CreateWorldDestMainMenu(this);
840                                         GUICreateWorld *menu = new GUICreateWorld(env, parent, -1,
841                                                         menumgr, dest, games);
842                                         menu->drop();
843                                 }
844                                 return true;
845                         }
846                         case GUI_ID_CONFIGURE_WORLD_BUTTON: {
847                                 GUIMessageMenu *menu = new GUIMessageMenu(env, parent,
848                                                 -1, menumgr,
849                                                 wgettext("Nothing here"));
850                                 menu->drop();
851                                 return true;
852                         }
853                         }
854                 }
855                 if(event.GUIEvent.EventType==gui::EGET_EDITBOX_ENTER)
856                 {
857                         switch(event.GUIEvent.Caller->getID())
858                         {
859                                 case GUI_ID_ADDRESS_INPUT: case GUI_ID_PORT_INPUT: case GUI_ID_NAME_INPUT: case 264:
860                                 acceptInput();
861                                 quitMenu();
862                                 return true;
863                         }
864                 }
865                 if(event.GUIEvent.EventType==gui::EGET_LISTBOX_SELECTED_AGAIN)
866                 {
867                         switch(event.GUIEvent.Caller->getID())
868                         {
869                         case GUI_ID_WORLD_LISTBOX:
870                                 acceptInput();
871                                 if(getTab() != TAB_SINGLEPLAYER)
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