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