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/dialog.hpp"
23 #include "gui/menu.hpp"
24 #include "gui/mousecursor.hpp"
25 #include "math/sizef.hpp"
26 #include "supertux/globals.hpp"
27 #include "supertux/menu/menu_storage.hpp"
28 #include "supertux/timer.hpp"
29 #include "util/log.hpp"
30 #include "video/drawing_context.hpp"
32 MenuManager* MenuManager::s_instance = 0;
35 MenuManager::instance()
43 Rectf menu2rect(const Menu& menu)
45 return Rectf(menu.get_center_pos().x - menu.get_width() / 2,
46 menu.get_center_pos().y - menu.get_height() / 2,
47 menu.get_center_pos().x + menu.get_width() / 2,
48 menu.get_center_pos().y + menu.get_height() / 2);
59 float m_effect_progress;
60 float m_effect_start_time;
67 m_effect_progress(1.0f),
68 m_effect_start_time(),
73 void start(const Rectf& from_rect,
76 m_from_rect = from_rect;
79 m_effect_start_time = real_time;
80 m_effect_progress = 0.0f;
85 void set(const Rectf& rect)
87 m_to_rect = m_from_rect = rect;
94 m_effect_progress = (real_time - m_effect_start_time) * 6.0f;
96 if (m_effect_progress > 1.0f)
98 m_effect_progress = 1.0f;
104 void draw(DrawingContext& context)
106 float p = m_effect_progress;
108 Rectf rect = m_to_rect;
111 rect.p1.x = (m_to_rect.p1.x * p) + (m_from_rect.p1.x * (1.0f - p));
112 rect.p1.y = (m_to_rect.p1.y * p) + (m_from_rect.p1.y * (1.0f - p));
113 rect.p2.x = (m_to_rect.p2.x * p) + (m_from_rect.p2.x * (1.0f - p));
114 rect.p2.y = (m_to_rect.p2.y * p) + (m_from_rect.p2.y * (1.0f - p));
117 // draw menu background rectangles
118 context.draw_filled_rect(Rectf(rect.p1.x - 4, rect.p1.y - 10-4,
119 rect.p2.x + 4, rect.p2.y + 10 + 4),
120 Color(0.2f, 0.3f, 0.4f, 0.8f),
124 context.draw_filled_rect(Rectf(rect.p1.x, rect.p1.y - 10,
125 rect.p2.x, rect.p2.y + 10),
126 Color(0.6f, 0.7f, 0.8f, 0.5f),
137 MenuManager::MenuManager() :
140 m_transition(new MenuTransition)
145 MenuManager::~MenuManager()
147 s_instance = nullptr;
151 MenuManager::refresh()
153 for(auto i = m_menu_stack.begin(); i != m_menu_stack.end(); ++i)
160 MenuManager::process_input()
164 m_dialog->process_input(*InputManager::current()->get_controller());
166 else if (current_menu())
168 current_menu()->process_input();
173 MenuManager::event(const SDL_Event& ev)
175 if (!m_transition->is_active())
181 else if (current_menu())
183 // only pass events when the menu is fully visible and not in a
184 // transition animation
185 current_menu()->event(ev);
191 MenuManager::draw(DrawingContext& context)
193 if (m_transition->is_active())
195 m_transition->update();
196 m_transition->draw(context);
202 m_dialog->draw(context);
204 else if (current_menu())
206 // brute force the transition into the right shape in case the
207 // menu has changed sizes
208 m_transition->set(menu2rect(*current_menu()));
209 m_transition->draw(context);
211 current_menu()->draw(context);
215 if (current_menu() && MouseCursor::current())
217 MouseCursor::current()->draw(context);
222 MenuManager::set_dialog(std::unique_ptr<Dialog> dialog)
224 m_dialog = std::move(dialog);
228 MenuManager::push_menu(int id)
230 push_menu(MenuStorage::instance().create(static_cast<MenuStorage::MenuId>(id)));
234 MenuManager::set_menu(int id)
236 set_menu(MenuStorage::instance().create(static_cast<MenuStorage::MenuId>(id)));
240 MenuManager::push_menu(std::unique_ptr<Menu> menu)
243 transition(m_menu_stack.empty() ? nullptr : m_menu_stack.back().get(),
245 m_menu_stack.push_back(std::move(menu));
249 MenuManager::pop_menu()
251 if (m_menu_stack.empty())
253 log_warning << "trying to pop on an empty menu_stack" << std::endl;
257 transition(m_menu_stack.back().get(),
258 (m_menu_stack.size() >= 2)
259 ? m_menu_stack[m_menu_stack.size() - 2].get()
262 m_menu_stack.pop_back();
267 MenuManager::set_menu(std::unique_ptr<Menu> menu)
271 transition(m_menu_stack.empty() ? nullptr : m_menu_stack.back().get(),
273 m_menu_stack.clear();
274 m_menu_stack.push_back(std::move(menu));
278 transition(m_menu_stack.empty() ? nullptr : m_menu_stack.back().get(),
280 m_menu_stack.clear();
283 // just to be sure...
284 InputManager::current()->reset();
288 MenuManager::clear_menu_stack()
290 transition(m_menu_stack.empty() ? nullptr : m_menu_stack.back().get(),
292 m_menu_stack.clear();
296 MenuManager::on_window_resize()
298 for(auto i = m_menu_stack.begin(); i != m_menu_stack.end(); ++i)
300 (*i)->on_window_resize();
305 MenuManager::current_menu() const
307 if (m_menu_stack.empty())
313 return m_menu_stack.back().get();
318 MenuManager::transition(Menu* from, Menu* to)
329 from_rect = menu2rect(*from);
333 from_rect = Rectf(to->get_center_pos(), Sizef(0, 0));
339 to_rect = menu2rect(*to);
343 to_rect = Rectf(from->get_center_pos(), Sizef(0, 0));
346 m_transition->start(from_rect, to_rect);