diff --git a/src/gui/menu_manager.cpp b/src/gui/menu_manager.cpp index c96fe7f124f..b029e0f1f55 100644 --- a/src/gui/menu_manager.cpp +++ b/src/gui/menu_manager.cpp @@ -24,6 +24,7 @@ #include "supertux/globals.hpp" #include "supertux/menu/menu_storage.hpp" #include "supertux/timer.hpp" +#include "util/log.hpp" #include "video/drawing_context.hpp" MenuManager* MenuManager::s_instance = 0; @@ -35,26 +36,106 @@ MenuManager::instance() return *s_instance; } -MenuManager::MenuManager() : - m_menu_stack() +namespace { + +Rectf menu2rect(const Menu& menu) { - s_instance = this; + return Rectf(menu.get_pos().x, + menu.get_pos().y, + menu.get_pos().x + menu.get_width(), + menu.get_pos().y + menu.get_height()); } -MenuManager::~MenuManager() +Rectf pos2rect(const Menu& menu) { - s_instance = nullptr; + return Rectf(menu.get_pos().x, + menu.get_pos().y, + menu.get_pos().x, + menu.get_pos().y); } -void -MenuManager::draw(DrawingContext& context) +} // namespace + +class MenuTransition { - if (current()) +private: + Rectf m_from_rect; + Rectf m_to_rect; + + bool m_closing_animation; + float m_effect_progress; + float m_effect_start_time; + bool m_is_active; +public: + MenuTransition() : + m_is_active(false) { + } + + void start(const Rectf& to_rect) + { + m_to_rect = to_rect; + } + + void start(const Rectf& from_rect, + const Rectf& to_rect) + { + m_from_rect = from_rect; + m_to_rect = to_rect; + + m_effect_start_time = real_time; + m_effect_progress = 0.0f; + + m_is_active = true; + } + + void update() + { + m_effect_progress = (real_time - m_effect_start_time) * 6.0f; + + if (m_effect_progress >= 1.0f) { + m_effect_progress = 1.0f; + + /* if (close) + { + MenuManager::instance().m_current = 0; + close = false; + }*/ + } + else if (m_effect_progress <= 0.0f) + { + m_effect_progress = 0.0f; + } + } + + void draw(DrawingContext& context) + { +#ifdef GRUMBEL Vector pos = current()->get_pos(); float menu_width = current()->get_width(); float menu_height = current()->get_height(); + float p = m_effect_progress; + if (p != 1.0f) + { + if (close) + { + menu_width *= 1.0f - p; + menu_height *= 1.0f - p; + } + else if (MenuManager::instance().m_previous) + { + menu_width = (menu_width * p) + (MenuManager::instance().m_previous->get_width() * (1.0f - p)); + menu_height = (menu_height * p) + (MenuManager::instance().m_previous->get_height() * (1.0f - p)); + //std::cout << p << " " << this << " " << last_menus.back() << std::endl; + } + else + { + menu_width *= p; + menu_height *= p; + } + } + // draw menu background rectangles 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)), @@ -67,56 +148,68 @@ MenuManager::draw(DrawingContext& context) Color(0.6f, 0.7f, 0.8f, 0.5f), 16.0f, LAYER_GUI-10); - - current()->draw(context); - - if (MouseCursor::current()) - { - MouseCursor::current()->draw(context); - } +#endif } -#ifdef GRUMBEL - if (effect_progress != 1.0f) + bool is_active() { - 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; - } + return m_is_active; } +}; - //update - effect_progress = (real_time - effect_start_time) * 6.0f; +MenuManager::MenuManager() : + m_menu_stack(), + m_transition(new MenuTransition) +{ + s_instance = this; +} - if(effect_progress >= 1.0f) { - effect_progress = 1.0f; +MenuManager::~MenuManager() +{ + s_instance = nullptr; +} - if (close) { - MenuManager::instance().m_current = 0; - close = false; - } +void +MenuManager::update() +{ + if (current()) + { + current()->update(); + } +} + +void +MenuManager::event(const SDL_Event& event) +{ + if (current()) + { + current()->event(event); } - else if (effect_progress <= 0.0f) { - effect_progress = 0.0f; +} + +void +MenuManager::draw(DrawingContext& context) +{ + if (!current()) + { + return; } + m_transition->update(); + m_transition->draw(context); + +#ifdef GRUMBEL // only pass events in non-anim states - if(effect_progress != 1.0f) + if(m_effect_progress != 1.0f) return; - #endif + + current()->draw(context); + + if (MouseCursor::current()) + { + MouseCursor::current()->draw(context); + } } bool @@ -142,31 +235,28 @@ MenuManager::push_menu(int id) void MenuManager::push_menu(std::unique_ptr menu) { + //start_transition_effect(); m_menu_stack.push_back(std::move(menu)); - - //current()->effect_start_time = real_time; - //current()->effect_progress = 0.0f; } void MenuManager::pop_menu() { - if (!m_menu_stack.empty()) + if (m_menu_stack.empty()) { - m_menu_stack.pop_back(); - //current()->effect_start_time = real_time; - //current()->effect_progress = 0.0f; + log_warning << "trying to pop on an empty menu_stack" << std::endl; } else { - set_menu(MenuStorage::NO_MENU); + m_menu_stack.pop_back(); + //start_transition_effect(); } } void MenuManager::clear_menu_stack() { - set_menu(MenuStorage::NO_MENU); + m_menu_stack.clear(); } void @@ -180,16 +270,12 @@ MenuManager::set_menu(std::unique_ptr menu) { if (menu) { + m_transition->start(pos2rect(*menu), menu2rect(*menu)); m_menu_stack.push_back(std::move(menu)); - //current()->effect_start_time = real_time; - //current()->effect_progress = 0.0f; } else { m_menu_stack.clear(); - //current()->effect_start_time = real_time; - //current()->effect_progress = 0.0f; - //current()->close = true; } // just to be sure... @@ -206,4 +292,17 @@ MenuManager::recalc_pos() } } +Menu* +MenuManager::current() const +{ + if (m_menu_stack.empty()) + { + return nullptr; + } + else + { + return m_menu_stack.back().get(); + } +} + /* EOF */ diff --git a/src/gui/menu_manager.hpp b/src/gui/menu_manager.hpp index 85ba2ec00d7..3baf4ec67dd 100644 --- a/src/gui/menu_manager.hpp +++ b/src/gui/menu_manager.hpp @@ -21,8 +21,11 @@ #include #include -class Menu; +#include "SDL.h" + class DrawingContext; +class Menu; +class MenuTransition; class MenuManager { @@ -33,10 +36,7 @@ class MenuManager public: std::vector > m_menu_stack; - - bool close; - float effect_progress; - float effect_start_time; + std::unique_ptr m_transition; friend class Menu; @@ -44,39 +44,26 @@ class MenuManager MenuManager(); ~MenuManager(); + void event(const SDL_Event& event); + void update(); void draw(DrawingContext& context); bool check_menu(); void set_menu(int id); - void clear_menu_stack(); - - void push_menu(std::unique_ptr menu); + void set_menu(std::unique_ptr menu); void push_menu(int id); + void push_menu(std::unique_ptr menu); void pop_menu(); + void clear_menu_stack(); void recalc_pos(); - - /** Return the current active menu or NULL if none is active */ - Menu* current() const - { - if (m_menu_stack.empty()) - { - return nullptr; - } - else - { - return m_menu_stack.back().get(); - } - } - bool is_active() const { return !m_menu_stack.empty(); } private: - /** Set the current menu, if pmenu is NULL, hide the current menu */ - void set_menu(std::unique_ptr menu); + Menu* current() const; private: MenuManager(const MenuManager&); diff --git a/src/supertux/screen_manager.cpp b/src/supertux/screen_manager.cpp index a19f914fdfa..17e2ba2682e 100644 --- a/src/supertux/screen_manager.cpp +++ b/src/supertux/screen_manager.cpp @@ -174,8 +174,7 @@ ScreenManager::update_gamelogic(float elapsed_time) scripting::update_debugger(); scripting::TimeScheduler::instance->update(game_time); current_screen->update(elapsed_time); - if (m_menu_manager->current() != NULL) - m_menu_manager->current()->update(); + m_menu_manager->update(); if(screen_fade.get() != NULL) screen_fade->update(elapsed_time); Console::instance->update(elapsed_time); @@ -190,8 +189,7 @@ ScreenManager::process_events() { g_input_manager->process_event(event); - if(m_menu_manager->current() != NULL) - m_menu_manager->current()->event(event); + m_menu_manager->event(event); switch(event.type) { diff --git a/src/supertux/title_screen.cpp b/src/supertux/title_screen.cpp index ae5cd231195..681e3e3b7c8 100644 --- a/src/supertux/title_screen.cpp +++ b/src/supertux/title_screen.cpp @@ -157,10 +157,7 @@ TitleScreen::update(float elapsed_time) make_tux_jump(); - if (Menu* menu = MenuManager::instance().current()) - { - menu->check_menu(); - } + MenuManager::instance().check_menu(); // reopen menu if user closed it (so that the app doesn't close when user // accidently hit ESC)