3 Copyright (C) 2010-12 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
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 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser 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.
20 #include "guiMainMenu.h"
21 #include "guiKeyChangeMenu.h"
22 #include "guiCreateWorld.h"
23 #include "guiConfigureWorld.h"
24 #include "guiMessageMenu.h"
25 #include "guiConfirmMenu.h"
27 #include "serialization.h"
29 #include <IGUICheckBox.h>
30 #include <IGUIEditBox.h>
31 #include <IGUIButton.h>
32 #include <IGUIStaticText.h>
34 #include <IGUIListBox.h>
35 #include <IGUITabControl.h>
36 #include <IGUIImage.h>
38 #include "guiPauseMenu.h"
40 #include "tile.h" // getTexturePath
42 #include "util/string.h"
45 struct CreateWorldDestMainMenu : public CreateWorldDest
47 CreateWorldDestMainMenu(GUIMainMenu *menu):
50 void accepted(std::wstring name, std::string gameid)
52 std::string name_narrow = wide_to_narrow(name);
53 if(!string_allowed_blacklist(name_narrow, WORLDNAME_BLACKLISTED_CHARS))
55 m_menu->displayMessageMenu(wgettext("Cannot create world: Name contains invalid characters"));
58 std::vector<WorldSpec> worlds = getAvailableWorlds();
59 for(std::vector<WorldSpec>::iterator i = worlds.begin();
60 i != worlds.end(); i++)
62 if((*i).name == name_narrow)
64 m_menu->displayMessageMenu(wgettext("Cannot create world: A world by this name already exists"));
68 m_menu->createNewWorld(name, gameid);
73 struct ConfirmDestDeleteWorld : public ConfirmDest
75 ConfirmDestDeleteWorld(WorldSpec spec, GUIMainMenu *menu,
76 const std::vector<std::string> &paths):
81 void answer(bool answer)
85 m_menu->deleteWorld(m_paths);
89 std::vector<std::string> m_paths;
94 GUI_ID_QUIT_BUTTON = 101,
99 GUI_ID_SMOOTH_LIGHTING_CB,
101 GUI_ID_OPAQUE_WATER_CB,
103 GUI_ID_ANISOTROPIC_CB,
107 GUI_ID_PRELOAD_ITEM_VISUALS_CB,
108 GUI_ID_ENABLE_PARTICLES_CB,
111 GUI_ID_JOIN_GAME_BUTTON,
112 GUI_ID_CHANGE_KEYS_BUTTON,
113 GUI_ID_DELETE_WORLD_BUTTON,
114 GUI_ID_CREATE_WORLD_BUTTON,
115 GUI_ID_CONFIGURE_WORLD_BUTTON,
116 GUI_ID_WORLD_LISTBOX,
119 GUI_ID_SERVERLIST_TOGGLE,
120 GUI_ID_SERVERLIST_DELETE,
132 GUIMainMenu::GUIMainMenu(gui::IGUIEnvironment* env,
133 gui::IGUIElement* parent, s32 id,
134 IMenuManager *menumgr,
136 IGameCallback *gamecallback
138 GUIModalMenu(env, parent, id, menumgr),
141 m_gamecallback(gamecallback),
142 m_is_regenerating(false)
146 this->parent = parent;
148 this->menumgr = menumgr;
151 GUIMainMenu::~GUIMainMenu()
156 void GUIMainMenu::removeChildren()
158 const core::list<gui::IGUIElement*> &children = getChildren();
159 core::list<gui::IGUIElement*> children_copy;
160 for(core::list<gui::IGUIElement*>::ConstIterator
161 i = children.begin(); i != children.end(); i++)
163 children_copy.push_back(*i);
165 for(core::list<gui::IGUIElement*>::Iterator
166 i = children_copy.begin();
167 i != children_copy.end(); i++)
173 void GUIMainMenu::regenerateGui(v2u32 screensize)
175 m_is_regenerating = true;
177 Read stuff from elements into m_data
187 Calculate new sizes and positions
190 v2s32 size(screensize.X, screensize.Y);
192 core::rect<s32> rect(
193 screensize.X/2 - size.X/2,
194 screensize.Y/2 - size.Y/2,
195 screensize.X/2 + size.X/2,
196 screensize.Y/2 + size.Y/2
200 recalculateAbsolutePosition(false);
202 //v2s32 size = rect.getSize();
211 //if(m_data->selected_tab != TAB_CREDITS)
213 core::rect<s32> rect(0, 0, size.X, 40);
215 Environment->addStaticText(narrow_to_wide(
216 "Minetest " VERSION_STRING).c_str(),
217 rect, false, true, this, -1);
220 //v2s32 center(size.X/2, size.Y/2);
221 v2s32 c800(size.X/2-400, size.Y/2-300);
223 m_topleft_client = c800 + v2s32(90, 70+50+30);
224 m_size_client = v2s32(620, 270);
226 m_size_server = v2s32(620, 140);
228 if(m_data->selected_tab == TAB_ADVANCED)
230 m_topleft_client = c800 + v2s32(90, 70+50+30);
231 m_size_client = v2s32(620, 200);
233 m_size_server = v2s32(620, 140);
236 m_topleft_server = m_topleft_client + v2s32(0, m_size_client.Y+20);
241 core::rect<s32> rect(0, 0, m_size_client.X, 30);
242 rect += m_topleft_client + v2s32(0, -30);
243 gui::IGUITabControl *e = Environment->addTabControl(
244 rect, this, true, true, GUI_ID_TAB_CONTROL);
245 e->addTab(wgettext("Singleplayer"));
246 e->addTab(wgettext("Multiplayer"));
247 e->addTab(wgettext("Advanced"));
248 e->addTab(wgettext("Settings"));
249 e->addTab(wgettext("Credits"));
250 e->setActiveTab(m_data->selected_tab);
254 if(m_data->selected_tab == TAB_SINGLEPLAYER)
258 core::rect<s32> rect(0, 0, 10, m_size_client.Y);
259 rect += m_topleft_client + v2s32(15, 0);
260 //const wchar_t *text = L"H\nY\nB\nR\nI\nD";
261 const wchar_t *text = L"T\nA\nP\nE\n\nA\nN\nD\n\nG\nL\nU\nE";
262 gui::IGUIStaticText *t =
263 Environment->addStaticText(text, rect, false, false, this, -1);
264 t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
267 // World selection listbox
268 u32 world_sel_h = 160;
269 u32 world_sel_w = 365;
270 //s32 world_sel_x = 50;
271 s32 world_sel_x = m_size_client.X-world_sel_w-30;
272 s32 world_sel_y = 30;
273 u32 world_button_count = 3;
274 u32 world_button_w = (world_sel_w)/world_button_count - bs
275 + bs/(world_button_count-1);
277 core::rect<s32> rect(0, 0, world_sel_w-4, 20);
278 rect += m_topleft_client + v2s32(world_sel_x+4, world_sel_y-20);
279 /*gui::IGUIStaticText *e =*/ Environment->addStaticText(
280 wgettext("Select World:"),
281 rect, false, true, this, -1);
282 /*e->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);*/
285 core::rect<s32> rect(0, 0, world_sel_w, world_sel_h);
286 rect += m_topleft_client + v2s32(world_sel_x, world_sel_y);
287 gui::IGUIListBox *e = Environment->addListBox(rect, this,
288 GUI_ID_WORLD_LISTBOX);
289 e->setDrawBackground(true);
290 for(std::vector<WorldSpec>::const_iterator i = m_data->worlds.begin();
291 i != m_data->worlds.end(); i++){
292 e->addItem(narrow_to_wide(i->name+" ["+i->gameid+"]").c_str());
294 e->setSelected(m_data->selected_world);
295 Environment->setFocus(e);
297 // Delete world button
299 core::rect<s32> rect(0, 0, world_button_w, 30);
300 rect += m_topleft_client + v2s32(world_sel_x, world_sel_y+world_sel_h+0);
301 Environment->addButton(rect, this, GUI_ID_DELETE_WORLD_BUTTON,
304 // Create world button
306 core::rect<s32> rect(0, 0, world_button_w, 30);
307 rect += m_topleft_client + v2s32(world_sel_x+world_button_w+bs, world_sel_y+world_sel_h+0);
308 Environment->addButton(rect, this, GUI_ID_CREATE_WORLD_BUTTON,
311 // Configure world button
313 core::rect<s32> rect(0, 0, world_button_w, 30);
314 rect += m_topleft_client + v2s32(world_sel_x+(world_button_w+bs)*2,
315 world_sel_y+world_sel_h+0);
316 Environment->addButton(rect, this, GUI_ID_CONFIGURE_WORLD_BUTTON,
317 wgettext("Configure"));
321 /*core::rect<s32> rect(0, 0, world_button_w, 30);
322 rect += m_topleft_client + v2s32(world_sel_x+(world_button_w+bs)*3,
323 world_sel_y+world_sel_h+0);*/
325 /*core::rect<s32> rect(0, 0, bw, 30);
326 rect += m_topleft_client + v2s32(m_size_client.X-bw-30,
327 m_size_client.Y-30-15);*/
328 core::rect<s32> rect(0, 0, bw, 30);
329 rect += m_topleft_client + v2s32(world_sel_x+world_sel_w-bw,
330 world_sel_y+world_sel_h+30+bs);
331 Environment->addButton(rect, this,
332 GUI_ID_JOIN_GAME_BUTTON, wgettext("Play"));
336 //s32 option_x = 50+world_sel_w+20;
340 core::rect<s32> rect(0, 0, option_w, 30);
341 rect += m_topleft_client + v2s32(option_x, option_y+20*0);
342 Environment->addCheckBox(m_data->creative_mode, rect, this,
343 GUI_ID_CREATIVE_CB, wgettext("Creative Mode"));
346 core::rect<s32> rect(0, 0, option_w, 30);
347 rect += m_topleft_client + v2s32(option_x, option_y+20*1);
348 Environment->addCheckBox(m_data->enable_damage, rect, this,
349 GUI_ID_DAMAGE_CB, wgettext("Enable Damage"));
353 else if(m_data->selected_tab == TAB_MULTIPLAYER)
358 core::rect<s32> rect(0, 0, 10, m_size_client.Y);
359 rect += m_topleft_client + v2s32(15, 0);
360 const wchar_t *text = L"C\nL\nI\nE\nN\nT";
361 gui::IGUIStaticText *t =
362 Environment->addStaticText(text, rect, false, false, this, -1);
363 t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
365 // Nickname + password
367 core::rect<s32> rect(0, 0, 110, 20);
368 rect += m_topleft_client + v2s32(m_size_client.X-60-100, 10+6);
369 Environment->addStaticText(wgettext("Name/Password"),
370 rect, false, true, this, -1);
374 core::rect<s32> rect(0, 0, 120, 30);
375 rect += m_topleft_client + v2s32(m_size_client.X-60-100, 50);
376 gui::IGUIElement *e =
377 Environment->addEditBox(m_data->name.c_str(), rect, true, this, GUI_ID_NAME_INPUT);
378 if(m_data->name == L"")
379 Environment->setFocus(e);
382 core::rect<s32> rect(0, 0, 120, 30);
383 rect += m_topleft_client + v2s32(m_size_client.X-60-100, 90);
384 gui::IGUIEditBox *e =
385 Environment->addEditBox(L"", rect, true, this, 264);
386 e->setPasswordBox(true);
387 if(m_data->name != L"" && m_data->address != L"")
388 Environment->setFocus(e);
394 core::rect<s32> rect(0, 0, 390, 160);
395 rect += m_topleft_client + v2s32(50, 10);
396 gui::IGUIListBox *e = Environment->addListBox(rect, this,
398 e->setDrawBackground(true);
399 if (m_data->serverlist_show_available == false)
400 m_data->servers = ServerList::getLocal();
401 updateGuiServerList();
406 core::rect<s32> rect(0, 0, 110, 20);
407 rect += m_topleft_client + v2s32(50, m_size_client.Y-50-15+6);
408 Environment->addStaticText(wgettext("Address/Port"),
409 rect, false, true, this, -1);
413 core::rect<s32> rect(0, 0, 260, 30);
414 rect += m_topleft_client + v2s32(50, m_size_client.Y-25-15);
415 gui::IGUIElement *e =
416 Environment->addEditBox(m_data->address.c_str(), rect, true,
417 this, GUI_ID_ADDRESS_INPUT);
418 if(m_data->name != L"" && m_data->address == L"")
419 Environment->setFocus(e);
422 core::rect<s32> rect(0, 0, 120, 30);
423 rect += m_topleft_client + v2s32(50+260+10, m_size_client.Y-25-15);
424 Environment->addEditBox(m_data->port.c_str(), rect, true,
425 this, GUI_ID_PORT_INPUT);
429 // Toggle Serverlist (Favorites/Online)
431 core::rect<s32> rect(0, 0, 260, 30);
432 rect += m_topleft_client + v2s32(50,
434 gui::IGUIButton *e = Environment->addButton(rect, this, GUI_ID_SERVERLIST_TOGGLE,
435 wgettext("Show Public"));
436 e->setIsPushButton(true);
437 if (m_data->serverlist_show_available)
439 e->setText(wgettext("Show Favorites"));
444 // Delete Local Favorite
446 core::rect<s32> rect(0, 0, 120, 30);
447 rect += m_topleft_client + v2s32(50+260+10, 180);
448 gui::IGUIButton *e = Environment->addButton(rect, this, GUI_ID_SERVERLIST_DELETE,
450 if (m_data->serverlist_show_available) // Hidden on Show-Online mode
451 e->setVisible(false);
455 core::rect<s32> rect(0, 0, 120, 30);
456 rect += m_topleft_client + v2s32(m_size_client.X-130-30,
457 m_size_client.Y-25-15);
458 Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON,
459 wgettext("Connect"));
463 else if(m_data->selected_tab == TAB_ADVANCED)
468 core::rect<s32> rect(0, 0, 10, m_size_client.Y);
469 rect += m_topleft_client + v2s32(15, 0);
470 const wchar_t *text = L"C\nL\nI\nE\nN\nT";
471 gui::IGUIStaticText *t =
472 Environment->addStaticText(text, rect, false, false, this, -1);
473 t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
475 // Nickname + password
477 core::rect<s32> rect(0, 0, 110, 20);
478 rect += m_topleft_client + v2s32(35+30, 35+6);
479 Environment->addStaticText(wgettext("Name/Password"),
480 rect, false, true, this, -1);
484 core::rect<s32> rect(0, 0, 230, 30);
485 rect += m_topleft_client + v2s32(160+30, 35);
486 gui::IGUIElement *e =
487 Environment->addEditBox(m_data->name.c_str(), rect, true, this, GUI_ID_NAME_INPUT);
488 if(m_data->name == L"")
489 Environment->setFocus(e);
492 core::rect<s32> rect(0, 0, 120, 30);
493 rect += m_topleft_client + v2s32(m_size_client.X-60-100, 35);
494 gui::IGUIEditBox *e =
495 Environment->addEditBox(L"", rect, true, this, 264);
496 e->setPasswordBox(true);
497 if(m_data->name != L"" && m_data->address != L"")
498 Environment->setFocus(e);
504 core::rect<s32> rect(0, 0, 110, 20);
505 rect += m_topleft_client + v2s32(35+30, 75+6);
506 Environment->addStaticText(wgettext("Address/Port"),
507 rect, false, true, this, -1);
511 core::rect<s32> rect(0, 0, 230, 30);
512 rect += m_topleft_client + v2s32(160+30, 75);
513 gui::IGUIElement *e =
514 Environment->addEditBox(m_data->address.c_str(), rect, true,
515 this, GUI_ID_ADDRESS_INPUT);
516 if(m_data->name != L"" && m_data->address == L"")
517 Environment->setFocus(e);
520 core::rect<s32> rect(0, 0, 120, 30);
521 rect += m_topleft_client + v2s32(m_size_client.X-60-100, 75);
522 Environment->addEditBox(m_data->port.c_str(), rect, true,
523 this, GUI_ID_PORT_INPUT);
527 core::rect<s32> rect(0, 0, 400, 20);
528 rect += m_topleft_client + v2s32(160+30, 75+35);
529 Environment->addStaticText(wgettext("Leave address blank to start a local server."),
530 rect, false, true, this, -1);
534 core::rect<s32> rect(0, 0, 180, 30);
535 rect += m_topleft_client + v2s32(m_size_client.X-180-30,
536 m_size_client.Y-30-20);
537 Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON,
538 wgettext("Start Game / Connect"));
545 core::rect<s32> rect(0, 0, 10, m_size_server.Y);
546 rect += m_topleft_server + v2s32(15, 0);
547 const wchar_t *text = L"S\nE\nR\nV\nE\nR";
548 gui::IGUIStaticText *t =
549 Environment->addStaticText(text, rect, false, false, this, -1);
550 t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
554 core::rect<s32> rect(0, 0, 250, 30);
555 rect += m_topleft_server + v2s32(30+20+250+20, 20);
556 Environment->addCheckBox(m_data->creative_mode, rect, this, GUI_ID_CREATIVE_CB,
557 wgettext("Creative Mode"));
560 core::rect<s32> rect(0, 0, 250, 30);
561 rect += m_topleft_server + v2s32(30+20+250+20, 40);
562 Environment->addCheckBox(m_data->enable_damage, rect, this, GUI_ID_DAMAGE_CB,
563 wgettext("Enable Damage"));
565 // Delete world button
567 core::rect<s32> rect(0, 0, 130, 30);
568 rect += m_topleft_server + v2s32(30+20+250+20, 90);
569 Environment->addButton(rect, this, GUI_ID_DELETE_WORLD_BUTTON,
570 wgettext("Delete world"));
572 // Create world button
574 core::rect<s32> rect(0, 0, 130, 30);
575 rect += m_topleft_server + v2s32(30+20+250+20+140, 90);
576 Environment->addButton(rect, this, GUI_ID_CREATE_WORLD_BUTTON,
577 wgettext("Create world"));
579 // World selection listbox
581 core::rect<s32> rect(0, 0, 250, 120);
582 rect += m_topleft_server + v2s32(30+20, 10);
583 gui::IGUIListBox *e = Environment->addListBox(rect, this,
584 GUI_ID_WORLD_LISTBOX);
585 e->setDrawBackground(true);
586 for(std::vector<WorldSpec>::const_iterator i = m_data->worlds.begin();
587 i != m_data->worlds.end(); i++){
588 e->addItem(narrow_to_wide(i->name+" ["+i->gameid+"]").c_str());
590 e->setSelected(m_data->selected_world);
594 else if(m_data->selected_tab == TAB_SETTINGS)
597 core::rect<s32> rect(0, 0, 10, m_size_client.Y);
598 rect += m_topleft_client + v2s32(15, 0);
599 const wchar_t *text = L"S\nE\nT\nT\nI\nN\nG\nS";
600 gui::IGUIStaticText *t =
601 Environment->addStaticText(text, rect, false, false, this, -1);
602 t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
608 core::rect<s32> rect(0, 0, option_w, 30);
609 rect += m_topleft_client + v2s32(option_x, option_y);
610 Environment->addCheckBox(m_data->fancy_trees, rect, this,
611 GUI_ID_FANCYTREE_CB, wgettext("Fancy trees"));
614 core::rect<s32> rect(0, 0, option_w, 30);
615 rect += m_topleft_client + v2s32(option_x, option_y+20);
616 Environment->addCheckBox(m_data->smooth_lighting, rect, this,
617 GUI_ID_SMOOTH_LIGHTING_CB, wgettext("Smooth Lighting"));
620 core::rect<s32> rect(0, 0, option_w, 30);
621 rect += m_topleft_client + v2s32(option_x, option_y+20*2);
622 Environment->addCheckBox(m_data->clouds_3d, rect, this,
623 GUI_ID_3D_CLOUDS_CB, wgettext("3D Clouds"));
626 core::rect<s32> rect(0, 0, option_w, 30);
627 rect += m_topleft_client + v2s32(option_x, option_y+20*3);
628 Environment->addCheckBox(m_data->opaque_water, rect, this,
629 GUI_ID_OPAQUE_WATER_CB, wgettext("Opaque water"));
633 // Anisotropic/mipmap/bi-/trilinear settings
636 core::rect<s32> rect(0, 0, option_w+20, 30);
637 rect += m_topleft_client + v2s32(option_x+175, option_y);
638 Environment->addCheckBox(m_data->mip_map, rect, this,
639 GUI_ID_MIPMAP_CB, wgettext("Mip-Mapping"));
643 core::rect<s32> rect(0, 0, option_w+20, 30);
644 rect += m_topleft_client + v2s32(option_x+175, option_y+20);
645 Environment->addCheckBox(m_data->anisotropic_filter, rect, this,
646 GUI_ID_ANISOTROPIC_CB, wgettext("Anisotropic Filtering"));
650 core::rect<s32> rect(0, 0, option_w+20, 30);
651 rect += m_topleft_client + v2s32(option_x+175, option_y+20*2);
652 Environment->addCheckBox(m_data->bilinear_filter, rect, this,
653 GUI_ID_BILINEAR_CB, wgettext("Bi-Linear Filtering"));
657 core::rect<s32> rect(0, 0, option_w+20, 30);
658 rect += m_topleft_client + v2s32(option_x+175, option_y+20*3);
659 Environment->addCheckBox(m_data->trilinear_filter, rect, this,
660 GUI_ID_TRILINEAR_CB, wgettext("Tri-Linear Filtering"));
663 // shader/on demand image loading/particles settings
665 core::rect<s32> rect(0, 0, option_w+20, 30);
666 rect += m_topleft_client + v2s32(option_x+175*2, option_y);
667 Environment->addCheckBox(m_data->enable_shaders, rect, this,
668 GUI_ID_SHADERS_CB, wgettext("Shaders"));
672 core::rect<s32> rect(0, 0, option_w+20+20, 30);
673 rect += m_topleft_client + v2s32(option_x+175*2, option_y+20);
674 Environment->addCheckBox(m_data->preload_item_visuals, rect, this,
675 GUI_ID_PRELOAD_ITEM_VISUALS_CB, wgettext("Preload item visuals"));
679 core::rect<s32> rect(0, 0, option_w+20+20, 30);
680 rect += m_topleft_client + v2s32(option_x+175*2, option_y+20*2);
681 Environment->addCheckBox(m_data->enable_particles, rect, this,
682 GUI_ID_ENABLE_PARTICLES_CB, wgettext("Enable Particles"));
687 core::rect<s32> rect(0, 0, 120, 30);
688 /*rect += m_topleft_client + v2s32(m_size_client.X-120-30,
689 m_size_client.Y-30-20);*/
690 rect += m_topleft_client + v2s32(option_x, option_y+120);
691 Environment->addButton(rect, this,
692 GUI_ID_CHANGE_KEYS_BUTTON, wgettext("Change keys"));
696 else if(m_data->selected_tab == TAB_CREDITS)
700 core::rect<s32> rect(0, 0, 10, m_size_client.Y);
701 rect += m_topleft_client + v2s32(15, 0);
702 const wchar_t *text = L"C\nR\nE\nD\nI\nT\nS";
703 gui::IGUIStaticText *t =
704 Environment->addStaticText(text, rect, false, false, this, -1);
705 t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
708 core::rect<s32> rect(0, 0, 454, 250);
709 rect += m_topleft_client + v2s32(110, 50+35);
710 Environment->addStaticText(narrow_to_wide(
711 "Minetest " VERSION_STRING "\n"
712 "http://minetest.net/\n"
714 "by Perttu Ahola <celeron55@gmail.com>\n"
715 "and contributors: PilzAdam, Taoki, tango_, kahrl (kaaaaaahrl?), darkrose, matttpt, erlehmann, SpeedProg, JacobF, teddydestodes, marktraceur, Jonathan Neuschäfer, thexyz, VanessaE, sfan5... and tens of more random people."
716 ).c_str(), rect, false, true, this, -1);
720 m_is_regenerating = false;
723 void GUIMainMenu::drawMenu()
725 gui::IGUISkin* skin = Environment->getSkin();
728 video::IVideoDriver* driver = Environment->getVideoDriver();
730 /*video::SColor bgcolor(140,0,0,0);
731 driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);*/
733 video::SColor bgcolor(140,0,0,0);
735 if(getTab() == TAB_SINGLEPLAYER)
738 core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
739 rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
740 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
743 else if(getTab() == TAB_MULTIPLAYER)
746 core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
747 rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
748 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
751 else if(getTab() == TAB_ADVANCED)
754 core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
755 rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
756 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
759 core::rect<s32> rect(0, 0, m_size_server.X, m_size_server.Y);
760 rect += AbsoluteRect.UpperLeftCorner + m_topleft_server;
761 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
764 else if(getTab() == TAB_SETTINGS)
767 core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
768 rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
769 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
772 else if(getTab() == TAB_CREDITS)
775 core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
776 rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
777 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
779 video::ITexture *logotexture =
780 driver->getTexture(getTexturePath("menulogo.png").c_str());
783 v2s32 logosize(logotexture->getOriginalSize().Width,
784 logotexture->getOriginalSize().Height);
786 core::rect<s32> rect(0,0,logosize.X,logosize.Y);
787 rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
788 rect += v2s32(130, 50);
789 driver->draw2DImage(logotexture, rect,
790 core::rect<s32>(core::position2d<s32>(0,0),
791 core::dimension2di(logotexture->getSize())),
796 gui::IGUIElement::draw();
799 void GUIMainMenu::readInput(MainMenuData *dst)
802 gui::IGUIElement *e = getElementFromId(GUI_ID_TAB_CONTROL);
803 if(e != NULL && e->getType() == gui::EGUIET_TAB_CONTROL)
804 dst->selected_tab = ((gui::IGUITabControl*)e)->getActiveTab();
806 if(dst->selected_tab == TAB_SINGLEPLAYER)
808 dst->simple_singleplayer_mode = true;
812 dst->simple_singleplayer_mode = false;
814 gui::IGUIElement *e = getElementFromId(GUI_ID_NAME_INPUT);
816 dst->name = e->getText();
819 gui::IGUIElement *e = getElementFromId(264);
821 dst->password = e->getText();
824 gui::IGUIElement *e = getElementFromId(GUI_ID_ADDRESS_INPUT);
826 dst->address = e->getText();
829 gui::IGUIElement *e = getElementFromId(GUI_ID_PORT_INPUT);
831 dst->port = e->getText();
835 gui::IGUIElement *e = getElementFromId(GUI_ID_CREATIVE_CB);
836 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
837 dst->creative_mode = ((gui::IGUICheckBox*)e)->isChecked();
840 gui::IGUIElement *e = getElementFromId(GUI_ID_DAMAGE_CB);
841 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
842 dst->enable_damage = ((gui::IGUICheckBox*)e)->isChecked();
845 gui::IGUIElement *e = getElementFromId(GUI_ID_FANCYTREE_CB);
846 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
847 dst->fancy_trees = ((gui::IGUICheckBox*)e)->isChecked();
850 gui::IGUIElement *e = getElementFromId(GUI_ID_SMOOTH_LIGHTING_CB);
851 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
852 dst->smooth_lighting = ((gui::IGUICheckBox*)e)->isChecked();
855 gui::IGUIElement *e = getElementFromId(GUI_ID_3D_CLOUDS_CB);
856 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
857 dst->clouds_3d = ((gui::IGUICheckBox*)e)->isChecked();
860 gui::IGUIElement *e = getElementFromId(GUI_ID_OPAQUE_WATER_CB);
861 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
862 dst->opaque_water = ((gui::IGUICheckBox*)e)->isChecked();
866 gui::IGUIElement *e = getElementFromId(GUI_ID_MIPMAP_CB);
867 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
868 dst->mip_map = ((gui::IGUICheckBox*)e)->isChecked();
872 gui::IGUIElement *e = getElementFromId(GUI_ID_ANISOTROPIC_CB);
873 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
874 dst->anisotropic_filter = ((gui::IGUICheckBox*)e)->isChecked();
878 gui::IGUIElement *e = getElementFromId(GUI_ID_BILINEAR_CB);
879 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
880 dst->bilinear_filter = ((gui::IGUICheckBox*)e)->isChecked();
884 gui::IGUIElement *e = getElementFromId(GUI_ID_TRILINEAR_CB);
885 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
886 dst->trilinear_filter = ((gui::IGUICheckBox*)e)->isChecked();
890 gui::IGUIElement *e = getElementFromId(GUI_ID_SHADERS_CB);
891 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
892 dst->enable_shaders = ((gui::IGUICheckBox*)e)->isChecked() ? 2 : 0;
896 gui::IGUIElement *e = getElementFromId(GUI_ID_PRELOAD_ITEM_VISUALS_CB);
897 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
898 dst->preload_item_visuals = ((gui::IGUICheckBox*)e)->isChecked();
902 gui::IGUIElement *e = getElementFromId(GUI_ID_ENABLE_PARTICLES_CB);
903 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
904 dst->enable_particles = ((gui::IGUICheckBox*)e)->isChecked();
908 gui::IGUIElement *e = getElementFromId(GUI_ID_WORLD_LISTBOX);
909 if(e != NULL && e->getType() == gui::EGUIET_LIST_BOX)
910 dst->selected_world = ((gui::IGUIListBox*)e)->getSelected();
913 ServerListSpec server =
914 getServerListSpec(wide_to_narrow(dst->address), wide_to_narrow(dst->port));
915 dst->servername = server.name;
916 dst->serverdescription = server.description;
920 void GUIMainMenu::acceptInput()
926 bool GUIMainMenu::OnEvent(const SEvent& event)
928 if(event.EventType==EET_KEY_INPUT_EVENT)
930 if(event.KeyInput.Key==KEY_ESCAPE && event.KeyInput.PressedDown)
932 m_gamecallback->exitToOS();
936 if(event.KeyInput.Key==KEY_RETURN && event.KeyInput.PressedDown)
943 if(event.EventType==EET_GUI_EVENT)
945 if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST
948 if(!canTakeFocus(event.GUIEvent.Element))
950 dstream<<"GUIMainMenu: Not allowing focus change."
952 // Returning true disables focus change
956 if(event.GUIEvent.EventType==gui::EGET_TAB_CHANGED)
958 if(!m_is_regenerating)
959 regenerateGui(m_screensize_old);
962 if(event.GUIEvent.EventType==gui::EGET_LISTBOX_CHANGED && event.GUIEvent.Caller->getID() == GUI_ID_SERVERLIST)
964 serverListOnSelected();
967 if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED)
969 switch(event.GUIEvent.Caller->getID())
971 case GUI_ID_JOIN_GAME_BUTTON: {
974 if (getTab() == TAB_MULTIPLAYER && cur.address == L"")
976 (new GUIMessageMenu(env, parent, -1, menumgr,
977 wgettext("Address required."))
985 case GUI_ID_CHANGE_KEYS_BUTTON: {
986 GUIKeyChangeMenu *kmenu = new GUIKeyChangeMenu(env, parent, -1,menumgr);
990 case GUI_ID_DELETE_WORLD_BUTTON: {
993 if(cur.selected_world == -1){
994 (new GUIMessageMenu(env, parent, -1, menumgr,
995 wgettext("Cannot delete world: Nothing selected"))
998 WorldSpec spec = m_data->worlds[cur.selected_world];
999 // Get files and directories involved
1000 std::vector<std::string> paths;
1001 paths.push_back(spec.path);
1002 fs::GetRecursiveSubPaths(spec.path, paths);
1003 // Launch confirmation dialog
1004 ConfirmDestDeleteWorld *dest = new
1005 ConfirmDestDeleteWorld(spec, this, paths);
1006 std::wstring text = wgettext("Delete world");
1008 text += narrow_to_wide(spec.name);
1010 text += wgettext("Files to be deleted");
1012 for(u32 i=0; i<paths.size(); i++){
1013 if(i == 3){ text += L"..."; break; }
1014 text += narrow_to_wide(paths[i]) + L"\n";
1016 (new GUIConfirmMenu(env, parent, -1, menumgr, dest,
1017 text.c_str()))->drop();
1021 case GUI_ID_CREATE_WORLD_BUTTON: {
1022 std::vector<SubgameSpec> games = getAvailableGames();
1023 if(games.size() == 0){
1024 GUIMessageMenu *menu = new GUIMessageMenu(env, parent,
1026 wgettext("Cannot create world: No games found"));
1029 CreateWorldDest *dest = new CreateWorldDestMainMenu(this);
1030 GUICreateWorld *menu = new GUICreateWorld(env, parent, -1,
1031 menumgr, dest, games);
1036 case GUI_ID_CONFIGURE_WORLD_BUTTON: {
1039 if(cur.selected_world == -1)
1041 (new GUIMessageMenu(env, parent, -1, menumgr,
1042 wgettext("Cannot configure world: Nothing selected"))
1047 WorldSpec wspec = m_data->worlds[cur.selected_world];
1048 GUIConfigureWorld *menu = new GUIConfigureWorld(env, parent,
1049 -1, menumgr, wspec);
1054 case GUI_ID_SERVERLIST_DELETE: {
1055 gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST);
1056 s32 selected = ((gui::IGUIListBox*)serverlist)->getSelected();
1057 if (selected == -1) return true;
1058 ServerList::deleteEntry(m_data->servers[selected]);
1059 m_data->servers = ServerList::getLocal();
1060 updateGuiServerList();
1063 serverlist->setSelected(selected);
1064 serverListOnSelected();
1068 case GUI_ID_SERVERLIST_TOGGLE: {
1069 gui::IGUIElement *togglebutton = getElementFromId(GUI_ID_SERVERLIST_TOGGLE);
1070 gui::IGUIElement *deletebutton = getElementFromId(GUI_ID_SERVERLIST_DELETE);
1071 gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST);
1072 if (m_data->serverlist_show_available) // switch to favorite list
1074 m_data->servers = ServerList::getLocal();
1075 togglebutton->setText(wgettext("Show Public"));
1076 deletebutton->setVisible(true);
1077 updateGuiServerList();
1078 serverlist->setSelected(0);
1080 else // switch to online list
1082 m_data->servers = ServerList::getOnline();
1083 togglebutton->setText(wgettext("Show Favorites"));
1084 deletebutton->setVisible(false);
1085 updateGuiServerList();
1086 serverlist->setSelected(0);
1088 serverListOnSelected();
1090 m_data->serverlist_show_available = !m_data->serverlist_show_available;
1095 if(event.GUIEvent.EventType==gui::EGET_EDITBOX_ENTER)
1097 switch(event.GUIEvent.Caller->getID())
1099 case GUI_ID_ADDRESS_INPUT: case GUI_ID_PORT_INPUT: case GUI_ID_NAME_INPUT: case 264:
1105 if(event.GUIEvent.EventType==gui::EGET_LISTBOX_SELECTED_AGAIN)
1107 switch(event.GUIEvent.Caller->getID())
1109 case GUI_ID_WORLD_LISTBOX:
1111 if(getTab() != TAB_SINGLEPLAYER)
1112 m_data->address = L""; // Force local game
1115 case GUI_ID_SERVERLIST:
1116 gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST);
1117 if (serverlist->getSelected() > -1)
1127 return Parent ? Parent->OnEvent(event) : false;
1130 void GUIMainMenu::createNewWorld(std::wstring name, std::string gameid)
1135 m_data->create_world_name = name;
1136 m_data->create_world_gameid = gameid;
1140 void GUIMainMenu::deleteWorld(const std::vector<std::string> &paths)
1143 bool did = fs::DeletePaths(paths);
1145 GUIMessageMenu *menu = new GUIMessageMenu(env, parent,
1146 -1, menumgr, wgettext("Failed to delete all world files"));
1149 // Quit menu to refresh it
1151 m_data->only_refresh = true;
1155 int GUIMainMenu::getTab()
1157 gui::IGUIElement *e = getElementFromId(GUI_ID_TAB_CONTROL);
1158 if(e != NULL && e->getType() == gui::EGUIET_TAB_CONTROL)
1159 return ((gui::IGUITabControl*)e)->getActiveTab();
1160 return TAB_SINGLEPLAYER; // Default
1163 void GUIMainMenu::displayMessageMenu(std::wstring msg)
1165 (new GUIMessageMenu(env, parent, -1, menumgr, msg))->drop();
1168 void GUIMainMenu::updateGuiServerList()
1170 gui::IGUIListBox *serverlist = (gui::IGUIListBox *)getElementFromId(GUI_ID_SERVERLIST);
1171 serverlist->clear();
1173 for(std::vector<ServerListSpec>::iterator i = m_data->servers.begin();
1174 i != m_data->servers.end(); i++)
1177 if (i->name != "" && i->description != "")
1178 text = i->name + " (" + i->description + ")";
1179 else if (i->name !="")
1182 text = i->address + ":" + i->port;
1184 serverlist->addItem(narrow_to_wide(text).c_str());
1188 void GUIMainMenu::serverListOnSelected()
1190 if (!m_data->servers.empty())
1192 gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST);
1193 u16 id = serverlist->getSelected();
1195 ((gui::IGUIEditBox*)getElementFromId(GUI_ID_ADDRESS_INPUT))
1196 ->setText(narrow_to_wide(m_data->servers[id].address).c_str());
1197 ((gui::IGUIEditBox*)getElementFromId(GUI_ID_PORT_INPUT))
1198 ->setText(narrow_to_wide(m_data->servers[id].port).c_str());
1202 ServerListSpec GUIMainMenu::getServerListSpec(std::string address, std::string port)
1204 ServerListSpec server;
1205 server.address = address;
1207 for(std::vector<ServerListSpec>::iterator i = m_data->servers.begin();
1208 i != m_data->servers.end(); i++)
1210 if (i->address == address && i->port == port)
1212 server.description = i->description;
1213 server.name = i->name;