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,
62 GUI_ID_KEY_ZOOM_BUTTON,
64 GUI_ID_CB_AUX1_DESCENDS,
65 GUI_ID_CB_DOUBLETAP_JUMP,
68 GUIKeyChangeMenu::GUIKeyChangeMenu(gui::IGUIEnvironment* env,
69 gui::IGUIElement* parent, s32 id, IMenuManager *menumgr) :
70 GUIModalMenu(env, parent, id, menumgr)
74 this->key_used_text = NULL;
76 for(size_t i=0; i<key_settings.size(); i++)
77 this->key_used.push_back(key_settings.at(i)->key);
80 GUIKeyChangeMenu::~GUIKeyChangeMenu()
84 for (std::vector<key_setting*>::iterator iter = key_settings.begin();
85 iter != key_settings.end(); ++iter) {
86 delete[] (*iter)->button_name;
92 void GUIKeyChangeMenu::removeChildren()
94 const core::list<gui::IGUIElement*> &children = getChildren();
95 core::list<gui::IGUIElement*> children_copy;
96 for (core::list<gui::IGUIElement*>::ConstIterator i = children.begin(); i
97 != children.end(); i++)
99 children_copy.push_back(*i);
101 for (core::list<gui::IGUIElement*>::Iterator i = children_copy.begin(); i
102 != children_copy.end(); i++)
108 void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
111 v2s32 size(620, 430);
113 core::rect < s32 > rect(screensize.X / 2 - size.X / 2,
114 screensize.Y / 2 - size.Y / 2, screensize.X / 2 + size.X / 2,
115 screensize.Y / 2 + size.Y / 2);
118 recalculateAbsolutePosition(false);
123 core::rect < s32 > rect(0, 0, 600, 40);
124 rect += topleft + v2s32(25, 3);
125 //gui::IGUIStaticText *t =
126 const wchar_t *text = wgettext("Keybindings. (If this menu screws up, remove stuff from minetest.conf)");
127 Environment->addStaticText(text,
128 rect, false, true, this, -1);
130 //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
135 v2s32 offset(25, 60);
137 for(size_t i = 0; i < key_settings.size(); i++)
139 key_setting *k = key_settings.at(i);
141 core::rect < s32 > rect(0, 0, 150, 20);
142 rect += topleft + v2s32(offset.X, offset.Y);
143 Environment->addStaticText(k->button_name, rect, false, true, this, -1);
147 core::rect < s32 > rect(0, 0, 100, 30);
148 rect += topleft + v2s32(offset.X + 115, offset.Y - 5);
149 const wchar_t *text = wgettext(k->key.name());
150 k->button = Environment->addButton(rect, this, k->id, text);
153 if(i + 1 == KMaxButtonPerColumns)
154 offset = v2s32(260, 60);
156 offset += v2s32(0, 25);
160 s32 option_x = offset.X;
161 s32 option_y = offset.Y + 5;
164 core::rect<s32> rect(0, 0, option_w, 30);
165 rect += topleft + v2s32(option_x, option_y);
166 const wchar_t *text = wgettext("\"Use\" = climb down");
167 Environment->addCheckBox(g_settings->getBool("aux1_descends"), rect, this,
168 GUI_ID_CB_AUX1_DESCENDS, text);
171 offset += v2s32(0, 25);
175 s32 option_x = offset.X;
176 s32 option_y = offset.Y + 5;
179 core::rect<s32> rect(0, 0, option_w, 30);
180 rect += topleft + v2s32(option_x, option_y);
181 const wchar_t *text = wgettext("Double tap \"jump\" to toggle fly");
182 Environment->addCheckBox(g_settings->getBool("doubletap_jump"), rect, this,
183 GUI_ID_CB_DOUBLETAP_JUMP, text);
186 offset += v2s32(0, 25);
190 core::rect < s32 > rect(0, 0, 100, 30);
191 rect += topleft + v2s32(size.X / 2 - 105, size.Y - 40);
192 const wchar_t *text = wgettext("Save");
193 Environment->addButton(rect, this, GUI_ID_BACK_BUTTON,
198 core::rect < s32 > rect(0, 0, 100, 30);
199 rect += topleft + v2s32(size.X / 2 + 5, size.Y - 40);
200 const wchar_t *text = wgettext("Cancel");
201 Environment->addButton(rect, this, GUI_ID_ABORT_BUTTON,
207 void GUIKeyChangeMenu::drawMenu()
209 gui::IGUISkin* skin = Environment->getSkin();
212 video::IVideoDriver* driver = Environment->getVideoDriver();
214 video::SColor bgcolor(140, 0, 0, 0);
217 core::rect < s32 > rect(0, 0, 620, 620);
218 rect += AbsoluteRect.UpperLeftCorner;
219 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
222 gui::IGUIElement::draw();
225 bool GUIKeyChangeMenu::acceptInput()
227 for(size_t i = 0; i < key_settings.size(); i++)
229 key_setting *k = key_settings.at(i);
230 g_settings->set(k->setting_name, k->key.sym());
233 gui::IGUIElement *e = getElementFromId(GUI_ID_CB_AUX1_DESCENDS);
234 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
235 g_settings->setBool("aux1_descends", ((gui::IGUICheckBox*)e)->isChecked());
238 gui::IGUIElement *e = getElementFromId(GUI_ID_CB_DOUBLETAP_JUMP);
239 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
240 g_settings->setBool("doubletap_jump", ((gui::IGUICheckBox*)e)->isChecked());
245 g_gamecallback->signalKeyConfigChange();
250 bool GUIKeyChangeMenu::resetMenu()
254 for(size_t i = 0; i < key_settings.size(); i++)
256 key_setting *k = key_settings.at(i);
257 if(k->id == activeKey)
259 const wchar_t *text = wgettext(k->key.name());
260 k->button->setText(text);
270 bool GUIKeyChangeMenu::OnEvent(const SEvent& event)
272 if (event.EventType == EET_KEY_INPUT_EVENT && activeKey >= 0
273 && 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
331 } else if (event.EventType == EET_KEY_INPUT_EVENT && activeKey < 0
332 && event.KeyInput.PressedDown
333 && event.KeyInput.Key == irr::KEY_ESCAPE) {
336 } else if (event.EventType == EET_GUI_EVENT) {
337 if (event.GUIEvent.EventType == gui::EGET_ELEMENT_FOCUS_LOST
340 if (!canTakeFocus(event.GUIEvent.Element))
342 dstream << "GUIMainMenu: Not allowing focus change."
344 // Returning true disables focus change
348 if (event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED)
350 switch (event.GUIEvent.Caller->getID())
352 case GUI_ID_BACK_BUTTON: //back
356 case GUI_ID_ABORT_BUTTON: //abort
360 key_setting *k = NULL;
361 for(size_t i = 0; i < key_settings.size(); i++)
363 if(key_settings.at(i)->id == event.GUIEvent.Caller->getID())
365 k = key_settings.at(i);
369 FATAL_ERROR_IF(k == NULL, "Key setting not found");
373 activeKey = event.GUIEvent.Caller->getID();
374 const wchar_t *text = wgettext("press key");
375 k->button->setText(text);
377 this->key_used.erase(std::remove(this->key_used.begin(),
378 this->key_used.end(), k->key), this->key_used.end());
381 Environment->setFocus(this);
384 return Parent ? Parent->OnEvent(event) : false;
387 void GUIKeyChangeMenu::add_key(int id, const wchar_t *button_name, const std::string &setting_name)
389 key_setting *k = new key_setting;
392 k->button_name = button_name;
393 k->setting_name = setting_name;
394 k->key = getKeySetting(k->setting_name.c_str());
395 key_settings.push_back(k);
398 void GUIKeyChangeMenu::init_keys()
400 this->add_key(GUI_ID_KEY_FORWARD_BUTTON, wgettext("Forward"), "keymap_forward");
401 this->add_key(GUI_ID_KEY_BACKWARD_BUTTON, wgettext("Backward"), "keymap_backward");
402 this->add_key(GUI_ID_KEY_LEFT_BUTTON, wgettext("Left"), "keymap_left");
403 this->add_key(GUI_ID_KEY_RIGHT_BUTTON, wgettext("Right"), "keymap_right");
404 this->add_key(GUI_ID_KEY_USE_BUTTON, wgettext("Use"), "keymap_special1");
405 this->add_key(GUI_ID_KEY_JUMP_BUTTON, wgettext("Jump"), "keymap_jump");
406 this->add_key(GUI_ID_KEY_SNEAK_BUTTON, wgettext("Sneak"), "keymap_sneak");
407 this->add_key(GUI_ID_KEY_DROP_BUTTON, wgettext("Drop"), "keymap_drop");
408 this->add_key(GUI_ID_KEY_INVENTORY_BUTTON, wgettext("Inventory"), "keymap_inventory");
409 this->add_key(GUI_ID_KEY_CHAT_BUTTON, wgettext("Chat"), "keymap_chat");
410 this->add_key(GUI_ID_KEY_CMD_BUTTON, wgettext("Command"), "keymap_cmd");
411 this->add_key(GUI_ID_KEY_CONSOLE_BUTTON, wgettext("Console"), "keymap_console");
412 this->add_key(GUI_ID_KEY_FLY_BUTTON, wgettext("Toggle fly"), "keymap_freemove");
413 this->add_key(GUI_ID_KEY_FAST_BUTTON, wgettext("Toggle fast"), "keymap_fastmove");
414 this->add_key(GUI_ID_KEY_CINEMATIC_BUTTON, wgettext("Toggle Cinematic"), "keymap_cinematic");
415 this->add_key(GUI_ID_KEY_NOCLIP_BUTTON, wgettext("Toggle noclip"), "keymap_noclip");
416 this->add_key(GUI_ID_KEY_RANGE_BUTTON, wgettext("Range select"), "keymap_rangeselect");
417 this->add_key(GUI_ID_KEY_DUMP_BUTTON, wgettext("Print stacks"), "keymap_print_debug_stacks");
418 this->add_key(GUI_ID_KEY_ZOOM_BUTTON, wgettext("Zoom"), "keymap_zoom");