X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fgui%2Fmenu.cpp;h=fd253e9beca49bd40746c3535ca6c137ce57ae66;hb=HEAD;hp=55415ee4b1cf0336a546b41c6a45fa797df429eb;hpb=b26a4e8ac7eedb0def71d2a0d9b0b4b2c2d42cc9;p=supertux.git diff --git a/src/gui/menu.cpp b/src/gui/menu.cpp index 55415ee4b..fd253e9be 100644 --- a/src/gui/menu.cpp +++ b/src/gui/menu.cpp @@ -19,40 +19,33 @@ #include #include -#include "control/joystickkeyboardcontroller.hpp" +#include "control/input_manager.hpp" #include "gui/menu_item.hpp" #include "gui/menu_manager.hpp" #include "gui/mousecursor.hpp" +#include "supertux/colorscheme.hpp" #include "supertux/globals.hpp" -#include "supertux/screen_manager.hpp" #include "supertux/resources.hpp" +#include "supertux/screen_manager.hpp" #include "supertux/timer.hpp" #include "util/gettext.hpp" #include "video/drawing_context.hpp" #include "video/font.hpp" #include "video/renderer.hpp" +#include "video/video_system.hpp" static const float MENU_REPEAT_INITIAL = 0.4f; static const float MENU_REPEAT_RATE = 0.1f; Menu::Menu() : - hit_item(), pos(), - menuaction(), delete_character(), mn_input_char(), menu_repeat_time(), - close(false), items(), - effect_progress(), - effect_start_time(), arrange_left(), active_item() { - MenuManager::all_menus.push_back(this); - - hit_item = -1; - menuaction = MENU_ACTION_NONE; delete_character = 0; mn_input_char = '\0'; @@ -60,40 +53,25 @@ Menu::Menu() : pos.y = SCREEN_HEIGHT/2; arrange_left = 0; active_item = -1; - - effect_progress = 0.0f; - effect_start_time = 0.0f; } Menu::~Menu() { - MenuManager::all_menus.remove(this); - - for(std::vector::iterator i = items.begin(); - i != items.end(); ++i) - { - delete *i; - } - - if (MenuManager::current_ == this) - MenuManager::current_ = NULL; - - if (MenuManager::previous == this) - MenuManager::previous = NULL; } void -Menu::set_pos(float x, float y, float rw, float rh) +Menu::set_center_pos(float x, float y) { - pos.x = x + get_width() * rw; - pos.y = y + get_height() * rh; + pos.x = x; + pos.y = y; } /* Add an item to a menu */ -void -Menu::additem(MenuItem* item) +MenuItem* +Menu::add_item(std::unique_ptr new_item) { - items.push_back(item); + items.push_back(std::move(new_item)); + MenuItem* item = items.back().get(); /* If a new menu is being built, the active item shouldn't be set to * something that isn't selectable. Set the active_item to the first @@ -102,109 +80,98 @@ Menu::additem(MenuItem* item) if (active_item == -1 && item->kind != MN_HL && item->kind != MN_LABEL - && item->kind != MN_INACTIVE) { + && item->kind != MN_INACTIVE) + { active_item = items.size() - 1; } + + return item; } MenuItem* Menu::add_hl() { - MenuItem* item = new MenuItem(MN_HL); - additem(item); - return item; + std::unique_ptr item(new MenuItem(MN_HL)); + return add_item(std::move(item)); } MenuItem* Menu::add_label(const std::string& text) { - MenuItem* item = new MenuItem(MN_LABEL); + std::unique_ptr item(new MenuItem(MN_LABEL)); item->text = text; - additem(item); - return item; + return add_item(std::move(item)); } MenuItem* Menu::add_controlfield(int id, const std::string& text, const std::string& mapping) { - MenuItem* item = new MenuItem(MN_CONTROLFIELD, id); + std::unique_ptr item(new MenuItem(MN_CONTROLFIELD, id)); item->change_text(text); item->change_input(mapping); - additem(item); - return item; + return add_item(std::move(item)); } MenuItem* Menu::add_entry(int id, const std::string& text) { - MenuItem* item = new MenuItem(MN_ACTION, id); + std::unique_ptr item(new MenuItem(MN_ACTION, id)); item->text = text; - additem(item); - return item; + return add_item(std::move(item)); } MenuItem* Menu::add_inactive(int id, const std::string& text) { - MenuItem* item = new MenuItem(MN_INACTIVE, id); + std::unique_ptr item(new MenuItem(MN_INACTIVE, id)); item->text = text; - additem(item); - return item; + return add_item(std::move(item)); } MenuItem* Menu::add_toggle(int id, const std::string& text, bool toogled) { - MenuItem* item = new MenuItem(MN_TOGGLE, id); + std::unique_ptr item(new MenuItem(MN_TOGGLE, id)); item->text = text; item->toggled = toogled; - additem(item); - return item; + return add_item(std::move(item)); } MenuItem* Menu::add_string_select(int id, const std::string& text) { - MenuItem* item = new MenuItem(MN_STRINGSELECT, id); + std::unique_ptr item(new MenuItem(MN_STRINGSELECT, id)); item->text = text; - additem(item); - return item; + return add_item(std::move(item)); } MenuItem* Menu::add_back(const std::string& text) { - MenuItem* item = new MenuItem(MN_BACK); + std::unique_ptr item(new MenuItem(MN_BACK)); item->text = text; - additem(item); - return item; + return add_item(std::move(item)); } MenuItem* -Menu::add_submenu(const std::string& text, Menu* submenu, int id) +Menu::add_submenu(const std::string& text, int submenu) { - MenuItem* item = new MenuItem(MN_GOTO, id); + std::unique_ptr item(new MenuItem(MN_GOTO)); item->text = text; item->target_menu = submenu; - additem(item); - return item; + return add_item(std::move(item)); } void Menu::clear() { - for(std::vector::iterator i = items.begin(); - i != items.end(); ++i) { - delete *i; - } items.clear(); active_item = -1; } -/* Process actions done on the menu */ void -Menu::update() +Menu::process_input() { int menu_height = (int) get_height(); if (menu_height > SCREEN_HEIGHT) @@ -213,21 +180,8 @@ Menu::update() pos.y = SCREEN_HEIGHT/2 - scroll_offset * ((float(active_item) / (items.size()-1)) - 0.5f) * 2.0f; } - effect_progress = (real_time - effect_start_time) * 6.0f; - - if(effect_progress >= 1.0f) { - effect_progress = 1.0f; - - if (close) { - MenuManager::current_ = 0; - close = false; - } - } - else if (effect_progress <= 0.0f) { - effect_progress = 0.0f; - } - - Controller* controller = g_jk_controller->get_controller(); + MenuAction menuaction = MENU_ACTION_NONE; + Controller* controller = InputManager::current()->get_controller(); /** check main input controller... */ if(controller->pressed(Controller::UP)) { menuaction = MENU_ACTION_UP; @@ -273,15 +227,24 @@ Menu::update() || controller->pressed(Controller::MENU_SELECT)) { menuaction = MENU_ACTION_HIT; } - if(controller->pressed(Controller::PAUSE_MENU) - || controller->pressed(Controller::MENU_BACK)) { + if(controller->pressed(Controller::ESCAPE) || + controller->pressed(Controller::START) || + controller->pressed(Controller::MENU_BACK)) { menuaction = MENU_ACTION_BACK; } - hit_item = -1; if(items.size() == 0) return; + // The menu_action() call can pop() the menu from the stack and thus + // delete it, so it's important that no further member variables are + // accessed after this call + process_action(menuaction); +} + +void +Menu::process_action(MenuAction menuaction) +{ int last_active_item = active_item; switch(menuaction) { case MENU_ACTION_UP: @@ -316,8 +279,8 @@ Menu::update() items[active_item]->selected--; else items[active_item]->selected = items[active_item]->list.size()-1; - - menu_action(items[active_item]); + + menu_action(items[active_item].get()); } break; @@ -327,30 +290,29 @@ Menu::update() items[active_item]->selected++; else items[active_item]->selected = 0; - - menu_action(items[active_item]); + + menu_action(items[active_item].get()); } break; case MENU_ACTION_HIT: { - hit_item = active_item; switch (items[active_item]->kind) { case MN_GOTO: assert(items[active_item]->target_menu != 0); - MenuManager::push_current(items[active_item]->target_menu); + MenuManager::instance().push_menu(items[active_item]->target_menu); break; case MN_TOGGLE: items[active_item]->toggled = !items[active_item]->toggled; - menu_action(items[active_item]); + menu_action(items[active_item].get()); break; case MN_CONTROLFIELD: - menu_action(items[active_item]); + menu_action(items[active_item].get()); break; case MN_ACTION: - menu_action(items[active_item]); + menu_action(items[active_item].get()); break; case MN_STRINGSELECT: @@ -359,18 +321,19 @@ Menu::update() else items[active_item]->selected = 0; - menu_action(items[active_item]); + menu_action(items[active_item].get()); break; case MN_TEXTFIELD: case MN_NUMFIELD: menuaction = MENU_ACTION_DOWN; - update(); + process_input(); break; case MN_BACK: - MenuManager::pop_current(); - break; + MenuManager::instance().pop_menu(); + return; + default: break; } @@ -404,36 +367,15 @@ Menu::update() break; case MENU_ACTION_BACK: - MenuManager::pop_current(); - break; + MenuManager::instance().pop_menu(); + return; case MENU_ACTION_NONE: break; } - menuaction = MENU_ACTION_NONE; - - assert(active_item < int(items.size())); -} - -int -Menu::check() -{ - if (hit_item != -1) - { - int id = items[hit_item]->id; - // Clear event when checked out.. (we would end up in a loop when we try to leave "fake" submenu like Addons or Contrib) - hit_item = -1; - return id; - } - else - return -1; } void -Menu::menu_action(MenuItem* ) -{} - -void Menu::draw_item(DrawingContext& context, int index) { float menu_height = get_height(); @@ -441,7 +383,7 @@ Menu::draw_item(DrawingContext& context, int index) MenuItem& pitem = *(items[index]); - Color text_color = default_color; + Color text_color = ColorScheme::Menu::default_color; float x_pos = pos.x; float y_pos = pos.y + 24*index - menu_height/2 + 12; int text_width = int(Resources::normal_font->get_text_width(pitem.text)); @@ -460,7 +402,7 @@ Menu::draw_item(DrawingContext& context, int index) if(index == active_item) { - text_color = active_color; + text_color = ColorScheme::Menu::active_color; } if(active_item == index) @@ -484,7 +426,7 @@ Menu::draw_item(DrawingContext& context, int index) { context.draw_text(Resources::normal_font, pitem.text, Vector(pos.x, y_pos - int(Resources::normal_font->get_height()/2)), - ALIGN_CENTER, LAYER_GUI, inactive_color); + ALIGN_CENTER, LAYER_GUI, ColorScheme::Menu::inactive_color); break; } @@ -506,7 +448,7 @@ Menu::draw_item(DrawingContext& context, int index) { context.draw_text(Resources::big_font, pitem.text, Vector(pos.x, y_pos - int(Resources::big_font->get_height()/2)), - ALIGN_CENTER, LAYER_GUI, label_color); + ALIGN_CENTER, LAYER_GUI, ColorScheme::Menu::label_color); break; } case MN_TEXTFIELD: @@ -519,17 +461,17 @@ Menu::draw_item(DrawingContext& context, int index) context.draw_text(Resources::normal_font, pitem.get_input_with_symbol(true), Vector(right, y_pos - int(Resources::normal_font->get_height()/2)), - ALIGN_RIGHT, LAYER_GUI, field_color); + ALIGN_RIGHT, LAYER_GUI, ColorScheme::Menu::field_color); else context.draw_text(Resources::normal_font, pitem.get_input_with_symbol(false), Vector(right, y_pos - int(Resources::normal_font->get_height()/2)), - ALIGN_RIGHT, LAYER_GUI, field_color); + ALIGN_RIGHT, LAYER_GUI, ColorScheme::Menu::field_color); } else context.draw_text(Resources::normal_font, pitem.input, Vector(right, y_pos - int(Resources::normal_font->get_height()/2)), - ALIGN_RIGHT, LAYER_GUI, field_color); + ALIGN_RIGHT, LAYER_GUI, ColorScheme::Menu::field_color); context.draw_text(Resources::normal_font, pitem.text, Vector(left, y_pos - int(Resources::normal_font->get_height()/2)), @@ -615,7 +557,7 @@ Menu::get_width() const w += 32; if (items[i]->kind == MN_STRINGSELECT) w += font->get_text_width(items[i]->list[items[i]->selected]) + 32; - + if(w > menu_width) menu_width = w; @@ -630,68 +572,34 @@ Menu::get_height() const return items.size() * 24; } -/* Draw the current menu. */ void -Menu::draw(DrawingContext& context) +Menu::on_window_resize() { - if(MouseCursor::current()) { - MouseCursor::current()->draw(context); - } - - float menu_width = get_width(); - float menu_height = get_height(); - - if (effect_progress != 1.0f) - { - if (close) - { - menu_width = (MenuManager::current_->get_width() * (1.0f - effect_progress)); - menu_height = (MenuManager::current_->get_height() * (1.0f - effect_progress)); - } - else if (MenuManager::previous) - { - menu_width = (menu_width * effect_progress) + (MenuManager::previous->get_width() * (1.0f - effect_progress)); - menu_height = (menu_height * effect_progress) + (MenuManager::previous->get_height() * (1.0f - effect_progress)); - //std::cout << effect_progress << " " << this << " " << last_menus.back() << std::endl; - } - else - { - menu_width *= effect_progress; - menu_height *= effect_progress; - } - } - - /* Draw a transparent background */ - context.draw_filled_rect(Rectf(Vector(pos.x - menu_width/2-4, pos.y - menu_height/2 - 10-4), - Vector(pos.x + menu_width/2+4, pos.y - menu_height/2 + 10 + menu_height+4)), - Color(0.2f, 0.3f, 0.4f, 0.8f), - 20.0f, - LAYER_GUI-10); - - context.draw_filled_rect(Rectf(Vector(pos.x - menu_width/2, pos.y - menu_height/2 - 10), - Vector(pos.x + menu_width/2, pos.y - menu_height/2 + 10 + menu_height)), - Color(0.6f, 0.7f, 0.8f, 0.5f), - 16.0f, - LAYER_GUI-10); + pos.x = SCREEN_WIDTH / 2; + pos.y = SCREEN_HEIGHT / 2; +} +void +Menu::draw(DrawingContext& context) +{ if (!items[active_item]->help.empty()) { int text_width = (int) Resources::normal_font->get_text_width(items[active_item]->help); int text_height = (int) Resources::normal_font->get_text_height(items[active_item]->help); - - Rectf text_rect(pos.x - text_width/2 - 8, + + Rectf text_rect(pos.x - text_width/2 - 8, SCREEN_HEIGHT - 48 - text_height/2 - 4, - pos.x + text_width/2 + 8, + pos.x + text_width/2 + 8, SCREEN_HEIGHT - 48 + text_height/2 + 4); - + context.draw_filled_rect(Rectf(text_rect.p1 - Vector(4,4), text_rect.p2 + Vector(4,4)), - Color(0.2f, 0.3f, 0.4f, 0.8f), + Color(0.2f, 0.3f, 0.4f, 0.8f), 16.0f, LAYER_GUI-10); - + context.draw_filled_rect(text_rect, - Color(0.6f, 0.7f, 0.8f, 0.5f), + Color(0.6f, 0.7f, 0.8f, 0.5f), 16.0f, LAYER_GUI-10); @@ -700,36 +608,35 @@ Menu::draw(DrawingContext& context) ALIGN_CENTER, LAYER_GUI); } - if (effect_progress == 1.0f) - for(unsigned int i = 0; i < items.size(); ++i) - { - draw_item(context, i); - } + for(unsigned int i = 0; i < items.size(); ++i) + { + draw_item(context, i); + } } MenuItem& Menu::get_item_by_id(int id) { - for(std::vector::iterator i = items.begin(); - i != items.end(); ++i) { - MenuItem& item = **i; - - if(item.id == id) - return item; + for (const auto& item : items) + { + if (item->id == id) + { + return *item; + } } - throw std::runtime_error("MenuItem not found"); + throw std::runtime_error("MenuItem not found: " + std::to_string(id)); } const MenuItem& Menu::get_item_by_id(int id) const { - for(std::vector::const_iterator i = items.begin(); - i != items.end(); ++i) { - const MenuItem& item = **i; - - if(item.id == id) - return item; + for (const auto& item : items) + { + if (item->id == id) + { + return *item; + } } throw std::runtime_error("MenuItem not found"); @@ -752,27 +659,14 @@ Menu::set_toggled(int id, bool toggled) get_item_by_id(id).toggled = toggled; } -Menu* -Menu::get_parent() const -{ - if (MenuManager::last_menus.empty()) - return 0; - else - return MenuManager::last_menus.back(); -} - -/* Check for menu event */ void -Menu::event(const SDL_Event& event) +Menu::event(const SDL_Event& ev) { - if(effect_progress != 1.0f) - return; - - switch(event.type) { + switch(ev.type) { case SDL_MOUSEBUTTONDOWN: - if(event.button.button == SDL_BUTTON_LEFT) + if(ev.button.button == SDL_BUTTON_LEFT) { - Vector mouse_pos = Renderer::instance()->to_logical(event.motion.x, event.motion.y); + Vector mouse_pos = VideoSystem::current()->get_renderer().to_logical(ev.motion.x, ev.motion.y); int x = int(mouse_pos.x); int y = int(mouse_pos.y); @@ -781,14 +675,14 @@ Menu::event(const SDL_Event& event) y > pos.y - get_height()/2 && y < pos.y + get_height()/2) { - menuaction = MENU_ACTION_HIT; + process_action(MENU_ACTION_HIT); } } break; case SDL_MOUSEMOTION: { - Vector mouse_pos = Renderer::instance()->to_logical(event.motion.x, event.motion.y); + Vector mouse_pos = VideoSystem::current()->get_renderer().to_logical(ev.motion.x, ev.motion.y); float x = mouse_pos.x; float y = mouse_pos.y; @@ -826,8 +720,7 @@ void Menu::set_active_item(int id) { for(size_t i = 0; i < items.size(); ++i) { - MenuItem* item = items[i]; - if(item->id == id) { + if(items[i]->id == id) { active_item = i; break; }