#include "gui/menu_item.hpp"
#include "gui/menu_manager.hpp"
#include "gui/mousecursor.hpp"
+#include "supertux/colorscheme.hpp"
#include "supertux/globals.hpp"
#include "supertux/resources.hpp"
#include "supertux/screen_manager.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::instance().m_all_menus.push_back(this);
-
- hit_item = -1;
- menuaction = MENU_ACTION_NONE;
delete_character = 0;
mn_input_char = '\0';
pos.y = SCREEN_HEIGHT/2;
arrange_left = 0;
active_item = -1;
-
- effect_progress = 0.0f;
- effect_start_time = 0.0f;
}
Menu::~Menu()
{
- MenuManager::instance().m_all_menus.remove(this);
-
- if (MenuManager::instance().m_current == this)
- MenuManager::instance().m_current = nullptr;
-
- if (MenuManager::instance().m_previous == this)
- MenuManager::instance().m_previous = nullptr;
}
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 */
}
MenuItem*
-Menu::add_submenu(const std::string& text, int submenu, int id)
+Menu::add_submenu(const std::string& text, int submenu)
{
- std::unique_ptr<MenuItem> item(new MenuItem(MN_GOTO, id));
+ std::unique_ptr<MenuItem> item(new MenuItem(MN_GOTO));
item->text = text;
item->target_menu = submenu;
return add_item(std::move(item));
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)
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::instance().m_current = 0;
- close = false;
- }
- }
- else if (effect_progress <= 0.0f) {
- effect_progress = 0.0f;
- }
-
- Controller* controller = g_input_manager->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;
|| 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:
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::instance().push_current(items[active_item]->target_menu);
+ MenuManager::instance().push_menu(items[active_item]->target_menu);
break;
case MN_TOGGLE:
case MN_TEXTFIELD:
case MN_NUMFIELD:
menuaction = MENU_ACTION_DOWN;
- update();
+ process_input();
break;
case MN_BACK:
- MenuManager::instance().pop_current();
- break;
+ MenuManager::instance().pop_menu();
+ return;
+
default:
break;
}
break;
case MENU_ACTION_BACK:
- MenuManager::instance().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)
{
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));
if(index == active_item)
{
- text_color = active_color;
+ text_color = ColorScheme::Menu::active_color;
}
if(active_item == 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;
}
{
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:
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)),
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 *= 1.0f - effect_progress;
- menu_height *= 1.0f - effect_progress;
- }
- else if (MenuManager::instance().m_previous)
- {
- menu_width = (menu_width * effect_progress) + (MenuManager::instance().m_previous->get_width() * (1.0f - effect_progress));
- menu_height = (menu_height * effect_progress) + (MenuManager::instance().m_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);
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&
}
}
- throw std::runtime_error("MenuItem not found");
+ throw std::runtime_error("MenuItem not found: " + std::to_string(id));
}
const MenuItem&
get_item_by_id(id).toggled = toggled;
}
-/* 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);
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;