3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4 Copyright (C) 2013 Ciaran Gultnieks <ciaran@ciarang.com>
5 Copyright (C) 2013 teddydestodes <derkomtur@schattengang.net>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "guiKeyChangeMenu.h"
24 #include "serialization.h"
26 #include <IGUICheckBox.h>
27 #include <IGUIEditBox.h>
28 #include <IGUIButton.h>
29 #include <IGUIStaticText.h>
34 #include "mainmenumanager.h" // for g_gamecallback
36 #define KMaxButtonPerColumns 12
38 extern MainGameCallback *g_gamecallback;
42 GUI_ID_BACK_BUTTON = 101, GUI_ID_ABORT_BUTTON, GUI_ID_SCROLL_BAR,
44 GUI_ID_KEY_FORWARD_BUTTON,
45 GUI_ID_KEY_BACKWARD_BUTTON,
46 GUI_ID_KEY_LEFT_BUTTON,
47 GUI_ID_KEY_RIGHT_BUTTON,
48 GUI_ID_KEY_USE_BUTTON,
49 GUI_ID_KEY_FLY_BUTTON,
50 GUI_ID_KEY_FAST_BUTTON,
51 GUI_ID_KEY_JUMP_BUTTON,
52 GUI_ID_KEY_NOCLIP_BUTTON,
53 GUI_ID_KEY_CINEMATIC_BUTTON,
54 GUI_ID_KEY_CHAT_BUTTON,
55 GUI_ID_KEY_CMD_BUTTON,
56 GUI_ID_KEY_CMD_LOCAL_BUTTON,
57 GUI_ID_KEY_CONSOLE_BUTTON,
58 GUI_ID_KEY_SNEAK_BUTTON,
59 GUI_ID_KEY_DROP_BUTTON,
60 GUI_ID_KEY_INVENTORY_BUTTON,
61 GUI_ID_KEY_HOTBAR_PREV_BUTTON,
62 GUI_ID_KEY_HOTBAR_NEXT_BUTTON,
63 GUI_ID_KEY_MUTE_BUTTON,
64 GUI_ID_KEY_DEC_VOLUME_BUTTON,
65 GUI_ID_KEY_INC_VOLUME_BUTTON,
66 GUI_ID_KEY_DUMP_BUTTON,
67 GUI_ID_KEY_RANGE_BUTTON,
68 GUI_ID_KEY_ZOOM_BUTTON,
69 GUI_ID_KEY_CAMERA_BUTTON,
70 GUI_ID_KEY_MINIMAP_BUTTON,
71 GUI_ID_KEY_SCREENSHOT_BUTTON,
72 GUI_ID_KEY_CHATLOG_BUTTON,
73 GUI_ID_KEY_HUD_BUTTON,
74 GUI_ID_KEY_FOG_BUTTON,
75 GUI_ID_KEY_DEC_RANGE_BUTTON,
76 GUI_ID_KEY_INC_RANGE_BUTTON,
77 GUI_ID_KEY_AUTOFWD_BUTTON,
79 GUI_ID_CB_AUX1_DESCENDS,
80 GUI_ID_CB_DOUBLETAP_JUMP,
83 GUIKeyChangeMenu::GUIKeyChangeMenu(gui::IGUIEnvironment* env,
84 gui::IGUIElement* parent, s32 id, IMenuManager *menumgr) :
85 GUIModalMenu(env, parent, id, menumgr)
88 for (size_t i = 0; i < key_settings.size(); i++)
89 key_used.push_back(key_settings.at(i)->key);
92 GUIKeyChangeMenu::~GUIKeyChangeMenu()
96 for (std::vector<key_setting*>::iterator iter = key_settings.begin();
97 iter != key_settings.end(); ++iter) {
98 delete[] (*iter)->button_name;
101 key_settings.clear();
104 void GUIKeyChangeMenu::removeChildren()
106 const core::list<gui::IGUIElement*> &children = getChildren();
107 core::list<gui::IGUIElement*> children_copy;
108 for (core::list<gui::IGUIElement*>::ConstIterator i = children.begin(); i
109 != children.end(); i++)
111 children_copy.push_back(*i);
113 for (core::list<gui::IGUIElement*>::Iterator i = children_copy.begin(); i
114 != children_copy.end(); i++)
120 void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
123 v2s32 size(745, 430);
125 core::rect < s32 > rect(screensize.X / 2 - size.X / 2,
126 screensize.Y / 2 - size.Y / 2, screensize.X / 2 + size.X / 2,
127 screensize.Y / 2 + size.Y / 2);
130 recalculateAbsolutePosition(false);
135 core::rect < s32 > rect(0, 0, 600, 40);
136 rect += topleft + v2s32(25, 3);
137 //gui::IGUIStaticText *t =
138 const wchar_t *text = wgettext("Keybindings. (If this menu screws up, remove stuff from minetest.conf)");
139 Environment->addStaticText(text,
140 rect, false, true, this, -1);
142 //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
147 v2s32 offset(25, 60);
149 for(size_t i = 0; i < key_settings.size(); i++)
151 key_setting *k = key_settings.at(i);
153 core::rect < s32 > rect(0, 0, 150, 20);
154 rect += topleft + v2s32(offset.X, offset.Y);
155 Environment->addStaticText(k->button_name, rect, false, true, this, -1);
159 core::rect < s32 > rect(0, 0, 100, 30);
160 rect += topleft + v2s32(offset.X + 120, offset.Y - 5);
161 const wchar_t *text = wgettext(k->key.name());
162 k->button = Environment->addButton(rect, this, k->id, text);
165 if ((i + 1) % KMaxButtonPerColumns == 0) {
169 offset += v2s32(0, 25);
174 s32 option_x = offset.X;
175 s32 option_y = offset.Y + 5;
178 core::rect<s32> rect(0, 0, option_w, 30);
179 rect += topleft + v2s32(option_x, option_y);
180 const wchar_t *text = wgettext("\"Special\" = climb down");
181 Environment->addCheckBox(g_settings->getBool("aux1_descends"), rect, this,
182 GUI_ID_CB_AUX1_DESCENDS, text);
185 offset += v2s32(0, 25);
189 s32 option_x = offset.X;
190 s32 option_y = offset.Y + 5;
193 core::rect<s32> rect(0, 0, option_w, 30);
194 rect += topleft + v2s32(option_x, option_y);
195 const wchar_t *text = wgettext("Double tap \"jump\" to toggle fly");
196 Environment->addCheckBox(g_settings->getBool("doubletap_jump"), rect, this,
197 GUI_ID_CB_DOUBLETAP_JUMP, text);
200 offset += v2s32(0, 25);
204 core::rect < s32 > rect(0, 0, 100, 30);
205 rect += topleft + v2s32(size.X / 2 - 105, size.Y - 40);
206 const wchar_t *text = wgettext("Save");
207 Environment->addButton(rect, this, GUI_ID_BACK_BUTTON,
212 core::rect < s32 > rect(0, 0, 100, 30);
213 rect += topleft + v2s32(size.X / 2 + 5, size.Y - 40);
214 const wchar_t *text = wgettext("Cancel");
215 Environment->addButton(rect, this, GUI_ID_ABORT_BUTTON,
221 void GUIKeyChangeMenu::drawMenu()
223 gui::IGUISkin* skin = Environment->getSkin();
226 video::IVideoDriver* driver = Environment->getVideoDriver();
228 video::SColor bgcolor(140, 0, 0, 0);
231 core::rect < s32 > rect(0, 0, 745, 620);
232 rect += AbsoluteRect.UpperLeftCorner;
233 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
236 gui::IGUIElement::draw();
239 bool GUIKeyChangeMenu::acceptInput()
241 for(size_t i = 0; i < key_settings.size(); i++)
243 key_setting *k = key_settings.at(i);
244 g_settings->set(k->setting_name, k->key.sym());
247 gui::IGUIElement *e = getElementFromId(GUI_ID_CB_AUX1_DESCENDS);
248 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
249 g_settings->setBool("aux1_descends", ((gui::IGUICheckBox*)e)->isChecked());
252 gui::IGUIElement *e = getElementFromId(GUI_ID_CB_DOUBLETAP_JUMP);
253 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
254 g_settings->setBool("doubletap_jump", ((gui::IGUICheckBox*)e)->isChecked());
259 g_gamecallback->signalKeyConfigChange();
264 bool GUIKeyChangeMenu::resetMenu()
268 for(size_t i = 0; i < key_settings.size(); i++)
270 key_setting *k = key_settings.at(i);
271 if(k->id == activeKey)
273 const wchar_t *text = wgettext(k->key.name());
274 k->button->setText(text);
284 bool GUIKeyChangeMenu::OnEvent(const SEvent& event)
286 if (event.EventType == EET_KEY_INPUT_EVENT && activeKey >= 0
287 && event.KeyInput.PressedDown) {
289 bool prefer_character = shift_down;
290 KeyPress kp(event.KeyInput, prefer_character);
292 bool shift_went_down = false;
294 (event.KeyInput.Key == irr::KEY_SHIFT ||
295 event.KeyInput.Key == irr::KEY_LSHIFT ||
296 event.KeyInput.Key == irr::KEY_RSHIFT))
297 shift_went_down = true;
299 // Remove Key already in use message
300 if(this->key_used_text)
302 this->key_used_text->remove();
303 this->key_used_text = NULL;
305 // Display Key already in use message
306 if (std::find(this->key_used.begin(), this->key_used.end(), kp) != this->key_used.end())
308 core::rect < s32 > rect(0, 0, 600, 40);
309 rect += v2s32(0, 0) + v2s32(25, 30);
310 const wchar_t *text = wgettext("Key already in use");
311 this->key_used_text = Environment->addStaticText(text,
312 rect, false, true, this, -1);
314 //infostream << "Key already in use" << std::endl;
319 key_setting *k = NULL;
320 for(size_t i = 0; i < key_settings.size(); i++)
322 if(key_settings.at(i)->id == activeKey)
324 k = key_settings.at(i);
328 FATAL_ERROR_IF(k == NULL, "Key setting not found");
330 const wchar_t *text = wgettext(k->key.name());
331 k->button->setText(text);
334 this->key_used.push_back(kp);
336 // Allow characters made with shift
345 } else if (event.EventType == EET_KEY_INPUT_EVENT && activeKey < 0
346 && event.KeyInput.PressedDown
347 && event.KeyInput.Key == irr::KEY_ESCAPE) {
350 } else if (event.EventType == EET_GUI_EVENT) {
351 if (event.GUIEvent.EventType == gui::EGET_ELEMENT_FOCUS_LOST
354 if (!canTakeFocus(event.GUIEvent.Element))
356 dstream << "GUIMainMenu: Not allowing focus change."
358 // Returning true disables focus change
362 if (event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED)
364 switch (event.GUIEvent.Caller->getID())
366 case GUI_ID_BACK_BUTTON: //back
370 case GUI_ID_ABORT_BUTTON: //abort
374 key_setting *k = NULL;
375 for(size_t i = 0; i < key_settings.size(); i++)
377 if(key_settings.at(i)->id == event.GUIEvent.Caller->getID())
379 k = key_settings.at(i);
383 FATAL_ERROR_IF(k == NULL, "Key setting not found");
387 activeKey = event.GUIEvent.Caller->getID();
388 const wchar_t *text = wgettext("press key");
389 k->button->setText(text);
391 this->key_used.erase(std::remove(this->key_used.begin(),
392 this->key_used.end(), k->key), this->key_used.end());
395 Environment->setFocus(this);
398 return Parent ? Parent->OnEvent(event) : false;
401 void GUIKeyChangeMenu::add_key(int id, const wchar_t *button_name, const std::string &setting_name)
403 key_setting *k = new key_setting;
406 k->button_name = button_name;
407 k->setting_name = setting_name;
408 k->key = getKeySetting(k->setting_name.c_str());
409 key_settings.push_back(k);
412 void GUIKeyChangeMenu::init_keys()
414 this->add_key(GUI_ID_KEY_FORWARD_BUTTON, wgettext("Forward"), "keymap_forward");
415 this->add_key(GUI_ID_KEY_BACKWARD_BUTTON, wgettext("Backward"), "keymap_backward");
416 this->add_key(GUI_ID_KEY_LEFT_BUTTON, wgettext("Left"), "keymap_left");
417 this->add_key(GUI_ID_KEY_RIGHT_BUTTON, wgettext("Right"), "keymap_right");
418 this->add_key(GUI_ID_KEY_USE_BUTTON, wgettext("Special"), "keymap_special1");
419 this->add_key(GUI_ID_KEY_JUMP_BUTTON, wgettext("Jump"), "keymap_jump");
420 this->add_key(GUI_ID_KEY_SNEAK_BUTTON, wgettext("Sneak"), "keymap_sneak");
421 this->add_key(GUI_ID_KEY_DROP_BUTTON, wgettext("Drop"), "keymap_drop");
422 this->add_key(GUI_ID_KEY_INVENTORY_BUTTON, wgettext("Inventory"), "keymap_inventory");
423 this->add_key(GUI_ID_KEY_HOTBAR_PREV_BUTTON,wgettext("Prev. item"), "keymap_hotbar_previous");
424 this->add_key(GUI_ID_KEY_HOTBAR_NEXT_BUTTON,wgettext("Next item"), "keymap_hotbar_next");
425 this->add_key(GUI_ID_KEY_ZOOM_BUTTON, wgettext("Zoom"), "keymap_zoom");
426 this->add_key(GUI_ID_KEY_CAMERA_BUTTON, wgettext("Change camera"), "keymap_camera_mode");
427 this->add_key(GUI_ID_KEY_CINEMATIC_BUTTON, wgettext("Toggle Cinematic"), "keymap_cinematic");
428 this->add_key(GUI_ID_KEY_MINIMAP_BUTTON, wgettext("Toggle minimap"), "keymap_minimap");
429 this->add_key(GUI_ID_KEY_FLY_BUTTON, wgettext("Toggle fly"), "keymap_freemove");
430 this->add_key(GUI_ID_KEY_FAST_BUTTON, wgettext("Toggle fast"), "keymap_fastmove");
431 this->add_key(GUI_ID_KEY_NOCLIP_BUTTON, wgettext("Toggle noclip"), "keymap_noclip");
432 this->add_key(GUI_ID_KEY_MUTE_BUTTON, wgettext("Mute"), "keymap_mute");
433 this->add_key(GUI_ID_KEY_DEC_VOLUME_BUTTON,wgettext("Dec. volume"), "keymap_decrease_volume");
434 this->add_key(GUI_ID_KEY_INC_VOLUME_BUTTON,wgettext("Inc. volume"), "keymap_increase_volume");
435 this->add_key(GUI_ID_KEY_AUTOFWD_BUTTON, wgettext("Autoforward"), "keymap_autoforward");
436 this->add_key(GUI_ID_KEY_CHAT_BUTTON, wgettext("Chat"), "keymap_chat");
437 this->add_key(GUI_ID_KEY_SCREENSHOT_BUTTON,wgettext("Screenshot"), "keymap_screenshot");
438 this->add_key(GUI_ID_KEY_RANGE_BUTTON, wgettext("Range select"), "keymap_rangeselect");
439 this->add_key(GUI_ID_KEY_DEC_RANGE_BUTTON, wgettext("Dec. range"), "keymap_decrease_viewing_range_min");
440 this->add_key(GUI_ID_KEY_INC_RANGE_BUTTON, wgettext("Inc. range"), "keymap_increase_viewing_range_min");
441 this->add_key(GUI_ID_KEY_CONSOLE_BUTTON, wgettext("Console"), "keymap_console");
442 this->add_key(GUI_ID_KEY_CMD_BUTTON, wgettext("Command"), "keymap_cmd");
443 this->add_key(GUI_ID_KEY_CMD_LOCAL_BUTTON, wgettext("Local command"), "keymap_cmd_local");
444 this->add_key(GUI_ID_KEY_HUD_BUTTON, wgettext("Toggle HUD"), "keymap_toggle_hud");
445 this->add_key(GUI_ID_KEY_CHATLOG_BUTTON, wgettext("Toggle chat log"), "keymap_toggle_chat");
446 this->add_key(GUI_ID_KEY_FOG_BUTTON, wgettext("Toggle fog"), "keymap_toggle_force_fog_off");
447 this->add_key(GUI_ID_KEY_DUMP_BUTTON, wgettext("Print stacks"), "keymap_print_debug_stacks");