]> git.lizzy.rs Git - minetest.git/blob - src/guiKeyChangeMenu.cpp
Add aux1_descends to key change menu
[minetest.git] / src / guiKeyChangeMenu.cpp
1 /*
2  Minetest-c55
3  Copyright (C) 2010-11 celeron55, Perttu Ahola <celeron55@gmail.com>
4  Copyright (C) 2011 Ciaran Gultnieks <ciaran@ciarang.com>
5  Copyright (C) 2011 teddydestodes <derkomtur@schattengang.net>
6
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.
11
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.
16
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.
20  */
21
22 #include "guiKeyChangeMenu.h"
23 #include "debug.h"
24 #include "serialization.h"
25 #include "main.h"
26 #include <string>
27 #include <IGUICheckBox.h>
28 #include <IGUIEditBox.h>
29 #include <IGUIButton.h>
30 #include <IGUIStaticText.h>
31 #include <IGUIFont.h>
32 #include "settings.h"
33 #include <algorithm>
34
35 #define KMaxButtonPerColumns 12
36
37 enum
38 {
39         GUI_ID_BACK_BUTTON = 101, GUI_ID_ABORT_BUTTON, GUI_ID_SCROLL_BAR,
40         // buttons
41         GUI_ID_KEY_FORWARD_BUTTON,
42         GUI_ID_KEY_BACKWARD_BUTTON,
43         GUI_ID_KEY_LEFT_BUTTON,
44         GUI_ID_KEY_RIGHT_BUTTON,
45         GUI_ID_KEY_USE_BUTTON,
46         GUI_ID_KEY_FLY_BUTTON,
47         GUI_ID_KEY_FAST_BUTTON,
48         GUI_ID_KEY_JUMP_BUTTON,
49         GUI_ID_KEY_CHAT_BUTTON,
50         GUI_ID_KEY_CMD_BUTTON,
51         GUI_ID_KEY_CONSOLE_BUTTON,
52         GUI_ID_KEY_SNEAK_BUTTON,
53         GUI_ID_KEY_DROP_BUTTON,
54         GUI_ID_KEY_INVENTORY_BUTTON,
55         GUI_ID_KEY_DUMP_BUTTON,
56         GUI_ID_KEY_RANGE_BUTTON,
57         // other
58         GUI_ID_CB_AUX1_DESCENDS,
59 };
60
61 GUIKeyChangeMenu::GUIKeyChangeMenu(gui::IGUIEnvironment* env,
62                                 gui::IGUIElement* parent, s32 id, IMenuManager *menumgr) :
63 GUIModalMenu(env, parent, id, menumgr)
64 {
65         shift_down = false;
66         activeKey = -1;
67         this->key_used_text = NULL;
68         init_keys();
69         for(size_t i=0; i<key_settings.size(); i++)
70                 this->key_used.push_back(key_settings.at(i)->key);
71 }
72
73 GUIKeyChangeMenu::~GUIKeyChangeMenu()
74 {
75         removeChildren();
76 }
77
78 void GUIKeyChangeMenu::removeChildren()
79 {
80         const core::list<gui::IGUIElement*> &children = getChildren();
81         core::list<gui::IGUIElement*> children_copy;
82         for (core::list<gui::IGUIElement*>::ConstIterator i = children.begin(); i
83                  != children.end(); i++)
84         {
85                 children_copy.push_back(*i);
86         }
87         for (core::list<gui::IGUIElement*>::Iterator i = children_copy.begin(); i
88                  != children_copy.end(); i++)
89         {
90                 (*i)->remove();
91         }
92 }
93
94 void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
95 {
96         removeChildren();
97         v2s32 size(620, 430);
98         
99         core::rect < s32 > rect(screensize.X / 2 - size.X / 2,
100                                                         screensize.Y / 2 - size.Y / 2, screensize.X / 2 + size.X / 2,
101                                                         screensize.Y / 2 + size.Y / 2);
102
103         DesiredRect = rect;
104         recalculateAbsolutePosition(false);
105
106         v2s32 topleft(0, 0);
107         changeCtype("");
108         {
109                 core::rect < s32 > rect(0, 0, 600, 40);
110                 rect += topleft + v2s32(25, 3);
111                 //gui::IGUIStaticText *t =
112                 Environment->addStaticText(wgettext("Keybindings. (If this menu screws up, remove stuff from minetest.conf)"),
113                                                                    rect, false, true, this, -1);
114                 //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
115         }
116
117         // Build buttons
118
119         v2s32 offset(25, 60);
120
121         for(size_t i = 0; i < key_settings.size(); i++)
122         {
123                 key_setting *k = key_settings.at(i);
124                 {
125                         core::rect < s32 > rect(0, 0, 100, 20);
126                         rect += topleft + v2s32(offset.X, offset.Y);
127                         Environment->addStaticText(k->button_name, rect, false, true, this, -1);
128                 }
129
130                 {
131                         core::rect < s32 > rect(0, 0, 100, 30);
132                         rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
133                         k->button = Environment->addButton(rect, this, k->id, wgettext(k->key.name()));
134                 }
135                 if(i + 1 == KMaxButtonPerColumns)
136                         offset = v2s32(250, 60);
137                 else
138                         offset += v2s32(0, 25);
139         }
140         
141         {
142                 s32 option_x = offset.X + 10;
143                 s32 option_y = offset.Y;
144                 u32 option_w = 180;
145                 {
146                         core::rect<s32> rect(0, 0, option_w, 30);
147                         rect += topleft + v2s32(option_x, option_y);
148                         Environment->addCheckBox(g_settings->getBool("aux1_descends"), rect, this,
149                                         GUI_ID_CB_AUX1_DESCENDS, wgettext("\"Use\" = climb down"));
150                 }
151         }
152
153         {
154                 core::rect < s32 > rect(0, 0, 100, 30);
155                 rect += topleft + v2s32(size.X - 100 - 20, size.Y - 40);
156                 Environment->addButton(rect, this, GUI_ID_BACK_BUTTON,
157                                                            wgettext("Save"));
158         }
159         {
160                 core::rect < s32 > rect(0, 0, 100, 30);
161                 rect += topleft + v2s32(size.X - 100 - 20 - 100 - 20, size.Y - 40);
162                 Environment->addButton(rect, this, GUI_ID_ABORT_BUTTON,
163                                                            wgettext("Cancel"));
164         }
165         changeCtype("C");
166         
167 }
168
169 void GUIKeyChangeMenu::drawMenu()
170 {
171         gui::IGUISkin* skin = Environment->getSkin();
172         if (!skin)
173                 return;
174         video::IVideoDriver* driver = Environment->getVideoDriver();
175
176         video::SColor bgcolor(140, 0, 0, 0);
177
178         {
179                 core::rect < s32 > rect(0, 0, 620, 620);
180                 rect += AbsoluteRect.UpperLeftCorner;
181                 driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
182         }
183
184         gui::IGUIElement::draw();
185 }
186
187 bool GUIKeyChangeMenu::acceptInput()
188 {
189         for(size_t i = 0; i < key_settings.size(); i++)
190         {
191                 key_setting *k = key_settings.at(i);
192                 g_settings->set(k->setting_name, k->key.sym());
193         }
194         {
195                 gui::IGUIElement *e = getElementFromId(GUI_ID_CB_AUX1_DESCENDS);
196                 if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
197                         g_settings->setBool("aux1_descends", ((gui::IGUICheckBox*)e)->isChecked());
198         }
199         clearKeyCache();
200         return true;
201 }
202
203 bool GUIKeyChangeMenu::resetMenu()
204 {
205         if (activeKey >= 0)
206         {
207                 for(size_t i = 0; i < key_settings.size(); i++)
208                 {
209                         key_setting *k = key_settings.at(i);
210                         if(k->id == activeKey)
211                         {
212                                 k->button->setText(wgettext(k->key.name()));
213                                 break;
214                         }
215                 }
216                 activeKey = -1;
217                 return false;
218         }
219         return true;
220 }
221 bool GUIKeyChangeMenu::OnEvent(const SEvent& event)
222 {
223         if (event.EventType == EET_KEY_INPUT_EVENT && activeKey >= 0
224                 && event.KeyInput.PressedDown)
225         {
226                 changeCtype("");
227                 bool prefer_character = shift_down;
228                 KeyPress kp(event.KeyInput, prefer_character);
229                 
230                 bool shift_went_down = false;
231                 if(!shift_down &&
232                                 (event.KeyInput.Key == irr::KEY_SHIFT ||
233                                 event.KeyInput.Key == irr::KEY_LSHIFT ||
234                                 event.KeyInput.Key == irr::KEY_RSHIFT))
235                         shift_went_down = true;
236
237                 // Remove Key already in use message
238                 if(this->key_used_text)
239                 {
240                         this->key_used_text->remove();
241                         this->key_used_text = NULL;
242                 }
243                 // Display Key already in use message
244                 if (std::find(this->key_used.begin(), this->key_used.end(), kp) != this->key_used.end())
245                 {
246                         core::rect < s32 > rect(0, 0, 600, 40);
247                         rect += v2s32(0, 0) + v2s32(25, 30);
248                         this->key_used_text = Environment->addStaticText(wgettext("Key already in use"),
249                                                                         rect, false, true, this, -1);
250                         //infostream << "Key already in use" << std::endl;
251                 }
252
253                 // But go on
254                 {
255                         key_setting *k=NULL;
256                         for(size_t i = 0; i < key_settings.size(); i++)
257                         {
258                                 if(key_settings.at(i)->id == activeKey)
259                                 {
260                                         k = key_settings.at(i);
261                                         break;
262                                 }
263                         }
264                         assert(k);
265                         k->key = kp;
266                         k->button->setText(wgettext(k->key.name()));
267
268                         this->key_used.push_back(kp);
269
270                         changeCtype("C");
271                         // Allow characters made with shift
272                         if(shift_went_down){
273                                 shift_down = true;
274                                 return false;
275                         }else{
276                                 activeKey = -1;
277                                 return true;
278                         }
279                 }
280         }
281         if (event.EventType == EET_GUI_EVENT)
282         {
283                 if (event.GUIEvent.EventType == gui::EGET_ELEMENT_FOCUS_LOST
284                         && isVisible())
285                 {
286                         if (!canTakeFocus(event.GUIEvent.Element))
287                         {
288                                 dstream << "GUIMainMenu: Not allowing focus change."
289                                 << std::endl;
290                                 // Returning true disables focus change
291                                 return true;
292                         }
293                 }
294                 if (event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED)
295                 {
296                         if(event.GUIEvent.Caller->getID() != GUI_ID_BACK_BUTTON &&
297                            event.GUIEvent.Caller->getID() != GUI_ID_ABORT_BUTTON)
298                         {
299                                 changeCtype("");
300                         }
301
302                         switch (event.GUIEvent.Caller->getID())
303                         {
304                                 case GUI_ID_BACK_BUTTON: //back
305                                         acceptInput();
306                                         quitMenu();
307                                         return true;
308                                 case GUI_ID_ABORT_BUTTON: //abort
309                                         quitMenu();
310                                         return true;
311                                 default:
312                                         key_setting *k = NULL;
313                                         for(size_t i = 0; i < key_settings.size(); i++)
314                                         {
315                                                 if(key_settings.at(i)->id == event.GUIEvent.Caller->getID())
316                                                 {
317                                                         k = key_settings.at(i);
318                                                         break;
319                                                 }
320                                         }
321                                         assert(k);
322
323                                         resetMenu();
324                                         shift_down = false;
325                                         activeKey = event.GUIEvent.Caller->getID();
326                                         k->button->setText(wgettext("press key"));
327                                         this->key_used.erase(std::remove(this->key_used.begin(),
328                                                         this->key_used.end(), k->key), this->key_used.end());
329                                         break;
330                         }
331                         Environment->setFocus(this);
332                         //Buttons
333                         changeCtype("C");
334                 }
335         }
336         return Parent ? Parent->OnEvent(event) : false;
337 }
338
339 void GUIKeyChangeMenu::add_key(int id, std::string button_name, std::string setting_name)
340 {
341         key_setting *k = new key_setting;
342         k->id = id;
343         k->button_name = wgettext(button_name.c_str());
344         k->setting_name = setting_name;
345         k->key = getKeySetting(k->setting_name.c_str());
346         key_settings.push_back(k);
347 }
348
349 void GUIKeyChangeMenu::init_keys()
350 {
351         this->add_key(GUI_ID_KEY_FORWARD_BUTTON, "Forward", "keymap_forward");
352         this->add_key(GUI_ID_KEY_BACKWARD_BUTTON, "Backward", "keymap_backward");
353         this->add_key(GUI_ID_KEY_LEFT_BUTTON, "Left", "keymap_left");
354         this->add_key(GUI_ID_KEY_RIGHT_BUTTON, "Right", "keymap_right");
355         this->add_key(GUI_ID_KEY_USE_BUTTON, "Use", "keymap_special1");
356         this->add_key(GUI_ID_KEY_JUMP_BUTTON, "Jump", "keymap_jump");
357         this->add_key(GUI_ID_KEY_SNEAK_BUTTON, "Sneak", "keymap_sneak");
358         this->add_key(GUI_ID_KEY_DROP_BUTTON, "Drop", "keymap_drop");
359         this->add_key(GUI_ID_KEY_INVENTORY_BUTTON, "Inventory", "keymap_inventory");
360         this->add_key(GUI_ID_KEY_CHAT_BUTTON, "Chat", "keymap_chat");
361         this->add_key(GUI_ID_KEY_CMD_BUTTON, "Command", "keymap_cmd");
362         this->add_key(GUI_ID_KEY_CONSOLE_BUTTON, "Console", "keymap_console");
363         this->add_key(GUI_ID_KEY_FLY_BUTTON, "Toggle fly", "keymap_freemove");
364         this->add_key(GUI_ID_KEY_FAST_BUTTON, "Toggle fast", "keymap_fastmove");
365         this->add_key(GUI_ID_KEY_RANGE_BUTTON, "Range select", "keymap_rangeselect");
366         this->add_key(GUI_ID_KEY_DUMP_BUTTON, "Print stacks", "keymap_print_debug_stacks");
367 }