Back to index

supertuxkart  0.5+dfsg1
player_controls.cpp
Go to the documentation of this file.
00001 //  $Id: player_controls.cpp 2111 2008-05-31 07:04:30Z cosmosninja $
00002 //
00003 //  SuperTuxKart - a fun racing game with go-kart
00004 //  Copyright (C) 2006 SuperTuxKart-Team
00005 //
00006 //  This program is free software; you can redistribute it and/or
00007 //  modify it under the terms of the GNU General Public License
00008 //  as published by the Free Software Foundation; either version 2
00009 //  of the License, or (at your option) any later version.
00010 //
00011 //  This program is distributed in the hope that it will be useful,
00012 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //  GNU General Public License for more details.
00015 //
00016 //  You should have received a copy of the GNU General Public License
00017 //  along with this program; if not, write to the Free Software
00018 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00019 
00020 #include <SDL/SDL.h>
00021 
00022 #include "widget_manager.hpp"
00023 #include "player_controls.hpp"
00024 #include "user_config.hpp"
00025 #include "menu_manager.hpp"
00026 #include "translation.hpp"
00027 #include "sdldrv.hpp"
00028 #if defined(WIN32) && !defined(__CYGWIN__)
00029 #  define snprintf _snprintf
00030 #endif
00031 
00032 enum WidgetTokens
00033 {
00034     WTOK_TITLE,
00035     WTOK_PLYR_NAME0,
00036     WTOK_PLYR_NAME1,
00037 
00038     WTOK_LEFT,
00039     WTOK_RIGHT,
00040     WTOK_ACCEL,
00041     WTOK_BRAKE,
00042     WTOK_WHEELIE,
00043     WTOK_JUMP,
00044     WTOK_RESCUE,
00045     WTOK_FIRE,
00046     WTOK_LOOK_BACK,
00047 
00048     WTOK_KEY0,
00049     WTOK_KEY1,
00050     WTOK_KEY2,
00051     WTOK_KEY3,
00052     WTOK_KEY4,
00053     WTOK_KEY5,
00054     WTOK_KEY6,
00055     WTOK_KEY7,
00056     WTOK_KEY8,
00057 
00058     WTOK_QUIT
00059 };
00060 
00062 const size_t PlayerControls::PLAYER_NAME_MAX = 10;
00063 
00064 const char *sKartAction2String[KA_LAST+1] = {_("Left"), _("Right"), _("Accelerate"),
00065                                              _("Brake"),  _("Wheelie"), _("Jump"),
00066                                              _("Rescue"), _("Fire"), _("Look back") };
00067 
00068 
00069 PlayerControls::PlayerControls(int whichPlayer):
00070     m_player_index(whichPlayer),
00071     m_grab_input(false)
00072 {
00073     char heading[MAX_MESSAGE_LENGTH];
00074     snprintf(heading, sizeof(heading), _("Choose your controls, %s"),
00075             user_config->m_player[m_player_index].getName().c_str() );
00076 
00077     widget_manager->addTitleWgt( WTOK_TITLE, 60, 7, heading );
00078     widget_manager->breakLine();
00079 
00080     widget_manager->addTextWgt( WTOK_PLYR_NAME0, 30, 7, _("Player name") );
00081 
00082     m_name = user_config->m_player[m_player_index].getName();
00083     widget_manager->addTextButtonWgt( WTOK_PLYR_NAME1, 30, 7, m_name );
00084     widget_manager->breakLine();
00085 
00086     widget_manager->switchOrder();
00087     for(int i = KA_FIRST; i <= KA_LAST; i++)
00088     {
00089         // Note: even though that all strings in sKartAction2Strings above
00090         // are in _(), they are not translated (since gettext is actually 
00091         // called at startup (just after loading) of the program, when
00092         // gettext is not yet initialised - so it returns the untranslated
00093         // strings). So we add an additional _() here (and in help_page_one).
00094         widget_manager->addTextWgt( WTOK_KEY0 + i, 30, 7, _(sKartAction2String[i]) );
00095     }
00096     widget_manager->breakLine();
00097 
00098 
00099     KartAction control;
00100     widget_manager->switchOrder();
00101     for(int i = KA_FIRST; i <= KA_LAST; i++)
00102     {
00103         control = (KartAction)i;
00104         m_key_names[control] = user_config->getMappingAsString(m_player_index, control);
00105 
00106         widget_manager->addTextButtonWgt( WTOK_LEFT + i, 30, 7,
00107             m_key_names[control].c_str());
00108     }
00109     widget_manager->breakLine();
00110     widget_manager->breakLine();
00111 
00112     widget_manager->addTextButtonWgt( WTOK_QUIT, 60, 7, _("Press <ESC> to go back") );
00113     widget_manager->setWgtTextSize( WTOK_QUIT, WGT_FNT_SML);
00114 
00115     widget_manager->layout(WGT_AREA_ALL);
00116 }   // PlayerControls
00117 
00118 //-----------------------------------------------------------------------------
00119 PlayerControls::~PlayerControls()
00120 {
00121     widget_manager->reset();
00122     // The unicode translation is not generally needed, so disable it again.
00123 }   // ~PlayerControls
00124 
00125 //-----------------------------------------------------------------------------
00126 void
00127 PlayerControls::select()
00128 {
00129     const int selected = widget_manager->getSelectedWgt();
00130        switch (selected)
00131        {
00132               case WTOK_PLYR_NAME1:
00133                      // Switch to typing in the player's name.
00134                      widget_manager->setWgtText(WTOK_PLYR_NAME1, (m_name + "<").c_str());
00135               
00136                      inputDriver->setMode(LOWLEVEL);
00137               
00138               break;
00139               case WTOK_QUIT:
00140                      // Leave menu.
00141                menu_manager->popMenu();
00142               
00143                      break;
00144               default:
00145                      // Switch to input sensing.
00146 
00147                      // If the only remaining and not yet handled widgets are the ones
00148                      // that deal with the kart controls and the values are still in the
00149                      // correct order the assertion should hold. If not did something
00150                      // bad.
00151                      assert (selected >= WTOK_LEFT
00152                                    && selected <= WTOK_LOOK_BACK);
00153               
00154                      
00155                   m_edit_action = static_cast<KartAction>(selected - WTOK_LEFT);
00156                   widget_manager->setWgtText(selected, _("Press key"));
00157                      
00158                      inputDriver->setMode(INPUT_SENSE);
00159                      
00160                      break;
00161        }
00162 }   // select
00163 //-----------------------------------------------------------------------------
00164 void
00165 PlayerControls::inputKeyboard(SDLKey key, int unicode)
00166 {
00167        switch (key)
00168        {
00169        case SDLK_RSHIFT:
00170        case SDLK_LSHIFT:
00171               // Ignore shift, otherwise shift will disable input
00172               // (making it impossible to enter upper case characters)
00173        case SDLK_SPACE:
00174               // Ignore space to prevent invisible names.
00175                      
00176               // Note: This will never happen as long as SPACE has a mapping which
00177               // causes GA_ENTER and therefore finishes the typing. Please leave this
00178               // because I am not sure whether this is good behavior (that SPACE
00179               // cannot reach inputKeyboard()) and with some changes to the input
00180               // driver this code has suddenly a useful effect.
00181        case SDLK_KP_ENTER:
00182        case SDLK_RETURN:
00183        case SDLK_ESCAPE:
00184               // Ignore some control keys. What they could provide is implemented
00185               // in the handle() method.
00186               return;
00187        case SDLK_BACKSPACE:
00188               // Handle backspace.
00189               if (m_name.size() >=1)
00190                      m_name.erase(m_name.size()-1, 1);
00191               
00192               widget_manager->setWgtText(WTOK_PLYR_NAME1, (m_name + "<").c_str());
00193               break;
00194               break;
00195        default:
00196               // Adds the character to the name.
00197               // For this menu only unicode translation is enabled.
00198               // So we use the unicode character here, since this will
00199               // take care of upper/lower case etc.
00200               if (unicode && m_name.size() <= PLAYER_NAME_MAX)
00201                      m_name += (char) unicode;
00202               widget_manager->setWgtText(WTOK_PLYR_NAME1, (m_name + "<").c_str());
00203               break;
00204        }
00205 
00206 }
00207 //-----------------------------------------------------------------------------
00208 void
00209 PlayerControls::clearMapping()
00210 {
00211        const int selected = widget_manager->getSelectedWgt();
00212        if (selected >= WTOK_LEFT && selected <= WTOK_LOOK_BACK)
00213        {
00214               user_config->clearInput(m_player_index,
00215                                                    (KartAction) (selected - WTOK_LEFT));
00216               updateAllKeyLabels();
00217        }
00218 }
00219 //-----------------------------------------------------------------------------
00220 void PlayerControls::handle(GameAction ga, int value)
00221 {
00222        if (value)
00223               return;
00224        
00225        switch (ga)
00226        {
00227               case GA_CLEAR_MAPPING:
00228             clearMapping();
00229 
00230                      break;
00231               case GA_SENSE_COMPLETE:
00232                      // Updates the configuration with the newly sensed input.
00233             user_config->setInput(m_player_index,
00234                                                           m_edit_action,
00235                                                           inputDriver->getSensedInput());
00236                      // Fall through to recover the widget labels.
00237               case GA_SENSE_CANCEL:
00238                      inputDriver->setMode(MENU);
00239               
00240                      // Refresh all key labels since they mave changed because of
00241                      // conflicting bindings.
00242                      updateAllKeyLabels();
00243                      break;
00244               case GA_ENTER:
00245                      // If the user is typing her name this will be finished at this
00246                      // point.
00247                      if (inputDriver->isInMode(LOWLEVEL))
00248                      {
00249                             // Prevents zero-length names.
00250                             if (m_name.length() == 0)
00251                                    m_name = _("Player ") + m_player_index;
00252                             user_config->m_player[m_player_index].setName(m_name);
00253                             widget_manager->setWgtText(WTOK_PLYR_NAME1, m_name.c_str());
00254 
00255                             inputDriver->setMode(MENU);
00256                      }
00257                      else
00258                             select();
00259                      break;
00260               case GA_LEAVE:
00261                      // If the user is typing her name this will be cancelled at this
00262                      // point.
00263                      if (inputDriver->isInMode(LOWLEVEL))
00264                      {
00265                             m_name = user_config->m_player[m_player_index].getName();
00266                             widget_manager->setWgtText(WTOK_PLYR_NAME1, m_name.c_str());
00267 
00268                             inputDriver->setMode(MENU);
00269                             break;
00270                      }
00271                      // Fall through to reach the usual GA_LEAVE code (leave menu).
00272               default:
00273                      BaseGUI::handle(ga, value);
00274        }
00275        
00276 }
00277 
00278 //-----------------------------------------------------------------------------
00279 void
00280 PlayerControls::updateAllKeyLabels()
00281 {
00282        for (int i = KA_FIRST; i <= KA_LAST; i++)
00283   {
00284     m_key_names[i] = user_config->getMappingAsString(m_player_index,
00285                                                                                             (KartAction) i);
00286     widget_manager->setWgtText(WTOK_LEFT + i, m_key_names[i].c_str());
00287   }
00288 }