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 | |
29 | Gradient::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 | |
40 | Gradient::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 | |
109 | ObjectSettings |
110 | Gradient::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 | |
148 | Gradient::~Gradient() |
149 | { |
150 | } |
151 | |
152 | void |
153 | Gradient::update(float) |
154 | { |
155 | } |
156 | |
157 | void |
158 | Gradient::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 | |
180 | void |
181 | Gradient::set_direction(const GradientDirection& direction) |
182 | { |
183 | m_gradient_direction = direction; |
184 | } |
185 | |
186 | void |
187 | Gradient::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 | |
214 | bool |
215 | Gradient::is_saveable() const |
216 | { |
217 | return !(Level::current() && |
218 | Level::current()->is_worldmap()); |
219 | } |
220 | |
221 | /* EOF */ |
222 | |