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