3 Copyright (C) 2010-2013 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 #define ARRAYLEN(x) (sizeof(x) / sizeof((x)[0]))
47 const wchar_t *contrib_core_strs[] = {
48 L"Perttu Ahola (celeron55) <celeron55@gmail.com>",
49 L"Ryan Kwolek (kwolekr) <kwolekr@minetest.net>",
50 L"PilzAdam <pilzadam@minetest.net>",
51 L"Ilya Zhuravlev (thexyz) <xyz@minetest.net>",
52 L"Lisa Milne (darkrose) <lisa@ltmnet.com>"
55 const wchar_t *contrib_active_strs[] = {
56 L"RealBadAngel <mk@realbadangel.pl>",
57 L"sfan5 <sfan5@live.de>",
58 L"sapier <sapier@gmx.net>",
59 L"proller <proler@gmail.com>",
60 L"Vanessa Ezekowitz (VanessaE) <vanessaezekowitz@gmail.com>",
61 L"Jurgen Doser (doserj) <jurgen.doser@gmail.com>",
63 L"dannydark <the_skeleton_of_a_child@yahoo.co.uk>",
64 L"Jeija <jeija@mesecons.net>",
65 L"MirceaKitsune <sonichedgehog_hyperblast00@yahoo.com>"
68 const wchar_t *contrib_previous_strs[] = {
69 L"kahrl <kahrl@gmx.net>",
70 L"Giuseppe Bilotta (Oblomov) <giuseppe.bilotta@gmail.com>",
71 L"Jonathan Neuschafer <j.neuschaefer@gmx.net>",
72 L"Nils Dagsson Moskopp (erlehmann) <nils@dieweltistgarnichtso.net>",
73 L"Constantin Wenger (SpeedProg) <constantin.wenger@googlemail.com>",
74 L"matttpt <matttpt@gmail.com>",
75 L"JacobF <queatz@gmail.com>"
79 struct CreateWorldDestMainMenu : public CreateWorldDest
81 CreateWorldDestMainMenu(GUIMainMenu *menu):
84 void accepted(std::wstring name, std::string gameid)
86 std::string name_narrow = wide_to_narrow(name);
87 if(!string_allowed_blacklist(name_narrow, WORLDNAME_BLACKLISTED_CHARS))
89 m_menu->displayMessageMenu(wgettext("Cannot create world: Name contains invalid characters"));
92 std::vector<WorldSpec> worlds = getAvailableWorlds();
93 for(std::vector<WorldSpec>::iterator i = worlds.begin();
94 i != worlds.end(); i++)
96 if((*i).name == name_narrow)
98 m_menu->displayMessageMenu(wgettext("Cannot create world: A world by this name already exists"));
102 m_menu->createNewWorld(name, gameid);
107 struct ConfirmDestDeleteWorld : public ConfirmDest
109 ConfirmDestDeleteWorld(WorldSpec spec, GUIMainMenu *menu,
110 const std::vector<std::string> &paths):
115 void answer(bool answer)
119 m_menu->deleteWorld(m_paths);
123 std::vector<std::string> m_paths;
128 GUI_ID_QUIT_BUTTON = 101,
130 GUI_ID_ADDRESS_INPUT,
133 GUI_ID_SMOOTH_LIGHTING_CB,
135 GUI_ID_OPAQUE_WATER_CB,
137 GUI_ID_ANISOTROPIC_CB,
141 GUI_ID_PRELOAD_ITEM_VISUALS_CB,
142 GUI_ID_ENABLE_PARTICLES_CB,
146 GUI_ID_JOIN_GAME_BUTTON,
147 GUI_ID_CHANGE_KEYS_BUTTON,
148 GUI_ID_DELETE_WORLD_BUTTON,
149 GUI_ID_CREATE_WORLD_BUTTON,
150 GUI_ID_CONFIGURE_WORLD_BUTTON,
151 GUI_ID_WORLD_LISTBOX,
154 GUI_ID_SERVERLIST_TOGGLE,
155 GUI_ID_SERVERLIST_DELETE,
167 GUIMainMenu::GUIMainMenu(gui::IGUIEnvironment* env,
168 gui::IGUIElement* parent, s32 id,
169 IMenuManager *menumgr,
171 IGameCallback *gamecallback
173 GUIModalMenu(env, parent, id, menumgr),
176 m_gamecallback(gamecallback),
177 m_is_regenerating(false)
181 this->parent = parent;
183 this->menumgr = menumgr;
186 GUIMainMenu::~GUIMainMenu()
191 void GUIMainMenu::removeChildren()
193 const core::list<gui::IGUIElement*> &children = getChildren();
194 core::list<gui::IGUIElement*> children_copy;
195 for(core::list<gui::IGUIElement*>::ConstIterator
196 i = children.begin(); i != children.end(); i++)
198 children_copy.push_back(*i);
200 for(core::list<gui::IGUIElement*>::Iterator
201 i = children_copy.begin();
202 i != children_copy.end(); i++)
208 void GUIMainMenu::regenerateGui(v2u32 screensize)
210 m_is_regenerating = true;
212 Read stuff from elements into m_data
222 Calculate new sizes and positions
225 v2s32 size(screensize.X, screensize.Y);
227 core::rect<s32> rect(
228 screensize.X/2 - size.X/2,
229 screensize.Y/2 - size.Y/2,
230 screensize.X/2 + size.X/2,
231 screensize.Y/2 + size.Y/2
235 recalculateAbsolutePosition(false);
237 //v2s32 size = rect.getSize();
247 core::rect<s32> rect(0, 0, size.X, 40);
249 Environment->addStaticText(narrow_to_wide(
250 "Minetest " VERSION_STRING).c_str(),
251 rect, false, true, this, -1);
254 //v2s32 center(size.X/2, size.Y/2);
255 v2s32 c800(size.X/2-400, size.Y/2-270);
257 m_topleft_client = c800 + v2s32(90, 70+50+30);
258 m_size_client = v2s32(620, 270);
260 m_size_server = v2s32(620, 140);
262 if(m_data->selected_tab == TAB_ADVANCED)
264 m_topleft_client = c800 + v2s32(90, 70+50+30);
265 m_size_client = v2s32(620, 200);
267 m_size_server = v2s32(620, 140);
270 m_topleft_server = m_topleft_client + v2s32(0, m_size_client.Y+20);
274 core::rect<s32> rect(0, 0, m_size_client.X, 30);
275 rect += m_topleft_client + v2s32(0, -30);
276 gui::IGUITabControl *e = Environment->addTabControl(
277 rect, this, true, true, GUI_ID_TAB_CONTROL);
278 e->addTab(wgettext("Singleplayer"));
279 e->addTab(wgettext("Multiplayer"));
280 e->addTab(wgettext("Advanced"));
281 e->addTab(wgettext("Settings"));
282 e->addTab(wgettext("Credits"));
283 e->setActiveTab(m_data->selected_tab);
286 if(m_data->selected_tab == TAB_SINGLEPLAYER)
290 core::rect<s32> rect(0, 0, 10, m_size_client.Y);
291 rect += m_topleft_client + v2s32(15, 0);
292 //const wchar_t *text = L"H\nY\nB\nR\nI\nD";
293 const wchar_t *text = L"S\nI\nN\nG\nL\nE\n \nP\nL\nA\nY\nE\nR\n";
294 gui::IGUIStaticText *t =
295 Environment->addStaticText(text, rect, false, true, this, -1);
296 t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
299 // World selection listbox
300 u32 world_sel_h = 160;
301 u32 world_sel_w = 365;
302 //s32 world_sel_x = 50;
303 s32 world_sel_x = m_size_client.X-world_sel_w-30;
304 s32 world_sel_y = 30;
305 u32 world_button_count = 3;
306 u32 world_button_w = (world_sel_w)/world_button_count - bs
307 + bs/(world_button_count-1);
309 core::rect<s32> rect(0, 0, world_sel_w-4, 20);
310 rect += m_topleft_client + v2s32(world_sel_x+4, world_sel_y-20);
311 /*gui::IGUIStaticText *e =*/ Environment->addStaticText(
312 wgettext("Select World:"),
313 rect, false, true, this, -1);
314 /*e->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);*/
317 core::rect<s32> rect(0, 0, world_sel_w, world_sel_h);
318 rect += m_topleft_client + v2s32(world_sel_x, world_sel_y);
319 gui::IGUIListBox *e = Environment->addListBox(rect, this,
320 GUI_ID_WORLD_LISTBOX);
321 e->setDrawBackground(true);
322 for(std::vector<WorldSpec>::const_iterator i = m_data->worlds.begin();
323 i != m_data->worlds.end(); i++){
324 e->addItem(narrow_to_wide(i->name+" ["+i->gameid+"]").c_str());
326 e->setSelected(m_data->selected_world);
327 Environment->setFocus(e);
329 // Delete world button
331 core::rect<s32> rect(0, 0, world_button_w, 30);
332 rect += m_topleft_client + v2s32(world_sel_x, world_sel_y+world_sel_h+0);
333 Environment->addButton(rect, this, GUI_ID_DELETE_WORLD_BUTTON,
336 // Create world button
338 core::rect<s32> rect(0, 0, world_button_w, 30);
339 rect += m_topleft_client + v2s32(world_sel_x+world_button_w+bs, world_sel_y+world_sel_h+0);
340 Environment->addButton(rect, this, GUI_ID_CREATE_WORLD_BUTTON,
343 // Configure world button
345 core::rect<s32> rect(0, 0, world_button_w, 30);
346 rect += m_topleft_client + v2s32(world_sel_x+(world_button_w+bs)*2,
347 world_sel_y+world_sel_h+0);
348 Environment->addButton(rect, this, GUI_ID_CONFIGURE_WORLD_BUTTON,
349 wgettext("Configure"));
353 /*core::rect<s32> rect(0, 0, world_button_w, 30);
354 rect += m_topleft_client + v2s32(world_sel_x+(world_button_w+bs)*3,
355 world_sel_y+world_sel_h+0);*/
357 /*core::rect<s32> rect(0, 0, bw, 30);
358 rect += m_topleft_client + v2s32(m_size_client.X-bw-30,
359 m_size_client.Y-30-15);*/
360 core::rect<s32> rect(0, 0, bw, 30);
361 rect += m_topleft_client + v2s32(world_sel_x+world_sel_w-bw,
362 world_sel_y+world_sel_h+30+bs);
363 Environment->addButton(rect, this,
364 GUI_ID_JOIN_GAME_BUTTON, wgettext("Play"));
368 //s32 option_x = 50+world_sel_w+20;
372 core::rect<s32> rect(0, 0, option_w, 30);
373 rect += m_topleft_client + v2s32(option_x, option_y+20*0);
374 Environment->addCheckBox(m_data->creative_mode, rect, this,
375 GUI_ID_CREATIVE_CB, wgettext("Creative Mode"));
378 core::rect<s32> rect(0, 0, option_w, 30);
379 rect += m_topleft_client + v2s32(option_x, option_y+20*1);
380 Environment->addCheckBox(m_data->enable_damage, rect, this,
381 GUI_ID_DAMAGE_CB, wgettext("Enable Damage"));
385 else if(m_data->selected_tab == TAB_MULTIPLAYER)
390 core::rect<s32> rect(0, 0, 10, m_size_client.Y);
391 rect += m_topleft_client + v2s32(15, 0);
392 const wchar_t *text = L"C\nL\nI\nE\nN\nT";
393 gui::IGUIStaticText *t =
394 Environment->addStaticText(text, rect, false, true, this, -1);
395 t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
397 // Nickname + password
399 core::rect<s32> rect(0, 0, 110, 20);
400 rect += m_topleft_client + v2s32(m_size_client.X-60-100, 10+6);
401 Environment->addStaticText(wgettext("Name/Password"),
402 rect, false, true, this, -1);
406 core::rect<s32> rect(0, 0, 120, 30);
407 rect += m_topleft_client + v2s32(m_size_client.X-60-100, 50);
408 gui::IGUIElement *e =
409 Environment->addEditBox(m_data->name.c_str(), rect, true, this, GUI_ID_NAME_INPUT);
410 if(m_data->name == L"")
411 Environment->setFocus(e);
414 core::rect<s32> rect(0, 0, 120, 30);
415 rect += m_topleft_client + v2s32(m_size_client.X-60-100, 90);
416 gui::IGUIEditBox *e =
417 Environment->addEditBox(L"", rect, true, this, 264);
418 e->setPasswordBox(true);
419 if(m_data->name != L"" && m_data->address != L"")
420 Environment->setFocus(e);
426 core::rect<s32> rect(0, 0, 390, 160);
427 rect += m_topleft_client + v2s32(50, 10);
428 gui::IGUIListBox *e = Environment->addListBox(rect, this,
430 e->setDrawBackground(true);
431 if (m_data->serverlist_show_available == false)
432 m_data->servers = ServerList::getLocal();
433 updateGuiServerList();
438 core::rect<s32> rect(0, 0, 110, 20);
439 rect += m_topleft_client + v2s32(50, m_size_client.Y-50-15+6);
440 Environment->addStaticText(wgettext("Address/Port"),
441 rect, false, true, this, -1);
445 core::rect<s32> rect(0, 0, 260, 30);
446 rect += m_topleft_client + v2s32(50, m_size_client.Y-25-15);
447 gui::IGUIElement *e =
448 Environment->addEditBox(m_data->address.c_str(), rect, true,
449 this, GUI_ID_ADDRESS_INPUT);
450 if(m_data->name != L"" && m_data->address == L"")
451 Environment->setFocus(e);
454 core::rect<s32> rect(0, 0, 120, 30);
455 rect += m_topleft_client + v2s32(50+260+10, m_size_client.Y-25-15);
456 Environment->addEditBox(m_data->port.c_str(), rect, true,
457 this, GUI_ID_PORT_INPUT);
461 // Toggle Serverlist (Favorites/Online)
463 core::rect<s32> rect(0, 0, 260, 30);
464 rect += m_topleft_client + v2s32(50,
466 gui::IGUIButton *e = Environment->addButton(rect, this, GUI_ID_SERVERLIST_TOGGLE,
467 wgettext("Show Public"));
468 e->setIsPushButton(true);
469 if (m_data->serverlist_show_available)
471 e->setText(wgettext("Show Favorites"));
476 // Delete Local Favorite
478 core::rect<s32> rect(0, 0, 120, 30);
479 rect += m_topleft_client + v2s32(50+260+10, 180);
480 gui::IGUIButton *e = Environment->addButton(rect, this, GUI_ID_SERVERLIST_DELETE,
482 if (m_data->serverlist_show_available) // Hidden on Show-Online mode
483 e->setVisible(false);
487 core::rect<s32> rect(0, 0, 120, 30);
488 rect += m_topleft_client + v2s32(m_size_client.X-130-30,
489 m_size_client.Y-25-15);
490 Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON,
491 wgettext("Connect"));
495 else if(m_data->selected_tab == TAB_ADVANCED)
500 core::rect<s32> rect(0, 0, 10, m_size_client.Y);
501 rect += m_topleft_client + v2s32(15, 0);
502 const wchar_t *text = L"C\nL\nI\nE\nN\nT";
503 gui::IGUIStaticText *t =
504 Environment->addStaticText(text, rect, false, true, this, -1);
505 t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
507 // Nickname + password
509 core::rect<s32> rect(0, 0, 110, 20);
510 rect += m_topleft_client + v2s32(35+30, 35+6);
511 Environment->addStaticText(wgettext("Name/Password"),
512 rect, false, true, this, -1);
516 core::rect<s32> rect(0, 0, 230, 30);
517 rect += m_topleft_client + v2s32(160+30, 35);
518 gui::IGUIElement *e =
519 Environment->addEditBox(m_data->name.c_str(), rect, true, this, GUI_ID_NAME_INPUT);
520 if(m_data->name == L"")
521 Environment->setFocus(e);
524 core::rect<s32> rect(0, 0, 120, 30);
525 rect += m_topleft_client + v2s32(m_size_client.X-60-100, 35);
526 gui::IGUIEditBox *e =
527 Environment->addEditBox(L"", rect, true, this, 264);
528 e->setPasswordBox(true);
529 if(m_data->name != L"" && m_data->address != L"")
530 Environment->setFocus(e);
536 core::rect<s32> rect(0, 0, 110, 20);
537 rect += m_topleft_client + v2s32(35+30, 75+6);
538 Environment->addStaticText(wgettext("Address/Port"),
539 rect, false, true, this, -1);
543 core::rect<s32> rect(0, 0, 230, 30);
544 rect += m_topleft_client + v2s32(160+30, 75);
545 gui::IGUIElement *e =
546 Environment->addEditBox(m_data->address.c_str(), rect, true,
547 this, GUI_ID_ADDRESS_INPUT);
548 if(m_data->name != L"" && m_data->address == L"")
549 Environment->setFocus(e);
552 core::rect<s32> rect(0, 0, 120, 30);
553 rect += m_topleft_client + v2s32(m_size_client.X-60-100, 75);
554 Environment->addEditBox(m_data->port.c_str(), rect, true,
555 this, GUI_ID_PORT_INPUT);
559 core::rect<s32> rect(0, 0, 400, 20);
560 rect += m_topleft_client + v2s32(160+30, 75+35);
561 Environment->addStaticText(wgettext("Leave address blank to start a local server."),
562 rect, false, true, this, -1);
566 core::rect<s32> rect(0, 0, 180, 30);
567 rect += m_topleft_client + v2s32(m_size_client.X-180-30,
568 m_size_client.Y-30-20);
569 Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON,
570 wgettext("Start Game / Connect"));
577 core::rect<s32> rect(0, 0, 10, m_size_server.Y);
578 rect += m_topleft_server + v2s32(15, 0);
579 const wchar_t *text = L"S\nE\nR\nV\nE\nR";
580 gui::IGUIStaticText *t =
581 Environment->addStaticText(text, rect, false, true, this, -1);
582 t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
586 core::rect<s32> rect(0, 0, 250, 30);
587 rect += m_topleft_server + v2s32(30+20+250+20, 20);
588 Environment->addCheckBox(m_data->creative_mode, rect, this, GUI_ID_CREATIVE_CB,
589 wgettext("Creative Mode"));
592 core::rect<s32> rect(0, 0, 250, 30);
593 rect += m_topleft_server + v2s32(30+20+250+20, 40);
594 Environment->addCheckBox(m_data->enable_damage, rect, this, GUI_ID_DAMAGE_CB,
595 wgettext("Enable Damage"));
599 core::rect<s32> rect(0, 0, 250, 30);
600 rect += m_topleft_server + v2s32(30+20+250+20, 60);
601 Environment->addCheckBox(m_data->enable_public, rect, this, GUI_ID_PUBLIC_CB,
605 // Delete world button
607 core::rect<s32> rect(0, 0, 130, 30);
608 rect += m_topleft_server + v2s32(30+20+250+20, 90);
609 Environment->addButton(rect, this, GUI_ID_DELETE_WORLD_BUTTON,
610 wgettext("Delete world"));
612 // Create world button
614 core::rect<s32> rect(0, 0, 130, 30);
615 rect += m_topleft_server + v2s32(30+20+250+20+140, 90);
616 Environment->addButton(rect, this, GUI_ID_CREATE_WORLD_BUTTON,
617 wgettext("Create world"));
619 // World selection listbox
621 core::rect<s32> rect(0, 0, 250, 120);
622 rect += m_topleft_server + v2s32(30+20, 10);
623 gui::IGUIListBox *e = Environment->addListBox(rect, this,
624 GUI_ID_WORLD_LISTBOX);
625 e->setDrawBackground(true);
626 for(std::vector<WorldSpec>::const_iterator i = m_data->worlds.begin();
627 i != m_data->worlds.end(); i++){
628 e->addItem(narrow_to_wide(i->name+" ["+i->gameid+"]").c_str());
630 e->setSelected(m_data->selected_world);
634 else if(m_data->selected_tab == TAB_SETTINGS)
637 core::rect<s32> rect(0, 0, 10, m_size_client.Y);
638 rect += m_topleft_client + v2s32(15, 0);
639 const wchar_t *text = L"S\nE\nT\nT\nI\nN\nG\nS";
640 gui::IGUIStaticText *t =
641 Environment->addStaticText(text, rect, false, true, this, -1);
642 t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
648 core::rect<s32> rect(0, 0, option_w, 30);
649 rect += m_topleft_client + v2s32(option_x, option_y);
650 Environment->addCheckBox(m_data->fancy_trees, rect, this,
651 GUI_ID_FANCYTREE_CB, wgettext("Fancy trees"));
654 core::rect<s32> rect(0, 0, option_w, 30);
655 rect += m_topleft_client + v2s32(option_x, option_y+20);
656 Environment->addCheckBox(m_data->smooth_lighting, rect, this,
657 GUI_ID_SMOOTH_LIGHTING_CB, wgettext("Smooth Lighting"));
660 core::rect<s32> rect(0, 0, option_w, 30);
661 rect += m_topleft_client + v2s32(option_x, option_y+20*2);
662 Environment->addCheckBox(m_data->clouds_3d, rect, this,
663 GUI_ID_3D_CLOUDS_CB, wgettext("3D Clouds"));
666 core::rect<s32> rect(0, 0, option_w, 30);
667 rect += m_topleft_client + v2s32(option_x, option_y+20*3);
668 Environment->addCheckBox(m_data->opaque_water, rect, this,
669 GUI_ID_OPAQUE_WATER_CB, wgettext("Opaque water"));
673 // Anisotropic/mipmap/bi-/trilinear settings
676 core::rect<s32> rect(0, 0, option_w+20, 30);
677 rect += m_topleft_client + v2s32(option_x+175, option_y);
678 Environment->addCheckBox(m_data->mip_map, rect, this,
679 GUI_ID_MIPMAP_CB, wgettext("Mip-Mapping"));
683 core::rect<s32> rect(0, 0, option_w+20, 30);
684 rect += m_topleft_client + v2s32(option_x+175, option_y+20);
685 Environment->addCheckBox(m_data->anisotropic_filter, rect, this,
686 GUI_ID_ANISOTROPIC_CB, wgettext("Anisotropic Filtering"));
690 core::rect<s32> rect(0, 0, option_w+20, 30);
691 rect += m_topleft_client + v2s32(option_x+175, option_y+20*2);
692 Environment->addCheckBox(m_data->bilinear_filter, rect, this,
693 GUI_ID_BILINEAR_CB, wgettext("Bi-Linear Filtering"));
697 core::rect<s32> rect(0, 0, option_w+20, 30);
698 rect += m_topleft_client + v2s32(option_x+175, option_y+20*3);
699 Environment->addCheckBox(m_data->trilinear_filter, rect, this,
700 GUI_ID_TRILINEAR_CB, wgettext("Tri-Linear Filtering"));
703 // shader/on demand image loading/particles settings
705 core::rect<s32> rect(0, 0, option_w+20, 30);
706 rect += m_topleft_client + v2s32(option_x+175*2, option_y);
707 Environment->addCheckBox(m_data->enable_shaders, rect, this,
708 GUI_ID_SHADERS_CB, wgettext("Shaders"));
712 core::rect<s32> rect(0, 0, option_w+20+20, 30);
713 rect += m_topleft_client + v2s32(option_x+175*2, option_y+20);
714 Environment->addCheckBox(m_data->preload_item_visuals, rect, this,
715 GUI_ID_PRELOAD_ITEM_VISUALS_CB, wgettext("Preload item visuals"));
719 core::rect<s32> rect(0, 0, option_w+20+20, 30);
720 rect += m_topleft_client + v2s32(option_x+175*2, option_y+20*2);
721 Environment->addCheckBox(m_data->enable_particles, rect, this,
722 GUI_ID_ENABLE_PARTICLES_CB, wgettext("Enable Particles"));
727 core::rect<s32> rect(0, 0, 120, 30);
728 /*rect += m_topleft_client + v2s32(m_size_client.X-120-30,
729 m_size_client.Y-30-20);*/
730 rect += m_topleft_client + v2s32(option_x, option_y+120);
731 Environment->addButton(rect, this,
732 GUI_ID_CHANGE_KEYS_BUTTON, wgettext("Change keys"));
736 else if(m_data->selected_tab == TAB_CREDITS)
740 core::rect<s32> rect(0, 0, 9, m_size_client.Y);
741 rect += m_topleft_client + v2s32(15, 0);
742 const wchar_t *text = L"C\nR\nE\nD\nI\nT\nS";
743 gui::IGUIStaticText *t =
744 Environment->addStaticText(text, rect, false, true, this, -1);
745 t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
748 core::rect<s32> rect(0, 0, 130, 70);
749 rect += m_topleft_client + v2s32(35, 160);
750 Environment->addStaticText(
751 L"Minetest " VERSION_STRING "\nhttp://minetest.net/",
752 rect, false, true, this, -1);
755 video::SColor yellow(255, 255, 255, 0);
756 core::rect<s32> rect(0, 0, 450, 260);
757 rect += m_topleft_client + v2s32(168, 5);
759 irr::gui::IGUIListBox *list = Environment->addListBox(rect, this);
761 list->addItem(L"Core Developers");
762 list->setItemOverrideColor(list->getItemCount() - 1, yellow);
763 for (int i = 0; i != ARRAYLEN(contrib_core_strs); i++)
764 list->addItem(contrib_core_strs[i]);
766 list->addItem(L"Active Contributors");
767 list->setItemOverrideColor(list->getItemCount() - 1, yellow);
768 for (int i = 0; i != ARRAYLEN(contrib_active_strs); i++)
769 list->addItem(contrib_active_strs[i]);
771 list->addItem(L"Previous Contributors");
772 list->setItemOverrideColor(list->getItemCount() - 1, yellow);
773 for (int i = 0; i != ARRAYLEN(contrib_previous_strs); i++)
774 list->addItem(contrib_previous_strs[i]);
779 m_is_regenerating = false;
782 void GUIMainMenu::drawMenu()
784 gui::IGUISkin* skin = Environment->getSkin();
787 video::IVideoDriver* driver = Environment->getVideoDriver();
789 /*video::SColor bgcolor(140,0,0,0);
790 driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);*/
792 video::SColor bgcolor(140,0,0,0);
794 if(getTab() == TAB_SINGLEPLAYER)
797 core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
798 rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
799 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
802 else if(getTab() == TAB_MULTIPLAYER)
805 core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
806 rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
807 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
810 else if(getTab() == TAB_ADVANCED)
813 core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
814 rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
815 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
818 core::rect<s32> rect(0, 0, m_size_server.X, m_size_server.Y);
819 rect += AbsoluteRect.UpperLeftCorner + m_topleft_server;
820 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
823 else if(getTab() == TAB_SETTINGS)
826 core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
827 rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
828 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
831 else if(getTab() == TAB_CREDITS)
834 core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
835 rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
836 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
838 video::ITexture *logotexture =
839 driver->getTexture(getTexturePath("logo.png").c_str());
842 v2s32 logosize(logotexture->getOriginalSize().Width,
843 logotexture->getOriginalSize().Height);
845 core::rect<s32> rect(0,0,logosize.X,logosize.Y);
846 rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
847 rect += v2s32(50, 60);
848 driver->draw2DImage(logotexture, rect,
849 core::rect<s32>(core::position2d<s32>(0,0),
850 core::dimension2di(logotexture->getSize())),
855 gui::IGUIElement::draw();
858 void GUIMainMenu::readInput(MainMenuData *dst)
861 gui::IGUIElement *e = getElementFromId(GUI_ID_TAB_CONTROL);
862 if(e != NULL && e->getType() == gui::EGUIET_TAB_CONTROL)
863 dst->selected_tab = ((gui::IGUITabControl*)e)->getActiveTab();
865 if(dst->selected_tab == TAB_SINGLEPLAYER)
867 dst->simple_singleplayer_mode = true;
871 dst->simple_singleplayer_mode = false;
873 gui::IGUIElement *e = getElementFromId(GUI_ID_NAME_INPUT);
875 dst->name = e->getText();
878 gui::IGUIElement *e = getElementFromId(264);
880 dst->password = e->getText();
883 gui::IGUIElement *e = getElementFromId(GUI_ID_ADDRESS_INPUT);
885 dst->address = e->getText();
888 gui::IGUIElement *e = getElementFromId(GUI_ID_PORT_INPUT);
890 dst->port = e->getText();
894 gui::IGUIElement *e = getElementFromId(GUI_ID_CREATIVE_CB);
895 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
896 dst->creative_mode = ((gui::IGUICheckBox*)e)->isChecked();
899 gui::IGUIElement *e = getElementFromId(GUI_ID_DAMAGE_CB);
900 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
901 dst->enable_damage = ((gui::IGUICheckBox*)e)->isChecked();
904 gui::IGUIElement *e = getElementFromId(GUI_ID_PUBLIC_CB);
905 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
906 dst->enable_public = ((gui::IGUICheckBox*)e)->isChecked();
909 gui::IGUIElement *e = getElementFromId(GUI_ID_FANCYTREE_CB);
910 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
911 dst->fancy_trees = ((gui::IGUICheckBox*)e)->isChecked();
914 gui::IGUIElement *e = getElementFromId(GUI_ID_SMOOTH_LIGHTING_CB);
915 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
916 dst->smooth_lighting = ((gui::IGUICheckBox*)e)->isChecked();
919 gui::IGUIElement *e = getElementFromId(GUI_ID_3D_CLOUDS_CB);
920 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
921 dst->clouds_3d = ((gui::IGUICheckBox*)e)->isChecked();
924 gui::IGUIElement *e = getElementFromId(GUI_ID_OPAQUE_WATER_CB);
925 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
926 dst->opaque_water = ((gui::IGUICheckBox*)e)->isChecked();
930 gui::IGUIElement *e = getElementFromId(GUI_ID_MIPMAP_CB);
931 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
932 dst->mip_map = ((gui::IGUICheckBox*)e)->isChecked();
936 gui::IGUIElement *e = getElementFromId(GUI_ID_ANISOTROPIC_CB);
937 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
938 dst->anisotropic_filter = ((gui::IGUICheckBox*)e)->isChecked();
942 gui::IGUIElement *e = getElementFromId(GUI_ID_BILINEAR_CB);
943 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
944 dst->bilinear_filter = ((gui::IGUICheckBox*)e)->isChecked();
948 gui::IGUIElement *e = getElementFromId(GUI_ID_TRILINEAR_CB);
949 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
950 dst->trilinear_filter = ((gui::IGUICheckBox*)e)->isChecked();
954 gui::IGUIElement *e = getElementFromId(GUI_ID_SHADERS_CB);
955 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
956 dst->enable_shaders = ((gui::IGUICheckBox*)e)->isChecked() ? 2 : 0;
960 gui::IGUIElement *e = getElementFromId(GUI_ID_PRELOAD_ITEM_VISUALS_CB);
961 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
962 dst->preload_item_visuals = ((gui::IGUICheckBox*)e)->isChecked();
966 gui::IGUIElement *e = getElementFromId(GUI_ID_ENABLE_PARTICLES_CB);
967 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
968 dst->enable_particles = ((gui::IGUICheckBox*)e)->isChecked();
972 gui::IGUIElement *e = getElementFromId(GUI_ID_WORLD_LISTBOX);
973 if(e != NULL && e->getType() == gui::EGUIET_LIST_BOX)
974 dst->selected_world = ((gui::IGUIListBox*)e)->getSelected();
977 ServerListSpec server =
978 getServerListSpec(wide_to_narrow(dst->address), wide_to_narrow(dst->port));
979 dst->servername = server["name"].asString();
980 dst->serverdescription = server["description"].asString();
984 void GUIMainMenu::acceptInput()
990 bool GUIMainMenu::OnEvent(const SEvent& event)
992 if(event.EventType==EET_KEY_INPUT_EVENT)
994 if(event.KeyInput.Key==KEY_ESCAPE && event.KeyInput.PressedDown)
996 m_gamecallback->exitToOS();
1000 if(event.KeyInput.Key==KEY_RETURN && event.KeyInput.PressedDown)
1007 if(event.EventType==EET_GUI_EVENT)
1009 if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST
1012 if(!canTakeFocus(event.GUIEvent.Element))
1014 dstream<<"GUIMainMenu: Not allowing focus change."
1016 // Returning true disables focus change
1020 if(event.GUIEvent.EventType==gui::EGET_TAB_CHANGED)
1022 if(!m_is_regenerating)
1023 regenerateGui(m_screensize_old);
1026 if(event.GUIEvent.EventType==gui::EGET_LISTBOX_CHANGED && event.GUIEvent.Caller->getID() == GUI_ID_SERVERLIST)
1028 serverListOnSelected();
1031 if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED)
1033 switch(event.GUIEvent.Caller->getID())
1035 case GUI_ID_JOIN_GAME_BUTTON: {
1038 if (getTab() == TAB_MULTIPLAYER && cur.address == L"")
1040 (new GUIMessageMenu(env, parent, -1, menumgr,
1041 wgettext("Address required."))
1049 case GUI_ID_CHANGE_KEYS_BUTTON: {
1050 GUIKeyChangeMenu *kmenu = new GUIKeyChangeMenu(env, parent, -1,menumgr);
1054 case GUI_ID_DELETE_WORLD_BUTTON: {
1057 if(cur.selected_world == -1){
1058 (new GUIMessageMenu(env, parent, -1, menumgr,
1059 wgettext("Cannot delete world: Nothing selected"))
1062 WorldSpec spec = m_data->worlds[cur.selected_world];
1063 // Get files and directories involved
1064 std::vector<std::string> paths;
1065 paths.push_back(spec.path);
1066 fs::GetRecursiveSubPaths(spec.path, paths);
1067 // Launch confirmation dialog
1068 ConfirmDestDeleteWorld *dest = new
1069 ConfirmDestDeleteWorld(spec, this, paths);
1070 std::wstring text = wgettext("Delete world");
1072 text += narrow_to_wide(spec.name);
1074 text += wgettext("Files to be deleted");
1076 for(u32 i=0; i<paths.size(); i++){
1077 if(i == 3){ text += L"..."; break; }
1078 text += narrow_to_wide(paths[i]) + L"\n";
1080 (new GUIConfirmMenu(env, parent, -1, menumgr, dest,
1081 text.c_str()))->drop();
1085 case GUI_ID_CREATE_WORLD_BUTTON: {
1086 std::vector<SubgameSpec> games = getAvailableGames();
1087 if(games.size() == 0){
1088 GUIMessageMenu *menu = new GUIMessageMenu(env, parent,
1090 wgettext("Cannot create world: No games found"));
1093 CreateWorldDest *dest = new CreateWorldDestMainMenu(this);
1094 GUICreateWorld *menu = new GUICreateWorld(env, parent, -1,
1095 menumgr, dest, games);
1100 case GUI_ID_CONFIGURE_WORLD_BUTTON: {
1103 if(cur.selected_world == -1)
1105 (new GUIMessageMenu(env, parent, -1, menumgr,
1106 wgettext("Cannot configure world: Nothing selected"))
1111 WorldSpec wspec = m_data->worlds[cur.selected_world];
1112 GUIConfigureWorld *menu = new GUIConfigureWorld(env, parent,
1113 -1, menumgr, wspec);
1118 case GUI_ID_SERVERLIST_DELETE: {
1119 gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST);
1120 s32 selected = ((gui::IGUIListBox*)serverlist)->getSelected();
1121 if (selected == -1) return true;
1122 ServerList::deleteEntry(m_data->servers[selected]);
1123 m_data->servers = ServerList::getLocal();
1124 updateGuiServerList();
1127 serverlist->setSelected(selected);
1128 serverListOnSelected();
1132 case GUI_ID_SERVERLIST_TOGGLE: {
1133 gui::IGUIElement *togglebutton = getElementFromId(GUI_ID_SERVERLIST_TOGGLE);
1134 gui::IGUIElement *deletebutton = getElementFromId(GUI_ID_SERVERLIST_DELETE);
1135 gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST);
1136 if (m_data->serverlist_show_available) // switch to favorite list
1138 m_data->servers = ServerList::getLocal();
1139 togglebutton->setText(wgettext("Show Public"));
1140 deletebutton->setVisible(true);
1141 updateGuiServerList();
1142 serverlist->setSelected(0);
1144 else // switch to online list
1146 m_data->servers = ServerList::getOnline();
1147 togglebutton->setText(wgettext("Show Favorites"));
1148 deletebutton->setVisible(false);
1149 updateGuiServerList();
1150 serverlist->setSelected(0);
1152 serverListOnSelected();
1154 m_data->serverlist_show_available = !m_data->serverlist_show_available;
1159 if(event.GUIEvent.EventType==gui::EGET_EDITBOX_ENTER)
1161 switch(event.GUIEvent.Caller->getID())
1163 case GUI_ID_ADDRESS_INPUT: case GUI_ID_PORT_INPUT: case GUI_ID_NAME_INPUT: case 264:
1169 if(event.GUIEvent.EventType==gui::EGET_LISTBOX_SELECTED_AGAIN)
1171 switch(event.GUIEvent.Caller->getID())
1173 case GUI_ID_WORLD_LISTBOX:
1175 if(getTab() != TAB_SINGLEPLAYER)
1176 m_data->address = L""; // Force local game
1179 case GUI_ID_SERVERLIST:
1180 gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST);
1181 if (serverlist->getSelected() > -1)
1191 return Parent ? Parent->OnEvent(event) : false;
1194 void GUIMainMenu::createNewWorld(std::wstring name, std::string gameid)
1199 m_data->create_world_name = name;
1200 m_data->create_world_gameid = gameid;
1204 void GUIMainMenu::deleteWorld(const std::vector<std::string> &paths)
1207 bool did = fs::DeletePaths(paths);
1209 GUIMessageMenu *menu = new GUIMessageMenu(env, parent,
1210 -1, menumgr, wgettext("Failed to delete all world files"));
1213 // Quit menu to refresh it
1215 m_data->only_refresh = true;
1219 int GUIMainMenu::getTab()
1221 gui::IGUIElement *e = getElementFromId(GUI_ID_TAB_CONTROL);
1222 if(e != NULL && e->getType() == gui::EGUIET_TAB_CONTROL)
1223 return ((gui::IGUITabControl*)e)->getActiveTab();
1224 return TAB_SINGLEPLAYER; // Default
1227 void GUIMainMenu::displayMessageMenu(std::wstring msg)
1229 (new GUIMessageMenu(env, parent, -1, menumgr, msg))->drop();
1232 void GUIMainMenu::updateGuiServerList()
1234 gui::IGUIListBox *serverlist = (gui::IGUIListBox *)getElementFromId(GUI_ID_SERVERLIST);
1235 serverlist->clear();
1237 for(std::vector<ServerListSpec>::iterator i = m_data->servers.begin();
1238 i != m_data->servers.end(); i++)
1242 if ((*i)["clients"].asString().size())
1243 text += (*i)["clients"].asString();
1244 if ((*i)["clients_max"].asString().size())
1245 text += "/" + (*i)["clients_max"].asString();
1247 if ((*i)["version"].asString().size())
1248 text += (*i)["version"].asString() + " ";
1249 if ((*i)["password"].asString().size())
1251 if ((*i)["creative"].asString().size())
1253 if ((*i)["damage"].asString().size())
1255 if ((*i)["pvp"].asString().size())
1259 if ((*i)["name"] != "" && (*i)["description"] != "")
1260 text += (*i)["name"].asString() + " (" + (*i)["description"].asString() + ")";
1261 else if ((*i)["name"] !="")
1262 text += (*i)["name"].asString();
1264 text += (*i)["address"].asString() + ":" + (*i)["port"].asString();
1266 serverlist->addItem(narrow_to_wide(text).c_str());
1270 void GUIMainMenu::serverListOnSelected()
1272 if (!m_data->servers.empty())
1274 gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST);
1275 u16 id = serverlist->getSelected();
1276 //if (id < 0) return; // u16>0!
1277 ((gui::IGUIEditBox*)getElementFromId(GUI_ID_ADDRESS_INPUT))
1278 ->setText(narrow_to_wide(m_data->servers[id]["address"].asString()).c_str());
1279 ((gui::IGUIEditBox*)getElementFromId(GUI_ID_PORT_INPUT))
1280 ->setText(narrow_to_wide(m_data->servers[id]["port"].asString()).c_str());
1284 ServerListSpec GUIMainMenu::getServerListSpec(std::string address, std::string port)
1286 ServerListSpec server;
1287 server["address"] = address;
1288 server["port"] = port;
1289 for(std::vector<ServerListSpec>::iterator i = m_data->servers.begin();
1290 i != m_data->servers.end(); i++)
1292 if ((*i)["address"] == address && (*i)["port"] == port)
1294 server["description"] = (*i)["description"];
1295 server["name"] = (*i)["name"];