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)
80 this->key_used_text = NULL;
82 for(size_t i=0; i<key_settings.size(); i++)
83 this->key_used.push_back(key_settings.at(i)->key);
86 GUIKeyChangeMenu::~GUIKeyChangeMenu()
90 for (std::vector<key_setting*>::iterator iter = key_settings.begin();
91 iter != key_settings.end(); ++iter) {
92 delete[] (*iter)->button_name;
98 void GUIKeyChangeMenu::removeChildren()
100 const core::list<gui::IGUIElement*> &children = getChildren();
101 core::list<gui::IGUIElement*> children_copy;
102 for (core::list<gui::IGUIElement*>::ConstIterator i = children.begin(); i
103 != children.end(); i++)
105 children_copy.push_back(*i);
107 for (core::list<gui::IGUIElement*>::Iterator i = children_copy.begin(); i
108 != children_copy.end(); i++)
114 void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
117 v2s32 size(745, 430);
119 core::rect < s32 > rect(screensize.X / 2 - size.X / 2,
120 screensize.Y / 2 - size.Y / 2, screensize.X / 2 + size.X / 2,
121 screensize.Y / 2 + size.Y / 2);
124 recalculateAbsolutePosition(false);
129 core::rect < s32 > rect(0, 0, 600, 40);
130 rect += topleft + v2s32(25, 3);
131 //gui::IGUIStaticText *t =
132 const wchar_t *text = wgettext("Keybindings. (If this menu screws up, remove stuff from minetest.conf)");
133 Environment->addStaticText(text,
134 rect, false, true, this, -1);
136 //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
141 v2s32 offset(25, 60);
143 for(size_t i = 0; i < key_settings.size(); i++)
145 key_setting *k = key_settings.at(i);
147 core::rect < s32 > rect(0, 0, 150, 20);
148 rect += topleft + v2s32(offset.X, offset.Y);
149 Environment->addStaticText(k->button_name, rect, false, true, this, -1);
153 core::rect < s32 > rect(0, 0, 100, 30);
154 rect += topleft + v2s32(offset.X + 120, offset.Y - 5);
155 const wchar_t *text = wgettext(k->key.name());
156 k->button = Environment->addButton(rect, this, k->id, text);
159 if ((i + 1) % KMaxButtonPerColumns == 0) {
163 offset += v2s32(0, 25);
168 s32 option_x = offset.X;
169 s32 option_y = offset.Y + 5;
172 core::rect<s32> rect(0, 0, option_w, 30);
173 rect += topleft + v2s32(option_x, option_y);
174 const wchar_t *text = wgettext("\"Use\" = climb down");
175 Environment->addCheckBox(g_settings->getBool("aux1_descends"), rect, this,
176 GUI_ID_CB_AUX1_DESCENDS, text);
179 offset += v2s32(0, 25);
183 s32 option_x = offset.X;
184 s32 option_y = offset.Y + 5;
187 core::rect<s32> rect(0, 0, option_w, 30);
188 rect += topleft + v2s32(option_x, option_y);
189 const wchar_t *text = wgettext("Double tap \"jump\" to toggle fly");
190 Environment->addCheckBox(g_settings->getBool("doubletap_jump"), rect, this,
191 GUI_ID_CB_DOUBLETAP_JUMP, text);
194 offset += v2s32(0, 25);
198 core::rect < s32 > rect(0, 0, 100, 30);
199 rect += topleft + v2s32(size.X / 2 - 105, size.Y - 40);
200 const wchar_t *text = wgettext("Save");
201 Environment->addButton(rect, this, GUI_ID_BACK_BUTTON,
206 core::rect < s32 > rect(0, 0, 100, 30);
207 rect += topleft + v2s32(size.X / 2 + 5, size.Y - 40);
208 const wchar_t *text = wgettext("Cancel");
209 Environment->addButton(rect, this, GUI_ID_ABORT_BUTTON,
215 void GUIKeyChangeMenu::drawMenu()
217 gui::IGUISkin* skin = Environment->getSkin();
220 video::IVideoDriver* driver = Environment->getVideoDriver();
222 video::SColor bgcolor(140, 0, 0, 0);
225 core::rect < s32 > rect(0, 0, 745, 620);
226 rect += AbsoluteRect.UpperLeftCorner;
227 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
230 gui::IGUIElement::draw();
233 bool GUIKeyChangeMenu::acceptInput()
235 for(size_t i = 0; i < key_settings.size(); i++)
237 key_setting *k = key_settings.at(i);
238 g_settings->set(k->setting_name, k->key.sym());
241 gui::IGUIElement *e = getElementFromId(GUI_ID_CB_AUX1_DESCENDS);
242 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
243 g_settings->setBool("aux1_descends", ((gui::IGUICheckBox*)e)->isChecked());
246 gui::IGUIElement *e = getElementFromId(GUI_ID_CB_DOUBLETAP_JUMP);
247 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
248 g_settings->setBool("doubletap_jump", ((gui::IGUICheckBox*)e)->isChecked());
253 g_gamecallback->signalKeyConfigChange();
258 bool GUIKeyChangeMenu::resetMenu()
262 for(size_t i = 0; i < key_settings.size(); i++)
264 key_setting *k = key_settings.at(i);
265 if(k->id == activeKey)
267 const wchar_t *text = wgettext(k->key.name());
268 k->button->setText(text);
278 bool GUIKeyChangeMenu::OnEvent(const SEvent& event)
280 if (event.EventType == EET_KEY_INPUT_EVENT && activeKey >= 0
281 && event.KeyInput.PressedDown) {
283 bool prefer_character = shift_down;
284 KeyPress kp(event.KeyInput, prefer_character);
286 bool shift_went_down = false;
288 (event.KeyInput.Key == irr::KEY_SHIFT ||
289 event.KeyInput.Key == irr::KEY_LSHIFT ||
290 event.KeyInput.Key == irr::KEY_RSHIFT))
291 shift_went_down = true;
293 // Remove Key already in use message
294 if(this->key_used_text)
296 this->key_used_text->remove();
297 this->key_used_text = NULL;
299 // Display Key already in use message
300 if (std::find(this->key_used.begin(), this->key_used.end(), kp) != this->key_used.end())
302 core::rect < s32 > rect(0, 0, 600, 40);
303 rect += v2s32(0, 0) + v2s32(25, 30);
304 const wchar_t *text = wgettext("Key already in use");
305 this->key_used_text = Environment->addStaticText(text,
306 rect, false, true, this, -1);
308 //infostream << "Key already in use" << std::endl;
313 key_setting *k = NULL;
314 for(size_t i = 0; i < key_settings.size(); i++)
316 if(key_settings.at(i)->id == activeKey)
318 k = key_settings.at(i);
322 FATAL_ERROR_IF(k == NULL, "Key setting not found");
324 const wchar_t *text = wgettext(k->key.name());
325 k->button->setText(text);
328 this->key_used.push_back(kp);
330 // Allow characters made with shift
339 } else if (event.EventType == EET_KEY_INPUT_EVENT && activeKey < 0
340 && event.KeyInput.PressedDown
341 && event.KeyInput.Key == irr::KEY_ESCAPE) {
344 } else if (event.EventType == EET_GUI_EVENT) {
345 if (event.GUIEvent.EventType == gui::EGET_ELEMENT_FOCUS_LOST
348 if (!canTakeFocus(event.GUIEvent.Element))
350 dstream << "GUIMainMenu: Not allowing focus change."
352 // Returning true disables focus change
356 if (event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED)
358 switch (event.GUIEvent.Caller->getID())
360 case GUI_ID_BACK_BUTTON: //back
364 case GUI_ID_ABORT_BUTTON: //abort
368 key_setting *k = NULL;
369 for(size_t i = 0; i < key_settings.size(); i++)
371 if(key_settings.at(i)->id == event.GUIEvent.Caller->getID())
373 k = key_settings.at(i);
377 FATAL_ERROR_IF(k == NULL, "Key setting not found");
381 activeKey = event.GUIEvent.Caller->getID();
382 const wchar_t *text = wgettext("press key");
383 k->button->setText(text);
385 this->key_used.erase(std::remove(this->key_used.begin(),
386 this->key_used.end(), k->key), this->key_used.end());
389 Environment->setFocus(this);
392 return Parent ? Parent->OnEvent(event) : false;
395 void GUIKeyChangeMenu::add_key(int id, const wchar_t *button_name, const std::string &setting_name)
397 key_setting *k = new key_setting;
400 k->button_name = button_name;
401 k->setting_name = setting_name;
402 k->key = getKeySetting(k->setting_name.c_str());
403 key_settings.push_back(k);
406 void GUIKeyChangeMenu::init_keys()
408 this->add_key(GUI_ID_KEY_FORWARD_BUTTON, wgettext("Forward"), "keymap_forward");
409 this->add_key(GUI_ID_KEY_BACKWARD_BUTTON, wgettext("Backward"), "keymap_backward");
410 this->add_key(GUI_ID_KEY_LEFT_BUTTON, wgettext("Left"), "keymap_left");
411 this->add_key(GUI_ID_KEY_RIGHT_BUTTON, wgettext("Right"), "keymap_right");
412 this->add_key(GUI_ID_KEY_USE_BUTTON, wgettext("Use"), "keymap_special1");
413 this->add_key(GUI_ID_KEY_JUMP_BUTTON, wgettext("Jump"), "keymap_jump");
414 this->add_key(GUI_ID_KEY_SNEAK_BUTTON, wgettext("Sneak"), "keymap_sneak");
415 this->add_key(GUI_ID_KEY_DROP_BUTTON, wgettext("Drop"), "keymap_drop");
416 this->add_key(GUI_ID_KEY_INVENTORY_BUTTON, wgettext("Inventory"), "keymap_inventory");
417 this->add_key(GUI_ID_KEY_HOTBAR_PREV_BUTTON,wgettext("Prev. item"), "keymap_hotbar_previous");
418 this->add_key(GUI_ID_KEY_HOTBAR_NEXT_BUTTON,wgettext("Next item"), "keymap_hotbar_next");
419 this->add_key(GUI_ID_KEY_MUTE_BUTTON, wgettext("Mute"), "keymap_mute");
420 this->add_key(GUI_ID_KEY_DEC_VOLUME_BUTTON,wgettext("Dec. volume"), "keymap_decrease_volume");
421 this->add_key(GUI_ID_KEY_INC_VOLUME_BUTTON,wgettext("Inc. volume"), "keymap_increase_volume");
422 this->add_key(GUI_ID_KEY_CHAT_BUTTON, wgettext("Chat"), "keymap_chat");
423 this->add_key(GUI_ID_KEY_CMD_BUTTON, wgettext("Command"), "keymap_cmd");
424 this->add_key(GUI_ID_KEY_CMD_LOCAL_BUTTON, wgettext("Local command"), "keymap_cmd_local");
425 this->add_key(GUI_ID_KEY_CONSOLE_BUTTON, wgettext("Console"), "keymap_console");
426 this->add_key(GUI_ID_KEY_FLY_BUTTON, wgettext("Toggle fly"), "keymap_freemove");
427 this->add_key(GUI_ID_KEY_FAST_BUTTON, wgettext("Toggle fast"), "keymap_fastmove");
428 this->add_key(GUI_ID_KEY_CINEMATIC_BUTTON, wgettext("Toggle Cinematic"), "keymap_cinematic");
429 this->add_key(GUI_ID_KEY_NOCLIP_BUTTON, wgettext("Toggle noclip"), "keymap_noclip");
430 this->add_key(GUI_ID_KEY_RANGE_BUTTON, wgettext("Range select"), "keymap_rangeselect");
431 this->add_key(GUI_ID_KEY_DUMP_BUTTON, wgettext("Print stacks"), "keymap_print_debug_stacks");
432 this->add_key(GUI_ID_KEY_ZOOM_BUTTON, wgettext("Zoom"), "keymap_zoom");