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 (key_setting *ks : key_settings)
89 key_used.push_back(ks->key);
92 GUIKeyChangeMenu::~GUIKeyChangeMenu()
96 for (key_setting *ks : key_settings) {
97 delete[] ks->button_name;
100 key_settings.clear();
103 void GUIKeyChangeMenu::removeChildren()
105 const core::list<gui::IGUIElement*> &children = getChildren();
106 core::list<gui::IGUIElement*> children_copy;
107 for (gui::IGUIElement*i : children) {
108 children_copy.push_back(i);
111 for (gui::IGUIElement *i : children_copy) {
116 void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
119 v2s32 size(745, 430);
121 core::rect < s32 > rect(screensize.X / 2 - size.X / 2,
122 screensize.Y / 2 - size.Y / 2, screensize.X / 2 + size.X / 2,
123 screensize.Y / 2 + size.Y / 2);
126 recalculateAbsolutePosition(false);
131 core::rect < s32 > rect(0, 0, 600, 40);
132 rect += topleft + v2s32(25, 3);
133 //gui::IGUIStaticText *t =
134 const wchar_t *text = wgettext("Keybindings. (If this menu screws up, remove stuff from minetest.conf)");
135 Environment->addStaticText(text,
136 rect, false, true, this, -1);
138 //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
143 v2s32 offset(25, 60);
145 for(size_t i = 0; i < key_settings.size(); i++)
147 key_setting *k = key_settings.at(i);
149 core::rect < s32 > rect(0, 0, 150, 20);
150 rect += topleft + v2s32(offset.X, offset.Y);
151 Environment->addStaticText(k->button_name, rect, false, true, this, -1);
155 core::rect < s32 > rect(0, 0, 100, 30);
156 rect += topleft + v2s32(offset.X + 120, offset.Y - 5);
157 const wchar_t *text = wgettext(k->key.name());
158 k->button = Environment->addButton(rect, this, k->id, text);
161 if ((i + 1) % KMaxButtonPerColumns == 0) {
165 offset += v2s32(0, 25);
170 s32 option_x = offset.X;
171 s32 option_y = offset.Y + 5;
174 core::rect<s32> rect(0, 0, option_w, 30);
175 rect += topleft + v2s32(option_x, option_y);
176 const wchar_t *text = wgettext("\"Special\" = climb down");
177 Environment->addCheckBox(g_settings->getBool("aux1_descends"), rect, this,
178 GUI_ID_CB_AUX1_DESCENDS, text);
181 offset += v2s32(0, 25);
185 s32 option_x = offset.X;
186 s32 option_y = offset.Y + 5;
189 core::rect<s32> rect(0, 0, option_w, 30);
190 rect += topleft + v2s32(option_x, option_y);
191 const wchar_t *text = wgettext("Double tap \"jump\" to toggle fly");
192 Environment->addCheckBox(g_settings->getBool("doubletap_jump"), rect, this,
193 GUI_ID_CB_DOUBLETAP_JUMP, text);
196 offset += v2s32(0, 25);
200 core::rect < s32 > rect(0, 0, 100, 30);
201 rect += topleft + v2s32(size.X / 2 - 105, size.Y - 40);
202 const wchar_t *text = wgettext("Save");
203 Environment->addButton(rect, this, GUI_ID_BACK_BUTTON,
208 core::rect < s32 > rect(0, 0, 100, 30);
209 rect += topleft + v2s32(size.X / 2 + 5, size.Y - 40);
210 const wchar_t *text = wgettext("Cancel");
211 Environment->addButton(rect, this, GUI_ID_ABORT_BUTTON,
217 void GUIKeyChangeMenu::drawMenu()
219 gui::IGUISkin* skin = Environment->getSkin();
222 video::IVideoDriver* driver = Environment->getVideoDriver();
224 video::SColor bgcolor(140, 0, 0, 0);
227 core::rect < s32 > rect(0, 0, 745, 620);
228 rect += AbsoluteRect.UpperLeftCorner;
229 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
232 gui::IGUIElement::draw();
235 bool GUIKeyChangeMenu::acceptInput()
237 for (key_setting *k : key_settings) {
238 g_settings->set(k->setting_name, k->key.sym());
242 gui::IGUIElement *e = getElementFromId(GUI_ID_CB_AUX1_DESCENDS);
243 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
244 g_settings->setBool("aux1_descends", ((gui::IGUICheckBox*)e)->isChecked());
247 gui::IGUIElement *e = getElementFromId(GUI_ID_CB_DOUBLETAP_JUMP);
248 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
249 g_settings->setBool("doubletap_jump", ((gui::IGUICheckBox*)e)->isChecked());
254 g_gamecallback->signalKeyConfigChange();
259 bool GUIKeyChangeMenu::resetMenu()
263 for (key_setting *k : key_settings) {
264 if (k->id == activeKey) {
265 const wchar_t *text = wgettext(k->key.name());
266 k->button->setText(text);
276 bool GUIKeyChangeMenu::OnEvent(const SEvent& event)
278 if (event.EventType == EET_KEY_INPUT_EVENT && activeKey >= 0
279 && event.KeyInput.PressedDown) {
281 bool prefer_character = shift_down;
282 KeyPress kp(event.KeyInput, prefer_character);
284 bool shift_went_down = false;
286 (event.KeyInput.Key == irr::KEY_SHIFT ||
287 event.KeyInput.Key == irr::KEY_LSHIFT ||
288 event.KeyInput.Key == irr::KEY_RSHIFT))
289 shift_went_down = true;
291 // Remove Key already in use message
292 if(this->key_used_text)
294 this->key_used_text->remove();
295 this->key_used_text = NULL;
297 // Display Key already in use message
298 if (std::find(this->key_used.begin(), this->key_used.end(), kp) != this->key_used.end())
300 core::rect < s32 > rect(0, 0, 600, 40);
301 rect += v2s32(0, 0) + v2s32(25, 30);
302 const wchar_t *text = wgettext("Key already in use");
303 this->key_used_text = Environment->addStaticText(text,
304 rect, false, true, this, -1);
306 //infostream << "Key already in use" << std::endl;
311 key_setting *k = NULL;
312 for (key_setting *ks : key_settings) {
313 if (ks->id == activeKey) {
318 FATAL_ERROR_IF(k == NULL, "Key setting not found");
320 const wchar_t *text = wgettext(k->key.name());
321 k->button->setText(text);
324 this->key_used.push_back(kp);
326 // Allow characters made with shift
335 } else if (event.EventType == EET_KEY_INPUT_EVENT && activeKey < 0
336 && event.KeyInput.PressedDown
337 && event.KeyInput.Key == irr::KEY_ESCAPE) {
340 } else if (event.EventType == EET_GUI_EVENT) {
341 if (event.GUIEvent.EventType == gui::EGET_ELEMENT_FOCUS_LOST
344 if (!canTakeFocus(event.GUIEvent.Element))
346 dstream << "GUIMainMenu: Not allowing focus change."
348 // Returning true disables focus change
352 if (event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED)
354 switch (event.GUIEvent.Caller->getID())
356 case GUI_ID_BACK_BUTTON: //back
360 case GUI_ID_ABORT_BUTTON: //abort
364 key_setting *k = NULL;
366 for (key_setting *ks : key_settings) {
367 if (ks->id == event.GUIEvent.Caller->getID()) {
372 FATAL_ERROR_IF(k == NULL, "Key setting not found");
376 activeKey = event.GUIEvent.Caller->getID();
377 const wchar_t *text = wgettext("press key");
378 k->button->setText(text);
380 this->key_used.erase(std::remove(this->key_used.begin(),
381 this->key_used.end(), k->key), this->key_used.end());
384 Environment->setFocus(this);
387 return Parent ? Parent->OnEvent(event) : false;
390 void GUIKeyChangeMenu::add_key(int id, const wchar_t *button_name, const std::string &setting_name)
392 key_setting *k = new key_setting;
395 k->button_name = button_name;
396 k->setting_name = setting_name;
397 k->key = getKeySetting(k->setting_name.c_str());
398 key_settings.push_back(k);
401 void GUIKeyChangeMenu::init_keys()
403 this->add_key(GUI_ID_KEY_FORWARD_BUTTON, wgettext("Forward"), "keymap_forward");
404 this->add_key(GUI_ID_KEY_BACKWARD_BUTTON, wgettext("Backward"), "keymap_backward");
405 this->add_key(GUI_ID_KEY_LEFT_BUTTON, wgettext("Left"), "keymap_left");
406 this->add_key(GUI_ID_KEY_RIGHT_BUTTON, wgettext("Right"), "keymap_right");
407 this->add_key(GUI_ID_KEY_USE_BUTTON, wgettext("Special"), "keymap_special1");
408 this->add_key(GUI_ID_KEY_JUMP_BUTTON, wgettext("Jump"), "keymap_jump");
409 this->add_key(GUI_ID_KEY_SNEAK_BUTTON, wgettext("Sneak"), "keymap_sneak");
410 this->add_key(GUI_ID_KEY_DROP_BUTTON, wgettext("Drop"), "keymap_drop");
411 this->add_key(GUI_ID_KEY_INVENTORY_BUTTON, wgettext("Inventory"), "keymap_inventory");
412 this->add_key(GUI_ID_KEY_HOTBAR_PREV_BUTTON,wgettext("Prev. item"), "keymap_hotbar_previous");
413 this->add_key(GUI_ID_KEY_HOTBAR_NEXT_BUTTON,wgettext("Next item"), "keymap_hotbar_next");
414 this->add_key(GUI_ID_KEY_ZOOM_BUTTON, wgettext("Zoom"), "keymap_zoom");
415 this->add_key(GUI_ID_KEY_CAMERA_BUTTON, wgettext("Change camera"), "keymap_camera_mode");
416 this->add_key(GUI_ID_KEY_CINEMATIC_BUTTON, wgettext("Toggle Cinematic"), "keymap_cinematic");
417 this->add_key(GUI_ID_KEY_MINIMAP_BUTTON, wgettext("Toggle minimap"), "keymap_minimap");
418 this->add_key(GUI_ID_KEY_FLY_BUTTON, wgettext("Toggle fly"), "keymap_freemove");
419 this->add_key(GUI_ID_KEY_FAST_BUTTON, wgettext("Toggle fast"), "keymap_fastmove");
420 this->add_key(GUI_ID_KEY_NOCLIP_BUTTON, wgettext("Toggle noclip"), "keymap_noclip");
421 this->add_key(GUI_ID_KEY_MUTE_BUTTON, wgettext("Mute"), "keymap_mute");
422 this->add_key(GUI_ID_KEY_DEC_VOLUME_BUTTON,wgettext("Dec. volume"), "keymap_decrease_volume");
423 this->add_key(GUI_ID_KEY_INC_VOLUME_BUTTON,wgettext("Inc. volume"), "keymap_increase_volume");
424 this->add_key(GUI_ID_KEY_AUTOFWD_BUTTON, wgettext("Autoforward"), "keymap_autoforward");
425 this->add_key(GUI_ID_KEY_CHAT_BUTTON, wgettext("Chat"), "keymap_chat");
426 this->add_key(GUI_ID_KEY_SCREENSHOT_BUTTON,wgettext("Screenshot"), "keymap_screenshot");
427 this->add_key(GUI_ID_KEY_RANGE_BUTTON, wgettext("Range select"), "keymap_rangeselect");
428 this->add_key(GUI_ID_KEY_DEC_RANGE_BUTTON, wgettext("Dec. range"), "keymap_decrease_viewing_range_min");
429 this->add_key(GUI_ID_KEY_INC_RANGE_BUTTON, wgettext("Inc. range"), "keymap_increase_viewing_range_min");
430 this->add_key(GUI_ID_KEY_CONSOLE_BUTTON, wgettext("Console"), "keymap_console");
431 this->add_key(GUI_ID_KEY_CMD_BUTTON, wgettext("Command"), "keymap_cmd");
432 this->add_key(GUI_ID_KEY_CMD_LOCAL_BUTTON, wgettext("Local command"), "keymap_cmd_local");
433 this->add_key(GUI_ID_KEY_HUD_BUTTON, wgettext("Toggle HUD"), "keymap_toggle_hud");
434 this->add_key(GUI_ID_KEY_CHATLOG_BUTTON, wgettext("Toggle chat log"), "keymap_toggle_chat");
435 this->add_key(GUI_ID_KEY_FOG_BUTTON, wgettext("Toggle fog"), "keymap_toggle_force_fog_off");
436 this->add_key(GUI_ID_KEY_DUMP_BUTTON, wgettext("Print stacks"), "keymap_print_debug_stacks");