1// SuperTux
2// Copyright (C) 2006 Matthias Braun <matze@braunis.de>
3// Copyright (C) 2016 M. Teufel <mteufel@supertux.org>
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18#include "supertux/textscroller_screen.hpp"
19
20#include <sstream>
21
22#include "audio/sound_manager.hpp"
23#include "control/input_manager.hpp"
24#include "object/textscroller.hpp"
25#include "supertux/fadetoblack.hpp"
26#include "supertux/globals.hpp"
27#include "supertux/info_box_line.hpp"
28#include "supertux/screen_manager.hpp"
29#include "util/log.hpp"
30#include "util/reader.hpp"
31#include "util/reader_document.hpp"
32#include "util/reader_mapping.hpp"
33#include "video/compositor.hpp"
34#include "video/drawing_context.hpp"
35#include "video/surface.hpp"
36#include "video/video_system.hpp"
37#include "video/viewport.hpp"
38
39namespace {
40
41const float DEFAULT_SPEED = 20;
42const float SCROLL = 60;
43
44} // namespace
45
46TextScrollerScreen::TextScrollerScreen(const std::string& filename) :
47 m_defaultspeed(DEFAULT_SPEED),
48 m_music(),
49 m_background(),
50 m_text_scroller(),
51 m_fading(false)
52{
53 std::string background_file;
54
55 try {
56 auto doc = ReaderDocument::from_file(filename);
57 auto root = doc.get_root();
58
59 m_text_scroller = std::make_unique<TextScroller>(root);
60
61 if (root.get_name() != "supertux-text") {
62 throw std::runtime_error("File isn't a supertux-text file");
63 } else {
64 auto text_mapping = root.get_mapping();
65
66 if (!text_mapping.get("background", background_file)) {
67 throw std::runtime_error("File doesn't contain a background file");
68 }
69
70 text_mapping.get("speed", m_defaultspeed);
71 text_mapping.get("music", m_music);
72 }
73 } catch (std::exception& e) {
74 std::ostringstream msg;
75 msg << "Couldn't load file '" << filename << "': " << e.what() << std::endl;
76 throw std::runtime_error(msg.str());
77 }
78
79 // load background image
80 m_background = Surface::from_file("images/background/" + background_file);
81}
82
83TextScrollerScreen::~TextScrollerScreen()
84{
85}
86
87void
88TextScrollerScreen::setup()
89{
90 SoundManager::current()->play_music(m_music);
91 ScreenManager::current()->set_screen_fade(std::make_unique<FadeToBlack>(FadeToBlack::FADEIN, 0.5));
92}
93
94void
95TextScrollerScreen::update(float dt_sec, const Controller& controller)
96{
97 if (controller.hold(Control::UP)) {
98 m_text_scroller->set_speed(-m_defaultspeed * 5);
99 } else if (controller.hold(Control::DOWN)) {
100 m_text_scroller->set_speed(m_defaultspeed * 5);
101 } else {
102 m_text_scroller->set_speed(m_defaultspeed);
103 }
104
105 if ((controller.pressed(Control::JUMP) ||
106 controller.pressed(Control::ACTION) ||
107 controller.pressed(Control::MENU_SELECT)) &&
108 !(controller.pressed(Control::UP))) { // prevent skipping if jump with up is enabled
109 m_text_scroller->scroll(SCROLL);
110 }
111
112 if (controller.pressed(Control::START) ||
113 controller.pressed(Control::ESCAPE)) {
114 ScreenManager::current()->pop_screen(std::make_unique<FadeToBlack>(FadeToBlack::FADEOUT, 0.5));
115 }
116
117 { // close when done
118 if (m_text_scroller->is_finished() && !m_fading)
119 {
120 m_fading = true;
121 ScreenManager::current()->pop_screen(std::make_unique<FadeToBlack>(FadeToBlack::FADEOUT, 0.5));
122 }
123 }
124
125 m_text_scroller->update(dt_sec);
126}
127
128void
129TextScrollerScreen::draw(Compositor& compositor)
130{
131 auto& context = compositor.make_context();
132
133 const float ctx_w = static_cast<float>(context.get_width());
134 const float ctx_h = static_cast<float>(context.get_height());
135
136 { // draw background
137 const float bg_w = static_cast<float>(m_background->get_width());
138 const float bg_h = static_cast<float>(m_background->get_height());
139
140 const float bg_ratio = bg_w / bg_h;
141 const float ctx_ratio = ctx_w / ctx_h;
142
143 if (bg_ratio > ctx_ratio)
144 {
145 const float new_bg_w = ctx_h * bg_ratio;
146 context.color().draw_surface_scaled(m_background,
147 Rectf::from_center(Vector(ctx_w / 2.0f, ctx_h / 2.0f),
148 Sizef(new_bg_w, ctx_h)),
149 0);
150 }
151 else
152 {
153 const float new_bg_h = ctx_w / bg_ratio;
154 context.color().draw_surface_scaled(m_background,
155 Rectf::from_center(Vector(ctx_w / 2.0f, ctx_h / 2.0f),
156 Sizef(ctx_w, new_bg_h)),
157 0);
158 }
159 }
160
161 m_text_scroller->draw(context);
162}
163
164/* EOF */
165