1
// $Id: screen_manager.cpp 3269 2007-10-01 04:24:14Z grumbel $
3
// Pingus - A free Lemmings clone
4
// Copyright (C) 2000 Ingo Ruhnke <grumbel@gmx.de>
6
// This program is free software; you can redistribute it and/or
7
// modify it under the terms of the GNU General Public License
8
// as published by the Free Software Foundation; either version 2
9
// of the License, or (at your option) any later version.
11
// This program is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
// GNU General Public License for more details.
16
// You should have received a copy of the GNU General Public License
17
// along with this program; if not, write to the Free Software
18
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
#include "../globals.hpp"
23
#include "math/size.hpp"
24
#include "pathname.hpp"
25
#include "display/cursor.hpp"
26
#include "display/display.hpp"
27
#include "screen_manager.hpp"
28
#include "../path_manager.hpp"
29
#include "screenshot.hpp"
30
#include "../display/drawing_context.hpp"
31
#include "../input/controller.hpp"
32
#include "../input/manager.hpp"
34
ScreenManager* ScreenManager::instance_ = 0;
36
ScreenManager::ScreenManager()
38
display_gc = new DrawingContext();
40
cached_action = CA_NONE;
43
ScreenManager::~ScreenManager ()
49
ScreenManager::display()
51
Input::Manager input_manager;
53
Input::Controller* input_controller = 0;
55
if (controller_file.empty())
56
input_controller = input_manager.create_controller(Pathname("controller/default.scm",
57
Pathname::DATA_PATH));
59
input_controller = input_manager.create_controller(Pathname(controller_file,
60
Pathname::SYSTEM_PATH));
65
cursor = new Cursor("core/cursors/animcross");
66
Display::add_flip_screen_hook(cursor);
67
SDL_ShowCursor(SDL_DISABLE);
70
DeltaManager delta_manager;
72
// Main loop for the menu
73
while (!screens.empty())
75
float time_delta = delta_manager.getset();
80
std::cout << "ScreenManager: detected large delta (" << time_delta
81
<< "), ignoring and doing frameskip" << std::endl;
85
input_manager.update(time_delta);
87
// Fill the delta with values
88
GameDelta delta(time_delta, delta_manager.get_absolute(),
89
input_controller->poll_events());
91
last_screen = get_current_screen();
93
// Most likly the screen will get changed in this update call
94
get_current_screen()->update (delta);
97
cursor->update(time_delta);
99
// Last screen has poped, so we are going to end here
103
while (cached_action != CA_NONE)
105
switch (cached_action)
111
real_pop_all_screens();
114
real_replace_screen(replace_screen_arg);
124
// FIXME: is there a more gentel way to do that instead of spreading the checks all around here?
125
// Last screen has poped, so we are going to end here
129
// skip draw if the screen changed to avoid glitches
130
if (last_screen == get_current_screen() || fast_mode)
132
if (get_current_screen()->draw(*display_gc))
134
display_gc->render(Display::get_screen(), Rect(Vector2i(0,0), Size(Display::get_width(),
135
Display::get_height())));
136
Display::flip_display ();
142
//std::cout << "ScreenManager: fading screens" << std::endl;
143
fade_over(last_screen, get_current_screen());
146
// Stupid hack to make this thing take less CPU
150
Display::remove_flip_screen_hook(cursor);
152
delete input_controller;
156
ScreenManager::get_current_screen()
158
assert(!screens.empty());
159
return screens.back ();
163
ScreenManager::instance ()
168
return instance_ = new ScreenManager ();
172
ScreenManager::push_screen (Screen* screen, bool delete_screen)
174
if (!screens.empty())
176
screens.back ()->on_shutdown ();
179
screens.push_back (ScreenPtr(screen, delete_screen));
180
screen->on_startup ();
184
ScreenManager::pop_screen ()
186
assert (cached_action == CA_NONE || cached_action == CA_POP);
187
cached_action = CA_POP;
191
ScreenManager::pop_all_screens()
193
assert(cached_action == CA_NONE);
194
cached_action = CA_POP_ALL;
198
ScreenManager::replace_screen (Screen* screen, bool delete_screen)
200
assert (cached_action == CA_NONE);
201
cached_action = CA_REPLACE;
202
replace_screen_arg = ScreenPtr(screen, delete_screen);
206
ScreenManager::real_replace_screen (const ScreenPtr& ptr)
208
cached_action = CA_NONE;
209
screens.back ()->on_shutdown ();
210
screens.back () = ptr;
211
screens.back ()->on_startup ();
215
ScreenManager::real_pop_screen ()
217
cached_action = CA_NONE;
218
ScreenPtr back = screens.back ();
222
if (!screens.empty ())
224
screens.back()->on_startup ();
229
ScreenManager::real_pop_all_screens()
231
cached_action = CA_NONE;
232
ScreenPtr back = screens.back();
240
ScreenManager::clear()
242
cached_action = CA_CLEAR;
246
ScreenManager::real_clear()
248
cached_action = CA_NONE;
253
ScreenManager::fade_over (ScreenPtr& old_screen, ScreenPtr& new_screen)
255
DeltaManager delta_manager;
256
float passed_time = 0;
258
float progress = 0.0f;
259
while (progress <= 1.0f)
261
float time_delta = delta_manager.getset ();
262
passed_time += time_delta;
264
int border_x = int((Display::get_width()/2) * (1.0f - progress));
265
int border_y = int((Display::get_height()/2) * (1.0f - progress));
267
old_screen->draw(*display_gc);
268
display_gc->render(Display::get_screen(), Rect(Vector2i(0,0), Size(Display::get_width(),
269
Display::get_height())));
272
Display::push_cliprect(Rect(Vector2i(0 + border_x, 0 + border_y),
273
Size(screen_width - 2*border_x, screen_height - 2*border_y)));
275
new_screen->draw(*display_gc);
276
display_gc->render(Display::get_screen(), Rect(Vector2i(0,0), Size(Display::get_width(),
277
Display::get_height())));
280
//GameDelta delta (time_delta, CL_System::get_time(), events);
281
// FIXME: Animation looks nifty but doesn't work all that good
282
//new_screen->update (delta);
283
//old_screen->update (delta);
285
Display::pop_cliprect();
286
Display::flip_display ();
289
progress = passed_time/1.0f;
294
ScreenManager::resize(const Size& size)
296
display_gc->set_rect(Rect(Vector2i(0, 0), size));
298
// FIXME: Calling this causes horrible flicker, any better way to resize the screen?
299
Display::set_video_mode(size.width, size.height);
301
get_current_screen()->resize(size);
305
ScreenManager::get_screen()
307
return get_current_screen().get();
311
ScreenManager::init()
317
ScreenManager::deinit()