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 "guiMessageMenu.h"
24 #include "guiConfirmMenu.h"
26 #include "serialization.h"
28 #include <IGUICheckBox.h>
29 #include <IGUIEditBox.h>
30 #include <IGUIButton.h>
31 #include <IGUIStaticText.h>
33 #include <IGUIListBox.h>
34 #include <IGUITabControl.h>
35 #include <IGUIImage.h>
37 #include "guiPauseMenu.h"
39 #include "tile.h" // getTexturePath
41 #include "util/string.h"
44 struct CreateWorldDestMainMenu : public CreateWorldDest
46 CreateWorldDestMainMenu(GUIMainMenu *menu):
49 void accepted(std::wstring name, std::string gameid)
51 std::string name_narrow = wide_to_narrow(name);
52 if(!string_allowed_blacklist(name_narrow, WORLDNAME_BLACKLISTED_CHARS))
54 m_menu->displayMessageMenu(wgettext("Cannot create world: Name contains invalid characters"));
57 std::vector<WorldSpec> worlds = getAvailableWorlds();
58 for(std::vector<WorldSpec>::iterator i = worlds.begin();
59 i != worlds.end(); i++)
61 if((*i).name == name_narrow)
63 m_menu->displayMessageMenu(wgettext("Cannot create world: A world by this name already exists"));
67 m_menu->createNewWorld(name, gameid);
72 struct ConfirmDestDeleteWorld : public ConfirmDest
74 ConfirmDestDeleteWorld(WorldSpec spec, GUIMainMenu *menu,
75 const std::vector<std::string> &paths):
80 void answer(bool answer)
84 m_menu->deleteWorld(m_paths);
88 std::vector<std::string> m_paths;
93 GUI_ID_QUIT_BUTTON = 101,
98 GUI_ID_SMOOTH_LIGHTING_CB,
100 GUI_ID_OPAQUE_WATER_CB,
102 GUI_ID_ANISOTROPIC_CB,
106 GUI_ID_PRELOAD_ITEM_VISUALS_CB,
107 GUI_ID_ENABLE_PARTICLES_CB,
110 GUI_ID_JOIN_GAME_BUTTON,
111 GUI_ID_CHANGE_KEYS_BUTTON,
112 GUI_ID_DELETE_WORLD_BUTTON,
113 GUI_ID_CREATE_WORLD_BUTTON,
114 GUI_ID_CONFIGURE_WORLD_BUTTON,
115 GUI_ID_WORLD_LISTBOX,
118 GUI_ID_SERVERLIST_TOGGLE,
119 GUI_ID_SERVERLIST_DELETE,
131 GUIMainMenu::GUIMainMenu(gui::IGUIEnvironment* env,
132 gui::IGUIElement* parent, s32 id,
133 IMenuManager *menumgr,
135 IGameCallback *gamecallback
137 GUIModalMenu(env, parent, id, menumgr),
140 m_gamecallback(gamecallback),
141 m_is_regenerating(false)
145 this->parent = parent;
147 this->menumgr = menumgr;
150 GUIMainMenu::~GUIMainMenu()
155 void GUIMainMenu::removeChildren()
157 const core::list<gui::IGUIElement*> &children = getChildren();
158 core::list<gui::IGUIElement*> children_copy;
159 for(core::list<gui::IGUIElement*>::ConstIterator
160 i = children.begin(); i != children.end(); i++)
162 children_copy.push_back(*i);
164 for(core::list<gui::IGUIElement*>::Iterator
165 i = children_copy.begin();
166 i != children_copy.end(); i++)
172 void GUIMainMenu::regenerateGui(v2u32 screensize)
174 m_is_regenerating = true;
176 Read stuff from elements into m_data
186 Calculate new sizes and positions
189 v2s32 size(screensize.X, screensize.Y);
191 core::rect<s32> rect(
192 screensize.X/2 - size.X/2,
193 screensize.Y/2 - size.Y/2,
194 screensize.X/2 + size.X/2,
195 screensize.Y/2 + size.Y/2
199 recalculateAbsolutePosition(false);
201 //v2s32 size = rect.getSize();
210 //if(m_data->selected_tab != TAB_CREDITS)
212 core::rect<s32> rect(0, 0, size.X, 40);
214 Environment->addStaticText(narrow_to_wide(
215 "Minetest " VERSION_STRING).c_str(),
216 rect, false, true, this, -1);
219 //v2s32 center(size.X/2, size.Y/2);
220 v2s32 c800(size.X/2-400, size.Y/2-300);
222 m_topleft_client = c800 + v2s32(90, 70+50+30);
223 m_size_client = v2s32(620, 270);
225 m_size_server = v2s32(620, 140);
227 if(m_data->selected_tab == TAB_ADVANCED)
229 m_topleft_client = c800 + v2s32(90, 70+50+30);
230 m_size_client = v2s32(620, 200);
232 m_size_server = v2s32(620, 140);
235 m_topleft_server = m_topleft_client + v2s32(0, m_size_client.Y+20);
240 core::rect<s32> rect(0, 0, m_size_client.X, 30);
241 rect += m_topleft_client + v2s32(0, -30);
242 gui::IGUITabControl *e = Environment->addTabControl(
243 rect, this, true, true, GUI_ID_TAB_CONTROL);
244 e->addTab(wgettext("Singleplayer"));
245 e->addTab(wgettext("Multiplayer"));
246 e->addTab(wgettext("Advanced"));
247 e->addTab(wgettext("Settings"));
248 e->addTab(wgettext("Credits"));
249 e->setActiveTab(m_data->selected_tab);
253 if(m_data->selected_tab == TAB_SINGLEPLAYER)
257 core::rect<s32> rect(0, 0, 10, m_size_client.Y);
258 rect += m_topleft_client + v2s32(15, 0);
259 //const wchar_t *text = L"H\nY\nB\nR\nI\nD";
260 const wchar_t *text = L"T\nA\nP\nE\n\nA\nN\nD\n\nG\nL\nU\nE";
261 gui::IGUIStaticText *t =
262 Environment->addStaticText(text, rect, false, false, this, -1);
263 t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
266 // World selection listbox
267 u32 world_sel_h = 160;
268 u32 world_sel_w = 365;
269 //s32 world_sel_x = 50;
270 s32 world_sel_x = m_size_client.X-world_sel_w-30;
271 s32 world_sel_y = 30;
272 u32 world_button_count = 3;
273 u32 world_button_w = (world_sel_w)/world_button_count - bs
274 + bs/(world_button_count-1);
276 core::rect<s32> rect(0, 0, world_sel_w-4, 20);
277 rect += m_topleft_client + v2s32(world_sel_x+4, world_sel_y-20);
278 /*gui::IGUIStaticText *e =*/ Environment->addStaticText(
279 wgettext("Select World:"),
280 rect, false, true, this, -1);
281 /*e->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);*/
284 core::rect<s32> rect(0, 0, world_sel_w, world_sel_h);
285 rect += m_topleft_client + v2s32(world_sel_x, world_sel_y);
286 gui::IGUIListBox *e = Environment->addListBox(rect, this,
287 GUI_ID_WORLD_LISTBOX);
288 e->setDrawBackground(true);
289 for(std::vector<WorldSpec>::const_iterator i = m_data->worlds.begin();
290 i != m_data->worlds.end(); i++){
291 e->addItem(narrow_to_wide(i->name+" ["+i->gameid+"]").c_str());
293 e->setSelected(m_data->selected_world);
294 Environment->setFocus(e);
296 // Delete world button
298 core::rect<s32> rect(0, 0, world_button_w, 30);
299 rect += m_topleft_client + v2s32(world_sel_x, world_sel_y+world_sel_h+0);
300 Environment->addButton(rect, this, GUI_ID_DELETE_WORLD_BUTTON,
303 // Create world button
305 core::rect<s32> rect(0, 0, world_button_w, 30);
306 rect += m_topleft_client + v2s32(world_sel_x+world_button_w+bs, world_sel_y+world_sel_h+0);
307 Environment->addButton(rect, this, GUI_ID_CREATE_WORLD_BUTTON,
310 // Configure world button
312 core::rect<s32> rect(0, 0, world_button_w, 30);
313 rect += m_topleft_client + v2s32(world_sel_x+(world_button_w+bs)*2,
314 world_sel_y+world_sel_h+0);
315 Environment->addButton(rect, this, GUI_ID_CONFIGURE_WORLD_BUTTON,
316 wgettext("Configure"));
320 /*core::rect<s32> rect(0, 0, world_button_w, 30);
321 rect += m_topleft_client + v2s32(world_sel_x+(world_button_w+bs)*3,
322 world_sel_y+world_sel_h+0);*/
324 /*core::rect<s32> rect(0, 0, bw, 30);
325 rect += m_topleft_client + v2s32(m_size_client.X-bw-30,
326 m_size_client.Y-30-15);*/
327 core::rect<s32> rect(0, 0, bw, 30);
328 rect += m_topleft_client + v2s32(world_sel_x+world_sel_w-bw,
329 world_sel_y+world_sel_h+30+bs);
330 Environment->addButton(rect, this,
331 GUI_ID_JOIN_GAME_BUTTON, wgettext("Play"));
335 //s32 option_x = 50+world_sel_w+20;
339 core::rect<s32> rect(0, 0, option_w, 30);
340 rect += m_topleft_client + v2s32(option_x, option_y+20*0);
341 Environment->addCheckBox(m_data->creative_mode, rect, this,
342 GUI_ID_CREATIVE_CB, wgettext("Creative Mode"));
345 core::rect<s32> rect(0, 0, option_w, 30);
346 rect += m_topleft_client + v2s32(option_x, option_y+20*1);
347 Environment->addCheckBox(m_data->enable_damage, rect, this,
348 GUI_ID_DAMAGE_CB, wgettext("Enable Damage"));
352 else if(m_data->selected_tab == TAB_MULTIPLAYER)
357 core::rect<s32> rect(0, 0, 10, m_size_client.Y);
358 rect += m_topleft_client + v2s32(15, 0);
359 const wchar_t *text = L"C\nL\nI\nE\nN\nT";
360 gui::IGUIStaticText *t =
361 Environment->addStaticText(text, rect, false, false, this, -1);
362 t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
364 // Nickname + password
366 core::rect<s32> rect(0, 0, 110, 20);
367 rect += m_topleft_client + v2s32(m_size_client.X-60-100, 10+6);
368 Environment->addStaticText(wgettext("Name/Password"),
369 rect, false, true, this, -1);
373 core::rect<s32> rect(0, 0, 120, 30);
374 rect += m_topleft_client + v2s32(m_size_client.X-60-100, 50);
375 gui::IGUIElement *e =
376 Environment->addEditBox(m_data->name.c_str(), rect, true, this, GUI_ID_NAME_INPUT);
377 if(m_data->name == L"")
378 Environment->setFocus(e);
381 core::rect<s32> rect(0, 0, 120, 30);
382 rect += m_topleft_client + v2s32(m_size_client.X-60-100, 90);
383 gui::IGUIEditBox *e =
384 Environment->addEditBox(L"", rect, true, this, 264);
385 e->setPasswordBox(true);
386 if(m_data->name != L"" && m_data->address != L"")
387 Environment->setFocus(e);
393 core::rect<s32> rect(0, 0, 390, 160);
394 rect += m_topleft_client + v2s32(50, 10);
395 gui::IGUIListBox *e = Environment->addListBox(rect, this,
397 e->setDrawBackground(true);
398 if (m_data->serverlist_show_available == false)
399 m_data->servers = ServerList::getLocal();
400 updateGuiServerList();
405 core::rect<s32> rect(0, 0, 110, 20);
406 rect += m_topleft_client + v2s32(50, m_size_client.Y-50-15+6);
407 Environment->addStaticText(wgettext("Address/Port"),
408 rect, false, true, this, -1);
412 core::rect<s32> rect(0, 0, 260, 30);
413 rect += m_topleft_client + v2s32(50, m_size_client.Y-25-15);
414 gui::IGUIElement *e =
415 Environment->addEditBox(m_data->address.c_str(), rect, true,
416 this, GUI_ID_ADDRESS_INPUT);
417 if(m_data->name != L"" && m_data->address == L"")
418 Environment->setFocus(e);
421 core::rect<s32> rect(0, 0, 120, 30);
422 rect += m_topleft_client + v2s32(50+260+10, m_size_client.Y-25-15);
423 Environment->addEditBox(m_data->port.c_str(), rect, true,
424 this, GUI_ID_PORT_INPUT);
428 // Toggle Serverlist (Favorites/Online)
430 core::rect<s32> rect(0, 0, 260, 30);
431 rect += m_topleft_client + v2s32(50,
433 gui::IGUIButton *e = Environment->addButton(rect, this, GUI_ID_SERVERLIST_TOGGLE,
434 wgettext("Show Public"));
435 e->setIsPushButton(true);
436 if (m_data->serverlist_show_available)
438 e->setText(wgettext("Show Favorites"));
443 // Delete Local Favorite
445 core::rect<s32> rect(0, 0, 120, 30);
446 rect += m_topleft_client + v2s32(50+260+10, 180);
447 gui::IGUIButton *e = Environment->addButton(rect, this, GUI_ID_SERVERLIST_DELETE,
449 if (m_data->serverlist_show_available) // Hidden on Show-Online mode
450 e->setVisible(false);
454 core::rect<s32> rect(0, 0, 120, 30);
455 rect += m_topleft_client + v2s32(m_size_client.X-130-30,
456 m_size_client.Y-25-15);
457 Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON,
458 wgettext("Connect"));
462 else if(m_data->selected_tab == TAB_ADVANCED)
467 core::rect<s32> rect(0, 0, 10, m_size_client.Y);
468 rect += m_topleft_client + v2s32(15, 0);
469 const wchar_t *text = L"C\nL\nI\nE\nN\nT";
470 gui::IGUIStaticText *t =
471 Environment->addStaticText(text, rect, false, false, this, -1);
472 t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
474 // Nickname + password
476 core::rect<s32> rect(0, 0, 110, 20);
477 rect += m_topleft_client + v2s32(35+30, 35+6);
478 Environment->addStaticText(wgettext("Name/Password"),
479 rect, false, true, this, -1);
483 core::rect<s32> rect(0, 0, 230, 30);
484 rect += m_topleft_client + v2s32(160+30, 35);
485 gui::IGUIElement *e =
486 Environment->addEditBox(m_data->name.c_str(), rect, true, this, GUI_ID_NAME_INPUT);
487 if(m_data->name == L"")
488 Environment->setFocus(e);
491 core::rect<s32> rect(0, 0, 120, 30);
492 rect += m_topleft_client + v2s32(m_size_client.X-60-100, 35);
493 gui::IGUIEditBox *e =
494 Environment->addEditBox(L"", rect, true, this, 264);
495 e->setPasswordBox(true);
496 if(m_data->name != L"" && m_data->address != L"")
497 Environment->setFocus(e);
503 core::rect<s32> rect(0, 0, 110, 20);
504 rect += m_topleft_client + v2s32(35+30, 75+6);
505 Environment->addStaticText(wgettext("Address/Port"),
506 rect, false, true, this, -1);
510 core::rect<s32> rect(0, 0, 230, 30);
511 rect += m_topleft_client + v2s32(160+30, 75);
512 gui::IGUIElement *e =
513 Environment->addEditBox(m_data->address.c_str(), rect, true,
514 this, GUI_ID_ADDRESS_INPUT);
515 if(m_data->name != L"" && m_data->address == L"")
516 Environment->setFocus(e);
519 core::rect<s32> rect(0, 0, 120, 30);
520 rect += m_topleft_client + v2s32(m_size_client.X-60-100, 75);
521 Environment->addEditBox(m_data->port.c_str(), rect, true,
522 this, GUI_ID_PORT_INPUT);
526 core::rect<s32> rect(0, 0, 400, 20);
527 rect += m_topleft_client + v2s32(160+30, 75+35);
528 Environment->addStaticText(wgettext("Leave address blank to start a local server."),
529 rect, false, true, this, -1);
533 core::rect<s32> rect(0, 0, 180, 30);
534 rect += m_topleft_client + v2s32(m_size_client.X-180-30,
535 m_size_client.Y-30-20);
536 Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON,
537 wgettext("Start Game / Connect"));
544 core::rect<s32> rect(0, 0, 10, m_size_server.Y);
545 rect += m_topleft_server + v2s32(15, 0);
546 const wchar_t *text = L"S\nE\nR\nV\nE\nR";
547 gui::IGUIStaticText *t =
548 Environment->addStaticText(text, rect, false, false, this, -1);
549 t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
553 core::rect<s32> rect(0, 0, 250, 30);
554 rect += m_topleft_server + v2s32(30+20+250+20, 20);
555 Environment->addCheckBox(m_data->creative_mode, rect, this, GUI_ID_CREATIVE_CB,
556 wgettext("Creative Mode"));
559 core::rect<s32> rect(0, 0, 250, 30);
560 rect += m_topleft_server + v2s32(30+20+250+20, 40);
561 Environment->addCheckBox(m_data->enable_damage, rect, this, GUI_ID_DAMAGE_CB,
562 wgettext("Enable Damage"));
564 // Delete world button
566 core::rect<s32> rect(0, 0, 130, 30);
567 rect += m_topleft_server + v2s32(30+20+250+20, 90);
568 Environment->addButton(rect, this, GUI_ID_DELETE_WORLD_BUTTON,
569 wgettext("Delete world"));
571 // Create world button
573 core::rect<s32> rect(0, 0, 130, 30);
574 rect += m_topleft_server + v2s32(30+20+250+20+140, 90);
575 Environment->addButton(rect, this, GUI_ID_CREATE_WORLD_BUTTON,
576 wgettext("Create world"));
578 // World selection listbox
580 core::rect<s32> rect(0, 0, 250, 120);
581 rect += m_topleft_server + v2s32(30+20, 10);
582 gui::IGUIListBox *e = Environment->addListBox(rect, this,
583 GUI_ID_WORLD_LISTBOX);
584 e->setDrawBackground(true);
585 for(std::vector<WorldSpec>::const_iterator i = m_data->worlds.begin();
586 i != m_data->worlds.end(); i++){
587 e->addItem(narrow_to_wide(i->name+" ["+i->gameid+"]").c_str());
589 e->setSelected(m_data->selected_world);
593 else if(m_data->selected_tab == TAB_SETTINGS)
596 core::rect<s32> rect(0, 0, 10, m_size_client.Y);
597 rect += m_topleft_client + v2s32(15, 0);
598 const wchar_t *text = L"S\nE\nT\nT\nI\nN\nG\nS";
599 gui::IGUIStaticText *t =
600 Environment->addStaticText(text, rect, false, false, this, -1);
601 t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
607 core::rect<s32> rect(0, 0, option_w, 30);
608 rect += m_topleft_client + v2s32(option_x, option_y);
609 Environment->addCheckBox(m_data->fancy_trees, rect, this,
610 GUI_ID_FANCYTREE_CB, wgettext("Fancy trees"));
613 core::rect<s32> rect(0, 0, option_w, 30);
614 rect += m_topleft_client + v2s32(option_x, option_y+20);
615 Environment->addCheckBox(m_data->smooth_lighting, rect, this,
616 GUI_ID_SMOOTH_LIGHTING_CB, wgettext("Smooth Lighting"));
619 core::rect<s32> rect(0, 0, option_w, 30);
620 rect += m_topleft_client + v2s32(option_x, option_y+20*2);
621 Environment->addCheckBox(m_data->clouds_3d, rect, this,
622 GUI_ID_3D_CLOUDS_CB, wgettext("3D Clouds"));
625 core::rect<s32> rect(0, 0, option_w, 30);
626 rect += m_topleft_client + v2s32(option_x, option_y+20*3);
627 Environment->addCheckBox(m_data->opaque_water, rect, this,
628 GUI_ID_OPAQUE_WATER_CB, wgettext("Opaque water"));
632 // Anisotropic/mipmap/bi-/trilinear settings
635 core::rect<s32> rect(0, 0, option_w+20, 30);
636 rect += m_topleft_client + v2s32(option_x+175, option_y);
637 Environment->addCheckBox(m_data->mip_map, rect, this,
638 GUI_ID_MIPMAP_CB, wgettext("Mip-Mapping"));
642 core::rect<s32> rect(0, 0, option_w+20, 30);
643 rect += m_topleft_client + v2s32(option_x+175, option_y+20);
644 Environment->addCheckBox(m_data->anisotropic_filter, rect, this,
645 GUI_ID_ANISOTROPIC_CB, wgettext("Anisotropic Filtering"));
649 core::rect<s32> rect(0, 0, option_w+20, 30);
650 rect += m_topleft_client + v2s32(option_x+175, option_y+20*2);
651 Environment->addCheckBox(m_data->bilinear_filter, rect, this,
652 GUI_ID_BILINEAR_CB, wgettext("Bi-Linear Filtering"));
656 core::rect<s32> rect(0, 0, option_w+20, 30);
657 rect += m_topleft_client + v2s32(option_x+175, option_y+20*3);
658 Environment->addCheckBox(m_data->trilinear_filter, rect, this,
659 GUI_ID_TRILINEAR_CB, wgettext("Tri-Linear Filtering"));
662 // shader/on demand image loading/particles settings
664 core::rect<s32> rect(0, 0, option_w+20, 30);
665 rect += m_topleft_client + v2s32(option_x+175*2, option_y);
666 Environment->addCheckBox(m_data->enable_shaders, rect, this,
667 GUI_ID_SHADERS_CB, wgettext("Shaders"));
671 core::rect<s32> rect(0, 0, option_w+20+20, 30);
672 rect += m_topleft_client + v2s32(option_x+175*2, option_y+20);
673 Environment->addCheckBox(m_data->preload_item_visuals, rect, this,
674 GUI_ID_PRELOAD_ITEM_VISUALS_CB, wgettext("Preload item visuals"));
678 core::rect<s32> rect(0, 0, option_w+20+20, 30);
679 rect += m_topleft_client + v2s32(option_x+175*2, option_y+20*2);
680 Environment->addCheckBox(m_data->enable_particles, rect, this,
681 GUI_ID_ENABLE_PARTICLES_CB, wgettext("Enable Particles"));
686 core::rect<s32> rect(0, 0, 120, 30);
687 /*rect += m_topleft_client + v2s32(m_size_client.X-120-30,
688 m_size_client.Y-30-20);*/
689 rect += m_topleft_client + v2s32(option_x, option_y+120);
690 Environment->addButton(rect, this,
691 GUI_ID_CHANGE_KEYS_BUTTON, wgettext("Change keys"));
695 else if(m_data->selected_tab == TAB_CREDITS)
699 core::rect<s32> rect(0, 0, 10, m_size_client.Y);
700 rect += m_topleft_client + v2s32(15, 0);
701 const wchar_t *text = L"C\nR\nE\nD\nI\nT\nS";
702 gui::IGUIStaticText *t =
703 Environment->addStaticText(text, rect, false, false, this, -1);
704 t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
707 core::rect<s32> rect(0, 0, 454, 250);
708 rect += m_topleft_client + v2s32(110, 50+35);
709 Environment->addStaticText(narrow_to_wide(
710 "Minetest " VERSION_STRING "\n"
711 "http://minetest.net/\n"
713 "by Perttu Ahola <celeron55@gmail.com>\n"
714 "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."
715 ).c_str(), rect, false, true, this, -1);
719 m_is_regenerating = false;
722 void GUIMainMenu::drawMenu()
724 gui::IGUISkin* skin = Environment->getSkin();
727 video::IVideoDriver* driver = Environment->getVideoDriver();
729 /*video::SColor bgcolor(140,0,0,0);
730 driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);*/
732 video::SColor bgcolor(140,0,0,0);
734 if(getTab() == TAB_SINGLEPLAYER)
737 core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
738 rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
739 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
742 else if(getTab() == TAB_MULTIPLAYER)
745 core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
746 rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
747 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
750 else if(getTab() == TAB_ADVANCED)
753 core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
754 rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
755 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
758 core::rect<s32> rect(0, 0, m_size_server.X, m_size_server.Y);
759 rect += AbsoluteRect.UpperLeftCorner + m_topleft_server;
760 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
763 else if(getTab() == TAB_SETTINGS)
766 core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
767 rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
768 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
771 else if(getTab() == TAB_CREDITS)
774 core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
775 rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
776 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
778 video::ITexture *logotexture =
779 driver->getTexture(getTexturePath("menulogo.png").c_str());
782 v2s32 logosize(logotexture->getOriginalSize().Width,
783 logotexture->getOriginalSize().Height);
785 core::rect<s32> rect(0,0,logosize.X,logosize.Y);
786 rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
787 rect += v2s32(130, 50);
788 driver->draw2DImage(logotexture, rect,
789 core::rect<s32>(core::position2d<s32>(0,0),
790 core::dimension2di(logotexture->getSize())),
795 gui::IGUIElement::draw();
798 void GUIMainMenu::readInput(MainMenuData *dst)
801 gui::IGUIElement *e = getElementFromId(GUI_ID_TAB_CONTROL);
802 if(e != NULL && e->getType() == gui::EGUIET_TAB_CONTROL)
803 dst->selected_tab = ((gui::IGUITabControl*)e)->getActiveTab();
805 if(dst->selected_tab == TAB_SINGLEPLAYER)
807 dst->simple_singleplayer_mode = true;
811 dst->simple_singleplayer_mode = false;
813 gui::IGUIElement *e = getElementFromId(GUI_ID_NAME_INPUT);
815 dst->name = e->getText();
818 gui::IGUIElement *e = getElementFromId(264);
820 dst->password = e->getText();
823 gui::IGUIElement *e = getElementFromId(GUI_ID_ADDRESS_INPUT);
825 dst->address = e->getText();
828 gui::IGUIElement *e = getElementFromId(GUI_ID_PORT_INPUT);
830 dst->port = e->getText();
834 gui::IGUIElement *e = getElementFromId(GUI_ID_CREATIVE_CB);
835 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
836 dst->creative_mode = ((gui::IGUICheckBox*)e)->isChecked();
839 gui::IGUIElement *e = getElementFromId(GUI_ID_DAMAGE_CB);
840 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
841 dst->enable_damage = ((gui::IGUICheckBox*)e)->isChecked();
844 gui::IGUIElement *e = getElementFromId(GUI_ID_FANCYTREE_CB);
845 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
846 dst->fancy_trees = ((gui::IGUICheckBox*)e)->isChecked();
849 gui::IGUIElement *e = getElementFromId(GUI_ID_SMOOTH_LIGHTING_CB);
850 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
851 dst->smooth_lighting = ((gui::IGUICheckBox*)e)->isChecked();
854 gui::IGUIElement *e = getElementFromId(GUI_ID_3D_CLOUDS_CB);
855 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
856 dst->clouds_3d = ((gui::IGUICheckBox*)e)->isChecked();
859 gui::IGUIElement *e = getElementFromId(GUI_ID_OPAQUE_WATER_CB);
860 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
861 dst->opaque_water = ((gui::IGUICheckBox*)e)->isChecked();
865 gui::IGUIElement *e = getElementFromId(GUI_ID_MIPMAP_CB);
866 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
867 dst->mip_map = ((gui::IGUICheckBox*)e)->isChecked();
871 gui::IGUIElement *e = getElementFromId(GUI_ID_ANISOTROPIC_CB);
872 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
873 dst->anisotropic_filter = ((gui::IGUICheckBox*)e)->isChecked();
877 gui::IGUIElement *e = getElementFromId(GUI_ID_BILINEAR_CB);
878 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
879 dst->bilinear_filter = ((gui::IGUICheckBox*)e)->isChecked();
883 gui::IGUIElement *e = getElementFromId(GUI_ID_TRILINEAR_CB);
884 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
885 dst->trilinear_filter = ((gui::IGUICheckBox*)e)->isChecked();
889 gui::IGUIElement *e = getElementFromId(GUI_ID_SHADERS_CB);
890 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
891 dst->enable_shaders = ((gui::IGUICheckBox*)e)->isChecked() ? 2 : 0;
895 gui::IGUIElement *e = getElementFromId(GUI_ID_PRELOAD_ITEM_VISUALS_CB);
896 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
897 dst->preload_item_visuals = ((gui::IGUICheckBox*)e)->isChecked();
901 gui::IGUIElement *e = getElementFromId(GUI_ID_ENABLE_PARTICLES_CB);
902 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
903 dst->enable_particles = ((gui::IGUICheckBox*)e)->isChecked();
907 gui::IGUIElement *e = getElementFromId(GUI_ID_WORLD_LISTBOX);
908 if(e != NULL && e->getType() == gui::EGUIET_LIST_BOX)
909 dst->selected_world = ((gui::IGUIListBox*)e)->getSelected();
912 ServerListSpec server =
913 getServerListSpec(wide_to_narrow(dst->address), wide_to_narrow(dst->port));
914 dst->servername = server.name;
915 dst->serverdescription = server.description;
919 void GUIMainMenu::acceptInput()
925 bool GUIMainMenu::OnEvent(const SEvent& event)
927 if(event.EventType==EET_KEY_INPUT_EVENT)
929 if(event.KeyInput.Key==KEY_ESCAPE && event.KeyInput.PressedDown)
931 m_gamecallback->exitToOS();
935 if(event.KeyInput.Key==KEY_RETURN && event.KeyInput.PressedDown)
942 if(event.EventType==EET_GUI_EVENT)
944 if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST
947 if(!canTakeFocus(event.GUIEvent.Element))
949 dstream<<"GUIMainMenu: Not allowing focus change."
951 // Returning true disables focus change
955 if(event.GUIEvent.EventType==gui::EGET_TAB_CHANGED)
957 if(!m_is_regenerating)
958 regenerateGui(m_screensize_old);
961 if(event.GUIEvent.EventType==gui::EGET_LISTBOX_CHANGED && event.GUIEvent.Caller->getID() == GUI_ID_SERVERLIST)
963 serverListOnSelected();
966 if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED)
968 switch(event.GUIEvent.Caller->getID())
970 case GUI_ID_JOIN_GAME_BUTTON: {
973 if (getTab() == TAB_MULTIPLAYER && cur.address == L"")
975 (new GUIMessageMenu(env, parent, -1, menumgr,
976 wgettext("Address required."))
984 case GUI_ID_CHANGE_KEYS_BUTTON: {
985 GUIKeyChangeMenu *kmenu = new GUIKeyChangeMenu(env, parent, -1,menumgr);
989 case GUI_ID_DELETE_WORLD_BUTTON: {
992 if(cur.selected_world == -1){
993 (new GUIMessageMenu(env, parent, -1, menumgr,
994 wgettext("Cannot delete world: Nothing selected"))
997 WorldSpec spec = m_data->worlds[cur.selected_world];
998 // Get files and directories involved
999 std::vector<std::string> paths;
1000 paths.push_back(spec.path);
1001 fs::GetRecursiveSubPaths(spec.path, paths);
1002 // Launch confirmation dialog
1003 ConfirmDestDeleteWorld *dest = new
1004 ConfirmDestDeleteWorld(spec, this, paths);
1005 std::wstring text = wgettext("Delete world");
1007 text += narrow_to_wide(spec.name);
1009 text += wgettext("Files to be deleted");
1011 for(u32 i=0; i<paths.size(); i++){
1012 if(i == 3){ text += L"..."; break; }
1013 text += narrow_to_wide(paths[i]) + L"\n";
1015 (new GUIConfirmMenu(env, parent, -1, menumgr, dest,
1016 text.c_str()))->drop();
1020 case GUI_ID_CREATE_WORLD_BUTTON: {
1021 std::vector<SubgameSpec> games = getAvailableGames();
1022 if(games.size() == 0){
1023 GUIMessageMenu *menu = new GUIMessageMenu(env, parent,
1025 wgettext("Cannot create world: No games found"));
1028 CreateWorldDest *dest = new CreateWorldDestMainMenu(this);
1029 GUICreateWorld *menu = new GUICreateWorld(env, parent, -1,
1030 menumgr, dest, games);
1035 case GUI_ID_CONFIGURE_WORLD_BUTTON: {
1036 GUIMessageMenu *menu = new GUIMessageMenu(env, parent,
1038 wgettext("Nothing here"));
1042 case GUI_ID_SERVERLIST_DELETE: {
1043 gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST);
1044 u16 selected = ((gui::IGUIListBox*)serverlist)->getSelected();
1045 if (selected == -1) return true;
1046 ServerList::deleteEntry(m_data->servers[selected]);
1047 m_data->servers = ServerList::getLocal();
1048 updateGuiServerList();
1051 serverlist->setSelected(selected);
1052 serverListOnSelected();
1056 case GUI_ID_SERVERLIST_TOGGLE: {
1057 gui::IGUIElement *togglebutton = getElementFromId(GUI_ID_SERVERLIST_TOGGLE);
1058 gui::IGUIElement *deletebutton = getElementFromId(GUI_ID_SERVERLIST_DELETE);
1059 gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST);
1060 if (m_data->serverlist_show_available) // switch to favorite list
1062 m_data->servers = ServerList::getLocal();
1063 togglebutton->setText(wgettext("Show Public"));
1064 deletebutton->setVisible(true);
1065 updateGuiServerList();
1066 serverlist->setSelected(0);
1068 else // switch to online list
1070 m_data->servers = ServerList::getOnline();
1071 togglebutton->setText(wgettext("Show Favorites"));
1072 deletebutton->setVisible(false);
1073 updateGuiServerList();
1074 serverlist->setSelected(0);
1076 serverListOnSelected();
1078 m_data->serverlist_show_available = !m_data->serverlist_show_available;
1083 if(event.GUIEvent.EventType==gui::EGET_EDITBOX_ENTER)
1085 switch(event.GUIEvent.Caller->getID())
1087 case GUI_ID_ADDRESS_INPUT: case GUI_ID_PORT_INPUT: case GUI_ID_NAME_INPUT: case 264:
1093 if(event.GUIEvent.EventType==gui::EGET_LISTBOX_SELECTED_AGAIN)
1095 switch(event.GUIEvent.Caller->getID())
1097 case GUI_ID_WORLD_LISTBOX:
1099 if(getTab() != TAB_SINGLEPLAYER)
1100 m_data->address = L""; // Force local game
1103 case GUI_ID_SERVERLIST:
1104 gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST);
1105 if (serverlist->getSelected() > -1)
1115 return Parent ? Parent->OnEvent(event) : false;
1118 void GUIMainMenu::createNewWorld(std::wstring name, std::string gameid)
1123 m_data->create_world_name = name;
1124 m_data->create_world_gameid = gameid;
1128 void GUIMainMenu::deleteWorld(const std::vector<std::string> &paths)
1131 bool did = fs::DeletePaths(paths);
1133 GUIMessageMenu *menu = new GUIMessageMenu(env, parent,
1134 -1, menumgr, wgettext("Failed to delete all world files"));
1137 // Quit menu to refresh it
1139 m_data->only_refresh = true;
1143 int GUIMainMenu::getTab()
1145 gui::IGUIElement *e = getElementFromId(GUI_ID_TAB_CONTROL);
1146 if(e != NULL && e->getType() == gui::EGUIET_TAB_CONTROL)
1147 return ((gui::IGUITabControl*)e)->getActiveTab();
1148 return TAB_SINGLEPLAYER; // Default
1151 void GUIMainMenu::displayMessageMenu(std::wstring msg)
1153 (new GUIMessageMenu(env, parent, -1, menumgr, msg))->drop();
1156 void GUIMainMenu::updateGuiServerList()
1158 gui::IGUIListBox *serverlist = (gui::IGUIListBox *)getElementFromId(GUI_ID_SERVERLIST);
1159 serverlist->clear();
1161 for(std::vector<ServerListSpec>::iterator i = m_data->servers.begin();
1162 i != m_data->servers.end(); i++)
1165 if (i->name != "" && i->description != "")
1166 text = i->name + " (" + i->description + ")";
1167 else if (i->name !="")
1170 text = i->address + ":" + i->port;
1172 serverlist->addItem(narrow_to_wide(text).c_str());
1176 void GUIMainMenu::serverListOnSelected()
1178 if (!m_data->servers.empty())
1180 gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST);
1181 u16 id = serverlist->getSelected();
1183 ((gui::IGUIEditBox*)getElementFromId(GUI_ID_ADDRESS_INPUT))
1184 ->setText(narrow_to_wide(m_data->servers[id].address).c_str());
1185 ((gui::IGUIEditBox*)getElementFromId(GUI_ID_PORT_INPUT))
1186 ->setText(narrow_to_wide(m_data->servers[id].port).c_str());
1190 ServerListSpec GUIMainMenu::getServerListSpec(std::string address, std::string port)
1192 ServerListSpec server;
1193 server.address = address;
1195 for(std::vector<ServerListSpec>::iterator i = m_data->servers.begin();
1196 i != m_data->servers.end(); i++)
1198 if (i->address == address && i->port == port)
1200 server.description = i->description;
1201 server.name = i->name;