LCOV - code coverage report
Current view: top level - src - guiKeyChangeMenu.cpp (source / functions) Hit Total Coverage
Test: report Lines: 1 224 0.4 %
Date: 2015-07-11 18:23:49 Functions: 2 15 13.3 %

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

Generated by: LCOV version 1.11