2 // Copyright (C) 2009 Ingo Ruhnke <grumbel@gmail.com>
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #include "gui/menu_manager.hpp"
21 #include "control/input_manager.hpp"
22 #include "gui/menu.hpp"
23 #include "gui/mousecursor.hpp"
24 #include "math/sizef.hpp"
25 #include "supertux/globals.hpp"
26 #include "supertux/menu/menu_storage.hpp"
27 #include "supertux/timer.hpp"
28 #include "util/log.hpp"
29 #include "video/drawing_context.hpp"
31 MenuManager* MenuManager::s_instance = 0;
34 MenuManager::instance()
42 Rectf menu2rect(const Menu& menu)
44 return Rectf(menu.get_center_pos().x - menu.get_width() / 2,
45 menu.get_center_pos().y - menu.get_height() / 2,
46 menu.get_center_pos().x + menu.get_width() / 2,
47 menu.get_center_pos().y + menu.get_height() / 2);
58 float m_effect_progress;
59 float m_effect_start_time;
66 m_effect_progress(1.0f),
67 m_effect_start_time(),
72 void start(const Rectf& from_rect,
75 m_from_rect = from_rect;
78 m_effect_start_time = real_time;
79 m_effect_progress = 0.0f;
84 void set(const Rectf& rect)
86 m_to_rect = m_from_rect = rect;
93 m_effect_progress = (real_time - m_effect_start_time) * 6.0f;
95 if (m_effect_progress > 1.0f)
97 m_effect_progress = 1.0f;
103 void draw(DrawingContext& context)
105 float p = m_effect_progress;
107 Rectf rect = m_to_rect;
110 rect.p1.x = (m_to_rect.p1.x * p) + (m_from_rect.p1.x * (1.0f - p));
111 rect.p1.y = (m_to_rect.p1.y * p) + (m_from_rect.p1.y * (1.0f - p));
112 rect.p2.x = (m_to_rect.p2.x * p) + (m_from_rect.p2.x * (1.0f - p));
113 rect.p2.y = (m_to_rect.p2.y * p) + (m_from_rect.p2.y * (1.0f - p));
116 // draw menu background rectangles
117 context.draw_filled_rect(Rectf(rect.p1.x - 4, rect.p1.y - 10-4,
118 rect.p2.x + 4, rect.p2.y + 10 + 4),
119 Color(0.2f, 0.3f, 0.4f, 0.8f),
123 context.draw_filled_rect(Rectf(rect.p1.x, rect.p1.y - 10,
124 rect.p2.x, rect.p2.y + 10),
125 Color(0.6f, 0.7f, 0.8f, 0.5f),
136 MenuManager::MenuManager() :
138 m_transition(new MenuTransition)
143 MenuManager::~MenuManager()
145 s_instance = nullptr;
149 MenuManager::refresh()
151 for(auto i = m_menu_stack.begin(); i != m_menu_stack.end(); ++i)
158 MenuManager::process_input()
162 current()->process_input();
167 MenuManager::event(const SDL_Event& event)
169 if (current() && !m_transition->is_active())
171 // only pass events when the menu is fully visible and not in a
172 // transition animation
173 current()->event(event);
178 MenuManager::draw(DrawingContext& context)
180 if (m_transition->is_active())
182 m_transition->update();
183 m_transition->draw(context);
189 // brute force the transition into the right shape in case the
190 // menu has changed sizes
191 m_transition->set(menu2rect(*current()));
192 m_transition->draw(context);
194 current()->draw(context);
198 if (current() && MouseCursor::current())
200 MouseCursor::current()->draw(context);
205 MenuManager::check_menu()
209 current()->check_menu();
219 MenuManager::push_menu(int id)
221 push_menu(MenuStorage::instance().create(static_cast<MenuStorage::MenuId>(id)));
225 MenuManager::set_menu(int id)
227 set_menu(MenuStorage::instance().create(static_cast<MenuStorage::MenuId>(id)));
231 MenuManager::push_menu(std::unique_ptr<Menu> menu)
234 transition(m_menu_stack.empty() ? nullptr : m_menu_stack.back().get(),
236 m_menu_stack.push_back(std::move(menu));
240 MenuManager::pop_menu()
242 if (m_menu_stack.empty())
244 log_warning << "trying to pop on an empty menu_stack" << std::endl;
248 transition(m_menu_stack.back().get(),
249 (m_menu_stack.size() >= 2)
250 ? m_menu_stack[m_menu_stack.size() - 2].get()
253 m_menu_stack.pop_back();
258 MenuManager::set_menu(std::unique_ptr<Menu> menu)
262 transition(m_menu_stack.empty() ? nullptr : m_menu_stack.back().get(),
264 m_menu_stack.clear();
265 m_menu_stack.push_back(std::move(menu));
269 transition(m_menu_stack.empty() ? nullptr : m_menu_stack.back().get(),
271 m_menu_stack.clear();
274 // just to be sure...
275 g_input_manager->reset();
279 MenuManager::clear_menu_stack()
281 transition(m_menu_stack.empty() ? nullptr : m_menu_stack.back().get(),
283 m_menu_stack.clear();
287 MenuManager::on_window_resize()
289 for(auto i = m_menu_stack.begin(); i != m_menu_stack.end(); ++i)
291 (*i)->on_window_resize();
296 MenuManager::current() const
298 if (m_menu_stack.empty())
304 return m_menu_stack.back().get();
309 MenuManager::transition(Menu* from, Menu* to)
320 from_rect = menu2rect(*from);
324 from_rect = Rectf(to->get_center_pos(), Sizef(0, 0));
330 to_rect = menu2rect(*to);
334 to_rect = Rectf(from->get_center_pos(), Sizef(0, 0));
337 m_transition->start(from_rect, to_rect);