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