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_DUMP_BUTTON,
62 GUI_ID_KEY_RANGE_BUTTON,
63 GUI_ID_KEY_ZOOM_BUTTON,
65 GUI_ID_CB_AUX1_DESCENDS,
66 GUI_ID_CB_DOUBLETAP_JUMP,
69 GUIKeyChangeMenu::GUIKeyChangeMenu(gui::IGUIEnvironment* env,
70 gui::IGUIElement* parent, s32 id, IMenuManager *menumgr) :
71 GUIModalMenu(env, parent, id, menumgr)
75 this->key_used_text = NULL;
77 for(size_t i=0; i<key_settings.size(); i++)
78 this->key_used.push_back(key_settings.at(i)->key);
81 GUIKeyChangeMenu::~GUIKeyChangeMenu()
85 for (std::vector<key_setting*>::iterator iter = key_settings.begin();
86 iter != key_settings.end(); ++iter) {
87 delete[] (*iter)->button_name;
93 void GUIKeyChangeMenu::removeChildren()
95 const core::list<gui::IGUIElement*> &children = getChildren();
96 core::list<gui::IGUIElement*> children_copy;
97 for (core::list<gui::IGUIElement*>::ConstIterator i = children.begin(); i
98 != children.end(); i++)
100 children_copy.push_back(*i);
102 for (core::list<gui::IGUIElement*>::Iterator i = children_copy.begin(); i
103 != children_copy.end(); i++)
109 void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
112 v2s32 size(620, 430);
114 core::rect < s32 > rect(screensize.X / 2 - size.X / 2,
115 screensize.Y / 2 - size.Y / 2, screensize.X / 2 + size.X / 2,
116 screensize.Y / 2 + size.Y / 2);
119 recalculateAbsolutePosition(false);
124 core::rect < s32 > rect(0, 0, 600, 40);
125 rect += topleft + v2s32(25, 3);
126 //gui::IGUIStaticText *t =
127 const wchar_t *text = wgettext("Keybindings. (If this menu screws up, remove stuff from minetest.conf)");
128 Environment->addStaticText(text,
129 rect, false, true, this, -1);
131 //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
136 v2s32 offset(25, 60);
138 for(size_t i = 0; i < key_settings.size(); i++)
140 key_setting *k = key_settings.at(i);
142 core::rect < s32 > rect(0, 0, 150, 20);
143 rect += topleft + v2s32(offset.X, offset.Y);
144 Environment->addStaticText(k->button_name, rect, false, true, this, -1);
148 core::rect < s32 > rect(0, 0, 100, 30);
149 rect += topleft + v2s32(offset.X + 115, offset.Y - 5);
150 const wchar_t *text = wgettext(k->key.name());
151 k->button = Environment->addButton(rect, this, k->id, text);
154 if(i + 1 == KMaxButtonPerColumns)
155 offset = v2s32(260, 60);
157 offset += v2s32(0, 25);
161 s32 option_x = offset.X;
162 s32 option_y = offset.Y + 5;
165 core::rect<s32> rect(0, 0, option_w, 30);
166 rect += topleft + v2s32(option_x, option_y);
167 const wchar_t *text = wgettext("\"Use\" = climb down");
168 Environment->addCheckBox(g_settings->getBool("aux1_descends"), rect, this,
169 GUI_ID_CB_AUX1_DESCENDS, text);
172 offset += v2s32(0, 25);
176 s32 option_x = offset.X;
177 s32 option_y = offset.Y + 5;
180 core::rect<s32> rect(0, 0, option_w, 30);
181 rect += topleft + v2s32(option_x, option_y);
182 const wchar_t *text = wgettext("Double tap \"jump\" to toggle fly");
183 Environment->addCheckBox(g_settings->getBool("doubletap_jump"), rect, this,
184 GUI_ID_CB_DOUBLETAP_JUMP, text);
187 offset += v2s32(0, 25);
191 core::rect < s32 > rect(0, 0, 100, 30);
192 rect += topleft + v2s32(size.X / 2 - 105, size.Y - 40);
193 const wchar_t *text = wgettext("Save");
194 Environment->addButton(rect, this, GUI_ID_BACK_BUTTON,
199 core::rect < s32 > rect(0, 0, 100, 30);
200 rect += topleft + v2s32(size.X / 2 + 5, size.Y - 40);
201 const wchar_t *text = wgettext("Cancel");
202 Environment->addButton(rect, this, GUI_ID_ABORT_BUTTON,
208 void GUIKeyChangeMenu::drawMenu()
210 gui::IGUISkin* skin = Environment->getSkin();
213 video::IVideoDriver* driver = Environment->getVideoDriver();
215 video::SColor bgcolor(140, 0, 0, 0);
218 core::rect < s32 > rect(0, 0, 620, 620);
219 rect += AbsoluteRect.UpperLeftCorner;
220 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
223 gui::IGUIElement::draw();
226 bool GUIKeyChangeMenu::acceptInput()
228 for(size_t i = 0; i < key_settings.size(); i++)
230 key_setting *k = key_settings.at(i);
231 g_settings->set(k->setting_name, k->key.sym());
234 gui::IGUIElement *e = getElementFromId(GUI_ID_CB_AUX1_DESCENDS);
235 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
236 g_settings->setBool("aux1_descends", ((gui::IGUICheckBox*)e)->isChecked());
239 gui::IGUIElement *e = getElementFromId(GUI_ID_CB_DOUBLETAP_JUMP);
240 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
241 g_settings->setBool("doubletap_jump", ((gui::IGUICheckBox*)e)->isChecked());
246 g_gamecallback->signalKeyConfigChange();
251 bool GUIKeyChangeMenu::resetMenu()
255 for(size_t i = 0; i < key_settings.size(); i++)
257 key_setting *k = key_settings.at(i);
258 if(k->id == activeKey)
260 const wchar_t *text = wgettext(k->key.name());
261 k->button->setText(text);
271 bool GUIKeyChangeMenu::OnEvent(const SEvent& event)
273 if (event.EventType == EET_KEY_INPUT_EVENT && activeKey >= 0
274 && event.KeyInput.PressedDown) {
276 bool prefer_character = shift_down;
277 KeyPress kp(event.KeyInput, prefer_character);
279 bool shift_went_down = false;
281 (event.KeyInput.Key == irr::KEY_SHIFT ||
282 event.KeyInput.Key == irr::KEY_LSHIFT ||
283 event.KeyInput.Key == irr::KEY_RSHIFT))
284 shift_went_down = true;
286 // Remove Key already in use message
287 if(this->key_used_text)
289 this->key_used_text->remove();
290 this->key_used_text = NULL;
292 // Display Key already in use message
293 if (std::find(this->key_used.begin(), this->key_used.end(), kp) != this->key_used.end())
295 core::rect < s32 > rect(0, 0, 600, 40);
296 rect += v2s32(0, 0) + v2s32(25, 30);
297 const wchar_t *text = wgettext("Key already in use");
298 this->key_used_text = Environment->addStaticText(text,
299 rect, false, true, this, -1);
301 //infostream << "Key already in use" << std::endl;
306 key_setting *k = NULL;
307 for(size_t i = 0; i < key_settings.size(); i++)
309 if(key_settings.at(i)->id == activeKey)
311 k = key_settings.at(i);
315 FATAL_ERROR_IF(k == NULL, "Key setting not found");
317 const wchar_t *text = wgettext(k->key.name());
318 k->button->setText(text);
321 this->key_used.push_back(kp);
323 // Allow characters made with shift
332 } else if (event.EventType == EET_KEY_INPUT_EVENT && activeKey < 0
333 && event.KeyInput.PressedDown
334 && event.KeyInput.Key == irr::KEY_ESCAPE) {
337 } else if (event.EventType == EET_GUI_EVENT) {
338 if (event.GUIEvent.EventType == gui::EGET_ELEMENT_FOCUS_LOST
341 if (!canTakeFocus(event.GUIEvent.Element))
343 dstream << "GUIMainMenu: Not allowing focus change."
345 // Returning true disables focus change
349 if (event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED)
351 switch (event.GUIEvent.Caller->getID())
353 case GUI_ID_BACK_BUTTON: //back
357 case GUI_ID_ABORT_BUTTON: //abort
361 key_setting *k = NULL;
362 for(size_t i = 0; i < key_settings.size(); i++)
364 if(key_settings.at(i)->id == event.GUIEvent.Caller->getID())
366 k = key_settings.at(i);
370 FATAL_ERROR_IF(k == NULL, "Key setting not found");
374 activeKey = event.GUIEvent.Caller->getID();
375 const wchar_t *text = wgettext("press key");
376 k->button->setText(text);
378 this->key_used.erase(std::remove(this->key_used.begin(),
379 this->key_used.end(), k->key), this->key_used.end());
382 Environment->setFocus(this);
385 return Parent ? Parent->OnEvent(event) : false;
388 void GUIKeyChangeMenu::add_key(int id, const wchar_t *button_name, const std::string &setting_name)
390 key_setting *k = new key_setting;
393 k->button_name = button_name;
394 k->setting_name = setting_name;
395 k->key = getKeySetting(k->setting_name.c_str());
396 key_settings.push_back(k);
399 void GUIKeyChangeMenu::init_keys()
401 this->add_key(GUI_ID_KEY_FORWARD_BUTTON, wgettext("Forward"), "keymap_forward");
402 this->add_key(GUI_ID_KEY_BACKWARD_BUTTON, wgettext("Backward"), "keymap_backward");
403 this->add_key(GUI_ID_KEY_LEFT_BUTTON, wgettext("Left"), "keymap_left");
404 this->add_key(GUI_ID_KEY_RIGHT_BUTTON, wgettext("Right"), "keymap_right");
405 this->add_key(GUI_ID_KEY_USE_BUTTON, wgettext("Use"), "keymap_special1");
406 this->add_key(GUI_ID_KEY_JUMP_BUTTON, wgettext("Jump"), "keymap_jump");
407 this->add_key(GUI_ID_KEY_SNEAK_BUTTON, wgettext("Sneak"), "keymap_sneak");
408 this->add_key(GUI_ID_KEY_DROP_BUTTON, wgettext("Drop"), "keymap_drop");
409 this->add_key(GUI_ID_KEY_INVENTORY_BUTTON, wgettext("Inventory"), "keymap_inventory");
410 this->add_key(GUI_ID_KEY_CHAT_BUTTON, wgettext("Chat"), "keymap_chat");
411 this->add_key(GUI_ID_KEY_CMD_BUTTON, wgettext("Command"), "keymap_cmd");
412 this->add_key(GUI_ID_KEY_CMD_LOCAL_BUTTON, wgettext("Local command"), "keymap_cmd_local");
413 this->add_key(GUI_ID_KEY_CONSOLE_BUTTON, wgettext("Console"), "keymap_console");
414 this->add_key(GUI_ID_KEY_FLY_BUTTON, wgettext("Toggle fly"), "keymap_freemove");
415 this->add_key(GUI_ID_KEY_FAST_BUTTON, wgettext("Toggle fast"), "keymap_fastmove");
416 this->add_key(GUI_ID_KEY_CINEMATIC_BUTTON, wgettext("Toggle Cinematic"), "keymap_cinematic");
417 this->add_key(GUI_ID_KEY_NOCLIP_BUTTON, wgettext("Toggle noclip"), "keymap_noclip");
418 this->add_key(GUI_ID_KEY_RANGE_BUTTON, wgettext("Range select"), "keymap_rangeselect");
419 this->add_key(GUI_ID_KEY_DUMP_BUTTON, wgettext("Print stacks"), "keymap_print_debug_stacks");
420 this->add_key(GUI_ID_KEY_ZOOM_BUTTON, wgettext("Zoom"), "keymap_zoom");