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,
70 GUI_ID_CB_AUX1_DESCENDS,
71 GUI_ID_CB_DOUBLETAP_JUMP,
74 GUIKeyChangeMenu::GUIKeyChangeMenu(gui::IGUIEnvironment* env,
75 gui::IGUIElement* parent, s32 id, IMenuManager *menumgr) :
76 GUIModalMenu(env, parent, id, menumgr)
79 for (size_t i = 0; i < key_settings.size(); i++)
80 key_used.push_back(key_settings.at(i)->key);
83 GUIKeyChangeMenu::~GUIKeyChangeMenu()
87 for (std::vector<key_setting*>::iterator iter = key_settings.begin();
88 iter != key_settings.end(); ++iter) {
89 delete[] (*iter)->button_name;
95 void GUIKeyChangeMenu::removeChildren()
97 const core::list<gui::IGUIElement*> &children = getChildren();
98 core::list<gui::IGUIElement*> children_copy;
99 for (core::list<gui::IGUIElement*>::ConstIterator i = children.begin(); i
100 != children.end(); i++)
102 children_copy.push_back(*i);
104 for (core::list<gui::IGUIElement*>::Iterator i = children_copy.begin(); i
105 != children_copy.end(); i++)
111 void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
114 v2s32 size(745, 430);
116 core::rect < s32 > rect(screensize.X / 2 - size.X / 2,
117 screensize.Y / 2 - size.Y / 2, screensize.X / 2 + size.X / 2,
118 screensize.Y / 2 + size.Y / 2);
121 recalculateAbsolutePosition(false);
126 core::rect < s32 > rect(0, 0, 600, 40);
127 rect += topleft + v2s32(25, 3);
128 //gui::IGUIStaticText *t =
129 const wchar_t *text = wgettext("Keybindings. (If this menu screws up, remove stuff from minetest.conf)");
130 Environment->addStaticText(text,
131 rect, false, true, this, -1);
133 //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
138 v2s32 offset(25, 60);
140 for(size_t i = 0; i < key_settings.size(); i++)
142 key_setting *k = key_settings.at(i);
144 core::rect < s32 > rect(0, 0, 150, 20);
145 rect += topleft + v2s32(offset.X, offset.Y);
146 Environment->addStaticText(k->button_name, rect, false, true, this, -1);
150 core::rect < s32 > rect(0, 0, 100, 30);
151 rect += topleft + v2s32(offset.X + 120, offset.Y - 5);
152 const wchar_t *text = wgettext(k->key.name());
153 k->button = Environment->addButton(rect, this, k->id, text);
156 if ((i + 1) % KMaxButtonPerColumns == 0) {
160 offset += v2s32(0, 25);
165 s32 option_x = offset.X;
166 s32 option_y = offset.Y + 5;
169 core::rect<s32> rect(0, 0, option_w, 30);
170 rect += topleft + v2s32(option_x, option_y);
171 const wchar_t *text = wgettext("\"Use\" = climb down");
172 Environment->addCheckBox(g_settings->getBool("aux1_descends"), rect, this,
173 GUI_ID_CB_AUX1_DESCENDS, text);
176 offset += v2s32(0, 25);
180 s32 option_x = offset.X;
181 s32 option_y = offset.Y + 5;
184 core::rect<s32> rect(0, 0, option_w, 30);
185 rect += topleft + v2s32(option_x, option_y);
186 const wchar_t *text = wgettext("Double tap \"jump\" to toggle fly");
187 Environment->addCheckBox(g_settings->getBool("doubletap_jump"), rect, this,
188 GUI_ID_CB_DOUBLETAP_JUMP, text);
191 offset += v2s32(0, 25);
195 core::rect < s32 > rect(0, 0, 100, 30);
196 rect += topleft + v2s32(size.X / 2 - 105, size.Y - 40);
197 const wchar_t *text = wgettext("Save");
198 Environment->addButton(rect, this, GUI_ID_BACK_BUTTON,
203 core::rect < s32 > rect(0, 0, 100, 30);
204 rect += topleft + v2s32(size.X / 2 + 5, size.Y - 40);
205 const wchar_t *text = wgettext("Cancel");
206 Environment->addButton(rect, this, GUI_ID_ABORT_BUTTON,
212 void GUIKeyChangeMenu::drawMenu()
214 gui::IGUISkin* skin = Environment->getSkin();
217 video::IVideoDriver* driver = Environment->getVideoDriver();
219 video::SColor bgcolor(140, 0, 0, 0);
222 core::rect < s32 > rect(0, 0, 745, 620);
223 rect += AbsoluteRect.UpperLeftCorner;
224 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
227 gui::IGUIElement::draw();
230 bool GUIKeyChangeMenu::acceptInput()
232 for(size_t i = 0; i < key_settings.size(); i++)
234 key_setting *k = key_settings.at(i);
235 g_settings->set(k->setting_name, k->key.sym());
238 gui::IGUIElement *e = getElementFromId(GUI_ID_CB_AUX1_DESCENDS);
239 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
240 g_settings->setBool("aux1_descends", ((gui::IGUICheckBox*)e)->isChecked());
243 gui::IGUIElement *e = getElementFromId(GUI_ID_CB_DOUBLETAP_JUMP);
244 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
245 g_settings->setBool("doubletap_jump", ((gui::IGUICheckBox*)e)->isChecked());
250 g_gamecallback->signalKeyConfigChange();
255 bool GUIKeyChangeMenu::resetMenu()
259 for(size_t i = 0; i < key_settings.size(); i++)
261 key_setting *k = key_settings.at(i);
262 if(k->id == activeKey)
264 const wchar_t *text = wgettext(k->key.name());
265 k->button->setText(text);
275 bool GUIKeyChangeMenu::OnEvent(const SEvent& event)
277 if (event.EventType == EET_KEY_INPUT_EVENT && activeKey >= 0
278 && event.KeyInput.PressedDown) {
280 bool prefer_character = shift_down;
281 KeyPress kp(event.KeyInput, prefer_character);
283 bool shift_went_down = false;
285 (event.KeyInput.Key == irr::KEY_SHIFT ||
286 event.KeyInput.Key == irr::KEY_LSHIFT ||
287 event.KeyInput.Key == irr::KEY_RSHIFT))
288 shift_went_down = true;
290 // Remove Key already in use message
291 if(this->key_used_text)
293 this->key_used_text->remove();
294 this->key_used_text = NULL;
296 // Display Key already in use message
297 if (std::find(this->key_used.begin(), this->key_used.end(), kp) != this->key_used.end())
299 core::rect < s32 > rect(0, 0, 600, 40);
300 rect += v2s32(0, 0) + v2s32(25, 30);
301 const wchar_t *text = wgettext("Key already in use");
302 this->key_used_text = Environment->addStaticText(text,
303 rect, false, true, this, -1);
305 //infostream << "Key already in use" << std::endl;
310 key_setting *k = NULL;
311 for(size_t i = 0; i < key_settings.size(); i++)
313 if(key_settings.at(i)->id == activeKey)
315 k = key_settings.at(i);
319 FATAL_ERROR_IF(k == NULL, "Key setting not found");
321 const wchar_t *text = wgettext(k->key.name());
322 k->button->setText(text);
325 this->key_used.push_back(kp);
327 // Allow characters made with shift
336 } else if (event.EventType == EET_KEY_INPUT_EVENT && activeKey < 0
337 && event.KeyInput.PressedDown
338 && event.KeyInput.Key == irr::KEY_ESCAPE) {
341 } else if (event.EventType == EET_GUI_EVENT) {
342 if (event.GUIEvent.EventType == gui::EGET_ELEMENT_FOCUS_LOST
345 if (!canTakeFocus(event.GUIEvent.Element))
347 dstream << "GUIMainMenu: Not allowing focus change."
349 // Returning true disables focus change
353 if (event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED)
355 switch (event.GUIEvent.Caller->getID())
357 case GUI_ID_BACK_BUTTON: //back
361 case GUI_ID_ABORT_BUTTON: //abort
365 key_setting *k = NULL;
366 for(size_t i = 0; i < key_settings.size(); i++)
368 if(key_settings.at(i)->id == event.GUIEvent.Caller->getID())
370 k = key_settings.at(i);
374 FATAL_ERROR_IF(k == NULL, "Key setting not found");
378 activeKey = event.GUIEvent.Caller->getID();
379 const wchar_t *text = wgettext("press key");
380 k->button->setText(text);
382 this->key_used.erase(std::remove(this->key_used.begin(),
383 this->key_used.end(), k->key), this->key_used.end());
386 Environment->setFocus(this);
389 return Parent ? Parent->OnEvent(event) : false;
392 void GUIKeyChangeMenu::add_key(int id, const wchar_t *button_name, const std::string &setting_name)
394 key_setting *k = new key_setting;
397 k->button_name = button_name;
398 k->setting_name = setting_name;
399 k->key = getKeySetting(k->setting_name.c_str());
400 key_settings.push_back(k);
403 void GUIKeyChangeMenu::init_keys()
405 this->add_key(GUI_ID_KEY_FORWARD_BUTTON, wgettext("Forward"), "keymap_forward");
406 this->add_key(GUI_ID_KEY_BACKWARD_BUTTON, wgettext("Backward"), "keymap_backward");
407 this->add_key(GUI_ID_KEY_LEFT_BUTTON, wgettext("Left"), "keymap_left");
408 this->add_key(GUI_ID_KEY_RIGHT_BUTTON, wgettext("Right"), "keymap_right");
409 this->add_key(GUI_ID_KEY_USE_BUTTON, wgettext("Use"), "keymap_special1");
410 this->add_key(GUI_ID_KEY_JUMP_BUTTON, wgettext("Jump"), "keymap_jump");
411 this->add_key(GUI_ID_KEY_SNEAK_BUTTON, wgettext("Sneak"), "keymap_sneak");
412 this->add_key(GUI_ID_KEY_DROP_BUTTON, wgettext("Drop"), "keymap_drop");
413 this->add_key(GUI_ID_KEY_INVENTORY_BUTTON, wgettext("Inventory"), "keymap_inventory");
414 this->add_key(GUI_ID_KEY_HOTBAR_PREV_BUTTON,wgettext("Prev. item"), "keymap_hotbar_previous");
415 this->add_key(GUI_ID_KEY_HOTBAR_NEXT_BUTTON,wgettext("Next item"), "keymap_hotbar_next");
416 this->add_key(GUI_ID_KEY_MUTE_BUTTON, wgettext("Mute"), "keymap_mute");
417 this->add_key(GUI_ID_KEY_DEC_VOLUME_BUTTON,wgettext("Dec. volume"), "keymap_decrease_volume");
418 this->add_key(GUI_ID_KEY_INC_VOLUME_BUTTON,wgettext("Inc. volume"), "keymap_increase_volume");
419 this->add_key(GUI_ID_KEY_CHAT_BUTTON, wgettext("Chat"), "keymap_chat");
420 this->add_key(GUI_ID_KEY_CMD_BUTTON, wgettext("Command"), "keymap_cmd");
421 this->add_key(GUI_ID_KEY_CMD_LOCAL_BUTTON, wgettext("Local command"), "keymap_cmd_local");
422 this->add_key(GUI_ID_KEY_CONSOLE_BUTTON, wgettext("Console"), "keymap_console");
423 this->add_key(GUI_ID_KEY_FLY_BUTTON, wgettext("Toggle fly"), "keymap_freemove");
424 this->add_key(GUI_ID_KEY_FAST_BUTTON, wgettext("Toggle fast"), "keymap_fastmove");
425 this->add_key(GUI_ID_KEY_CINEMATIC_BUTTON, wgettext("Toggle Cinematic"), "keymap_cinematic");
426 this->add_key(GUI_ID_KEY_NOCLIP_BUTTON, wgettext("Toggle noclip"), "keymap_noclip");
427 this->add_key(GUI_ID_KEY_RANGE_BUTTON, wgettext("Range select"), "keymap_rangeselect");
428 this->add_key(GUI_ID_KEY_DUMP_BUTTON, wgettext("Print stacks"), "keymap_print_debug_stacks");
429 this->add_key(GUI_ID_KEY_ZOOM_BUTTON, wgettext("Zoom"), "keymap_zoom");