gradient.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  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. #include <utility>
  17. #include "object/gradient.hpp"
  18. #include "editor/editor.hpp"
  19. #include "object/camera.hpp"
  20. #include "supertux/gameconfig.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. Gradient::Gradient() :
  29. ExposedObject<Gradient, scripting::Gradient>(this),
  30. m_layer(LAYER_BACKGROUND0),
  31. m_gradient_top(),
  32. m_gradient_bottom(),
  33. m_gradient_direction(),
  34. m_blend(),
  35. m_target(DrawingTarget::COLORMAP),
  36. m_start_gradient_top(),
  37. m_start_gradient_bottom(),
  38. m_fade_gradient_top(),
  39. m_fade_gradient_bottom(),
  40. m_fade_total_time(),
  41. m_fade_time()
  42. {
  43. }
  44. Gradient::Gradient(const ReaderMapping& reader) :
  45. GameObject(reader),
  46. ExposedObject<Gradient, scripting::Gradient>(this),
  47. m_layer(LAYER_BACKGROUND0),
  48. m_gradient_top(),
  49. m_gradient_bottom(),
  50. m_gradient_direction(),
  51. m_blend(),
  52. m_target(DrawingTarget::COLORMAP),
  53. m_start_gradient_top(),
  54. m_start_gradient_bottom(),
  55. m_fade_gradient_top(),
  56. m_fade_gradient_bottom(),
  57. m_fade_total_time(),
  58. m_fade_time()
  59. {
  60. m_layer = reader_get_layer (reader, LAYER_BACKGROUND0);
  61. std::vector<float> bkgd_top_color, bkgd_bottom_color;
  62. std::string direction;
  63. if (reader.get("direction", direction))
  64. {
  65. set_direction(direction);
  66. }
  67. else
  68. {
  69. set_direction(VERTICAL);
  70. }
  71. if (reader.get("top_color", bkgd_top_color)) {
  72. m_gradient_top = Color(bkgd_top_color);
  73. } else {
  74. m_gradient_top = Color(0.3f, 0.4f, 0.75f);
  75. }
  76. if (reader.get("bottom_color", bkgd_bottom_color)) {
  77. m_gradient_bottom = Color(bkgd_bottom_color);
  78. } else {
  79. m_gradient_bottom = Color(1, 1, 1);
  80. }
  81. reader.get_custom("blend", m_blend, Blend_from_string);
  82. reader.get_custom("target", m_target, DrawingTarget_from_string);
  83. }
  84. ObjectSettings
  85. Gradient::get_settings()
  86. {
  87. ObjectSettings result = GameObject::get_settings();
  88. result.add_rgba(_("Primary Colour"), &m_gradient_top, "top_color");
  89. result.add_rgba(_("Secondary Colour"), &m_gradient_bottom, "bottom_color");
  90. result.add_int(_("Z-pos"), &m_layer, "z-pos", LAYER_BACKGROUND0);
  91. result.add_enum(_("Direction"), reinterpret_cast<int*>(&m_gradient_direction),
  92. {_("Vertical"), _("Horizontal"), _("Vertical (whole sector)"), _("Horizontal (whole sector)")},
  93. {"vertical", "horizontal", "vertical_sector", "horizontal_sector"},
  94. static_cast<int>(VERTICAL), "direction");
  95. result.add_enum(_("Draw target"), reinterpret_cast<int*>(&m_target),
  96. {_("Normal"), _("Lightmap")},
  97. {"normal", "lightmap"},
  98. static_cast<int>(DrawingTarget::COLORMAP),
  99. "target");
  100. result.add_enum(_("Blend mode"), reinterpret_cast<int*>(&m_blend),
  101. {_("Blend"), _("Additive"), _("Modulate"), _("None")},
  102. {"blend", "add", "mod", "none"},
  103. static_cast<int>(Blend::BLEND),
  104. "blend");
  105. result.reorder({"blend", "top_color", "bottom_color", "target", "z-pos"});
  106. result.add_remove();
  107. return result;
  108. }
  109. Gradient::~Gradient()
  110. {
  111. }
  112. void
  113. Gradient::update(float delta)
  114. {
  115. if (m_fade_time <= 0) return;
  116. m_fade_time -= delta;
  117. if (m_fade_time <= 0)
  118. {
  119. m_fade_time = 0;
  120. m_gradient_top = m_fade_gradient_top;
  121. m_gradient_bottom = m_fade_gradient_bottom;
  122. return;
  123. }
  124. float progress = m_fade_time / m_fade_total_time;
  125. m_gradient_top = Color(
  126. m_fade_gradient_top.red + (m_start_gradient_top.red - m_fade_gradient_top.red) * progress,
  127. m_fade_gradient_top.green + (m_start_gradient_top.green - m_fade_gradient_top.green) * progress,
  128. m_fade_gradient_top.blue + (m_start_gradient_top.blue - m_fade_gradient_top.blue) * progress,
  129. m_fade_gradient_top.alpha + (m_start_gradient_top.alpha - m_fade_gradient_top.alpha) * progress
  130. );
  131. m_gradient_bottom = Color(
  132. m_fade_gradient_bottom.red + (m_start_gradient_bottom.red - m_fade_gradient_bottom.red) * progress,
  133. m_fade_gradient_bottom.green + (m_start_gradient_bottom.green - m_fade_gradient_bottom.green) * progress,
  134. m_fade_gradient_bottom.blue + (m_start_gradient_bottom.blue - m_fade_gradient_bottom.blue) * progress,
  135. m_fade_gradient_bottom.alpha + (m_start_gradient_bottom.alpha - m_fade_gradient_bottom.alpha) * progress
  136. );
  137. }
  138. void
  139. Gradient::set_gradient(const Color& top, const Color& bottom)
  140. {
  141. m_gradient_top = top;
  142. m_gradient_bottom = bottom;
  143. if (m_gradient_top.red > 1.0f ||
  144. m_gradient_top.green > 1.0f ||
  145. m_gradient_top.blue > 1.0f ||
  146. m_gradient_top.alpha > 1.0f)
  147. {
  148. log_warning << "Top gradient color has values above 1.0." << std::endl;
  149. }
  150. if (m_gradient_bottom.red > 1.0f ||
  151. m_gradient_bottom.green > 1.0f ||
  152. m_gradient_bottom.blue > 1.0f ||
  153. m_gradient_bottom.alpha > 1.0f)
  154. {
  155. log_warning << "Bottom gradient color has values above 1.0." << std::endl;
  156. }
  157. }
  158. void
  159. Gradient::fade_gradient(const Color& top, const Color& bottom, float time)
  160. {
  161. m_start_gradient_top = m_gradient_top;
  162. m_start_gradient_bottom = m_gradient_bottom;
  163. m_fade_gradient_top = top;
  164. m_fade_gradient_bottom = bottom;
  165. m_fade_total_time = time;
  166. m_fade_time = time;
  167. }
  168. std::string
  169. Gradient::get_direction_string() const
  170. {
  171. if (m_gradient_direction == HORIZONTAL)
  172. return "horizontal";
  173. if (m_gradient_direction == VERTICAL)
  174. return "vertical";
  175. if (m_gradient_direction == HORIZONTAL_SECTOR)
  176. return "horizontal_sector";
  177. if (m_gradient_direction == VERTICAL_SECTOR)
  178. return "vertical_sector";
  179. return nullptr;
  180. }
  181. void
  182. Gradient::set_direction(const GradientDirection& direction)
  183. {
  184. m_gradient_direction = direction;
  185. }
  186. void
  187. Gradient::set_direction(const std::string& direction)
  188. {
  189. if (direction == "horizontal")
  190. {
  191. m_gradient_direction = HORIZONTAL;
  192. }
  193. else if (direction == "horizontal_sector")
  194. {
  195. m_gradient_direction = HORIZONTAL_SECTOR;
  196. }
  197. else if (direction == "vertical_sector")
  198. {
  199. m_gradient_direction = VERTICAL_SECTOR;
  200. }
  201. else if (direction == "vertical")
  202. {
  203. m_gradient_direction = VERTICAL;
  204. }
  205. else
  206. {
  207. log_info << "Invalid direction for gradient \"" << direction << "\"";
  208. m_gradient_direction = VERTICAL;
  209. }
  210. }
  211. void
  212. Gradient::draw(DrawingContext& context)
  213. {
  214. if (Editor::is_active() && !g_config->editor_render_background)
  215. return;
  216. Rectf gradient_region;
  217. if (m_gradient_direction != HORIZONTAL && m_gradient_direction != VERTICAL)
  218. {
  219. auto camera_translation = Sector::get().get_camera().get_translation();
  220. auto sector_width = Sector::get().get_width();
  221. auto sector_height = Sector::get().get_height();
  222. gradient_region = Rectf(-camera_translation.x, -camera_translation.y, sector_width, sector_height);
  223. }
  224. else
  225. {
  226. gradient_region = context.get_rect();
  227. }
  228. context.push_transform();
  229. context.set_translation(Vector(0, 0));
  230. context.transform().scale = 1.f;
  231. context.get_canvas(m_target).draw_gradient(m_gradient_top, m_gradient_bottom, m_layer, m_gradient_direction,
  232. gradient_region, m_blend);
  233. context.pop_transform();
  234. }
  235. bool
  236. Gradient::is_saveable() const
  237. {
  238. return !(Level::current() &&
  239. Level::current()->is_worldmap());
  240. }
  241. void
  242. Gradient::on_flip(float height)
  243. {
  244. GameObject::on_flip(height);
  245. if (m_gradient_direction == VERTICAL || m_gradient_direction == VERTICAL_SECTOR)
  246. std::swap(m_gradient_top, m_gradient_bottom);
  247. }
  248. /* EOF */