💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

357 lines
10 KiB

  1. /*
  2. * Copyright (C) 2021 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper source code.
  5. *
  6. * Antkeeper source code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper source code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "game/state/graphics-menu.hpp"
  20. #include "game/state/options-menu.hpp"
  21. #include "application.hpp"
  22. #include "scene/text.hpp"
  23. #include "debug/logger.hpp"
  24. #include "game/fonts.hpp"
  25. #include "game/menu.hpp"
  26. #include "game/graphics.hpp"
  27. #include "animation/timeline.hpp"
  28. namespace game {
  29. namespace state {
  30. static void update_value_text_content(game::context* ctx);
  31. graphics_menu::graphics_menu(game::context& ctx):
  32. game::state::base(ctx)
  33. {
  34. ctx.logger->push_task("Entering graphics menu state");
  35. // Construct menu item texts
  36. scene::text* fullscreen_name_text = new scene::text();
  37. scene::text* fullscreen_value_text = new scene::text();
  38. scene::text* resolution_name_text = new scene::text();
  39. scene::text* resolution_value_text = new scene::text();
  40. scene::text* v_sync_name_text = new scene::text();
  41. scene::text* v_sync_value_text = new scene::text();
  42. scene::text* font_size_name_text = new scene::text();
  43. scene::text* font_size_value_text = new scene::text();
  44. scene::text* dyslexia_font_name_text = new scene::text();
  45. scene::text* dyslexia_font_value_text = new scene::text();
  46. scene::text* back_text = new scene::text();
  47. // Build list of menu item texts
  48. ctx.menu_item_texts.push_back({fullscreen_name_text, fullscreen_value_text});
  49. ctx.menu_item_texts.push_back({resolution_name_text, resolution_value_text});
  50. ctx.menu_item_texts.push_back({v_sync_name_text, v_sync_value_text});
  51. ctx.menu_item_texts.push_back({font_size_name_text, font_size_value_text});
  52. ctx.menu_item_texts.push_back({dyslexia_font_name_text, dyslexia_font_value_text});
  53. ctx.menu_item_texts.push_back({back_text, nullptr});
  54. // Set content of menu item texts
  55. fullscreen_name_text->set_content((*ctx.strings)["graphics_menu_fullscreen"]);
  56. resolution_name_text->set_content((*ctx.strings)["graphics_menu_resolution"]);
  57. v_sync_name_text->set_content((*ctx.strings)["graphics_menu_v_sync"]);
  58. font_size_name_text->set_content((*ctx.strings)["graphics_menu_font_size"]);
  59. dyslexia_font_name_text->set_content((*ctx.strings)["graphics_menu_dyslexia_font"]);
  60. back_text->set_content((*ctx.strings)["back"]);
  61. update_value_text_content();
  62. // Init menu item index
  63. game::menu::init_menu_item_index(ctx, "graphics");
  64. game::menu::update_text_color(ctx);
  65. game::menu::update_text_font(ctx);
  66. game::menu::align_text(ctx);
  67. game::menu::update_text_tweens(ctx);
  68. game::menu::add_text_to_ui(ctx);
  69. game::menu::setup_animations(ctx);
  70. // Construct menu item callbacks
  71. auto toggle_fullscreen_callback = [this, &ctx]()
  72. {
  73. bool fullscreen = !ctx.app->is_fullscreen();
  74. ctx.app->set_fullscreen(fullscreen);
  75. if (!fullscreen)
  76. {
  77. int2 resolution;
  78. resolution.x() = (*ctx.config)["windowed_resolution"][0].get<int>();
  79. resolution.y() = (*ctx.config)["windowed_resolution"][1].get<int>();
  80. ctx.app->resize_window(resolution.x(), resolution.y());
  81. }
  82. this->update_value_text_content();
  83. game::menu::align_text(ctx);
  84. game::menu::update_text_tweens(ctx);
  85. // Save display mode config
  86. (*ctx.config)["fullscreen"] = fullscreen;
  87. };
  88. auto increase_resolution_callback = [this, &ctx]()
  89. {
  90. // Increase resolution
  91. if (ctx.controls["menu_modifier"]->is_active())
  92. ctx.render_resolution_scale += 0.05f;
  93. else
  94. ctx.render_resolution_scale += 0.25f;
  95. // Limit resolution
  96. if (ctx.render_resolution_scale > 2.0f)
  97. ctx.render_resolution_scale = 2.0f;
  98. // Resize framebuffers
  99. game::graphics::change_render_resolution(ctx, ctx.render_resolution_scale);
  100. // Update text
  101. this->update_value_text_content();
  102. game::menu::align_text(ctx);
  103. game::menu::update_text_tweens(ctx);
  104. // Update config
  105. (*ctx.config)["render_resolution"] = ctx.render_resolution_scale;
  106. };
  107. auto decrease_resolution_callback = [this, &ctx]()
  108. {
  109. // Increase resolution
  110. if (ctx.controls["menu_modifier"]->is_active())
  111. ctx.render_resolution_scale -= 0.05f;
  112. else
  113. ctx.render_resolution_scale -= 0.25f;
  114. // Limit resolution
  115. if (ctx.render_resolution_scale < 0.25f)
  116. ctx.render_resolution_scale = 0.25f;
  117. // Resize framebuffers
  118. game::graphics::change_render_resolution(ctx, ctx.render_resolution_scale);
  119. // Update text
  120. this->update_value_text_content();
  121. game::menu::align_text(ctx);
  122. game::menu::update_text_tweens(ctx);
  123. // Update config
  124. (*ctx.config)["render_resolution"] = ctx.render_resolution_scale;
  125. };
  126. auto toggle_v_sync_callback = [this, &ctx]()
  127. {
  128. bool v_sync = !ctx.app->get_v_sync();
  129. ctx.app->set_v_sync(v_sync);
  130. this->update_value_text_content();
  131. game::menu::align_text(ctx);
  132. game::menu::update_text_tweens(ctx);
  133. // Save v-sync config
  134. (*ctx.config)["v_sync"] = v_sync;
  135. };
  136. auto increase_font_size_callback = [this, &ctx]()
  137. {
  138. // Increase font size
  139. if (ctx.controls["menu_modifier"]->is_active())
  140. ctx.font_size += 0.01f;
  141. else
  142. ctx.font_size += 0.1f;
  143. // Limit font size
  144. if (ctx.font_size > 2.0f)
  145. ctx.font_size = 2.0f;
  146. // Update value text
  147. this->update_value_text_content();
  148. // Update config
  149. (*ctx.config)["font_size"] = ctx.font_size;
  150. // Reload fonts
  151. ctx.logger->push_task("Reloading fonts");
  152. try
  153. {
  154. game::load_fonts(ctx);
  155. }
  156. catch (...)
  157. {
  158. ctx.logger->pop_task(EXIT_FAILURE);
  159. }
  160. ctx.logger->pop_task(EXIT_SUCCESS);
  161. // Refresh and realign text
  162. game::menu::refresh_text(ctx);
  163. game::menu::align_text(ctx);
  164. game::menu::update_text_tweens(ctx);
  165. };
  166. auto decrease_font_size_callback = [this, &ctx]()
  167. {
  168. // Decrease font size
  169. if (ctx.controls["menu_modifier"]->is_active())
  170. ctx.font_size -= 0.01f;
  171. else
  172. ctx.font_size -= 0.1f;
  173. // Limit font size
  174. if (ctx.font_size < 0.1f)
  175. ctx.font_size = 0.1f;
  176. // Update value text
  177. this->update_value_text_content();
  178. // Update config
  179. (*ctx.config)["font_size"] = ctx.font_size;
  180. // Reload fonts
  181. ctx.logger->push_task("Reloading fonts");
  182. try
  183. {
  184. game::load_fonts(ctx);
  185. }
  186. catch (...)
  187. {
  188. ctx.logger->pop_task(EXIT_FAILURE);
  189. }
  190. ctx.logger->pop_task(EXIT_SUCCESS);
  191. // Refresh and realign text
  192. game::menu::refresh_text(ctx);
  193. game::menu::align_text(ctx);
  194. game::menu::update_text_tweens(ctx);
  195. };
  196. auto toggle_dyslexia_font_callback = [this, &ctx]()
  197. {
  198. ctx.dyslexia_font = !ctx.dyslexia_font;
  199. // Update value text
  200. this->update_value_text_content();
  201. // Save dyslexia font config
  202. (*ctx.config)["dyslexia_font"] = ctx.dyslexia_font;
  203. // Reload fonts
  204. ctx.logger->push_task("Reloading fonts");
  205. try
  206. {
  207. game::load_fonts(ctx);
  208. }
  209. catch (...)
  210. {
  211. ctx.logger->pop_task(EXIT_FAILURE);
  212. }
  213. ctx.logger->pop_task(EXIT_SUCCESS);
  214. // Refresh and realign text
  215. game::menu::refresh_text(ctx);
  216. game::menu::align_text(ctx);
  217. game::menu::update_text_tweens(ctx);
  218. };
  219. auto select_back_callback = [&ctx]()
  220. {
  221. // Disable controls
  222. game::menu::clear_controls(ctx);
  223. game::menu::fade_out
  224. (
  225. ctx,
  226. [&ctx]()
  227. {
  228. // Queue change to options menu state
  229. ctx.function_queue.push
  230. (
  231. [&ctx]()
  232. {
  233. ctx.state_machine.pop();
  234. ctx.state_machine.emplace(new game::state::options_menu(ctx));
  235. }
  236. );
  237. }
  238. );
  239. };
  240. // Build list of menu select callbacks
  241. ctx.menu_select_callbacks.push_back(toggle_fullscreen_callback);
  242. ctx.menu_select_callbacks.push_back(increase_resolution_callback);
  243. ctx.menu_select_callbacks.push_back(toggle_v_sync_callback);
  244. ctx.menu_select_callbacks.push_back(increase_font_size_callback);
  245. ctx.menu_select_callbacks.push_back(toggle_dyslexia_font_callback);
  246. ctx.menu_select_callbacks.push_back(select_back_callback);
  247. // Build list of menu left callbacks
  248. ctx.menu_left_callbacks.push_back(toggle_fullscreen_callback);
  249. ctx.menu_left_callbacks.push_back(decrease_resolution_callback);
  250. ctx.menu_left_callbacks.push_back(toggle_v_sync_callback);
  251. ctx.menu_left_callbacks.push_back(decrease_font_size_callback);
  252. ctx.menu_left_callbacks.push_back(toggle_dyslexia_font_callback);
  253. ctx.menu_left_callbacks.push_back(nullptr);
  254. // Build list of menu right callbacks
  255. ctx.menu_right_callbacks.push_back(toggle_fullscreen_callback);
  256. ctx.menu_right_callbacks.push_back(increase_resolution_callback);
  257. ctx.menu_right_callbacks.push_back(toggle_v_sync_callback);
  258. ctx.menu_right_callbacks.push_back(increase_font_size_callback);
  259. ctx.menu_right_callbacks.push_back(toggle_dyslexia_font_callback);
  260. ctx.menu_right_callbacks.push_back(nullptr);
  261. // Set menu back callback
  262. ctx.menu_back_callback = select_back_callback;
  263. // Queue menu control setup
  264. ctx.function_queue.push(std::bind(game::menu::setup_controls, std::ref(ctx)));
  265. // Fade in menu
  266. game::menu::fade_in(ctx, nullptr);
  267. ctx.logger->pop_task(EXIT_SUCCESS);
  268. }
  269. graphics_menu::~graphics_menu()
  270. {
  271. ctx.logger->push_task("Exiting graphics menu state");
  272. // Destruct menu
  273. game::menu::clear_controls(ctx);
  274. game::menu::clear_callbacks(ctx);
  275. game::menu::delete_animations(ctx);
  276. game::menu::remove_text_from_ui(ctx);
  277. game::menu::delete_text(ctx);
  278. ctx.logger->pop_task(EXIT_SUCCESS);
  279. }
  280. void graphics_menu::update_value_text_content()
  281. {
  282. bool fullscreen = ctx.app->is_fullscreen();
  283. float resolution = ctx.render_resolution_scale;
  284. bool v_sync = ctx.app->get_v_sync();
  285. float font_size = ctx.font_size;
  286. bool dyslexia_font = ctx.dyslexia_font;
  287. const std::string string_on = (*ctx.strings)["on"];
  288. const std::string string_off = (*ctx.strings)["off"];
  289. std::get<1>(ctx.menu_item_texts[0])->set_content((fullscreen) ? string_on : string_off);
  290. std::get<1>(ctx.menu_item_texts[1])->set_content(std::to_string(static_cast<int>(std::round(resolution * 100.0f))) + "%");
  291. std::get<1>(ctx.menu_item_texts[2])->set_content((v_sync) ? string_on : string_off);
  292. std::get<1>(ctx.menu_item_texts[3])->set_content(std::to_string(static_cast<int>(std::round(font_size * 100.0f))) + "%");
  293. std::get<1>(ctx.menu_item_texts[4])->set_content((dyslexia_font) ? string_on : string_off);
  294. }
  295. } // namespace state
  296. } // namespace game