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)
275 bool prefer_character = shift_down;
276 KeyPress kp(event.KeyInput, prefer_character);
278 bool shift_went_down = false;
280 (event.KeyInput.Key == irr::KEY_SHIFT ||
281 event.KeyInput.Key == irr::KEY_LSHIFT ||
282 event.KeyInput.Key == irr::KEY_RSHIFT))
283 shift_went_down = true;
285 // Remove Key already in use message
286 if(this->key_used_text)
288 this->key_used_text->remove();
289 this->key_used_text = NULL;
291 // Display Key already in use message
292 if (std::find(this->key_used.begin(), this->key_used.end(), kp) != this->key_used.end())
294 core::rect < s32 > rect(0, 0, 600, 40);
295 rect += v2s32(0, 0) + v2s32(25, 30);
296 const wchar_t *text = wgettext("Key already in use");
297 this->key_used_text = Environment->addStaticText(text,
298 rect, false, true, this, -1);
300 //infostream << "Key already in use" << std::endl;
305 key_setting *k = NULL;
306 for(size_t i = 0; i < key_settings.size(); i++)
308 if(key_settings.at(i)->id == activeKey)
310 k = key_settings.at(i);
314 FATAL_ERROR_IF(k == NULL, "Key setting not found");
316 const wchar_t *text = wgettext(k->key.name());
317 k->button->setText(text);
320 this->key_used.push_back(kp);
322 // Allow characters made with shift
332 if (event.EventType == EET_GUI_EVENT)
334 if (event.GUIEvent.EventType == gui::EGET_ELEMENT_FOCUS_LOST
337 if (!canTakeFocus(event.GUIEvent.Element))
339 dstream << "GUIMainMenu: Not allowing focus change."
341 // Returning true disables focus change
345 if (event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED)
347 switch (event.GUIEvent.Caller->getID())
349 case GUI_ID_BACK_BUTTON: //back
353 case GUI_ID_ABORT_BUTTON: //abort
357 key_setting *k = NULL;
358 for(size_t i = 0; i < key_settings.size(); i++)
360 if(key_settings.at(i)->id == event.GUIEvent.Caller->getID())
362 k = key_settings.at(i);
366 FATAL_ERROR_IF(k == NULL, "Key setting not found");
370 activeKey = event.GUIEvent.Caller->getID();
371 const wchar_t *text = wgettext("press key");
372 k->button->setText(text);
374 this->key_used.erase(std::remove(this->key_used.begin(),
375 this->key_used.end(), k->key), this->key_used.end());
378 Environment->setFocus(this);
381 return Parent ? Parent->OnEvent(event) : false;
384 void GUIKeyChangeMenu::add_key(int id, const wchar_t *button_name, const std::string &setting_name)
386 key_setting *k = new key_setting;
389 k->button_name = button_name;
390 k->setting_name = setting_name;
391 k->key = getKeySetting(k->setting_name.c_str());
392 key_settings.push_back(k);
395 void GUIKeyChangeMenu::init_keys()
397 this->add_key(GUI_ID_KEY_FORWARD_BUTTON, wgettext("Forward"), "keymap_forward");
398 this->add_key(GUI_ID_KEY_BACKWARD_BUTTON, wgettext("Backward"), "keymap_backward");
399 this->add_key(GUI_ID_KEY_LEFT_BUTTON, wgettext("Left"), "keymap_left");
400 this->add_key(GUI_ID_KEY_RIGHT_BUTTON, wgettext("Right"), "keymap_right");
401 this->add_key(GUI_ID_KEY_USE_BUTTON, wgettext("Use"), "keymap_special1");
402 this->add_key(GUI_ID_KEY_JUMP_BUTTON, wgettext("Jump"), "keymap_jump");
403 this->add_key(GUI_ID_KEY_SNEAK_BUTTON, wgettext("Sneak"), "keymap_sneak");
404 this->add_key(GUI_ID_KEY_DROP_BUTTON, wgettext("Drop"), "keymap_drop");
405 this->add_key(GUI_ID_KEY_INVENTORY_BUTTON, wgettext("Inventory"), "keymap_inventory");
406 this->add_key(GUI_ID_KEY_CHAT_BUTTON, wgettext("Chat"), "keymap_chat");
407 this->add_key(GUI_ID_KEY_CMD_BUTTON, wgettext("Command"), "keymap_cmd");
408 this->add_key(GUI_ID_KEY_CONSOLE_BUTTON, wgettext("Console"), "keymap_console");
409 this->add_key(GUI_ID_KEY_FLY_BUTTON, wgettext("Toggle fly"), "keymap_freemove");
410 this->add_key(GUI_ID_KEY_FAST_BUTTON, wgettext("Toggle fast"), "keymap_fastmove");
411 this->add_key(GUI_ID_KEY_CINEMATIC_BUTTON, wgettext("Toggle Cinematic"), "keymap_cinematic");
412 this->add_key(GUI_ID_KEY_NOCLIP_BUTTON, wgettext("Toggle noclip"), "keymap_noclip");
413 this->add_key(GUI_ID_KEY_RANGE_BUTTON, wgettext("Range select"), "keymap_rangeselect");
414 this->add_key(GUI_ID_KEY_DUMP_BUTTON, wgettext("Print stacks"), "keymap_print_debug_stacks");