Cleaned up MenuManager some more, some ownership issues remain, so things will crash...
[supertux.git] / src / gui / menu_manager.cpp
1 //  SuperTux
2 //  Copyright (C) 2009 Ingo Ruhnke <grumbel@gmx.de>
3 //
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.
8 //
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.
13 //
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/>.
16
17 #include "gui/menu_manager.hpp"
18
19 #include <assert.h>
20
21 #include "control/input_manager.hpp"
22 #include "gui/menu.hpp"
23 #include "gui/mousecursor.hpp"
24 #include "supertux/globals.hpp"
25 #include "supertux/menu/menu_storage.hpp"
26 #include "supertux/timer.hpp"
27 #include "video/drawing_context.hpp"
28
29 MenuManager* MenuManager::s_instance = 0;
30
31 MenuManager&
32 MenuManager::instance()
33 {
34   assert(s_instance);
35   return *s_instance;
36 }
37
38 MenuManager::MenuManager() :
39   m_menu_stack()
40 {
41   s_instance = this;
42 }
43
44 MenuManager::~MenuManager()
45 {
46   s_instance = nullptr;
47 }
48
49 void
50 MenuManager::draw(DrawingContext& context)
51 {
52   if (current())
53   {
54     Vector pos = current()->get_pos();
55     float menu_width = current()->get_width();
56     float menu_height = current()->get_height();
57
58     // draw menu background rectangles
59     context.draw_filled_rect(Rectf(Vector(pos.x - menu_width/2-4, pos.y - menu_height/2 - 10-4),
60                                    Vector(pos.x + menu_width/2+4, pos.y - menu_height/2 + 10 + menu_height+4)),
61                              Color(0.2f, 0.3f, 0.4f, 0.8f),
62                              20.0f,
63                              LAYER_GUI-10);
64
65     context.draw_filled_rect(Rectf(Vector(pos.x - menu_width/2, pos.y - menu_height/2 - 10),
66                                    Vector(pos.x + menu_width/2, pos.y - menu_height/2 + 10 + menu_height)),
67                              Color(0.6f, 0.7f, 0.8f, 0.5f),
68                              16.0f,
69                              LAYER_GUI-10);
70
71     current()->draw(context);
72
73     if (MouseCursor::current())
74     {
75       MouseCursor::current()->draw(context);
76     }
77   }
78
79 #ifdef GRUMBEL
80   if (effect_progress != 1.0f)
81   {
82     if (close)
83     {
84       menu_width *= 1.0f - effect_progress;
85       menu_height *= 1.0f - effect_progress;
86     }
87     else if (MenuManager::instance().m_previous)
88     {
89       menu_width  = (menu_width  * effect_progress) + (MenuManager::instance().m_previous->get_width()  * (1.0f - effect_progress));
90       menu_height = (menu_height * effect_progress) + (MenuManager::instance().m_previous->get_height() * (1.0f - effect_progress));
91       //std::cout << effect_progress << " " << this << " " << last_menus.back() << std::endl;
92     }
93     else
94     {
95       menu_width  *= effect_progress;
96       menu_height *= effect_progress;
97     }
98   }
99
100   //update
101   effect_progress = (real_time - effect_start_time) * 6.0f;
102
103   if(effect_progress >= 1.0f) {
104     effect_progress = 1.0f;
105
106     if (close) {
107       MenuManager::instance().m_current = 0;
108       close = false;
109     }
110   }
111   else if (effect_progress <= 0.0f) {
112     effect_progress = 0.0f;
113   }
114
115   // only pass events in non-anim states
116   if(effect_progress != 1.0f)
117     return;
118
119 #endif
120 }
121
122 bool
123 MenuManager::check_menu()
124 {
125   if (current())
126   {
127     current()->check_menu();
128     return true;
129   }
130   else
131   {
132     return false;
133   }
134 }
135
136 void
137 MenuManager::push_menu(int id)
138 {
139   push_menu(MenuStorage::instance().create(static_cast<MenuStorage::MenuId>(id)));
140 }
141
142 void
143 MenuManager::push_menu(std::unique_ptr<Menu> menu)
144 {
145   m_menu_stack.push_back(std::move(menu));
146
147   //current()->effect_start_time = real_time;
148   //current()->effect_progress = 0.0f;
149 }
150
151 void
152 MenuManager::pop_menu()
153 {
154   if (!m_menu_stack.empty())
155   {
156     m_menu_stack.pop_back();
157     //current()->effect_start_time = real_time;
158     //current()->effect_progress   = 0.0f;
159   }
160   else
161   {
162     set_menu(MenuStorage::NO_MENU);
163   }
164 }
165
166 void
167 MenuManager::clear_menu_stack()
168 {
169   set_menu(MenuStorage::NO_MENU);
170 }
171
172 void
173 MenuManager::set_menu(int id)
174 {
175   set_menu(MenuStorage::instance().create(static_cast<MenuStorage::MenuId>(id)));
176 }
177
178 void
179 MenuManager::set_menu(std::unique_ptr<Menu> menu)
180 {
181   if (menu)
182   {
183     m_menu_stack.push_back(std::move(menu));
184     //current()->effect_start_time = real_time;
185     //current()->effect_progress = 0.0f;
186   }
187   else
188   {
189     m_menu_stack.clear();
190     //current()->effect_start_time = real_time;
191     //current()->effect_progress = 0.0f;
192     //current()->close = true;
193   }
194
195   // just to be sure...
196   g_input_manager->reset();
197 }
198
199 void
200 MenuManager::recalc_pos()
201 {
202   for(auto i = m_menu_stack.begin(); i != m_menu_stack.end(); ++i)
203   {
204     // FIXME: This is of course not quite right, since it ignores any previous set_pos() calls
205     (*i)->set_pos(SCREEN_WIDTH/2, SCREEN_HEIGHT/2);
206   }
207 }
208
209 /* EOF */