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 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,
112 GUI_ID_JOIN_GAME_BUTTON,
113 GUI_ID_CHANGE_KEYS_BUTTON,
114 GUI_ID_DELETE_WORLD_BUTTON,
115 GUI_ID_CREATE_WORLD_BUTTON,
116 GUI_ID_CONFIGURE_WORLD_BUTTON,
117 GUI_ID_WORLD_LISTBOX,
120 GUI_ID_SERVERLIST_TOGGLE,
121 GUI_ID_SERVERLIST_DELETE,
133 GUIMainMenu::GUIMainMenu(gui::IGUIEnvironment* env,
134 gui::IGUIElement* parent, s32 id,
135 IMenuManager *menumgr,
137 IGameCallback *gamecallback
139 GUIModalMenu(env, parent, id, menumgr),
142 m_gamecallback(gamecallback),
143 m_is_regenerating(false)
147 this->parent = parent;
149 this->menumgr = menumgr;
152 GUIMainMenu::~GUIMainMenu()
157 void GUIMainMenu::removeChildren()
159 const core::list<gui::IGUIElement*> &children = getChildren();
160 core::list<gui::IGUIElement*> children_copy;
161 for(core::list<gui::IGUIElement*>::ConstIterator
162 i = children.begin(); i != children.end(); i++)
164 children_copy.push_back(*i);
166 for(core::list<gui::IGUIElement*>::Iterator
167 i = children_copy.begin();
168 i != children_copy.end(); i++)
174 void GUIMainMenu::regenerateGui(v2u32 screensize)
176 m_is_regenerating = true;
178 Read stuff from elements into m_data
188 Calculate new sizes and positions
191 v2s32 size(screensize.X, screensize.Y);
193 core::rect<s32> rect(
194 screensize.X/2 - size.X/2,
195 screensize.Y/2 - size.Y/2,
196 screensize.X/2 + size.X/2,
197 screensize.Y/2 + size.Y/2
201 recalculateAbsolutePosition(false);
203 //v2s32 size = rect.getSize();
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-270);
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);
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);
252 if(m_data->selected_tab == TAB_SINGLEPLAYER)
256 core::rect<s32> rect(0, 0, 10, m_size_client.Y);
257 rect += m_topleft_client + v2s32(15, 0);
258 //const wchar_t *text = L"H\nY\nB\nR\nI\nD";
259 const wchar_t *text = L"T\nA\nP\nE\n\nA\nN\nD\n\nG\nL\nU\nE";
260 gui::IGUIStaticText *t =
261 Environment->addStaticText(text, rect, false, true, this, -1);
262 t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
265 // World selection listbox
266 u32 world_sel_h = 160;
267 u32 world_sel_w = 365;
268 //s32 world_sel_x = 50;
269 s32 world_sel_x = m_size_client.X-world_sel_w-30;
270 s32 world_sel_y = 30;
271 u32 world_button_count = 3;
272 u32 world_button_w = (world_sel_w)/world_button_count - bs
273 + bs/(world_button_count-1);
275 core::rect<s32> rect(0, 0, world_sel_w-4, 20);
276 rect += m_topleft_client + v2s32(world_sel_x+4, world_sel_y-20);
277 /*gui::IGUIStaticText *e =*/ Environment->addStaticText(
278 wgettext("Select World:"),
279 rect, false, true, this, -1);
280 /*e->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);*/
283 core::rect<s32> rect(0, 0, world_sel_w, world_sel_h);
284 rect += m_topleft_client + v2s32(world_sel_x, world_sel_y);
285 gui::IGUIListBox *e = Environment->addListBox(rect, this,
286 GUI_ID_WORLD_LISTBOX);
287 e->setDrawBackground(true);
288 for(std::vector<WorldSpec>::const_iterator i = m_data->worlds.begin();
289 i != m_data->worlds.end(); i++){
290 e->addItem(narrow_to_wide(i->name+" ["+i->gameid+"]").c_str());
292 e->setSelected(m_data->selected_world);
293 Environment->setFocus(e);
295 // Delete world button
297 core::rect<s32> rect(0, 0, world_button_w, 30);
298 rect += m_topleft_client + v2s32(world_sel_x, world_sel_y+world_sel_h+0);
299 Environment->addButton(rect, this, GUI_ID_DELETE_WORLD_BUTTON,
302 // Create world button
304 core::rect<s32> rect(0, 0, world_button_w, 30);
305 rect += m_topleft_client + v2s32(world_sel_x+world_button_w+bs, world_sel_y+world_sel_h+0);
306 Environment->addButton(rect, this, GUI_ID_CREATE_WORLD_BUTTON,
309 // Configure world button
311 core::rect<s32> rect(0, 0, world_button_w, 30);
312 rect += m_topleft_client + v2s32(world_sel_x+(world_button_w+bs)*2,
313 world_sel_y+world_sel_h+0);
314 Environment->addButton(rect, this, GUI_ID_CONFIGURE_WORLD_BUTTON,
315 wgettext("Configure"));
319 /*core::rect<s32> rect(0, 0, world_button_w, 30);
320 rect += m_topleft_client + v2s32(world_sel_x+(world_button_w+bs)*3,
321 world_sel_y+world_sel_h+0);*/
323 /*core::rect<s32> rect(0, 0, bw, 30);
324 rect += m_topleft_client + v2s32(m_size_client.X-bw-30,
325 m_size_client.Y-30-15);*/
326 core::rect<s32> rect(0, 0, bw, 30);
327 rect += m_topleft_client + v2s32(world_sel_x+world_sel_w-bw,
328 world_sel_y+world_sel_h+30+bs);
329 Environment->addButton(rect, this,
330 GUI_ID_JOIN_GAME_BUTTON, wgettext("Play"));
334 //s32 option_x = 50+world_sel_w+20;
338 core::rect<s32> rect(0, 0, option_w, 30);
339 rect += m_topleft_client + v2s32(option_x, option_y+20*0);
340 Environment->addCheckBox(m_data->creative_mode, rect, this,
341 GUI_ID_CREATIVE_CB, wgettext("Creative Mode"));
344 core::rect<s32> rect(0, 0, option_w, 30);
345 rect += m_topleft_client + v2s32(option_x, option_y+20*1);
346 Environment->addCheckBox(m_data->enable_damage, rect, this,
347 GUI_ID_DAMAGE_CB, wgettext("Enable Damage"));
351 else if(m_data->selected_tab == TAB_MULTIPLAYER)
356 core::rect<s32> rect(0, 0, 10, m_size_client.Y);
357 rect += m_topleft_client + v2s32(15, 0);
358 const wchar_t *text = L"C\nL\nI\nE\nN\nT";
359 gui::IGUIStaticText *t =
360 Environment->addStaticText(text, rect, false, true, this, -1);
361 t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
363 // Nickname + password
365 core::rect<s32> rect(0, 0, 110, 20);
366 rect += m_topleft_client + v2s32(m_size_client.X-60-100, 10+6);
367 Environment->addStaticText(wgettext("Name/Password"),
368 rect, false, true, this, -1);
372 core::rect<s32> rect(0, 0, 120, 30);
373 rect += m_topleft_client + v2s32(m_size_client.X-60-100, 50);
374 gui::IGUIElement *e =
375 Environment->addEditBox(m_data->name.c_str(), rect, true, this, GUI_ID_NAME_INPUT);
376 if(m_data->name == L"")
377 Environment->setFocus(e);
380 core::rect<s32> rect(0, 0, 120, 30);
381 rect += m_topleft_client + v2s32(m_size_client.X-60-100, 90);
382 gui::IGUIEditBox *e =
383 Environment->addEditBox(L"", rect, true, this, 264);
384 e->setPasswordBox(true);
385 if(m_data->name != L"" && m_data->address != L"")
386 Environment->setFocus(e);
392 core::rect<s32> rect(0, 0, 390, 160);
393 rect += m_topleft_client + v2s32(50, 10);
394 gui::IGUIListBox *e = Environment->addListBox(rect, this,
396 e->setDrawBackground(true);
397 if (m_data->serverlist_show_available == false)
398 m_data->servers = ServerList::getLocal();
399 updateGuiServerList();
404 core::rect<s32> rect(0, 0, 110, 20);
405 rect += m_topleft_client + v2s32(50, m_size_client.Y-50-15+6);
406 Environment->addStaticText(wgettext("Address/Port"),
407 rect, false, true, this, -1);
411 core::rect<s32> rect(0, 0, 260, 30);
412 rect += m_topleft_client + v2s32(50, m_size_client.Y-25-15);
413 gui::IGUIElement *e =
414 Environment->addEditBox(m_data->address.c_str(), rect, true,
415 this, GUI_ID_ADDRESS_INPUT);
416 if(m_data->name != L"" && m_data->address == L"")
417 Environment->setFocus(e);
420 core::rect<s32> rect(0, 0, 120, 30);
421 rect += m_topleft_client + v2s32(50+260+10, m_size_client.Y-25-15);
422 Environment->addEditBox(m_data->port.c_str(), rect, true,
423 this, GUI_ID_PORT_INPUT);
427 // Toggle Serverlist (Favorites/Online)
429 core::rect<s32> rect(0, 0, 260, 30);
430 rect += m_topleft_client + v2s32(50,
432 gui::IGUIButton *e = Environment->addButton(rect, this, GUI_ID_SERVERLIST_TOGGLE,
433 wgettext("Show Public"));
434 e->setIsPushButton(true);
435 if (m_data->serverlist_show_available)
437 e->setText(wgettext("Show Favorites"));
442 // Delete Local Favorite
444 core::rect<s32> rect(0, 0, 120, 30);
445 rect += m_topleft_client + v2s32(50+260+10, 180);
446 gui::IGUIButton *e = Environment->addButton(rect, this, GUI_ID_SERVERLIST_DELETE,
448 if (m_data->serverlist_show_available) // Hidden on Show-Online mode
449 e->setVisible(false);
453 core::rect<s32> rect(0, 0, 120, 30);
454 rect += m_topleft_client + v2s32(m_size_client.X-130-30,
455 m_size_client.Y-25-15);
456 Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON,
457 wgettext("Connect"));
461 else if(m_data->selected_tab == TAB_ADVANCED)
466 core::rect<s32> rect(0, 0, 10, m_size_client.Y);
467 rect += m_topleft_client + v2s32(15, 0);
468 const wchar_t *text = L"C\nL\nI\nE\nN\nT";
469 gui::IGUIStaticText *t =
470 Environment->addStaticText(text, rect, false, true, this, -1);
471 t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
473 // Nickname + password
475 core::rect<s32> rect(0, 0, 110, 20);
476 rect += m_topleft_client + v2s32(35+30, 35+6);
477 Environment->addStaticText(wgettext("Name/Password"),
478 rect, false, true, this, -1);
482 core::rect<s32> rect(0, 0, 230, 30);
483 rect += m_topleft_client + v2s32(160+30, 35);
484 gui::IGUIElement *e =
485 Environment->addEditBox(m_data->name.c_str(), rect, true, this, GUI_ID_NAME_INPUT);
486 if(m_data->name == L"")
487 Environment->setFocus(e);
490 core::rect<s32> rect(0, 0, 120, 30);
491 rect += m_topleft_client + v2s32(m_size_client.X-60-100, 35);
492 gui::IGUIEditBox *e =
493 Environment->addEditBox(L"", rect, true, this, 264);
494 e->setPasswordBox(true);
495 if(m_data->name != L"" && m_data->address != L"")
496 Environment->setFocus(e);
502 core::rect<s32> rect(0, 0, 110, 20);
503 rect += m_topleft_client + v2s32(35+30, 75+6);
504 Environment->addStaticText(wgettext("Address/Port"),
505 rect, false, true, this, -1);
509 core::rect<s32> rect(0, 0, 230, 30);
510 rect += m_topleft_client + v2s32(160+30, 75);
511 gui::IGUIElement *e =
512 Environment->addEditBox(m_data->address.c_str(), rect, true,
513 this, GUI_ID_ADDRESS_INPUT);
514 if(m_data->name != L"" && m_data->address == L"")
515 Environment->setFocus(e);
518 core::rect<s32> rect(0, 0, 120, 30);
519 rect += m_topleft_client + v2s32(m_size_client.X-60-100, 75);
520 Environment->addEditBox(m_data->port.c_str(), rect, true,
521 this, GUI_ID_PORT_INPUT);
525 core::rect<s32> rect(0, 0, 400, 20);
526 rect += m_topleft_client + v2s32(160+30, 75+35);
527 Environment->addStaticText(wgettext("Leave address blank to start a local server."),
528 rect, false, true, this, -1);
532 core::rect<s32> rect(0, 0, 180, 30);
533 rect += m_topleft_client + v2s32(m_size_client.X-180-30,
534 m_size_client.Y-30-20);
535 Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON,
536 wgettext("Start Game / Connect"));
543 core::rect<s32> rect(0, 0, 10, m_size_server.Y);
544 rect += m_topleft_server + v2s32(15, 0);
545 const wchar_t *text = L"S\nE\nR\nV\nE\nR";
546 gui::IGUIStaticText *t =
547 Environment->addStaticText(text, rect, false, true, this, -1);
548 t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
552 core::rect<s32> rect(0, 0, 250, 30);
553 rect += m_topleft_server + v2s32(30+20+250+20, 20);
554 Environment->addCheckBox(m_data->creative_mode, rect, this, GUI_ID_CREATIVE_CB,
555 wgettext("Creative Mode"));
558 core::rect<s32> rect(0, 0, 250, 30);
559 rect += m_topleft_server + v2s32(30+20+250+20, 40);
560 Environment->addCheckBox(m_data->enable_damage, rect, this, GUI_ID_DAMAGE_CB,
561 wgettext("Enable Damage"));
565 core::rect<s32> rect(0, 0, 250, 30);
566 rect += m_topleft_server + v2s32(30+20+250+20, 60);
567 Environment->addCheckBox(m_data->enable_public, rect, this, GUI_ID_PUBLIC_CB,
571 // Delete world button
573 core::rect<s32> rect(0, 0, 130, 30);
574 rect += m_topleft_server + v2s32(30+20+250+20, 90);
575 Environment->addButton(rect, this, GUI_ID_DELETE_WORLD_BUTTON,
576 wgettext("Delete world"));
578 // Create world button
580 core::rect<s32> rect(0, 0, 130, 30);
581 rect += m_topleft_server + v2s32(30+20+250+20+140, 90);
582 Environment->addButton(rect, this, GUI_ID_CREATE_WORLD_BUTTON,
583 wgettext("Create world"));
585 // World selection listbox
587 core::rect<s32> rect(0, 0, 250, 120);
588 rect += m_topleft_server + v2s32(30+20, 10);
589 gui::IGUIListBox *e = Environment->addListBox(rect, this,
590 GUI_ID_WORLD_LISTBOX);
591 e->setDrawBackground(true);
592 for(std::vector<WorldSpec>::const_iterator i = m_data->worlds.begin();
593 i != m_data->worlds.end(); i++){
594 e->addItem(narrow_to_wide(i->name+" ["+i->gameid+"]").c_str());
596 e->setSelected(m_data->selected_world);
600 else if(m_data->selected_tab == TAB_SETTINGS)
603 core::rect<s32> rect(0, 0, 10, m_size_client.Y);
604 rect += m_topleft_client + v2s32(15, 0);
605 const wchar_t *text = L"S\nE\nT\nT\nI\nN\nG\nS";
606 gui::IGUIStaticText *t =
607 Environment->addStaticText(text, rect, false, true, this, -1);
608 t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
614 core::rect<s32> rect(0, 0, option_w, 30);
615 rect += m_topleft_client + v2s32(option_x, option_y);
616 Environment->addCheckBox(m_data->fancy_trees, rect, this,
617 GUI_ID_FANCYTREE_CB, wgettext("Fancy trees"));
620 core::rect<s32> rect(0, 0, option_w, 30);
621 rect += m_topleft_client + v2s32(option_x, option_y+20);
622 Environment->addCheckBox(m_data->smooth_lighting, rect, this,
623 GUI_ID_SMOOTH_LIGHTING_CB, wgettext("Smooth Lighting"));
626 core::rect<s32> rect(0, 0, option_w, 30);
627 rect += m_topleft_client + v2s32(option_x, option_y+20*2);
628 Environment->addCheckBox(m_data->clouds_3d, rect, this,
629 GUI_ID_3D_CLOUDS_CB, wgettext("3D Clouds"));
632 core::rect<s32> rect(0, 0, option_w, 30);
633 rect += m_topleft_client + v2s32(option_x, option_y+20*3);
634 Environment->addCheckBox(m_data->opaque_water, rect, this,
635 GUI_ID_OPAQUE_WATER_CB, wgettext("Opaque water"));
639 // Anisotropic/mipmap/bi-/trilinear settings
642 core::rect<s32> rect(0, 0, option_w+20, 30);
643 rect += m_topleft_client + v2s32(option_x+175, option_y);
644 Environment->addCheckBox(m_data->mip_map, rect, this,
645 GUI_ID_MIPMAP_CB, wgettext("Mip-Mapping"));
649 core::rect<s32> rect(0, 0, option_w+20, 30);
650 rect += m_topleft_client + v2s32(option_x+175, option_y+20);
651 Environment->addCheckBox(m_data->anisotropic_filter, rect, this,
652 GUI_ID_ANISOTROPIC_CB, wgettext("Anisotropic Filtering"));
656 core::rect<s32> rect(0, 0, option_w+20, 30);
657 rect += m_topleft_client + v2s32(option_x+175, option_y+20*2);
658 Environment->addCheckBox(m_data->bilinear_filter, rect, this,
659 GUI_ID_BILINEAR_CB, wgettext("Bi-Linear Filtering"));
663 core::rect<s32> rect(0, 0, option_w+20, 30);
664 rect += m_topleft_client + v2s32(option_x+175, option_y+20*3);
665 Environment->addCheckBox(m_data->trilinear_filter, rect, this,
666 GUI_ID_TRILINEAR_CB, wgettext("Tri-Linear Filtering"));
669 // shader/on demand image loading/particles settings
671 core::rect<s32> rect(0, 0, option_w+20, 30);
672 rect += m_topleft_client + v2s32(option_x+175*2, option_y);
673 Environment->addCheckBox(m_data->enable_shaders, rect, this,
674 GUI_ID_SHADERS_CB, wgettext("Shaders"));
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);
680 Environment->addCheckBox(m_data->preload_item_visuals, rect, this,
681 GUI_ID_PRELOAD_ITEM_VISUALS_CB, wgettext("Preload item visuals"));
685 core::rect<s32> rect(0, 0, option_w+20+20, 30);
686 rect += m_topleft_client + v2s32(option_x+175*2, option_y+20*2);
687 Environment->addCheckBox(m_data->enable_particles, rect, this,
688 GUI_ID_ENABLE_PARTICLES_CB, wgettext("Enable Particles"));
693 core::rect<s32> rect(0, 0, 120, 30);
694 /*rect += m_topleft_client + v2s32(m_size_client.X-120-30,
695 m_size_client.Y-30-20);*/
696 rect += m_topleft_client + v2s32(option_x, option_y+120);
697 Environment->addButton(rect, this,
698 GUI_ID_CHANGE_KEYS_BUTTON, wgettext("Change keys"));
702 else if(m_data->selected_tab == TAB_CREDITS)
706 core::rect<s32> rect(0, 0, 10, m_size_client.Y);
707 rect += m_topleft_client + v2s32(15, 0);
708 const wchar_t *text = L"C\nR\nE\nD\nI\nT\nS";
709 gui::IGUIStaticText *t =
710 Environment->addStaticText(text, rect, false, true, this, -1);
711 t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
714 core::rect<s32> rect(0, 0, 454, 250);
715 rect += m_topleft_client + v2s32(110, 50+35);
716 Environment->addStaticText(narrow_to_wide(
717 "Minetest " VERSION_STRING "\n"
718 "http://minetest.net/\n"
720 "by Perttu Ahola <celeron55@gmail.com>\n"
721 "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."
722 ).c_str(), rect, false, true, this, -1);
726 m_is_regenerating = false;
729 void GUIMainMenu::drawMenu()
731 gui::IGUISkin* skin = Environment->getSkin();
734 video::IVideoDriver* driver = Environment->getVideoDriver();
736 /*video::SColor bgcolor(140,0,0,0);
737 driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);*/
739 video::SColor bgcolor(140,0,0,0);
741 if(getTab() == TAB_SINGLEPLAYER)
744 core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
745 rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
746 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
749 else if(getTab() == TAB_MULTIPLAYER)
752 core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
753 rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
754 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
757 else if(getTab() == TAB_ADVANCED)
760 core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
761 rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
762 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
765 core::rect<s32> rect(0, 0, m_size_server.X, m_size_server.Y);
766 rect += AbsoluteRect.UpperLeftCorner + m_topleft_server;
767 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
770 else if(getTab() == TAB_SETTINGS)
773 core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
774 rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
775 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
778 else if(getTab() == TAB_CREDITS)
781 core::rect<s32> rect(0, 0, m_size_client.X, m_size_client.Y);
782 rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
783 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
785 video::ITexture *logotexture =
786 driver->getTexture(getTexturePath("logo.png").c_str());
789 v2s32 logosize(logotexture->getOriginalSize().Width,
790 logotexture->getOriginalSize().Height);
792 core::rect<s32> rect(0,0,logosize.X,logosize.Y);
793 rect += AbsoluteRect.UpperLeftCorner + m_topleft_client;
794 rect += v2s32(500, 30);
795 driver->draw2DImage(logotexture, rect,
796 core::rect<s32>(core::position2d<s32>(0,0),
797 core::dimension2di(logotexture->getSize())),
802 gui::IGUIElement::draw();
805 void GUIMainMenu::readInput(MainMenuData *dst)
808 gui::IGUIElement *e = getElementFromId(GUI_ID_TAB_CONTROL);
809 if(e != NULL && e->getType() == gui::EGUIET_TAB_CONTROL)
810 dst->selected_tab = ((gui::IGUITabControl*)e)->getActiveTab();
812 if(dst->selected_tab == TAB_SINGLEPLAYER)
814 dst->simple_singleplayer_mode = true;
818 dst->simple_singleplayer_mode = false;
820 gui::IGUIElement *e = getElementFromId(GUI_ID_NAME_INPUT);
822 dst->name = e->getText();
825 gui::IGUIElement *e = getElementFromId(264);
827 dst->password = e->getText();
830 gui::IGUIElement *e = getElementFromId(GUI_ID_ADDRESS_INPUT);
832 dst->address = e->getText();
835 gui::IGUIElement *e = getElementFromId(GUI_ID_PORT_INPUT);
837 dst->port = e->getText();
841 gui::IGUIElement *e = getElementFromId(GUI_ID_CREATIVE_CB);
842 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
843 dst->creative_mode = ((gui::IGUICheckBox*)e)->isChecked();
846 gui::IGUIElement *e = getElementFromId(GUI_ID_DAMAGE_CB);
847 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
848 dst->enable_damage = ((gui::IGUICheckBox*)e)->isChecked();
851 gui::IGUIElement *e = getElementFromId(GUI_ID_PUBLIC_CB);
852 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
853 dst->enable_public = ((gui::IGUICheckBox*)e)->isChecked();
856 gui::IGUIElement *e = getElementFromId(GUI_ID_FANCYTREE_CB);
857 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
858 dst->fancy_trees = ((gui::IGUICheckBox*)e)->isChecked();
861 gui::IGUIElement *e = getElementFromId(GUI_ID_SMOOTH_LIGHTING_CB);
862 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
863 dst->smooth_lighting = ((gui::IGUICheckBox*)e)->isChecked();
866 gui::IGUIElement *e = getElementFromId(GUI_ID_3D_CLOUDS_CB);
867 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
868 dst->clouds_3d = ((gui::IGUICheckBox*)e)->isChecked();
871 gui::IGUIElement *e = getElementFromId(GUI_ID_OPAQUE_WATER_CB);
872 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
873 dst->opaque_water = ((gui::IGUICheckBox*)e)->isChecked();
877 gui::IGUIElement *e = getElementFromId(GUI_ID_MIPMAP_CB);
878 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
879 dst->mip_map = ((gui::IGUICheckBox*)e)->isChecked();
883 gui::IGUIElement *e = getElementFromId(GUI_ID_ANISOTROPIC_CB);
884 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
885 dst->anisotropic_filter = ((gui::IGUICheckBox*)e)->isChecked();
889 gui::IGUIElement *e = getElementFromId(GUI_ID_BILINEAR_CB);
890 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
891 dst->bilinear_filter = ((gui::IGUICheckBox*)e)->isChecked();
895 gui::IGUIElement *e = getElementFromId(GUI_ID_TRILINEAR_CB);
896 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
897 dst->trilinear_filter = ((gui::IGUICheckBox*)e)->isChecked();
901 gui::IGUIElement *e = getElementFromId(GUI_ID_SHADERS_CB);
902 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
903 dst->enable_shaders = ((gui::IGUICheckBox*)e)->isChecked() ? 2 : 0;
907 gui::IGUIElement *e = getElementFromId(GUI_ID_PRELOAD_ITEM_VISUALS_CB);
908 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
909 dst->preload_item_visuals = ((gui::IGUICheckBox*)e)->isChecked();
913 gui::IGUIElement *e = getElementFromId(GUI_ID_ENABLE_PARTICLES_CB);
914 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
915 dst->enable_particles = ((gui::IGUICheckBox*)e)->isChecked();
919 gui::IGUIElement *e = getElementFromId(GUI_ID_WORLD_LISTBOX);
920 if(e != NULL && e->getType() == gui::EGUIET_LIST_BOX)
921 dst->selected_world = ((gui::IGUIListBox*)e)->getSelected();
924 ServerListSpec server =
925 getServerListSpec(wide_to_narrow(dst->address), wide_to_narrow(dst->port));
926 dst->servername = server["name"].asString();
927 dst->serverdescription = server["description"].asString();
931 void GUIMainMenu::acceptInput()
937 bool GUIMainMenu::OnEvent(const SEvent& event)
939 if(event.EventType==EET_KEY_INPUT_EVENT)
941 if(event.KeyInput.Key==KEY_ESCAPE && event.KeyInput.PressedDown)
943 m_gamecallback->exitToOS();
947 if(event.KeyInput.Key==KEY_RETURN && event.KeyInput.PressedDown)
954 if(event.EventType==EET_GUI_EVENT)
956 if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST
959 if(!canTakeFocus(event.GUIEvent.Element))
961 dstream<<"GUIMainMenu: Not allowing focus change."
963 // Returning true disables focus change
967 if(event.GUIEvent.EventType==gui::EGET_TAB_CHANGED)
969 if(!m_is_regenerating)
970 regenerateGui(m_screensize_old);
973 if(event.GUIEvent.EventType==gui::EGET_LISTBOX_CHANGED && event.GUIEvent.Caller->getID() == GUI_ID_SERVERLIST)
975 serverListOnSelected();
978 if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED)
980 switch(event.GUIEvent.Caller->getID())
982 case GUI_ID_JOIN_GAME_BUTTON: {
985 if (getTab() == TAB_MULTIPLAYER && cur.address == L"")
987 (new GUIMessageMenu(env, parent, -1, menumgr,
988 wgettext("Address required."))
996 case GUI_ID_CHANGE_KEYS_BUTTON: {
997 GUIKeyChangeMenu *kmenu = new GUIKeyChangeMenu(env, parent, -1,menumgr);
1001 case GUI_ID_DELETE_WORLD_BUTTON: {
1004 if(cur.selected_world == -1){
1005 (new GUIMessageMenu(env, parent, -1, menumgr,
1006 wgettext("Cannot delete world: Nothing selected"))
1009 WorldSpec spec = m_data->worlds[cur.selected_world];
1010 // Get files and directories involved
1011 std::vector<std::string> paths;
1012 paths.push_back(spec.path);
1013 fs::GetRecursiveSubPaths(spec.path, paths);
1014 // Launch confirmation dialog
1015 ConfirmDestDeleteWorld *dest = new
1016 ConfirmDestDeleteWorld(spec, this, paths);
1017 std::wstring text = wgettext("Delete world");
1019 text += narrow_to_wide(spec.name);
1021 text += wgettext("Files to be deleted");
1023 for(u32 i=0; i<paths.size(); i++){
1024 if(i == 3){ text += L"..."; break; }
1025 text += narrow_to_wide(paths[i]) + L"\n";
1027 (new GUIConfirmMenu(env, parent, -1, menumgr, dest,
1028 text.c_str()))->drop();
1032 case GUI_ID_CREATE_WORLD_BUTTON: {
1033 std::vector<SubgameSpec> games = getAvailableGames();
1034 if(games.size() == 0){
1035 GUIMessageMenu *menu = new GUIMessageMenu(env, parent,
1037 wgettext("Cannot create world: No games found"));
1040 CreateWorldDest *dest = new CreateWorldDestMainMenu(this);
1041 GUICreateWorld *menu = new GUICreateWorld(env, parent, -1,
1042 menumgr, dest, games);
1047 case GUI_ID_CONFIGURE_WORLD_BUTTON: {
1050 if(cur.selected_world == -1)
1052 (new GUIMessageMenu(env, parent, -1, menumgr,
1053 wgettext("Cannot configure world: Nothing selected"))
1058 WorldSpec wspec = m_data->worlds[cur.selected_world];
1059 GUIConfigureWorld *menu = new GUIConfigureWorld(env, parent,
1060 -1, menumgr, wspec);
1065 case GUI_ID_SERVERLIST_DELETE: {
1066 gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST);
1067 s32 selected = ((gui::IGUIListBox*)serverlist)->getSelected();
1068 if (selected == -1) return true;
1069 ServerList::deleteEntry(m_data->servers[selected]);
1070 m_data->servers = ServerList::getLocal();
1071 updateGuiServerList();
1074 serverlist->setSelected(selected);
1075 serverListOnSelected();
1079 case GUI_ID_SERVERLIST_TOGGLE: {
1080 gui::IGUIElement *togglebutton = getElementFromId(GUI_ID_SERVERLIST_TOGGLE);
1081 gui::IGUIElement *deletebutton = getElementFromId(GUI_ID_SERVERLIST_DELETE);
1082 gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST);
1083 if (m_data->serverlist_show_available) // switch to favorite list
1085 m_data->servers = ServerList::getLocal();
1086 togglebutton->setText(wgettext("Show Public"));
1087 deletebutton->setVisible(true);
1088 updateGuiServerList();
1089 serverlist->setSelected(0);
1091 else // switch to online list
1093 m_data->servers = ServerList::getOnline();
1094 togglebutton->setText(wgettext("Show Favorites"));
1095 deletebutton->setVisible(false);
1096 updateGuiServerList();
1097 serverlist->setSelected(0);
1099 serverListOnSelected();
1101 m_data->serverlist_show_available = !m_data->serverlist_show_available;
1106 if(event.GUIEvent.EventType==gui::EGET_EDITBOX_ENTER)
1108 switch(event.GUIEvent.Caller->getID())
1110 case GUI_ID_ADDRESS_INPUT: case GUI_ID_PORT_INPUT: case GUI_ID_NAME_INPUT: case 264:
1116 if(event.GUIEvent.EventType==gui::EGET_LISTBOX_SELECTED_AGAIN)
1118 switch(event.GUIEvent.Caller->getID())
1120 case GUI_ID_WORLD_LISTBOX:
1122 if(getTab() != TAB_SINGLEPLAYER)
1123 m_data->address = L""; // Force local game
1126 case GUI_ID_SERVERLIST:
1127 gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST);
1128 if (serverlist->getSelected() > -1)
1138 return Parent ? Parent->OnEvent(event) : false;
1141 void GUIMainMenu::createNewWorld(std::wstring name, std::string gameid)
1146 m_data->create_world_name = name;
1147 m_data->create_world_gameid = gameid;
1151 void GUIMainMenu::deleteWorld(const std::vector<std::string> &paths)
1154 bool did = fs::DeletePaths(paths);
1156 GUIMessageMenu *menu = new GUIMessageMenu(env, parent,
1157 -1, menumgr, wgettext("Failed to delete all world files"));
1160 // Quit menu to refresh it
1162 m_data->only_refresh = true;
1166 int GUIMainMenu::getTab()
1168 gui::IGUIElement *e = getElementFromId(GUI_ID_TAB_CONTROL);
1169 if(e != NULL && e->getType() == gui::EGUIET_TAB_CONTROL)
1170 return ((gui::IGUITabControl*)e)->getActiveTab();
1171 return TAB_SINGLEPLAYER; // Default
1174 void GUIMainMenu::displayMessageMenu(std::wstring msg)
1176 (new GUIMessageMenu(env, parent, -1, menumgr, msg))->drop();
1179 void GUIMainMenu::updateGuiServerList()
1181 gui::IGUIListBox *serverlist = (gui::IGUIListBox *)getElementFromId(GUI_ID_SERVERLIST);
1182 serverlist->clear();
1184 for(std::vector<ServerListSpec>::iterator i = m_data->servers.begin();
1185 i != m_data->servers.end(); i++)
1189 if ((*i)["clients"].asString().size())
1190 text += (*i)["clients"].asString();
1191 if ((*i)["clients_max"].asString().size())
1192 text += "/" + (*i)["clients_max"].asString();
1194 if ((*i)["version"].asString().size())
1195 text += (*i)["version"].asString() + " ";
1196 if ((*i)["password"].asString().size())
1198 if ((*i)["creative"].asString().size())
1200 if ((*i)["damage"].asString().size())
1202 if ((*i)["pvp"].asString().size())
1206 if ((*i)["name"] != "" && (*i)["description"] != "")
1207 text += (*i)["name"].asString() + " (" + (*i)["description"].asString() + ")";
1208 else if ((*i)["name"] !="")
1209 text += (*i)["name"].asString();
1211 text += (*i)["address"].asString() + ":" + (*i)["port"].asString();
1213 serverlist->addItem(narrow_to_wide(text).c_str());
1217 void GUIMainMenu::serverListOnSelected()
1219 if (!m_data->servers.empty())
1221 gui::IGUIListBox *serverlist = (gui::IGUIListBox*)getElementFromId(GUI_ID_SERVERLIST);
1222 u16 id = serverlist->getSelected();
1223 //if (id < 0) return; // u16>0!
1224 ((gui::IGUIEditBox*)getElementFromId(GUI_ID_ADDRESS_INPUT))
1225 ->setText(narrow_to_wide(m_data->servers[id]["address"].asString()).c_str());
1226 ((gui::IGUIEditBox*)getElementFromId(GUI_ID_PORT_INPUT))
1227 ->setText(narrow_to_wide(m_data->servers[id]["port"].asString()).c_str());
1231 ServerListSpec GUIMainMenu::getServerListSpec(std::string address, std::string port)
1233 ServerListSpec server;
1234 server["address"] = address;
1235 server["port"] = port;
1236 for(std::vector<ServerListSpec>::iterator i = m_data->servers.begin();
1237 i != m_data->servers.end(); i++)
1239 if ((*i)["address"] == address && (*i)["port"] == port)
1241 server["description"] = (*i)["description"];
1242 server["name"] = (*i)["name"];