00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "MenuManager.h"
00015
00016 #include <cctype>
00017 #include "../Game/PlayerController.h"
00018 #include "../Util/GeneralException.h"
00019 #include "../Util/StringUtil.h"
00020 #include "../Util/STL_Helper.h"
00021
00022 using namespace Menu;
00023
00024 bool KeyMapContainer::initialized=false;
00025 KeyToStringMap_t KeyMapContainer::keyStringMap;
00026 StringToKeyMap_t KeyMapContainer::stringKeyMap;
00027
00028 #ifdef HAVE_SDL_TTF
00029
00030 MenuManager::MenuManager(const std::string& t, const SDL_Color& titleColor, const SDL_Color& bg ) :
00031 title(t),
00032 fontSize(DEFAULT_FONT_SIZE),
00033 titleCol(titleColor),
00034 bgCol(bg)
00035 {
00036 font = TTF_OpenFont(DEFAULT_FONT, DEFAULT_FONT_SIZE);
00037 if (font==NULL) throw Util::GeneralException(std::string("font ") + DEFAULT_FONT + " could not be opened",
00038 __FILE__, __LINE__);
00039
00040 currentSelection=0;
00041 }
00042
00043 bool MenuManager::run(SDL_Surface* screen) {
00044 itemVec[currentSelection]->select();
00045 SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, bgCol.r, bgCol.g, bgCol.b));
00046 while (1) {
00047 SDL_Event event;
00048 bool somethingHappened=false;
00049 while (SDL_PollEvent(&event)) {
00050 somethingHappened=true;
00051 MenuHandleResult result = itemVec[currentSelection]->handleEvent(&event);
00052 if (MENU_QUIT == result) return true;
00053 if (EVENT_HANDLED == result) {
00054 SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, bgCol.r, bgCol.g, bgCol.b));
00055 continue;
00056 }
00057
00058 switch (event.type) {
00059 case SDL_KEYDOWN:
00060 switch (event.key.keysym.sym) {
00061 case SDLK_ESCAPE: return true; break;
00062 case SDLK_DOWN: {
00063 itemVec[currentSelection]->deselect();
00064 currentSelection = (currentSelection + 1) % itemVec.size();
00065 itemVec[currentSelection]->select();
00066 }
00067 break;
00068 case SDLK_UP: {
00069 itemVec[currentSelection]->deselect();
00070 currentSelection = (currentSelection == 0) ? itemVec.size() - 1 : currentSelection -1;
00071 itemVec[currentSelection]->select();
00072 }
00073 break;
00074 }
00075 break;
00076 }
00077 }
00078
00079 if (somethingHappened) {
00080 SDL_Surface* titleText = TTF_RenderText_Solid(font, title.c_str(), titleCol);
00081 if (titleText == NULL) throw Util::GeneralException("Menu could not render text title", __FILE__, __LINE__);
00082 SDL_Rect rect;
00083
00084 rect.x = TEXT_CENTER_X - titleText->w/2;
00085 rect.y = TITLE_OFFSET_FROM_TOP;
00086
00087 SDL_BlitSurface(titleText, NULL, screen, &rect);
00088 SDL_FreeSurface(titleText);
00089
00090 rect.x = TEXT_CENTER_X;
00091 rect.y += VERTICAL_SPACING + DEFAULT_FONT_SIZE;
00092 for (std::vector<MenuItem*>::iterator i = itemVec.begin(); i != itemVec.end(); i++) {
00093 rect.y += VERTICAL_SPACING + DEFAULT_FONT_SIZE;
00094 (*i)->draw(screen, font, rect.x, rect.y);
00095 }
00096
00097 SDL_Flip(screen);
00098 }
00099 }
00100 }
00101
00102 void MenuManager::addMenuItem(MenuItem* item) {
00103 itemVec.push_back(item);
00104 }
00105
00106 MenuManager::~MenuManager() {
00107 Util::freeDynamicContainer(itemVec);
00108 TTF_CloseFont(font);
00109 }
00110
00111 DefaultMenuItem::DefaultMenuItem(const std::string& n, const SDL_Color& selected, const SDL_Color& deselected) :
00112 name(n),
00113 selectedColor(selected),
00114 deselectedColor(deselected),
00115 isSelected(false)
00116 {
00117 }
00118
00119 void DefaultMenuItem::select() {
00120 isSelected=true;
00121 }
00122
00123 void DefaultMenuItem::deselect() {
00124 isSelected=false;
00125 }
00126
00127 void DefaultMenuItem::draw(SDL_Surface* surf, TTF_Font* font, int centerX, int centerY) {
00128 SDL_Surface* text = NULL;
00129 SDL_Rect r;
00130
00131 text = TTF_RenderText_Solid(font, name.c_str(), getCurrentColor());
00132
00133 r.x = centerX - text->w / 2;
00134 r.y = centerY - text->h / 2;
00135
00136 SDL_BlitSurface(text, NULL, surf, &r);
00137 SDL_FreeSurface(text);
00138 }
00139
00140 const SDL_Color& DefaultMenuItem::getCurrentColor() {
00141 if (isSelected) return selectedColor;
00142 return deselectedColor;
00143 }
00144
00145 BooleanItem::BooleanItem(const std::string& name, bool& b, const SDL_Color& s, const SDL_Color& u) :
00146 DefaultMenuItem(name, s, u),
00147 optionEnabled(b)
00148 { }
00149
00150 MenuHandleResult BooleanItem::handleEvent(SDL_Event* e) {
00151 if (e->type == SDL_KEYDOWN && e->key.keysym.sym == SDLK_RETURN) {
00152 optionEnabled = !optionEnabled;
00153 return EVENT_HANDLED;
00154 }
00155 return EVENT_PASSED;
00156 }
00157
00158 void BooleanItem::draw(SDL_Surface* surf, TTF_Font* font, int centerX, int centerY) {
00159 DefaultMenuItem::draw(surf, font, centerX, centerY);
00160 SDL_Surface* optionText = NULL;
00161 SDL_Rect r;
00162
00163 if (optionEnabled) optionText = TTF_RenderText_Solid(font, "enabled", getCurrentColor());
00164 else optionText = TTF_RenderText_Solid(font, "disabled", getCurrentColor());
00165
00166 r.x = centerX + INPUT_HORIZ_SPACE;
00167 r.y = centerY - optionText->h/2;
00168 r.w = optionText->w;
00169 r.h = optionText->h;
00170
00171 SDL_BlitSurface(optionText, NULL, surf, &r);
00172 SDL_FreeSurface(optionText);
00173 }
00174
00175 GotoSubMenu::GotoSubMenu(const std::string& title, MenuManager& m, SDL_Surface* surf,
00176 const SDL_Color& s, const SDL_Color& u) :
00177 DefaultMenuItem(title, s, u),
00178 menu(m),
00179 screen(surf)
00180 { }
00181
00182 MenuHandleResult GotoSubMenu::handleEvent(SDL_Event* e) {
00183 if (e->type == SDL_KEYDOWN && e->key.keysym.sym == SDLK_RETURN) {
00184
00185 menu.run(screen);
00186 return EVENT_HANDLED;
00187 }
00188 return EVENT_PASSED;
00189 }
00190
00191 InputGetter::InputGetter(const std::string& n, const SDL_Color& s, const SDL_Color& u, const SDL_Color& a) :
00192 DefaultMenuItem(n, s, u),
00193 activeCol(a),
00194 active(false)
00195 { }
00196
00197 MenuHandleResult InputGetter::handleEvent(SDL_Event* e) {
00198 if (e->type != SDL_KEYDOWN) return EVENT_PASSED;
00199 SDLKey newKey = e->key.keysym.sym;
00200
00201
00202 if (!active) {
00203 if (newKey != SDLK_RETURN) return EVENT_PASSED;
00204 else {
00205 active = true;
00206 return EVENT_HANDLED;
00207 }
00208 }
00209
00210 if (newKey == SDLK_ESCAPE) {
00211 active = false;
00212 return EVENT_HANDLED;
00213 }
00214 return EVENT_PASSED;
00215 }
00216
00217 const SDL_Color& InputGetter::getCurrentColor() {
00218 if (active) return activeCol;
00219 return DefaultMenuItem::getCurrentColor();
00220 }
00221
00222 KeyInputter::KeyInputter(const std::string& title, SDLKey& k,
00223 const SDL_Color & sel, const SDL_Color& unsel, const SDL_Color& act) :
00224 InputGetter(title, sel, unsel, act),
00225 key(k)
00226 { }
00227
00228 void KeyInputter::draw(SDL_Surface* surf, TTF_Font* font, int centerX, int centerY) {
00229 InputGetter::draw(surf, font, centerX, centerY);
00230
00231 SDL_Surface* keyText=NULL;
00232 std::string keyName;
00233 SDL_Rect r;
00234
00235 const KeyToStringMap_t& keyMap = KeyMapContainer::getKeyToStringMap();
00236 if (keyMap.find(key) != keyMap.end()) keyName = keyMap.find(key)->second;
00237 else keyName = "No Key";
00238
00239 keyText = TTF_RenderText_Solid(font, keyName.c_str(), getCurrentColor());
00240
00241 r.x = centerX + INPUT_HORIZ_SPACE;
00242 r.y = centerY - keyText->h /2;
00243 r.w = keyText->w;
00244 r.h = keyText->h;
00245
00246 SDL_BlitSurface(keyText, NULL, surf, &r);
00247 SDL_FreeSurface(keyText);
00248 }
00249
00250 MenuHandleResult KeyInputter::handleEvent(SDL_Event* e) {
00251 MenuHandleResult r = InputGetter::handleEvent(e);
00252 if (EVENT_HANDLED == r) return EVENT_HANDLED;
00253
00254 if (isActive()) {
00255 SDLKey newKey = e->key.keysym.sym;
00256
00257 const KeyToStringMap_t& keyMap = KeyMapContainer::getKeyToStringMap();
00258
00259 if (keyMap.find(newKey) != keyMap.end()) {
00260 key = newKey;
00261 return EVENT_HANDLED;
00262 }
00263 }
00264
00265 return EVENT_PASSED;
00266 }
00267
00268 IntInputter::IntInputter(const std::string& name, int& i, int min_, int max_,
00269 const SDL_Color& s, const SDL_Color& u, const SDL_Color& a) :
00270 InputGetter(name, s, u, a),
00271 storageInt(i),
00272 min(min_),
00273 max(max_)
00274 { }
00275
00276 #include <iostream>
00277
00278 MenuHandleResult IntInputter::handleEvent(SDL_Event* e) {
00279 MenuHandleResult r = InputGetter::handleEvent(e);
00280 if (EVENT_HANDLED == r) return EVENT_HANDLED;
00281
00282 if (isActive()) {
00283 if (e->type != SDL_KEYDOWN) return EVENT_PASSED;
00284
00285 SDLKey newKey = e->key.keysym.sym;
00286
00287 if (newKey == SDLK_UP) {
00288 storageInt++;
00289 if (storageInt > max) storageInt = max;
00290 return EVENT_HANDLED;
00291 }
00292
00293 if (newKey == SDLK_DOWN) {
00294 storageInt--;
00295 if (storageInt < min) storageInt = min;
00296 return EVENT_HANDLED;
00297 }
00298
00299 std::string keyName;
00300 const KeyToStringMap_t& keyMap = KeyMapContainer::getKeyToStringMap();
00301 if (keyMap.find(newKey) != keyMap.end()) keyName = keyMap.find(newKey)->second;
00302
00303 int pressedInt=-1;
00304 for (size_t i = 0; i < keyName.length(); i++) {
00305 if (isdigit(keyName[i])) pressedInt = keyName[i] - '0';
00306 }
00307
00308 if (pressedInt >= min && pressedInt <= max) {
00309 storageInt = pressedInt;
00310 return EVENT_HANDLED;
00311 }
00312 }
00313 return EVENT_PASSED;
00314 }
00315
00316 void IntInputter::draw(SDL_Surface* surf, TTF_Font* font, int centerX, int centerY) {
00317 InputGetter::draw(surf, font, centerX, centerY);
00318 SDL_Surface* intText = TTF_RenderText_Solid(font, Util::toString<int>(storageInt).c_str(), getCurrentColor());
00319 SDL_Rect r;
00320
00321 r.x = centerX + INPUT_HORIZ_SPACE;
00322 r.y = centerY - intText->h /2;
00323 r.w = intText->w;
00324 r.h = intText->h;
00325
00326 SDL_BlitSurface(intText, NULL, surf, &r);
00327 SDL_FreeSurface(intText);
00328 }
00329
00330 #endif // ifdef HAVE_SDL_TTF
00331
00332 void KeyMapContainer::init() {
00333 addPair("a", SDLK_a);
00334 addPair("b", SDLK_b);
00335 addPair("c", SDLK_c);
00336 addPair("d", SDLK_d);
00337 addPair("e", SDLK_e);
00338 addPair("f", SDLK_f);
00339 addPair("g", SDLK_g);
00340 addPair("h", SDLK_h);
00341 addPair("i", SDLK_i);
00342 addPair("j", SDLK_j);
00343 addPair("k", SDLK_k);
00344 addPair("l", SDLK_l);
00345 addPair("m", SDLK_m);
00346 addPair("n", SDLK_n);
00347 addPair("o", SDLK_o);
00348 addPair("p", SDLK_p);
00349 addPair("q", SDLK_q);
00350 addPair("r", SDLK_r);
00351 addPair("s", SDLK_s);
00352 addPair("t", SDLK_t);
00353 addPair("u", SDLK_u);
00354 addPair("v", SDLK_v);
00355 addPair("w", SDLK_w);
00356 addPair("x", SDLK_x);
00357 addPair("y", SDLK_y);
00358 addPair("z", SDLK_z);
00359
00360 addPair("0", SDLK_0);
00361 addPair("1", SDLK_1);
00362 addPair("2", SDLK_2);
00363 addPair("3", SDLK_3);
00364 addPair("4", SDLK_4);
00365 addPair("5", SDLK_5);
00366 addPair("6", SDLK_6);
00367 addPair("7", SDLK_7);
00368 addPair("8", SDLK_8);
00369 addPair("9", SDLK_9);
00370
00371 addPair("kp0", SDLK_KP0);
00372 addPair("kp1", SDLK_KP1);
00373 addPair("kp2", SDLK_KP2);
00374 addPair("kp3", SDLK_KP3);
00375 addPair("kp4", SDLK_KP4);
00376 addPair("kp5", SDLK_KP5);
00377 addPair("kp6", SDLK_KP6);
00378 addPair("kp7", SDLK_KP7);
00379 addPair("kp8", SDLK_KP8);
00380 addPair("kp9", SDLK_KP9);
00381
00382 addPair("left", SDLK_LEFT);
00383 addPair("right", SDLK_RIGHT);
00384 addPair("down", SDLK_DOWN);
00385 addPair("up", SDLK_UP);
00386 }
00387
00388 const StringToKeyMap_t& KeyMapContainer::getStringToKeyMap() {
00389 if (!initialized) init();
00390 return stringKeyMap;
00391 }
00392
00393 const KeyToStringMap_t& KeyMapContainer::getKeyToStringMap() {
00394 if (!initialized) init();
00395 return keyStringMap;
00396 }
00397
00398 void KeyMapContainer::addPair(const std::string& s, const SDLKey& k ) {
00399 keyStringMap[k] = s;
00400 stringKeyMap[s] = k;
00401 }
00402