]> git.lizzy.rs Git - dragonfireclient.git/blob - src/guiMainMenu.cpp
World selection box in main menu (and random fixing)
[dragonfireclient.git] / src / guiMainMenu.cpp
1 /*
2 Minetest-c55
3 Copyright (C) 2010 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 "debug.h"
23 #include "serialization.h"
24 #include <string>
25 #include <IGUICheckBox.h>
26 #include <IGUIEditBox.h>
27 #include <IGUIButton.h>
28 #include <IGUIStaticText.h>
29 #include <IGUIFont.h>
30 #include <IGUIListBox.h>
31
32
33 #include "gettext.h"
34
35 GUIMainMenu::GUIMainMenu(gui::IGUIEnvironment* env,
36                 gui::IGUIElement* parent, s32 id,
37                 IMenuManager *menumgr,
38                 MainMenuData *data,
39                 IGameCallback *gamecallback
40 ):
41         GUIModalMenu(env, parent, id, menumgr),
42         m_data(data),
43         m_accepted(false),
44         m_gamecallback(gamecallback)
45 {
46         assert(m_data);
47         this->env = env;
48         this->parent = parent;
49         this->id = id;
50         this->menumgr = menumgr;
51 }
52
53 GUIMainMenu::~GUIMainMenu()
54 {
55         removeChildren();
56 }
57
58 void GUIMainMenu::removeChildren()
59 {
60         const core::list<gui::IGUIElement*> &children = getChildren();
61         core::list<gui::IGUIElement*> children_copy;
62         for(core::list<gui::IGUIElement*>::ConstIterator
63                         i = children.begin(); i != children.end(); i++)
64         {
65                 children_copy.push_back(*i);
66         }
67         for(core::list<gui::IGUIElement*>::Iterator
68                         i = children_copy.begin();
69                         i != children_copy.end(); i++)
70         {
71                 (*i)->remove();
72         }
73 }
74
75 void GUIMainMenu::regenerateGui(v2u32 screensize)
76 {
77         std::wstring text_name = m_data->name;
78         std::wstring text_address = m_data->address;
79         std::wstring text_port = m_data->port;
80         bool creative_mode = m_data->creative_mode;
81         bool enable_damage = m_data->enable_damage;
82         bool fancy_trees = m_data->fancy_trees;
83         bool smooth_lighting = m_data->smooth_lighting;
84         bool clouds_3d = m_data->clouds_3d;
85         bool opaque_water = m_data->opaque_water;
86         int selected_world = m_data->selected_world;
87         
88         // Client options
89         {
90                 gui::IGUIElement *e = getElementFromId(GUI_ID_NAME_INPUT);
91                 if(e != NULL)
92                         text_name = e->getText();
93         }
94         {
95                 gui::IGUIElement *e = getElementFromId(GUI_ID_ADDRESS_INPUT);
96                 if(e != NULL)
97                         text_address = e->getText();
98         }
99         {
100                 gui::IGUIElement *e = getElementFromId(GUI_ID_PORT_INPUT);
101                 if(e != NULL)
102                         text_port = e->getText();
103         }
104         {
105                 gui::IGUIElement *e = getElementFromId(GUI_ID_FANCYTREE_CB);
106                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
107                         fancy_trees = ((gui::IGUICheckBox*)e)->isChecked();
108         }
109         {
110                 gui::IGUIElement *e = getElementFromId(GUI_ID_SMOOTH_LIGHTING_CB);
111                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
112                         smooth_lighting = ((gui::IGUICheckBox*)e)->isChecked();
113         }
114         {
115                 gui::IGUIElement *e = getElementFromId(GUI_ID_3D_CLOUDS_CB);
116                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
117                         clouds_3d = ((gui::IGUICheckBox*)e)->isChecked();
118         }
119         {
120                 gui::IGUIElement *e = getElementFromId(GUI_ID_OPAQUE_WATER_CB);
121                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
122                         opaque_water = ((gui::IGUICheckBox*)e)->isChecked();
123         }
124         
125         // Server options
126         {
127                 gui::IGUIElement *e = getElementFromId(GUI_ID_CREATIVE_CB);
128                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
129                         creative_mode = ((gui::IGUICheckBox*)e)->isChecked();
130         }
131         {
132                 gui::IGUIElement *e = getElementFromId(GUI_ID_DAMAGE_CB);
133                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
134                         enable_damage = ((gui::IGUICheckBox*)e)->isChecked();
135         }
136         {
137                 gui::IGUIElement *e = getElementFromId(GUI_ID_WORLD_LISTBOX);
138                 if(e != NULL && e->getType() == gui::EGUIET_LIST_BOX)
139                         selected_world = ((gui::IGUIListBox*)e)->getSelected();
140         }
141
142         /*
143                 Remove stuff
144         */
145         removeChildren();
146         
147         /*
148                 Calculate new sizes and positions
149         */
150         
151         v2s32 size(620, 430);
152
153         core::rect<s32> rect(
154                         screensize.X/2 - size.X/2,
155                         screensize.Y/2 - size.Y/2,
156                         screensize.X/2 + size.X/2,
157                         screensize.Y/2 + size.Y/2
158         );
159
160         DesiredRect = rect;
161         recalculateAbsolutePosition(false);
162
163         //v2s32 size = rect.getSize();
164
165         /*
166                 Add stuff
167         */
168
169         /*
170                 Client section
171         */
172
173         v2s32 topleft_client(40, 0);
174         v2s32 size_client = size - v2s32(40, 0);
175         
176         changeCtype("");
177         
178         // Version
179         {
180                 core::rect<s32> rect(0, 0, 300, 30);
181                 rect += topleft_client + v2s32(-36, 0);
182                 Environment->addStaticText(narrow_to_wide(VERSION_STRING).c_str(), 
183                         rect, false, true, this, -1);
184         }
185         // CLIENT
186         {
187                 core::rect<s32> rect(0, 0, 20, 125);
188                 rect += topleft_client + v2s32(-15, 80);
189                 const wchar_t *text = L"C\nL\nI\nE\nN\nT";
190                 //gui::IGUIStaticText *t =
191                 Environment->addStaticText(text, rect, false, true, this, -1);
192                 //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
193         }
194         // Nickname + password
195         {
196                 core::rect<s32> rect(0, 0, 110, 20);
197                 rect += topleft_client + v2s32(35, 50+6);
198                 Environment->addStaticText(wgettext("Name/Password"), 
199                         rect, false, true, this, -1);
200         }
201         changeCtype("C");
202         {
203                 core::rect<s32> rect(0, 0, 230, 30);
204                 rect += topleft_client + v2s32(160, 50);
205                 gui::IGUIElement *e = 
206                 Environment->addEditBox(text_name.c_str(), rect, true, this, GUI_ID_NAME_INPUT);
207                 if(text_name == L"")
208                         Environment->setFocus(e);
209         }
210         {
211                 core::rect<s32> rect(0, 0, 120, 30);
212                 rect += topleft_client + v2s32(size_client.X-60-100, 50);
213                 gui::IGUIEditBox *e =
214                 Environment->addEditBox(L"", rect, true, this, 264);
215                 e->setPasswordBox(true);
216                 if(text_name != L"" && text_address != L"")
217                         Environment->setFocus(e);
218
219         }
220         changeCtype("");
221         // Address + port
222         {
223                 core::rect<s32> rect(0, 0, 110, 20);
224                 rect += topleft_client + v2s32(35, 100+6);
225                 Environment->addStaticText(wgettext("Address/Port"),
226                         rect, false, true, this, -1);
227         }
228         changeCtype("C");
229         {
230                 core::rect<s32> rect(0, 0, 230, 30);
231                 rect += topleft_client + v2s32(160, 100);
232                 gui::IGUIElement *e = 
233                 Environment->addEditBox(text_address.c_str(), rect, true, this, GUI_ID_ADDRESS_INPUT);
234                 if(text_name != L"" && text_address == L"")
235                         Environment->setFocus(e);
236         }
237         {
238                 core::rect<s32> rect(0, 0, 120, 30);
239                 //rect += topleft_client + v2s32(160+250+20, 125);
240                 rect += topleft_client + v2s32(size_client.X-60-100, 100);
241                 Environment->addEditBox(text_port.c_str(), rect, true, this, GUI_ID_PORT_INPUT);
242         }
243         changeCtype("");
244         {
245                 core::rect<s32> rect(0, 0, 400, 20);
246                 rect += topleft_client + v2s32(160, 100+35);
247                 Environment->addStaticText(wgettext("Leave address blank to start a local server."),
248                         rect, false, true, this, -1);
249         }
250         {
251                 core::rect<s32> rect(0, 0, 250, 30);
252                 rect += topleft_client + v2s32(35, 150);
253                 Environment->addCheckBox(fancy_trees, rect, this, GUI_ID_FANCYTREE_CB,
254                         wgettext("Fancy trees")); 
255         }
256         {
257                 core::rect<s32> rect(0, 0, 250, 30);
258                 rect += topleft_client + v2s32(35, 150+20);
259                 Environment->addCheckBox(smooth_lighting, rect, this, GUI_ID_SMOOTH_LIGHTING_CB,
260                                 wgettext("Smooth Lighting"));
261         }
262         {
263                 core::rect<s32> rect(0, 0, 250, 30);
264                 rect += topleft_client + v2s32(35, 150+40);
265                 Environment->addCheckBox(clouds_3d, rect, this, GUI_ID_3D_CLOUDS_CB,
266                                 wgettext("3D Clouds"));
267         }
268         {
269                 core::rect<s32> rect(0, 0, 250, 30);
270                 rect += topleft_client + v2s32(35, 150+60);
271                 Environment->addCheckBox(opaque_water, rect, this, GUI_ID_OPAQUE_WATER_CB,
272                                 wgettext("Opaque water"));
273         }
274         // Start game button
275         {
276                 core::rect<s32> rect(0, 0, 180, 30);
277                 //rect += topleft_client + v2s32(size_client.X/2-180/2, 225-30/2);
278                 rect += topleft_client + v2s32(size_client.X-180-40, 150+25);
279                 Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON,
280                         wgettext("Start Game / Connect"));
281         }
282
283         // Key change button
284         {
285                 core::rect<s32> rect(0, 0, 100, 30);
286                 //rect += topleft_client + v2s32(size_client.X/2-180/2, 225-30/2);
287                 rect += topleft_client + v2s32(size_client.X-180-40-100-20, 150+25);
288                 Environment->addButton(rect, this, GUI_ID_CHANGE_KEYS_BUTTON,
289                         wgettext("Change keys"));
290         }
291         /*
292                 Server section
293         */
294
295         v2s32 topleft_server(40, 290);
296         v2s32 size_server = size - v2s32(40, 0);
297         
298         // SERVER
299         {
300                 core::rect<s32> rect(0, 0, 20, 125);
301                 rect += topleft_server + v2s32(-15, 15);
302                 const wchar_t *text = L"S\nE\nR\nV\nE\nR";
303                 //gui::IGUIStaticText *t =
304                 Environment->addStaticText(text, rect, false, true, this, -1);
305                 //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
306         }
307         // Server parameters
308         {
309                 core::rect<s32> rect(0, 0, 250, 30);
310                 rect += topleft_server + v2s32(20+250+20, 20);
311                 Environment->addCheckBox(creative_mode, rect, this, GUI_ID_CREATIVE_CB,
312                         wgettext("Creative Mode"));
313         }
314         {
315                 core::rect<s32> rect(0, 0, 250, 30);
316                 rect += topleft_server + v2s32(20+250+20, 40);
317                 Environment->addCheckBox(enable_damage, rect, this, GUI_ID_DAMAGE_CB,
318                         wgettext("Enable Damage"));
319         }
320         // Map delete button
321         {
322                 core::rect<s32> rect(0, 0, 130, 30);
323                 rect += topleft_server + v2s32(20+250+20, 90);
324                 Environment->addButton(rect, this, GUI_ID_DELETE_MAP_BUTTON,
325                           wgettext("Delete map"));
326         }
327         // World selection listbox
328         {
329                 core::rect<s32> rect(0, 0, 250, 120);
330                 rect += topleft_server + v2s32(20, 10);
331                 gui::IGUIListBox *e = Environment->addListBox(rect, this,
332                                 GUI_ID_WORLD_LISTBOX);
333                 e->setDrawBackground(true);
334                 for(std::list<std::wstring>::const_iterator i = m_data->worlds.begin();
335                                 i != m_data->worlds.end(); i++){
336                         e->addItem(i->c_str());
337                 }
338                 e->setSelected(selected_world);
339         }
340         changeCtype("C");
341 }
342
343 void GUIMainMenu::drawMenu()
344 {
345         gui::IGUISkin* skin = Environment->getSkin();
346         if (!skin)
347                 return;
348         video::IVideoDriver* driver = Environment->getVideoDriver();
349         
350         /*video::SColor bgcolor(140,0,0,0);
351         driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);*/
352
353         video::SColor bgcolor(140,0,0,0);
354
355         {
356                 core::rect<s32> rect(0, 0, 620, 270);
357                 rect += AbsoluteRect.UpperLeftCorner;
358                 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
359         }
360
361         {
362                 core::rect<s32> rect(0, 290, 620, 430);
363                 rect += AbsoluteRect.UpperLeftCorner;
364                 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
365         }
366
367         gui::IGUIElement::draw();
368 }
369
370 void GUIMainMenu::acceptInput()
371 {
372         {
373                 gui::IGUIElement *e = getElementFromId(GUI_ID_NAME_INPUT);
374                 if(e != NULL)
375                         m_data->name = e->getText();
376         }
377         {
378                 gui::IGUIElement *e = getElementFromId(264);
379                 if(e != NULL)
380                         m_data->password = e->getText();
381         }
382         {
383                 gui::IGUIElement *e = getElementFromId(GUI_ID_ADDRESS_INPUT);
384                 if(e != NULL)
385                         m_data->address = e->getText();
386         }
387         {
388                 gui::IGUIElement *e = getElementFromId(GUI_ID_PORT_INPUT);
389                 if(e != NULL)
390                         m_data->port = e->getText();
391         }
392         {
393                 gui::IGUIElement *e = getElementFromId(GUI_ID_CREATIVE_CB);
394                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
395                         m_data->creative_mode = ((gui::IGUICheckBox*)e)->isChecked();
396         }
397         {
398                 gui::IGUIElement *e = getElementFromId(GUI_ID_DAMAGE_CB);
399                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
400                         m_data->enable_damage = ((gui::IGUICheckBox*)e)->isChecked();
401         }
402         {
403                 gui::IGUIElement *e = getElementFromId(GUI_ID_FANCYTREE_CB);
404                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
405                         m_data->fancy_trees = ((gui::IGUICheckBox*)e)->isChecked();
406         }
407         {
408                 gui::IGUIElement *e = getElementFromId(GUI_ID_SMOOTH_LIGHTING_CB);
409                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
410                         m_data->smooth_lighting = ((gui::IGUICheckBox*)e)->isChecked();
411         }
412         {
413                 gui::IGUIElement *e = getElementFromId(GUI_ID_3D_CLOUDS_CB);
414                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
415                         m_data->clouds_3d = ((gui::IGUICheckBox*)e)->isChecked();
416         }
417         {
418                 gui::IGUIElement *e = getElementFromId(GUI_ID_OPAQUE_WATER_CB);
419                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
420                         m_data->opaque_water = ((gui::IGUICheckBox*)e)->isChecked();
421         }
422
423         {
424                 gui::IGUIElement *e = getElementFromId(GUI_ID_WORLD_LISTBOX);
425                 if(e != NULL && e->getType() == gui::EGUIET_LIST_BOX)
426                         m_data->selected_world = ((gui::IGUIListBox*)e)->getSelected();
427         }
428         
429         m_accepted = true;
430 }
431
432 bool GUIMainMenu::OnEvent(const SEvent& event)
433 {
434         if(event.EventType==EET_KEY_INPUT_EVENT)
435         {
436                 if(event.KeyInput.Key==KEY_ESCAPE && event.KeyInput.PressedDown)
437                 {
438                         m_gamecallback->exitToOS();
439                         quitMenu();
440                         return true;
441                 }
442                 if(event.KeyInput.Key==KEY_RETURN && event.KeyInput.PressedDown)
443                 {
444                         acceptInput();
445                         quitMenu();
446                         return true;
447                 }
448         }
449         if(event.EventType==EET_GUI_EVENT)
450         {
451                 if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST
452                                 && isVisible())
453                 {
454                         if(!canTakeFocus(event.GUIEvent.Element))
455                         {
456                                 dstream<<"GUIMainMenu: Not allowing focus change."
457                                                 <<std::endl;
458                                 // Returning true disables focus change
459                                 return true;
460                         }
461                 }
462                 if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED)
463                 {
464                         switch(event.GUIEvent.Caller->getID())
465                         {
466                         case GUI_ID_JOIN_GAME_BUTTON: // Start game
467                                 acceptInput();
468                                 quitMenu();
469                                 return true;
470                         case GUI_ID_CHANGE_KEYS_BUTTON: {
471                                 GUIKeyChangeMenu *kmenu = new GUIKeyChangeMenu(env, parent, -1,menumgr);
472                                 kmenu->drop();
473                                 return true;
474                         }
475                         case GUI_ID_DELETE_MAP_BUTTON: // Delete map
476                                 acceptInput();
477                                 m_data->delete_world = true;
478                                 quitMenu();
479                                 return true;
480                         }
481                 }
482                 if(event.GUIEvent.EventType==gui::EGET_EDITBOX_ENTER)
483                 {
484                         switch(event.GUIEvent.Caller->getID())
485                         {
486                                 case GUI_ID_ADDRESS_INPUT: case GUI_ID_PORT_INPUT: case GUI_ID_NAME_INPUT: case 264:
487                                 acceptInput();
488                                 quitMenu();
489                                 return true;
490                         }
491                 }
492                 if(event.GUIEvent.EventType==gui::EGET_LISTBOX_SELECTED_AGAIN)
493                 {
494                         switch(event.GUIEvent.Caller->getID())
495                         {
496                                 case GUI_ID_WORLD_LISTBOX:
497                                 acceptInput();
498                                 m_data->address = L""; // Force local game
499                                 quitMenu();
500                                 return true;
501                         }
502                 }
503         }
504
505         return Parent ? Parent->OnEvent(event) : false;
506 }
507