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_CONSOLE_BUTTON,
57 GUI_ID_KEY_SNEAK_BUTTON,
58 GUI_ID_KEY_DROP_BUTTON,
59 GUI_ID_KEY_INVENTORY_BUTTON,
60 GUI_ID_KEY_DUMP_BUTTON,
61 GUI_ID_KEY_RANGE_BUTTON,
63 GUI_ID_CB_AUX1_DESCENDS,
64 GUI_ID_CB_DOUBLETAP_JUMP,
67 GUIKeyChangeMenu::GUIKeyChangeMenu(gui::IGUIEnvironment* env,
68 gui::IGUIElement* parent, s32 id, IMenuManager *menumgr) :
69 GUIModalMenu(env, parent, id, menumgr)
73 this->key_used_text = NULL;
75 for(size_t i=0; i<key_settings.size(); i++)
76 this->key_used.push_back(key_settings.at(i)->key);
79 GUIKeyChangeMenu::~GUIKeyChangeMenu()
83 for (std::vector<key_setting*>::iterator iter = key_settings.begin();
84 iter != key_settings.end(); iter ++) {
85 delete[] (*iter)->button_name;
91 void GUIKeyChangeMenu::removeChildren()
93 const core::list<gui::IGUIElement*> &children = getChildren();
94 core::list<gui::IGUIElement*> children_copy;
95 for (core::list<gui::IGUIElement*>::ConstIterator i = children.begin(); i
96 != children.end(); i++)
98 children_copy.push_back(*i);
100 for (core::list<gui::IGUIElement*>::Iterator i = children_copy.begin(); i
101 != children_copy.end(); i++)
107 void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
110 v2s32 size(620, 430);
112 core::rect < s32 > rect(screensize.X / 2 - size.X / 2,
113 screensize.Y / 2 - size.Y / 2, screensize.X / 2 + size.X / 2,
114 screensize.Y / 2 + size.Y / 2);
117 recalculateAbsolutePosition(false);
122 core::rect < s32 > rect(0, 0, 600, 40);
123 rect += topleft + v2s32(25, 3);
124 //gui::IGUIStaticText *t =
125 const wchar_t *text = wgettext("Keybindings. (If this menu screws up, remove stuff from minetest.conf)");
126 Environment->addStaticText(text,
127 rect, false, true, this, -1);
129 //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
134 v2s32 offset(25, 60);
136 for(size_t i = 0; i < key_settings.size(); i++)
138 key_setting *k = key_settings.at(i);
140 core::rect < s32 > rect(0, 0, 110, 20);
141 rect += topleft + v2s32(offset.X, offset.Y);
142 Environment->addStaticText(k->button_name, rect, false, true, this, -1);
146 core::rect < s32 > rect(0, 0, 100, 30);
147 rect += topleft + v2s32(offset.X + 115, offset.Y - 5);
148 const wchar_t *text = wgettext(k->key.name());
149 k->button = Environment->addButton(rect, this, k->id, text);
152 if(i + 1 == KMaxButtonPerColumns)
153 offset = v2s32(260, 60);
155 offset += v2s32(0, 25);
159 s32 option_x = offset.X;
160 s32 option_y = offset.Y + 5;
163 core::rect<s32> rect(0, 0, option_w, 30);
164 rect += topleft + v2s32(option_x, option_y);
165 const wchar_t *text = wgettext("\"Use\" = climb down");
166 Environment->addCheckBox(g_settings->getBool("aux1_descends"), rect, this,
167 GUI_ID_CB_AUX1_DESCENDS, text);
170 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("Double tap \"jump\" to toggle fly");
181 Environment->addCheckBox(g_settings->getBool("doubletap_jump"), rect, this,
182 GUI_ID_CB_DOUBLETAP_JUMP, text);
185 offset += v2s32(0, 25);
189 core::rect < s32 > rect(0, 0, 100, 30);
190 rect += topleft + v2s32(size.X - 100 - 20, size.Y - 40);
191 const wchar_t *text = wgettext("Save");
192 Environment->addButton(rect, this, GUI_ID_BACK_BUTTON,
197 core::rect < s32 > rect(0, 0, 100, 30);
198 rect += topleft + v2s32(size.X - 100 - 20 - 100 - 20, size.Y - 40);
199 const wchar_t *text = wgettext("Cancel");
200 Environment->addButton(rect, this, GUI_ID_ABORT_BUTTON,
206 void GUIKeyChangeMenu::drawMenu()
208 gui::IGUISkin* skin = Environment->getSkin();
211 video::IVideoDriver* driver = Environment->getVideoDriver();
213 video::SColor bgcolor(140, 0, 0, 0);
216 core::rect < s32 > rect(0, 0, 620, 620);
217 rect += AbsoluteRect.UpperLeftCorner;
218 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
221 gui::IGUIElement::draw();
224 bool GUIKeyChangeMenu::acceptInput()
226 for(size_t i = 0; i < key_settings.size(); i++)
228 key_setting *k = key_settings.at(i);
229 g_settings->set(k->setting_name, k->key.sym());
232 gui::IGUIElement *e = getElementFromId(GUI_ID_CB_AUX1_DESCENDS);
233 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
234 g_settings->setBool("aux1_descends", ((gui::IGUICheckBox*)e)->isChecked());
237 gui::IGUIElement *e = getElementFromId(GUI_ID_CB_DOUBLETAP_JUMP);
238 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
239 g_settings->setBool("doubletap_jump", ((gui::IGUICheckBox*)e)->isChecked());
244 g_gamecallback->signalKeyConfigChange();
249 bool GUIKeyChangeMenu::resetMenu()
253 for(size_t i = 0; i < key_settings.size(); i++)
255 key_setting *k = key_settings.at(i);
256 if(k->id == activeKey)
258 const wchar_t *text = wgettext(k->key.name());
259 k->button->setText(text);
269 bool GUIKeyChangeMenu::OnEvent(const SEvent& event)
271 if (event.EventType == EET_KEY_INPUT_EVENT && activeKey >= 0
272 && event.KeyInput.PressedDown) {
274 bool prefer_character = shift_down;
275 KeyPress kp(event.KeyInput, prefer_character);
277 bool shift_went_down = false;
279 (event.KeyInput.Key == irr::KEY_SHIFT ||
280 event.KeyInput.Key == irr::KEY_LSHIFT ||
281 event.KeyInput.Key == irr::KEY_RSHIFT))
282 shift_went_down = true;
284 // Remove Key already in use message
285 if(this->key_used_text)
287 this->key_used_text->remove();
288 this->key_used_text = NULL;
290 // Display Key already in use message
291 if (std::find(this->key_used.begin(), this->key_used.end(), kp) != this->key_used.end())
293 core::rect < s32 > rect(0, 0, 600, 40);
294 rect += v2s32(0, 0) + v2s32(25, 30);
295 const wchar_t *text = wgettext("Key already in use");
296 this->key_used_text = Environment->addStaticText(text,
297 rect, false, true, this, -1);
299 //infostream << "Key already in use" << std::endl;
304 key_setting *k = NULL;
305 for(size_t i = 0; i < key_settings.size(); i++)
307 if(key_settings.at(i)->id == activeKey)
309 k = key_settings.at(i);
313 FATAL_ERROR_IF(k == NULL, "Key setting not found");
315 const wchar_t *text = wgettext(k->key.name());
316 k->button->setText(text);
319 this->key_used.push_back(kp);
321 // Allow characters made with shift
330 } else if (event.EventType == EET_KEY_INPUT_EVENT && activeKey < 0
331 && event.KeyInput.PressedDown
332 && event.KeyInput.Key == irr::KEY_ESCAPE) {
335 } else if (event.EventType == EET_GUI_EVENT) {
336 if (event.GUIEvent.EventType == gui::EGET_ELEMENT_FOCUS_LOST
339 if (!canTakeFocus(event.GUIEvent.Element))
341 dstream << "GUIMainMenu: Not allowing focus change."
343 // Returning true disables focus change
347 if (event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED)
349 switch (event.GUIEvent.Caller->getID())
351 case GUI_ID_BACK_BUTTON: //back
355 case GUI_ID_ABORT_BUTTON: //abort
359 key_setting *k = NULL;
360 for(size_t i = 0; i < key_settings.size(); i++)
362 if(key_settings.at(i)->id == event.GUIEvent.Caller->getID())
364 k = key_settings.at(i);
368 FATAL_ERROR_IF(k == NULL, "Key setting not found");
372 activeKey = event.GUIEvent.Caller->getID();
373 const wchar_t *text = wgettext("press key");
374 k->button->setText(text);
376 this->key_used.erase(std::remove(this->key_used.begin(),
377 this->key_used.end(), k->key), this->key_used.end());
380 Environment->setFocus(this);
383 return Parent ? Parent->OnEvent(event) : false;
386 void GUIKeyChangeMenu::add_key(int id, const wchar_t *button_name, const std::string &setting_name)
388 key_setting *k = new key_setting;
391 k->button_name = button_name;
392 k->setting_name = setting_name;
393 k->key = getKeySetting(k->setting_name.c_str());
394 key_settings.push_back(k);
397 void GUIKeyChangeMenu::init_keys()
399 this->add_key(GUI_ID_KEY_FORWARD_BUTTON, wgettext("Forward"), "keymap_forward");
400 this->add_key(GUI_ID_KEY_BACKWARD_BUTTON, wgettext("Backward"), "keymap_backward");
401 this->add_key(GUI_ID_KEY_LEFT_BUTTON, wgettext("Left"), "keymap_left");
402 this->add_key(GUI_ID_KEY_RIGHT_BUTTON, wgettext("Right"), "keymap_right");
403 this->add_key(GUI_ID_KEY_USE_BUTTON, wgettext("Use"), "keymap_special1");
404 this->add_key(GUI_ID_KEY_JUMP_BUTTON, wgettext("Jump"), "keymap_jump");
405 this->add_key(GUI_ID_KEY_SNEAK_BUTTON, wgettext("Sneak"), "keymap_sneak");
406 this->add_key(GUI_ID_KEY_DROP_BUTTON, wgettext("Drop"), "keymap_drop");
407 this->add_key(GUI_ID_KEY_INVENTORY_BUTTON, wgettext("Inventory"), "keymap_inventory");
408 this->add_key(GUI_ID_KEY_CHAT_BUTTON, wgettext("Chat"), "keymap_chat");
409 this->add_key(GUI_ID_KEY_CMD_BUTTON, wgettext("Command"), "keymap_cmd");
410 this->add_key(GUI_ID_KEY_CONSOLE_BUTTON, wgettext("Console"), "keymap_console");
411 this->add_key(GUI_ID_KEY_FLY_BUTTON, wgettext("Toggle fly"), "keymap_freemove");
412 this->add_key(GUI_ID_KEY_FAST_BUTTON, wgettext("Toggle fast"), "keymap_fastmove");
413 this->add_key(GUI_ID_KEY_CINEMATIC_BUTTON, wgettext("Toggle Cinematic"), "keymap_cinematic");
414 this->add_key(GUI_ID_KEY_NOCLIP_BUTTON, wgettext("Toggle noclip"), "keymap_noclip");
415 this->add_key(GUI_ID_KEY_RANGE_BUTTON, wgettext("Range select"), "keymap_rangeselect");
416 this->add_key(GUI_ID_KEY_DUMP_BUTTON, wgettext("Print stacks"), "keymap_print_debug_stacks");