X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fgui%2Fmenu.cpp;h=0045fbc77e1b3fda8c2c0c2d39bb7a01deff095b;hb=07ddaed2a657e4d2a3d038fed223fc5827159caf;hp=88fffd57b70538989056fc20bf3665d77edcbbc5;hpb=c0093d25093395cb62fc2526ab42be65a9f015b8;p=supertux.git diff --git a/src/gui/menu.cpp b/src/gui/menu.cpp index 88fffd57b..0045fbc77 100644 --- a/src/gui/menu.cpp +++ b/src/gui/menu.cpp @@ -1,7 +1,7 @@ // $Id$ // // SuperTux -// Copyright (C) 2004 Tobias Glaesser +// Copyright (C) 2006 Matthias Braun // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -16,6 +16,7 @@ // 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. + #include #include @@ -29,30 +30,22 @@ #include #include -#include "app/globals.h" -#include "menu.h" -#include "video/screen.h" -#include "video/drawing_context.h" -#include "app/setup.h" -#include "app/gettext.h" -#include "math/vector.h" -#include "main.h" -#include "control/joystickkeyboardcontroller.h" +#include "menu.hpp" +#include "mainloop.hpp" +#include "video/screen.hpp" +#include "video/drawing_context.hpp" +#include "gettext.hpp" +#include "math/vector.hpp" +#include "main.hpp" +#include "resources.hpp" +#include "control/joystickkeyboardcontroller.hpp" static const int MENU_REPEAT_INITIAL = 400; static const int MENU_REPEAT_RATE = 200; -static const int FLICK_CURSOR_TIME=500; +static const int FLICK_CURSOR_TIME = 500; extern SDL_Surface* screen; -using namespace SuperTux; - -Surface* checkbox; -Surface* checkbox_checked; -Surface* back; -Surface* arrow_left; -Surface* arrow_right; - std::vector Menu::last_menus; Menu* Menu::current_ = 0; Font* Menu::default_font; @@ -76,24 +69,25 @@ bool confirm_dialog(Surface *background, std::string text) DrawingContext context; + // TODO make this a screen and not another mainloop... while(true) { SDL_Event event; - - if(event.type == SDL_QUIT) - throw std::runtime_error("received window close event"); - while (SDL_PollEvent(&event)) { + if(event.type == SDL_QUIT) + main_loop->quit(); + main_controller->process_event(event); dialog->event(event); } if(background == NULL) - context.draw_gradient(Color(200,240,220), Color(200,200,220), LAYER_BACKGROUND0); + context.draw_gradient(Color(0.8, 0.95, 0.85), Color(0.8, 0.8, 0.8), + LAYER_BACKGROUND0); else context.draw_surface(background, Vector(0,0), LAYER_BACKGROUND0); dialog->draw(context); - dialog->action(); + dialog->update(); switch (dialog->check()) { @@ -128,7 +122,7 @@ Menu::push_current(Menu* pmenu) last_menus.push_back(current_); current_ = pmenu; - current_->effect.start(500); + current_->effect_ticks = SDL_GetTicks(); } void @@ -136,9 +130,10 @@ Menu::pop_current() { if (last_menus.size() >= 1) { current_ = last_menus.back(); - current_->effect.start(500); - + current_->effect_ticks = SDL_GetTicks(); last_menus.pop_back(); + } else { + current_ = 0; } } @@ -148,7 +143,7 @@ Menu::set_current(Menu* menu) last_menus.clear(); if (menu) - menu->effect.start(500); + menu->effect_ticks = SDL_GetTicks(); current_ = menu; // just to be sure... @@ -161,9 +156,6 @@ MenuItem::MenuItem(MenuItemKind _kind, int _id) toggled = false; selected = false; target_menu = 0; - input_flickering = false; - input_flickering_timer.init(true); - input_flickering_timer.start(FLICK_CURSOR_TIME); } void @@ -180,19 +172,11 @@ MenuItem::change_input(const std::string& text_) std::string MenuItem::get_input_with_symbol(bool active_item) { - if(!active_item) + if(!active_item) { input_flickering = true; - else - { - if(input_flickering_timer.get_left() < 0) - { - if(input_flickering) - input_flickering = false; - else - input_flickering = true; - input_flickering_timer.start(FLICK_CURSOR_TIME); - } - } + } else { + input_flickering = (SDL_GetTicks() / FLICK_CURSOR_TIME) % 2; + } char str[1024]; if(input_flickering) @@ -223,15 +207,18 @@ Menu::Menu() pos_y = SCREEN_HEIGHT/2; arrange_left = 0; active_item = -1; - effect.init(false); - repeat_timer.init(true); + checkbox.reset(new Surface("images/engine/menu/checkbox-unchecked.png")); + checkbox_checked.reset(new Surface("images/engine/menu/checkbox-checked.png")); + back.reset(new Surface("images/engine/menu/arrow-back.png")); + arrow_left.reset(new Surface("images/engine/menu/arrow-left.png")); + arrow_right.reset(new Surface("images/engine/menu/arrow-right.png")); } -void Menu::set_pos(int x, int y, float rw, float rh) +void Menu::set_pos(float x, float y, float rw, float rh) { - pos_x = x + (int)((float)get_width() * rw); - pos_y = y + (int)((float)get_height() * rh); + pos_x = x + get_width() * rw; + pos_y = y + get_height() * rh; } /* Add an item to a menu */ @@ -331,24 +318,27 @@ Menu::clear() /* Process actions done on the menu */ void -Menu::action() +Menu::update() { /** check main input controller... */ + Uint32 ticks = SDL_GetTicks(); if(main_controller->pressed(Controller::UP)) { menuaction = MENU_ACTION_UP; - repeat_timer.start(MENU_REPEAT_INITIAL); + menu_repeat_ticks = ticks + MENU_REPEAT_INITIAL; } - if(main_controller->hold(Controller::UP) && !repeat_timer.check()) { + if(main_controller->hold(Controller::UP) && + menu_repeat_ticks != 0 && ticks > menu_repeat_ticks) { menuaction = MENU_ACTION_UP; - repeat_timer.start(MENU_REPEAT_RATE); + menu_repeat_ticks = ticks + MENU_REPEAT_RATE; } if(main_controller->pressed(Controller::DOWN)) { menuaction = MENU_ACTION_DOWN; - repeat_timer.start(MENU_REPEAT_INITIAL); + menu_repeat_ticks = ticks + MENU_REPEAT_INITIAL; } - if(main_controller->hold(Controller::DOWN) && !repeat_timer.check()) { + if(main_controller->hold(Controller::DOWN) && + menu_repeat_ticks != 0 && ticks > menu_repeat_ticks) { menuaction = MENU_ACTION_DOWN; - repeat_timer.start(MENU_REPEAT_RATE); + menu_repeat_ticks = ticks + MENU_REPEAT_RATE; } if(main_controller->pressed(Controller::JUMP) || main_controller->pressed(Controller::ACTION) @@ -433,7 +423,7 @@ Menu::action() case MN_TEXTFIELD: case MN_NUMFIELD: menuaction = MENU_ACTION_DOWN; - action(); + update(); break; case MN_BACK: @@ -499,24 +489,24 @@ Menu::menu_action(MenuItem* ) void Menu::draw_item(DrawingContext& context, int index) { - int menu_height = get_height(); - int menu_width = get_width(); + float menu_height = get_height(); + float menu_width = get_width(); MenuItem& pitem = *(items[index]); int effect_offset = 0; - { - int effect_time = 0; - - if(effect.check()) - effect_time = effect.get_left() / 4; - - effect_offset = (index % 2) ? effect_time : -effect_time; + if(effect_ticks != 0) { + if(SDL_GetTicks() - effect_ticks > 500) { + effect_ticks = 0; + } else { + Uint32 effect_time = (500 - (SDL_GetTicks() - effect_ticks)) / 4; + effect_offset = (index % 2) ? effect_time : -effect_time; + } } Font* text_font = default_font; - int x_pos = pos_x; - int y_pos = pos_y + 24*index - menu_height/2 + 12 + effect_offset; + float x_pos = pos_x; + float y_pos = pos_y + 24*index - menu_height/2 + 12 + effect_offset; int shadow_size = 2; int text_width = int(text_font->get_text_width(pitem.text)); int input_width = int(text_font->get_text_width(pitem.input) + 10); @@ -547,13 +537,15 @@ Menu::draw_item(DrawingContext& context, int index) case MN_HL: { // TODO - int x = pos_x - menu_width/2; - int y = y_pos - 12 - effect_offset; + float x = pos_x - menu_width/2; + float 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_GUI); + Vector(menu_width, 4), + Color(0.6f, 0.7f, 1.0f, 1.0f), LAYER_GUI); context.draw_filled_rect(Vector(x, y + 6), - Vector(menu_width, 2), Color(255,255,255,255), LAYER_GUI); + Vector(menu_width, 2), + Color(1.0f, 1.0f, 1.0f, 1.0f), LAYER_GUI); break; } case MN_LABEL: @@ -567,18 +559,18 @@ Menu::draw_item(DrawingContext& context, int index) case MN_NUMFIELD: case MN_CONTROLFIELD: { - int width = text_width + input_width + 5; - int text_pos = SCREEN_WIDTH/2 - width/2; - int input_pos = text_pos + text_width + 10; + float width = text_width + input_width + 5; + float text_pos = SCREEN_WIDTH/2 - width/2; + float 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_GUI-5); + Color(1.0f, 1.0f, 1.0f, 1.0f), LAYER_GUI-5); context.draw_filled_rect( Vector(input_pos - 4, y_pos - 9), Vector(input_width + 8, 18), - Color(0,0,0,128), LAYER_GUI-4); + Color(0, 0, 0, 0.5f), LAYER_GUI-4); if(pitem.kind == MN_TEXTFIELD || pitem.kind == MN_NUMFIELD) { @@ -610,10 +602,10 @@ Menu::draw_item(DrawingContext& context, int index) int text_pos = (text_width + 16)/2; /* Draw arrows */ - context.draw_surface(arrow_left, + context.draw_surface(arrow_left.get(), Vector(x_pos - list_pos + text_pos - 17, y_pos - 8), LAYER_GUI); - context.draw_surface(arrow_right, + context.draw_surface(arrow_right.get(), Vector(x_pos - list_pos + text_pos - 1 + list_pos_2, y_pos - 8), LAYER_GUI); @@ -621,11 +613,11 @@ Menu::draw_item(DrawingContext& context, int index) 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_GUI - 4); + Color(1.0f, 1.0f, 1.0f, 1.0f), LAYER_GUI - 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_GUI - 5); + Color(0, 0, 0, 0.5f), LAYER_GUI - 5); context.draw_text(text_font, pitem.list[pitem.selected], Vector(SCREEN_WIDTH/2 + text_pos, y_pos - int(text_font->get_height()/2)), @@ -640,7 +632,7 @@ Menu::draw_item(DrawingContext& context, int index) context.draw_text(text_font, pitem.text, Vector(SCREEN_WIDTH/2, y_pos - int(text_font->get_height()/2)), CENTER_ALLIGN, LAYER_GUI); - context.draw_surface(back, + context.draw_surface(back.get(), Vector(x_pos + text_width/2 + 16, y_pos - 8), LAYER_GUI); break; @@ -653,11 +645,11 @@ Menu::draw_item(DrawingContext& context, int index) CENTER_ALLIGN, LAYER_GUI); if(pitem.toggled) - context.draw_surface(checkbox_checked, + context.draw_surface(checkbox_checked.get(), Vector(x_pos + (text_width+16)/2, y_pos - 8), LAYER_GUI + 1); else - context.draw_surface(checkbox, + context.draw_surface(checkbox.get(), Vector(x_pos + (text_width+16)/2, y_pos - 8), LAYER_GUI + 1); break; @@ -676,42 +668,50 @@ Menu::draw_item(DrawingContext& context, int index) } } -int Menu::get_width() const +float Menu::get_width() const +{ + /* The width of the menu has to be more than the width of the text + with the most characters */ + float menu_width = 0; + for(unsigned int i = 0; i < items.size(); ++i) { - /* The width of the menu has to be more than the width of the text - with the most characters */ - int menu_width = 0; - for(unsigned int i = 0; i < items.size(); ++i) - { - int w = items[i]->text.size() + items[i]->input.size() + 1; - if(w > menu_width) - { - menu_width = w; - if( items[i]->kind == MN_TOGGLE) - menu_width += 2; - } - } - - return (menu_width * 16 + 24); + Font* font = default_font; + if(items[i]->kind == MN_LABEL) + font = label_font; + + float w = font->get_text_width(items[i]->text) + + label_font->get_text_width(items[i]->input) + 16; + if(items[i]->kind == MN_TOGGLE) + w += 32; + + if(w > menu_width) + menu_width = w; } + + return menu_width + 24; +} -int Menu::get_height() const - { - return items.size() * 24; - } +float Menu::get_height() const +{ + return items.size() * 24; +} /* Draw the current menu. */ void Menu::draw(DrawingContext& context) { - int menu_height = get_height(); - int menu_width = get_width(); + if(MouseCursor::current()) { + MouseCursor::current()->draw(context); + } + + float menu_height = get_height(); + float menu_width = get_width(); /* Draw a transparent background */ context.draw_filled_rect( Vector(pos_x - menu_width/2, pos_y - 24*items.size()/2 - 10), Vector(menu_width,menu_height + 20), - Color(150,180,200,125), LAYER_GUI-10); + Color(0.6f, 0.7f, 0.8f, 0.5f), LAYER_GUI-10); for(unsigned int i = 0; i < items.size(); ++i) { @@ -762,7 +762,7 @@ Menu::is_toggled(int id) const void Menu::event(const SDL_Event& event) { - if(effect.started()) + if(effect_ticks != 0) return; switch(event.type) { @@ -783,15 +783,16 @@ Menu::event(const SDL_Event& event) case SDL_MOUSEMOTION: { - int x = int(event.motion.x * float(SCREEN_WIDTH)/screen->w); - int y = int(event.motion.y * float(SCREEN_HEIGHT)/screen->h); + float x = event.motion.x * SCREEN_WIDTH/screen->w; + float y = event.motion.y * SCREEN_HEIGHT/screen->h; 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) { - int new_active_item = (y - (pos_y - get_height()/2)) / 24; + int new_active_item + = static_cast ((y - (pos_y - get_height()/2)) / 24); /* only change the mouse focus to a selectable item */ if ((items[new_active_item]->kind != MN_HL) @@ -818,12 +819,11 @@ Menu::event(const SDL_Event& event) void Menu::set_active_item(int id) { - for(int i = 0; i < items.size(); ++i) { - MenuItem* item = items[i]; - if(item->id == id) { - active_item = i; - break; - } - } + for(size_t i = 0; i < items.size(); ++i) { + MenuItem* item = items[i]; + if(item->id == id) { + active_item = i; + break; + } + } } -