gradient.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  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 "object/gradient.hpp"
  17. #include <utility>
  18. #include <simplesquirrel/class.hpp>
  19. #include <simplesquirrel/vm.hpp>
  20. #include "editor/editor.hpp"
  21. #include "object/camera.hpp"
  22. #include "supertux/gameconfig.hpp"
  23. #include "supertux/level.hpp"
  24. #include "supertux/sector.hpp"
  25. #include "util/reader.hpp"
  26. #include "util/reader_mapping.hpp"
  27. #include "util/writer.hpp"
  28. #include "video/video_system.hpp"
  29. #include "video/viewport.hpp"
  30. Gradient::Gradient() :
  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. m_start_gradient_top(),
  38. m_start_gradient_bottom(),
  39. m_fade_gradient_top(),
  40. m_fade_gradient_bottom(),
  41. m_fade_total_time(),
  42. m_fade_time()
  43. {
  44. }
  45. Gradient::Gradient(const ReaderMapping& reader) :
  46. GameObject(reader),
  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::set_color1(float red, float green, float blue)
  213. {
  214. set_gradient(Color(red, green, blue), m_gradient_bottom);
  215. }
  216. void
  217. Gradient::set_color2(float red, float green, float blue)
  218. {
  219. set_gradient(m_gradient_top, Color(red, green, blue));
  220. }
  221. void
  222. Gradient::set_colors(float red1, float green1, float blue1, float red2, float green2, float blue2)
  223. {
  224. set_gradient(Color(red1, green1, blue1), Color(red2, green2, blue2));
  225. }
  226. void
  227. Gradient::fade_color1(float red, float green, float blue, float time)
  228. {
  229. fade_gradient(Color(red, green, blue), m_gradient_bottom, time);
  230. }
  231. void
  232. Gradient::fade_color2(float red, float green, float blue, float time)
  233. {
  234. fade_gradient(m_gradient_top, Color(red, green, blue), time);
  235. }
  236. void
  237. Gradient::fade_colors(float red1, float green1, float blue1, float red2, float green2, float blue2, float time)
  238. {
  239. fade_gradient(Color(red1, green1, blue1), Color(red2, green2, blue2), time);
  240. }
  241. void
  242. Gradient::swap_colors()
  243. {
  244. set_gradient(m_gradient_bottom, m_gradient_top);
  245. }
  246. void
  247. Gradient::draw(DrawingContext& context)
  248. {
  249. if (Editor::is_active() && !g_config->editor_render_background)
  250. return;
  251. Rectf gradient_region;
  252. if (m_gradient_direction != HORIZONTAL && m_gradient_direction != VERTICAL)
  253. {
  254. auto camera_translation = Sector::get().get_camera().get_translation();
  255. auto sector_width = Sector::get().get_width();
  256. auto sector_height = Sector::get().get_height();
  257. gradient_region = Rectf(-camera_translation.x, -camera_translation.y, sector_width, sector_height);
  258. }
  259. else
  260. {
  261. gradient_region = context.get_rect();
  262. }
  263. context.push_transform();
  264. context.set_translation(Vector(0, 0));
  265. context.transform().scale = 1.f;
  266. context.get_canvas(m_target).draw_gradient(m_gradient_top, m_gradient_bottom, m_layer, m_gradient_direction,
  267. gradient_region, m_blend);
  268. context.pop_transform();
  269. }
  270. bool
  271. Gradient::is_saveable() const
  272. {
  273. return !(Level::current() &&
  274. Level::current()->is_worldmap());
  275. }
  276. void
  277. Gradient::on_flip(float height)
  278. {
  279. GameObject::on_flip(height);
  280. if (m_gradient_direction == VERTICAL || m_gradient_direction == VERTICAL_SECTOR)
  281. std::swap(m_gradient_top, m_gradient_bottom);
  282. }
  283. void
  284. Gradient::register_class(ssq::VM& vm)
  285. {
  286. ssq::Class cls = vm.addAbstractClass<Gradient>("Gradient", vm.findClass("GameObject"));
  287. cls.addFunc<void, Gradient, const std::string&>("set_direction", &Gradient::set_direction);
  288. cls.addFunc("get_direction", &Gradient::get_direction_string);
  289. cls.addFunc("set_color1", &Gradient::set_color1);
  290. cls.addFunc("set_color2", &Gradient::set_color2);
  291. cls.addFunc("set_colors", &Gradient::set_colors);
  292. cls.addFunc("fade_color1", &Gradient::fade_color1);
  293. cls.addFunc("fade_color2", &Gradient::fade_color2);
  294. cls.addFunc("fade_colors", &Gradient::fade_colors);
  295. cls.addFunc("swap_colors", &Gradient::swap_colors);
  296. }
  297. /* EOF */