Remove bogus assert
[supertux.git] / src / gui / menu.cpp
index 240f2fa..fd253e9 100644 (file)
@@ -23,6 +23,7 @@
 #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';
 
@@ -60,27 +53,17 @@ 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::instance().m_all_menus.remove(this);
-
-  if (MenuManager::instance().current() == this)
-    MenuManager::instance().m_current = nullptr;
-
-  if (MenuManager::instance().get_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 */
@@ -172,9 +155,9 @@ Menu::add_back(const std::string& text)
 }
 
 MenuItem*
-Menu::add_submenu(const std::string& text, Menu* 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));
@@ -187,9 +170,8 @@ Menu::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)
@@ -198,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::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;
@@ -258,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:
@@ -318,11 +296,10 @@ Menu::update()
       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:
@@ -350,12 +327,13 @@ Menu::update()
         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;
       }
@@ -389,35 +367,14 @@ Menu::update()
       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)
 {
@@ -426,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));
@@ -445,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)
@@ -469,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;
     }
 
@@ -491,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:
@@ -504,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,50 +572,16 @@ 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::instance().current()->get_width()  * (1.0f - effect_progress));
-      menu_height = (MenuManager::instance().current()->get_height() * (1.0f - effect_progress));
-    }
-    else if (MenuManager::instance().get_previous())
-    {
-      menu_width  = (menu_width  * effect_progress) + (MenuManager::instance().get_previous()->get_width()  * (1.0f - effect_progress));
-      menu_height = (menu_height * effect_progress) + (MenuManager::instance().get_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);
@@ -685,11 +608,10 @@ 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&
@@ -703,7 +625,7 @@ Menu::get_item_by_id(int id)
     }
   }
 
-  throw std::runtime_error("MenuItem not found");
+  throw std::runtime_error("MenuItem not found: " + std::to_string(id));
 }
 
 const MenuItem&
@@ -737,18 +659,14 @@ Menu::set_toggled(int id, bool toggled)
   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);
 
@@ -757,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;