1// SuperTux
2// Copyright (C) 2006 Matthias Braun <matze@braunis.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 "object/gradient.hpp"
18
19#include "editor/editor.hpp"
20#include "object/camera.hpp"
21#include "supertux/level.hpp"
22#include "supertux/sector.hpp"
23#include "util/reader.hpp"
24#include "util/reader_mapping.hpp"
25#include "util/writer.hpp"
26#include "video/video_system.hpp"
27#include "video/viewport.hpp"
28
29Gradient::Gradient() :
30 ExposedObject<Gradient, scripting::Gradient>(this),
31 m_layer(LAYER_BACKGROUND0),
32 m_gradient_top(),
33 m_gradient_bottom(),
34 m_gradient_direction(),
35 m_blend(),
36 m_target(DrawingTarget::COLORMAP)
37{
38}
39
40Gradient::Gradient(const ReaderMapping& reader) :
41 GameObject(reader),
42 ExposedObject<Gradient, scripting::Gradient>(this),
43 m_layer(LAYER_BACKGROUND0),
44 m_gradient_top(),
45 m_gradient_bottom(),
46 m_gradient_direction(),
47 m_blend(),
48 m_target(DrawingTarget::COLORMAP)
49{
50 m_layer = reader_get_layer (reader, LAYER_BACKGROUND0);
51 std::vector<float> bkgd_top_color, bkgd_bottom_color;
52 std::string direction;
53 if (reader.get("direction", direction))
54 {
55 if (direction == "horizontal")
56 {
57 m_gradient_direction = HORIZONTAL;
58 }
59 else if (direction == "horizontal_sector")
60 {
61 m_gradient_direction = HORIZONTAL_SECTOR;
62 }
63 else if (direction == "vertical_sector")
64 {
65 m_gradient_direction = VERTICAL_SECTOR;
66 }
67 else
68 {
69 m_gradient_direction = VERTICAL;
70 }
71 }
72 else
73 {
74 m_gradient_direction = VERTICAL;
75 }
76 if (m_gradient_direction == HORIZONTAL || m_gradient_direction == HORIZONTAL_SECTOR)
77 {
78 if (!reader.get("left_color", bkgd_top_color) ||
79 !reader.get("right_color", bkgd_bottom_color))
80 {
81 log_warning <<
82 "Horizontal gradients should use left_color and right_color, respectively. "
83 "Trying to parse top and bottom color instead" << std::endl;
84 }
85 else
86 {
87 m_gradient_top = Color(bkgd_top_color);
88 m_gradient_bottom = Color(bkgd_bottom_color);
89 return;
90 }
91 }
92
93 if (reader.get("top_color", bkgd_top_color)) {
94 m_gradient_top = Color(bkgd_top_color);
95 } else {
96 m_gradient_top = Color(0.3f, 0.4f, 0.75f);
97 }
98
99 if (reader.get("bottom_color", bkgd_bottom_color)) {
100 m_gradient_bottom = Color(bkgd_bottom_color);
101 } else {
102 m_gradient_bottom = Color(1, 1, 1);
103 }
104
105 reader.get_custom("blend", m_blend, Blend_from_string);
106 reader.get_custom("target", m_target, DrawingTarget_from_string);
107}
108
109ObjectSettings
110Gradient::get_settings()
111{
112 ObjectSettings result = GameObject::get_settings();
113
114 if (m_gradient_direction == HORIZONTAL || m_gradient_direction == HORIZONTAL_SECTOR) {
115 result.add_rgba(_("Left Colour"), &m_gradient_top, "left_color");
116 result.add_rgba(_("Right Colour"), &m_gradient_bottom, "right_color");
117 } else {
118 result.add_rgba(_("Top Colour"), &m_gradient_top, "top_color");
119 result.add_rgba(_("Bottom Colour"), &m_gradient_bottom, "bottom_color");
120 }
121
122 result.add_int(_("Z-pos"), &m_layer, "z-pos", LAYER_BACKGROUND0);
123
124 result.add_enum(_("Direction"), reinterpret_cast<int*>(&m_gradient_direction),
125 {_("Vertical"), _("Horizontal"), _("Vertical (whole sector)"), _("Horizontal (whole sector)")},
126 {"vertical", "horizontal", "vertical_sector", "horizontal_sector"},
127 static_cast<int>(VERTICAL));
128
129 result.add_enum(_("Draw target"), reinterpret_cast<int*>(&m_target),
130 {_("Normal"), _("Lightmap")},
131 {"normal", "lightmap"},
132 static_cast<int>(DrawingTarget::COLORMAP),
133 "target");
134
135 result.add_enum(_("Blend mode"), reinterpret_cast<int*>(&m_blend),
136 {_("Blend"), _("Additive"), _("Modulate"), _("None")},
137 {"blend", "add", "mod", "none"},
138 static_cast<int>(Blend::BLEND),
139 "blend");
140
141 result.reorder({"blend", "top_color", "bottom_color", "target", "z-pos"});
142
143 result.add_remove();
144
145 return result;
146}
147
148Gradient::~Gradient()
149{
150}
151
152void
153Gradient::update(float)
154{
155}
156
157void
158Gradient::set_gradient(Color top, Color bottom)
159{
160 m_gradient_top = top;
161 m_gradient_bottom = bottom;
162
163 if (m_gradient_top.red > 1.0f ||
164 m_gradient_top.green > 1.0f ||
165 m_gradient_top.blue > 1.0f ||
166 m_gradient_top.alpha > 1.0f)
167 {
168 log_warning << "top gradient color has values above 1.0" << std::endl;
169 }
170
171 if (m_gradient_bottom.red > 1.0f ||
172 m_gradient_bottom.green > 1.0f ||
173 m_gradient_bottom.blue > 1.0f ||
174 m_gradient_bottom.alpha > 1.0f)
175 {
176 log_warning << "bottom gradient color has values above 1.0" << std::endl;
177 }
178}
179
180void
181Gradient::set_direction(const GradientDirection& direction)
182{
183 m_gradient_direction = direction;
184}
185
186void
187Gradient::draw(DrawingContext& context)
188{
189 if (Editor::is_active() && !EditorOverlayWidget::render_background)
190 return;
191
192 Rectf gradient_region;
193 if (m_gradient_direction != HORIZONTAL && m_gradient_direction != VERTICAL)
194 {
195 auto camera_translation = Sector::get().get_camera().get_translation();
196 auto sector_width = Sector::get().get_width();
197 auto sector_height = Sector::get().get_height();
198 gradient_region = Rectf(-camera_translation.x, -camera_translation.y, sector_width, sector_height);
199 }
200 else
201 {
202 gradient_region = Rectf(0, 0,
203 static_cast<float>(context.get_width()),
204 static_cast<float>(context.get_height()));
205 }
206
207 context.push_transform();
208 context.set_translation(Vector(0, 0));
209 context.get_canvas(m_target).draw_gradient(m_gradient_top, m_gradient_bottom, m_layer, m_gradient_direction,
210 gradient_region, m_blend);
211 context.pop_transform();
212}
213
214bool
215Gradient::is_saveable() const
216{
217 return !(Level::current() &&
218 Level::current()->is_worldmap());
219}
220
221/* EOF */
222