X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fmenu.cpp;h=9932ed669ac6ee428d780a37252255d637dae106;hb=3369ed08e4b7126af560dc5f9c3442fc76b43ab4;hp=9eec207b3a0822385e60fc05facc0b88a9d9d664;hpb=bd7ba9109959cd12e5558af05ed51be1a06272c3;p=supertux.git diff --git a/src/menu.cpp b/src/menu.cpp index 9eec207b3..9932ed669 100644 --- a/src/menu.cpp +++ b/src/menu.cpp @@ -1,5 +1,5 @@ // $Id$ -// +// // SuperTux // Copyright (C) 2004 Tobias Glaesser // @@ -12,7 +12,7 @@ // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -// +// // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. @@ -23,20 +23,26 @@ #endif #include +#include #include #include -#include +#include +#include #include "defines.h" #include "globals.h" #include "menu.h" -#include "screen.h" +#include "screen/screen.h" +#include "screen/drawing_context.h" #include "setup.h" #include "sound.h" #include "scene.h" #include "leveleditor.h" #include "timer.h" #include "high_scores.h" +#include "gettext.h" + +#define FLICK_CURSOR_TIME 500 Surface* checkbox; Surface* checkbox_checked; @@ -59,12 +65,71 @@ Menu* contrib_subset_menu = 0; std::vector Menu::last_menus; Menu* Menu::current_ = 0; +/* just displays a Yes/No text that can be used to confirm stuff */ +bool confirm_dialog(Surface *background, std::string text) +{ + //Surface* cap_screen = Surface::CaptureScreen(); + + Menu* dialog = new Menu; + dialog->additem(MN_DEACTIVE, text,0,0); + dialog->additem(MN_HL,"",0,0); + dialog->additem(MN_ACTION,_("Yes"),0,0,true); + dialog->additem(MN_ACTION,_("No"),0,0,false); + dialog->additem(MN_HL,"",0,0); + + Menu::set_current(dialog); + + DrawingContext context; + + while(true) + { + SDL_Event event; + + while (SDL_PollEvent(&event)) + { + dialog->event(event); + } + + if(background == NULL) + context.draw_gradient(Color(200, 100, 200), Color(100, 200, 100), LAYER_BACKGROUND0); + else + context.draw_surface(background, Vector(0,0), LAYER_BACKGROUND0); + + dialog->draw(context); + dialog->action(); + + switch (dialog->check()) + { + case true: + //delete cap_screen; + Menu::set_current(0); + delete dialog; + return true; + break; + case false: + //delete cap_screen; + Menu::set_current(0); + delete dialog; + return false; + break; + default: + break; + } + + mouse_cursor->draw(context); + context.do_drawing(); + SDL_Delay(25); + } + + return false; +} + void Menu::push_current(Menu* pmenu) { if (current_) last_menus.push_back(current_); - + current_ = pmenu; current_->effect.start(500); } @@ -73,16 +138,16 @@ void Menu::pop_current() { if (!last_menus.empty()) - { - current_ = last_menus.back(); - current_->effect.start(500); + { + current_ = last_menus.back(); + current_->effect.start(500); - last_menus.pop_back(); - } + last_menus.pop_back(); + } else - { - current_ = 0; - } + { + current_ = 0; + } } void @@ -92,7 +157,7 @@ Menu::set_current(Menu* menu) if (menu) menu->effect.start(500); - + current_ = menu; } @@ -101,7 +166,7 @@ MenuItem* MenuItem::create(MenuItemKind kind_, const char *text_, int init_toggle_, Menu* target_menu_, int id, int* int_p_) { MenuItem *pnew_item = new MenuItem; - + pnew_item->kind = kind_; pnew_item->text = (char*) malloc(sizeof(char) * (strlen(text_) + 1)); strcpy(pnew_item->text, text_); @@ -116,16 +181,20 @@ MenuItem::create(MenuItemKind kind_, const char *text_, int init_toggle_, Menu* pnew_item->input[0] = '\0'; if(kind_ == MN_STRINGSELECT) - { - pnew_item->list = (string_list_type*) malloc(sizeof(string_list_type)); - string_list_init(pnew_item->list); - } + { + pnew_item->list = (string_list_type*) malloc(sizeof(string_list_type)); + string_list_init(pnew_item->list); + } else pnew_item->list = NULL; pnew_item->id = id; pnew_item->int_p = int_p_; + pnew_item->input_flickering = false; + pnew_item->input_flickering_timer.init(true); + pnew_item->input_flickering_timer.start(FLICK_CURSOR_TIME); + return pnew_item; } @@ -133,83 +202,122 @@ void MenuItem::change_text(const char *text_) { if (text_) - { - free(text); - text = (char*) malloc(sizeof(char )*(strlen(text_)+1)); - strcpy(text, text_); - } + { + free(text); + text = (char*) malloc(sizeof(char )*(strlen(text_)+1)); + strcpy(text, text_); + } } void MenuItem::change_input(const char *text_) { if(text) + { + free(input); + input = (char*) malloc(sizeof(char )*(strlen(text_)+1)); + strcpy(input, text_); + } +} + +std::string MenuItem::get_input_with_symbol(bool active_item) +{ + if(!active_item) + input_flickering = true; + else + { + if(input_flickering_timer.get_left() < 0) { - free(input); - input = (char*) malloc(sizeof(char )*(strlen(text_)+1)); - strcpy(input, text_); + if(input_flickering) + input_flickering = false; + else + input_flickering = true; + input_flickering_timer.start(FLICK_CURSOR_TIME); } + } + + char str[1024]; + if(input_flickering) + sprintf(str,"%s_",input); + else + sprintf(str,"%s ",input); + + std::string string = str; + + return string; } -/* Set ControlField a key */ +/* Set ControlField for keyboard key */ void Menu::get_controlfield_key_into_input(MenuItem *item) { -switch(*item->int_p) + switch(*item->int_p) { case SDLK_UP: - strcpy(item->input, "Up cursor"); + item->change_input(_("Up cursor")); break; case SDLK_DOWN: - strcpy(item->input, "Down cursor"); + item->change_input(_("Down cursor")); break; case SDLK_LEFT: - strcpy(item->input, "Left cursor"); + item->change_input(_("Left cursor")); break; case SDLK_RIGHT: - strcpy(item->input, "Right cursor"); + item->change_input(_("Right cursor")); break; case SDLK_RETURN: - strcpy(item->input, "Return"); + item->change_input(_("Return")); break; case SDLK_SPACE: - strcpy(item->input, "Space"); + item->change_input(_("Space")); break; case SDLK_RSHIFT: - strcpy(item->input, "Right Shift"); + item->change_input(_("Right Shift")); break; case SDLK_LSHIFT: - strcpy(item->input, "Left Shift"); + item->change_input(_("Left Shift")); break; case SDLK_RCTRL: - strcpy(item->input, "Right Control"); + item->change_input(_("Right Control")); break; case SDLK_LCTRL: - strcpy(item->input, "Left Control"); + item->change_input(_("Left Control")); break; case SDLK_RALT: - strcpy(item->input, "Right Alt"); + item->change_input(_("Right Alt")); break; case SDLK_LALT: - strcpy(item->input, "Left Alt"); + item->change_input(_("Left Alt")); break; default: - strcpy(item->input, (char*)item->int_p); + { + char tmp[64]; + snprintf(tmp, 64, "%d", *item->int_p); + item->change_input(tmp); + } break; } } +/* Set ControlField for joystick button */ +void Menu::get_controlfield_js_into_input(MenuItem *item) +{ + std::ostringstream oss; + oss << "Button " << *item->int_p; + item->change_input(oss.str().c_str()); +} + /* Free a menu and all its items */ Menu::~Menu() { if(item.size() != 0) + { + for(unsigned int i = 0; i < item.size(); ++i) { - for(unsigned int i = 0; i < item.size(); ++i) - { - free(item[i].text); - free(item[i].input); - string_list_free(item[i].list); - } + free(item[i].text); + free(item[i].input); + string_list_free(item[i].list); } + } } @@ -219,13 +327,14 @@ Menu::Menu() menuaction = MENU_ACTION_NONE; delete_character = 0; mn_input_char = '\0'; - + pos_x = screen->w/2; pos_y = screen->h/2; - has_backitem = false; arrange_left = 0; active_item = 0; effect.init(false); + + joystick_timer.init(true); } void Menu::set_pos(int x, int y, float rw, float rh) @@ -237,12 +346,6 @@ void Menu::set_pos(int x, int y, float rw, float rh) void Menu::additem(MenuItemKind kind_, const std::string& text_, int toggle_, Menu* menu_, int id, int* int_p) { - if(kind_ == MN_BACK) - has_backitem = true; - - if(id == -1) - id = int(item.size()); - additem(MenuItem::create(kind_, text_.c_str(), toggle_, menu_, id, int_p)); } @@ -250,9 +353,6 @@ Menu::additem(MenuItemKind kind_, const std::string& text_, int toggle_, Menu* m void Menu::additem(MenuItem* pmenu_item) { - if(pmenu_item->kind == MN_BACK) - has_backitem = true; - item.push_back(*pmenu_item); delete pmenu_item; } @@ -269,132 +369,138 @@ Menu::action() { hit_item = -1; if(item.size() != 0) + { + switch(menuaction) { - switch(menuaction) + case MENU_ACTION_UP: + if (active_item > 0) + --active_item; + else + active_item = int(item.size())-1; + break; + + case MENU_ACTION_DOWN: + if(active_item < int(item.size())-1) + ++active_item; + else + active_item = 0; + break; + + case MENU_ACTION_LEFT: + if(item[active_item].kind == MN_STRINGSELECT + && item[active_item].list->num_items != 0) + { + if(item[active_item].list->active_item > 0) + --item[active_item].list->active_item; + else + item[active_item].list->active_item = item[active_item].list->num_items-1; + } + break; + + case MENU_ACTION_RIGHT: + if(item[active_item].kind == MN_STRINGSELECT + && item[active_item].list->num_items != 0) + { + if(item[active_item].list->active_item < item[active_item].list->num_items-1) + ++item[active_item].list->active_item; + else + item[active_item].list->active_item = 0; + } + break; + + case MENU_ACTION_HIT: + { + hit_item = active_item; + switch (item[active_item].kind) { - case MENU_ACTION_UP: - if (active_item > 0) - --active_item; + case MN_GOTO: + if (item[active_item].target_menu != NULL) + Menu::push_current(item[active_item].target_menu); else - active_item = int(item.size())-1; + puts("NULLL"); break; - case MENU_ACTION_DOWN: - if(active_item < int(item.size())-1) - ++active_item; - else - active_item = 0; + case MN_TOGGLE: + item[active_item].toggled = !item[active_item].toggled; break; - case MENU_ACTION_LEFT: - if(item[active_item].kind == MN_STRINGSELECT - && item[active_item].list->num_items != 0) - { - if(item[active_item].list->active_item > 0) - --item[active_item].list->active_item; - else - item[active_item].list->active_item = item[active_item].list->num_items-1; - } + case MN_ACTION: + Menu::set_current(0); + item[active_item].toggled = true; + break; + case MN_TEXTFIELD: + case MN_NUMFIELD: + menuaction = MENU_ACTION_DOWN; + action(); break; - case MENU_ACTION_RIGHT: - if(item[active_item].kind == MN_STRINGSELECT - && item[active_item].list->num_items != 0) - { - if(item[active_item].list->active_item < item[active_item].list->num_items-1) - ++item[active_item].list->active_item; - else - item[active_item].list->active_item = 0; - } + case MN_BACK: + Menu::pop_current(); + break; + default: break; + } + } + break; - case MENU_ACTION_HIT: + case MENU_ACTION_REMOVE: + if(item[active_item].kind == MN_TEXTFIELD + || item[active_item].kind == MN_NUMFIELD) + { + if(item[active_item].input != NULL) + { + int i = strlen(item[active_item].input); + + while(delete_character > 0) /* remove charactes */ { - hit_item = active_item; - switch (item[active_item].kind) - { - case MN_GOTO: - if (item[active_item].target_menu != NULL) - Menu::push_current(item[active_item].target_menu); - else - puts("NULLL"); - break; - - case MN_TOGGLE: - item[active_item].toggled = !item[active_item].toggled; - break; - - case MN_ACTION: - case MN_TEXTFIELD: - case MN_NUMFIELD: - Menu::set_current(0); - item[active_item].toggled = true; - break; - - case MN_BACK: - Menu::pop_current(); - break; - default: - break; - } + item[active_item].input[i-1] = '\0'; + delete_character--; } - break; - - case MENU_ACTION_REMOVE: - if(item[active_item].kind == MN_TEXTFIELD - || item[active_item].kind == MN_NUMFIELD) - { - if(item[active_item].input != NULL) - { - int i = strlen(item[active_item].input); - - while(delete_character > 0) /* remove charactes */ - { - item[active_item].input[i-1] = '\0'; - delete_character--; - } - } - } - break; + } + } + break; - case MENU_ACTION_INPUT: - if(item[active_item].kind == MN_TEXTFIELD - || (item[active_item].kind == MN_NUMFIELD && mn_input_char >= '0' && mn_input_char <= '9')) - { - if(item[active_item].input != NULL) - { - int i = strlen(item[active_item].input); - item[active_item].input = (char*) realloc(item[active_item].input,sizeof(char)*(i + 2)); - item[active_item].input[i] = mn_input_char; - item[active_item].input[i+1] = '\0'; - } - else - { - item[active_item].input = (char*) malloc(2*sizeof(char)); - item[active_item].input[0] = mn_input_char; - item[active_item].input[1] = '\0'; - } - } - - case MENU_ACTION_NONE: - break; + case MENU_ACTION_INPUT: + if(item[active_item].kind == MN_TEXTFIELD + || (item[active_item].kind == MN_NUMFIELD && mn_input_char >= '0' && mn_input_char <= '9')) + { + if(item[active_item].input != NULL) + { + int i = strlen(item[active_item].input); + item[active_item].input = (char*) realloc(item[active_item].input,sizeof(char)*(i + 2)); + item[active_item].input[i] = mn_input_char; + item[active_item].input[i+1] = '\0'; + } + else + { + item[active_item].input = (char*) malloc(2*sizeof(char)); + item[active_item].input[0] = mn_input_char; + item[active_item].input[1] = '\0'; } + } + + case MENU_ACTION_NONE: + break; } + } MenuItem& new_item = item[active_item]; if(new_item.kind == MN_DEACTIVE || new_item.kind == MN_LABEL || new_item.kind == MN_HL) - { - // Skip the horzontal line item - if (menuaction != MENU_ACTION_UP && menuaction != MENU_ACTION_DOWN) - menuaction = MENU_ACTION_DOWN; + { + // Skip the horzontal line item + if (menuaction != MENU_ACTION_UP && menuaction != MENU_ACTION_DOWN) + menuaction = MENU_ACTION_DOWN; - if (item.size() > 1) - action(); - } + if (item.size() > 1) + action(); + } menuaction = MENU_ACTION_NONE; + + if (active_item >= int(item.size())) + active_item = int(item.size()) - 1; } int @@ -407,13 +513,12 @@ Menu::check() } void -Menu::draw_item(int index, // Position of the current item in the menu - int menu_width, - int menu_height) +Menu::draw_item(DrawingContext& context, + int index, // Position of the current item in the menu + int menu_width, int menu_height) { MenuItem& pitem = item[index]; - int font_width = 16; int effect_offset = 0; { int effect_time = 0; @@ -424,135 +529,170 @@ Menu::draw_item(int index, // Position of the current item in the menu effect_offset = (index % 2) ? effect_time : -effect_time; } + Font* text_font = white_text; int x_pos = pos_x; int y_pos = pos_y + 24*index - menu_height/2 + 12 + effect_offset; int shadow_size = 2; - int text_width = strlen(pitem.text) * font_width; - int input_width = strlen(pitem.input) * font_width; - int list_width = strlen(string_list_active(pitem.list)) * font_width; - Text* text_font = white_text; + int text_width = int(text_font->get_text_width(pitem.text)); + int input_width = int(text_font->get_text_width(pitem.input) + 10); + int list_width = + int(text_font->get_text_width(string_list_active(pitem.list))); if (arrange_left) x_pos += 24 - menu_width/2 + (text_width + input_width + list_width)/2; if(index == active_item) - { - shadow_size = 3; - text_font = blue_text; - } + { + shadow_size = 3; + text_font = blue_text; + } switch (pitem.kind) + { + case MN_DEACTIVE: { - case MN_DEACTIVE: - { - black_text->draw_align(pitem.text, - x_pos, y_pos, - A_HMIDDLE, A_VMIDDLE, 2); - break; - } - - case MN_HL: - { - int x = pos_x - menu_width/2; - int y = y_pos - 12 - effect_offset; - /* Draw a horizontal line with a little 3d effect */ - fillrect(x, y + 6, - menu_width, 4, - 150,200,255,225); - fillrect(x, y + 6, - menu_width, 2, - 255,255,255,255); - break; - } - case MN_LABEL: - { - white_big_text->draw_align(pitem.text, - x_pos, y_pos, - A_HMIDDLE, A_VMIDDLE, 2); - break; - } - case MN_TEXTFIELD: - case MN_NUMFIELD: - case MN_CONTROLFIELD: - { - int input_pos = input_width/2; - int text_pos = (text_width + font_width)/2; - - fillrect(x_pos - input_pos + text_pos - 1, y_pos - 10, - input_width + font_width + 2, 20, - 255,255,255,255); - fillrect(x_pos - input_pos + text_pos, y_pos - 9, - input_width + font_width, 18, - 0,0,0,128); - - if(pitem.kind == MN_CONTROLFIELD) - get_controlfield_key_into_input(&pitem); - - gold_text->draw_align(pitem.input, - x_pos + text_pos, y_pos, - A_HMIDDLE, A_VMIDDLE, 2); - - text_font->draw_align(pitem.text, - x_pos - (input_width + font_width)/2, y_pos, - A_HMIDDLE, A_VMIDDLE, shadow_size); - break; - } - case MN_STRINGSELECT: - { - int list_pos_2 = list_width + font_width; - int list_pos = list_width/2; - int text_pos = (text_width + font_width)/2; - - /* Draw arrows */ - arrow_left->draw( x_pos - list_pos + text_pos - 17, y_pos - 8); - arrow_right->draw( x_pos - list_pos + text_pos - 1 + list_pos_2, y_pos - 8); - - /* Draw input background */ - fillrect(x_pos - list_pos + text_pos - 1, y_pos - 10, - list_pos_2 + 2, 20, - 255,255,255,255); - fillrect(x_pos - list_pos + text_pos, y_pos - 9, - list_pos_2, 18, - 0,0,0,128); - - gold_text->draw_align(string_list_active(pitem.list), - x_pos + text_pos, y_pos, - A_HMIDDLE, A_VMIDDLE,2); - - text_font->draw_align(pitem.text, - x_pos - list_pos_2/2, y_pos, - A_HMIDDLE, A_VMIDDLE, shadow_size); - break; - } - case MN_BACK: - { - text_font->draw_align(pitem.text, x_pos, y_pos, A_HMIDDLE, A_VMIDDLE, shadow_size); - back->draw( x_pos + text_width/2 + font_width, y_pos - 8); - break; - } + context.draw_text_center(blue_text, pitem.text, + Vector(0, y_pos - int(blue_text->get_height()/2)), + LAYER_FOREGROUND1); + break; + } - case MN_TOGGLE: + case MN_HL: + { + // TODO + int x = pos_x - menu_width/2; + int y = y_pos - 12 - effect_offset; + /* Draw a horizontal line with a little 3d effect */ + context.draw_filled_rect(Vector(x, y + 6), + Vector(menu_width, 4), Color(150,200,255,225), LAYER_FOREGROUND1); + context.draw_filled_rect(Vector(x, y + 6), + Vector(menu_width, 2), Color(255,255,255,255), LAYER_FOREGROUND1); + break; + } + case MN_LABEL: + { + context.draw_text_center(white_big_text, + pitem.text, Vector(0, y_pos - int(white_big_text->get_height()/2)), + LAYER_FOREGROUND1); + break; + } + case MN_TEXTFIELD: + case MN_NUMFIELD: + case MN_CONTROLFIELD_KB: + case MN_CONTROLFIELD_JS: + { + int width = text_width + input_width + 5; + int text_pos = screen->w/2 - width/2; + int input_pos = text_pos + text_width + 10; + + context.draw_filled_rect( + Vector(input_pos - 5, y_pos - 10), + Vector(input_width + 10, 20), + Color(255,255,255,255), LAYER_FOREGROUND1-5); + context.draw_filled_rect( + Vector(input_pos - 4, y_pos - 9), + Vector(input_width + 8, 18), + Color(0,0,0,128), LAYER_FOREGROUND1-4); + + if(pitem.kind == MN_CONTROLFIELD_KB) + get_controlfield_key_into_input(&pitem); + else if (pitem.kind == MN_CONTROLFIELD_JS) + get_controlfield_js_into_input(&pitem); + + if(pitem.kind == MN_TEXTFIELD || pitem.kind == MN_NUMFIELD) { - text_font->draw_align(pitem.text, x_pos, y_pos, A_HMIDDLE, A_VMIDDLE, shadow_size); - - if(pitem.toggled) - checkbox_checked->draw( - x_pos + (text_width+font_width)/2, - y_pos - 8); + if(active_item == index) + context.draw_text(gold_text, + pitem.get_input_with_symbol(true), + Vector(input_pos, y_pos - int(gold_text->get_height()/2)), + LAYER_FOREGROUND1); else - checkbox->draw( - x_pos + (text_width+font_width)/2, - y_pos - 8); - break; + context.draw_text(gold_text, + pitem.get_input_with_symbol(false), + Vector(input_pos, y_pos - int(gold_text->get_height()/2)), + LAYER_FOREGROUND1); } - case MN_ACTION: - text_font->draw_align(pitem.text, x_pos, y_pos, A_HMIDDLE, A_VMIDDLE, shadow_size); + else + context.draw_text(gold_text, pitem.input, + Vector(input_pos, y_pos - int(gold_text->get_height()/2)), + LAYER_FOREGROUND1); + + context.draw_text(text_font, pitem.text, + Vector(text_pos, y_pos - int(text_font->get_height()/2)), + LAYER_FOREGROUND1); + break; + } + case MN_STRINGSELECT: + { + int list_pos_2 = list_width + 16; + int list_pos = list_width/2; + int text_pos = (text_width + 16)/2; + + /* Draw arrows */ + context.draw_surface(arrow_left, + Vector(x_pos - list_pos + text_pos - 17, y_pos - 8), + LAYER_FOREGROUND1); + context.draw_surface(arrow_right, + Vector(x_pos - list_pos + text_pos - 1 + list_pos_2, y_pos - 8), + LAYER_FOREGROUND1); + + /* Draw input background */ + context.draw_filled_rect( + Vector(x_pos - list_pos + text_pos - 1, y_pos - 10), + Vector(list_pos_2 + 2, 20), + Color(255,255,255,255), LAYER_FOREGROUND1 - 4); + context.draw_filled_rect( + Vector(x_pos - list_pos + text_pos, y_pos - 9), + Vector(list_pos_2, 18), + Color(0,0,0,128), LAYER_FOREGROUND1 - 5); + + context.draw_text_center(text_font, string_list_active(pitem.list), + Vector(text_pos, y_pos - int(text_font->get_height()/2)), + LAYER_FOREGROUND1); + context.draw_text_center(text_font, pitem.text, + Vector(list_pos_2/2, y_pos - int(text_font->get_height()/2)), + LAYER_FOREGROUND1); break; + } + case MN_BACK: + { + context.draw_text_center(text_font, pitem.text, + Vector(0, y_pos - int(text_font->get_height()/2)), + LAYER_FOREGROUND1); + context.draw_surface(back, + Vector(x_pos + text_width/2 + 16, y_pos - 8), + LAYER_FOREGROUND1); + break; + } - case MN_GOTO: - text_font->draw_align(pitem.text, x_pos, y_pos, A_HMIDDLE, A_VMIDDLE, shadow_size); + case MN_TOGGLE: + { + context.draw_text_center(text_font, pitem.text, + Vector(0, y_pos - (text_font->get_height()/2)), + LAYER_FOREGROUND1); + + if(pitem.toggled) + context.draw_surface(checkbox_checked, + Vector(x_pos + (text_width+16)/2, y_pos - 8), + LAYER_FOREGROUND1 + 1); + else + context.draw_surface(checkbox, + Vector(x_pos + (text_width+16)/2, y_pos - 8), + LAYER_FOREGROUND1 + 1); break; } + case MN_ACTION: + context.draw_text_center(text_font, pitem.text, + Vector(0, y_pos - int(text_font->get_height()/2)), + LAYER_FOREGROUND1); + break; + + case MN_GOTO: + context.draw_text_center(text_font, pitem.text, + Vector(0, y_pos - int(text_font->get_height()/2)), + LAYER_FOREGROUND1); + break; + } } int Menu::get_width() const @@ -561,15 +701,15 @@ int Menu::get_width() const with the most characters */ int menu_width = 0; for(unsigned int i = 0; i < item.size(); ++i) + { + int w = strlen(item[i].text) + (item[i].input ? strlen(item[i].input) + 1 : 0) + strlen(string_list_active(item[i].list)); + if( w > menu_width ) { - int w = strlen(item[i].text) + (item[i].input ? strlen(item[i].input) + 1 : 0) + strlen(string_list_active(item[i].list)); - if( w > menu_width ) - { - menu_width = w; - if( item[i].kind == MN_TOGGLE) - menu_width += 2; - } + menu_width = w; + if( item[i].kind == MN_TOGGLE) + menu_width += 2; } + } return (menu_width * 16 + 24); } @@ -581,21 +721,46 @@ int Menu::get_height() const /* Draw the current menu. */ void -Menu::draw() +Menu::draw(DrawingContext& context) { int menu_height = get_height(); int menu_width = get_width(); /* Draw a transparent background */ - fillrect(pos_x - menu_width/2, - pos_y - 24*item.size()/2 - 10, - menu_width,menu_height + 20, - 150,180,200,125); + context.draw_filled_rect( + Vector(pos_x - menu_width/2, pos_y - 24*item.size()/2 - 10), + Vector(menu_width,menu_height + 20), + Color(150,180,200,125), LAYER_FOREGROUND1-10); for(unsigned int i = 0; i < item.size(); ++i) - { - draw_item(i, menu_width, menu_height); - } + { + draw_item(context, i, menu_width, menu_height); + } +} + +MenuItem& +Menu::get_item_by_id(int id) +{ + for(std::vector::iterator i = item.begin(); i != item.end(); ++i) + { + if(i->id == id) + return *i; + } + + assert(false); + static MenuItem dummyitem; + return dummyitem; +} + +int Menu::get_active_item_id() +{ + return item[active_item].id; +} + +bool +Menu::isToggled(int id) +{ + return get_item_by_id(id).toggled; } /* Check for menu event */ @@ -604,126 +769,139 @@ Menu::event(SDL_Event& event) { SDLKey key; switch(event.type) + { + case SDL_KEYDOWN: + key = event.key.keysym.sym; + SDLMod keymod; + char ch[2]; + keymod = SDL_GetModState(); + int x,y; + + /* If the current unicode character is an ASCII character, + assign it to ch. */ + if ( (event.key.keysym.unicode & 0xFF80) == 0 ) { - case SDL_KEYDOWN: - key = event.key.keysym.sym; - SDLMod keymod; - char ch[2]; - keymod = SDL_GetModState(); - int x,y; - - /* If the current unicode character is an ASCII character, - assign it to ch. */ - if ( (event.key.keysym.unicode & 0xFF80) == 0 ) - { - ch[0] = event.key.keysym.unicode & 0x7F; - ch[1] = '\0'; - } - else - { - /* An International Character. */ - } + ch[0] = event.key.keysym.unicode & 0x7F; + ch[1] = '\0'; + } + else + { + /* An International Character. */ + } - if(item[active_item].kind == MN_CONTROLFIELD) - { - if(key == SDLK_ESCAPE) - { - Menu::pop_current(); - return; - } - *item[active_item].int_p = key; - menuaction = MENU_ACTION_DOWN; + if(item[active_item].kind == MN_CONTROLFIELD_KB) + { + if(key == SDLK_ESCAPE) + { + Menu::pop_current(); return; - } + } + *item[active_item].int_p = key; + menuaction = MENU_ACTION_DOWN; + return; + } - switch(key) - { - case SDLK_UP: /* Menu Up */ - menuaction = MENU_ACTION_UP; - break; - case SDLK_DOWN: /* Menu Down */ - menuaction = MENU_ACTION_DOWN; - break; - case SDLK_LEFT: /* Menu Up */ - menuaction = MENU_ACTION_LEFT; - break; - case SDLK_RIGHT: /* Menu Down */ - menuaction = MENU_ACTION_RIGHT; - break; - case SDLK_SPACE: - if(item[active_item].kind == MN_TEXTFIELD) - { - menuaction = MENU_ACTION_INPUT; - mn_input_char = ' '; - break; - } - case SDLK_RETURN: /* Menu Hit */ - menuaction = MENU_ACTION_HIT; - break; - case SDLK_DELETE: - case SDLK_BACKSPACE: - menuaction = MENU_ACTION_REMOVE; - delete_character++; - break; - case SDLK_ESCAPE: - Menu::pop_current(); - break; - default: - if( (key >= SDLK_0 && key <= SDLK_9) || (key >= SDLK_a && key <= SDLK_z) || (key >= SDLK_SPACE && key <= SDLK_SLASH)) - { - menuaction = MENU_ACTION_INPUT; - mn_input_char = *ch; - } - else - { - mn_input_char = '\0'; - } - break; - } + switch(key) + { + case SDLK_UP: /* Menu Up */ + menuaction = MENU_ACTION_UP; break; - case SDL_JOYAXISMOTION: - if(event.jaxis.axis == joystick_keymap.y_axis) - { - if (event.jaxis.value > 1024) - menuaction = MENU_ACTION_DOWN; - else if (event.jaxis.value < -1024) - menuaction = MENU_ACTION_UP; - } + case SDLK_DOWN: /* Menu Down */ + menuaction = MENU_ACTION_DOWN; + break; + case SDLK_LEFT: /* Menu Up */ + menuaction = MENU_ACTION_LEFT; + break; + case SDLK_RIGHT: /* Menu Down */ + menuaction = MENU_ACTION_RIGHT; break; - case SDL_JOYBUTTONDOWN: + case SDLK_SPACE: + if(item[active_item].kind == MN_TEXTFIELD) + { + menuaction = MENU_ACTION_INPUT; + mn_input_char = ' '; + break; + } + case SDLK_RETURN: /* Menu Hit */ menuaction = MENU_ACTION_HIT; break; - case SDL_MOUSEBUTTONDOWN: - x = event.motion.x; - y = event.motion.y; - if(x > pos_x - get_width()/2 && - x < pos_x + get_width()/2 && - y > pos_y - get_height()/2 && - y < pos_y + get_height()/2) - { - menuaction = MENU_ACTION_HIT; - } + case SDLK_DELETE: + case SDLK_BACKSPACE: + menuaction = MENU_ACTION_REMOVE; + delete_character++; break; - case SDL_MOUSEMOTION: - x = event.motion.x; - y = event.motion.y; - if(x > pos_x - get_width()/2 && - x < pos_x + get_width()/2 && - y > pos_y - get_height()/2 && - y < pos_y + get_height()/2) - { - active_item = (y - (pos_y - get_height()/2)) / 24; - mouse_cursor->set_state(MC_LINK); - } - else - { - mouse_cursor->set_state(MC_NORMAL); - } + case SDLK_ESCAPE: + Menu::pop_current(); break; default: + if( (key >= SDLK_0 && key <= SDLK_9) || (key >= SDLK_a && key <= SDLK_z) || (key >= SDLK_SPACE && key <= SDLK_SLASH)) + { + menuaction = MENU_ACTION_INPUT; + mn_input_char = *ch; + } + else + { + mn_input_char = '\0'; + } break; } + break; + case SDL_JOYAXISMOTION: + if(event.jaxis.axis == joystick_keymap.y_axis) + { + if (event.jaxis.value > joystick_keymap.dead_zone && !joystick_timer.started()) + { + menuaction = MENU_ACTION_DOWN; + joystick_timer.start(JOYSTICK_MENU_DELAY); + } + else if (event.jaxis.value < -joystick_keymap.dead_zone && !joystick_timer.started()) + { + menuaction = MENU_ACTION_UP; + joystick_timer.start(JOYSTICK_MENU_DELAY); + } + else + joystick_timer.stop(); + } + break; + case SDL_JOYBUTTONDOWN: + if (item[active_item].kind == MN_CONTROLFIELD_JS) + { + *item[active_item].int_p = key; + menuaction = MENU_ACTION_DOWN; + } + menuaction = MENU_ACTION_HIT; + break; + case SDL_MOUSEBUTTONDOWN: + x = event.motion.x; + y = event.motion.y; + if(x > pos_x - get_width()/2 && + x < pos_x + get_width()/2 && + y > pos_y - get_height()/2 && + y < pos_y + get_height()/2) + { + menuaction = MENU_ACTION_HIT; + } + break; + case SDL_MOUSEMOTION: + x = event.motion.x; + y = event.motion.y; + if(x > pos_x - get_width()/2 && + x < pos_x + get_width()/2 && + y > pos_y - get_height()/2 && + y < pos_y + get_height()/2) + { + active_item = (y - (pos_y - get_height()/2)) / 24; + mouse_cursor->set_state(MC_LINK); + } + else + { + mouse_cursor->set_state(MC_NORMAL); + } + break; + default: + break; + } }