💿🐜 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.

436 lines
16 KiB

1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
1 year ago
  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/states/sound-menu.hpp"
  20. #include "game/states/options-menu.hpp"
  21. #include "application.hpp"
  22. #include "scene/text.hpp"
  23. #include "render/passes/clear-pass.hpp"
  24. #include "debug/logger.hpp"
  25. namespace game {
  26. namespace state {
  27. namespace sound_menu {
  28. static void update_text_color(game::context* ctx)
  29. {
  30. float4 inactive_color = {1.0f, 1.0f, 1.0f, 0.5f};
  31. float4 active_color = {1.0f, 1.0f, 1.0f, 1.0f};
  32. for (std::size_t i = 0; i < ctx->sound_menu_label_texts.size(); ++i)
  33. {
  34. scene::text* label_text = ctx->sound_menu_label_texts[i];
  35. scene::text* value_text = ctx->sound_menu_value_texts[i];
  36. if (i == ctx->sound_menu_index)
  37. {
  38. label_text->set_color(active_color);
  39. if (value_text)
  40. value_text->set_color(active_color);
  41. }
  42. else
  43. {
  44. label_text->set_color(inactive_color);
  45. if (value_text)
  46. value_text->set_color(inactive_color);
  47. }
  48. }
  49. }
  50. static void align_texts(game::context* ctx)
  51. {
  52. // Calculate menu width
  53. float menu_width = 0.0f;
  54. float menu_spacing = ctx->menu_font.get_glyph_metrics(U'M').width;
  55. for (std::size_t i = 0; i < ctx->sound_menu_label_texts.size(); ++i)
  56. {
  57. scene::text* label_text = ctx->sound_menu_label_texts[i];
  58. scene::text* value_text = ctx->sound_menu_value_texts[i];
  59. float row_width = 0.0f;
  60. // Add label width to width
  61. const auto& label_bounds = static_cast<const geom::aabb<float>&>(label_text->get_local_bounds());
  62. row_width += label_bounds.max_point.x - label_bounds.min_point.x;
  63. if (value_text != nullptr)
  64. {
  65. // Add value width to width
  66. //const auto& value_bounds = static_cast<const geom::aabb<float>&>(value_text->get_local_bounds());
  67. //row_width += value_bounds.max_point.x - value_bounds.min_point.x;
  68. // Add spacing to row width
  69. row_width += menu_spacing * 4.0f;
  70. }
  71. menu_width = std::max<float>(menu_width, row_width);
  72. }
  73. // Align texts
  74. float menu_height = ctx->sound_menu_label_texts.size() * ctx->menu_font.get_font_metrics().linespace;
  75. float menu_x = -menu_width * 0.5f;
  76. float menu_y = menu_height * 0.5f - ctx->menu_font.get_font_metrics().linespace;
  77. for (std::size_t i = 0; i < ctx->sound_menu_label_texts.size(); ++i)
  78. {
  79. scene::text* label_text = ctx->sound_menu_label_texts[i];
  80. float x = menu_x;
  81. float y = menu_y - ctx->menu_font.get_font_metrics().linespace * i;
  82. label_text->set_translation({std::round(x), std::round(y), 0.0f});
  83. scene::text* value_text = ctx->sound_menu_value_texts[i];
  84. if (value_text)
  85. {
  86. const auto& value_bounds = static_cast<const geom::aabb<float>&>(value_text->get_local_bounds());
  87. const float value_width = value_bounds.max_point.x - value_bounds.min_point.x;
  88. x = menu_x + menu_width - value_width;
  89. value_text->set_translation({std::round(x), std::round(y), 0.0f});
  90. }
  91. }
  92. }
  93. static void update_text_tweens(game::context* ctx)
  94. {
  95. for (std::size_t i = 0; i < ctx->sound_menu_label_texts.size(); ++i)
  96. {
  97. scene::text* label_text = ctx->sound_menu_label_texts[i];
  98. scene::text* value_text = ctx->sound_menu_value_texts[i];
  99. label_text->update_tweens();
  100. if (value_text)
  101. value_text->update_tweens();
  102. }
  103. }
  104. void enter(game::context* ctx)
  105. {
  106. ctx->ui_clear_pass->set_cleared_buffers(true, true, false);
  107. // Construct sound menu texts
  108. ctx->sound_menu_master_volume_label_text = new scene::text();
  109. ctx->sound_menu_master_volume_value_text = new scene::text();
  110. ctx->sound_menu_ambience_volume_label_text = new scene::text();
  111. ctx->sound_menu_ambience_volume_value_text = new scene::text();
  112. ctx->sound_menu_effects_volume_label_text = new scene::text();
  113. ctx->sound_menu_effects_volume_value_text = new scene::text();
  114. ctx->sound_menu_mono_audio_label_text = new scene::text();
  115. ctx->sound_menu_mono_audio_value_text = new scene::text();
  116. ctx->sound_menu_captions_label_text = new scene::text();
  117. ctx->sound_menu_captions_value_text = new scene::text();
  118. ctx->sound_menu_captions_size_label_text = new scene::text();
  119. ctx->sound_menu_captions_size_value_text = new scene::text();
  120. ctx->sound_menu_back_label_text = new scene::text();
  121. // Set text content
  122. const std::string string_on = (*ctx->strings)["on"];
  123. const std::string string_off = (*ctx->strings)["off"];
  124. ctx->sound_menu_master_volume_label_text->set_content((*ctx->strings)["sound_menu_master_volume"]);
  125. ctx->sound_menu_master_volume_value_text->set_content(std::to_string(static_cast<int>(ctx->master_volume * 100.0f + 0.5f)) + "%");
  126. ctx->sound_menu_ambience_volume_label_text->set_content((*ctx->strings)["sound_menu_ambience_volume"]);
  127. ctx->sound_menu_ambience_volume_value_text->set_content(std::to_string(static_cast<int>(ctx->ambience_volume * 100.0f + 0.5f)) + "%");
  128. ctx->sound_menu_effects_volume_label_text->set_content((*ctx->strings)["sound_menu_effects_volume"]);
  129. ctx->sound_menu_effects_volume_value_text->set_content(std::to_string(static_cast<int>(ctx->effects_volume * 100.0f + 0.5f)) + "%");
  130. ctx->sound_menu_mono_audio_label_text->set_content((*ctx->strings)["sound_menu_mono_audio"]);
  131. ctx->sound_menu_mono_audio_value_text->set_content((ctx->mono_audio) ? string_on : string_off);
  132. ctx->sound_menu_captions_label_text->set_content((*ctx->strings)["sound_menu_captions"]);
  133. ctx->sound_menu_captions_value_text->set_content((ctx->captions) ? string_on : string_off);
  134. ctx->sound_menu_captions_size_label_text->set_content((*ctx->strings)["sound_menu_captions_size"]);
  135. ctx->sound_menu_captions_size_value_text->set_content(std::to_string(static_cast<int>(ctx->captions_size * 100.0f + 0.5f)) + "%");
  136. ctx->sound_menu_back_label_text->set_content((*ctx->strings)["back"]);
  137. // Build lists of sound menu texts
  138. ctx->sound_menu_label_texts.push_back(ctx->sound_menu_master_volume_label_text);
  139. ctx->sound_menu_label_texts.push_back(ctx->sound_menu_ambience_volume_label_text);
  140. ctx->sound_menu_label_texts.push_back(ctx->sound_menu_effects_volume_label_text);
  141. ctx->sound_menu_label_texts.push_back(ctx->sound_menu_mono_audio_label_text);
  142. ctx->sound_menu_label_texts.push_back(ctx->sound_menu_captions_label_text);
  143. ctx->sound_menu_label_texts.push_back(ctx->sound_menu_captions_size_label_text);
  144. ctx->sound_menu_label_texts.push_back(ctx->sound_menu_back_label_text);
  145. ctx->sound_menu_value_texts.push_back(ctx->sound_menu_master_volume_value_text);
  146. ctx->sound_menu_value_texts.push_back(ctx->sound_menu_ambience_volume_value_text);
  147. ctx->sound_menu_value_texts.push_back(ctx->sound_menu_effects_volume_value_text);
  148. ctx->sound_menu_value_texts.push_back(ctx->sound_menu_mono_audio_value_text);
  149. ctx->sound_menu_value_texts.push_back(ctx->sound_menu_captions_value_text);
  150. ctx->sound_menu_value_texts.push_back(ctx->sound_menu_captions_size_value_text);
  151. ctx->sound_menu_value_texts.push_back(nullptr);
  152. // Set text fonts
  153. for (std::size_t i = 0; i < ctx->sound_menu_label_texts.size(); ++i)
  154. {
  155. scene::text* label_text = ctx->sound_menu_label_texts[i];
  156. label_text->set_material(&ctx->menu_font_material);
  157. label_text->set_font(&ctx->menu_font);
  158. scene::text* value_text = ctx->sound_menu_value_texts[i];
  159. if (value_text)
  160. {
  161. value_text->set_material(&ctx->menu_font_material);
  162. value_text->set_font(&ctx->menu_font);
  163. }
  164. }
  165. align_texts(ctx);
  166. // Construct sound menu callbacks
  167. auto menu_back_callback = [ctx]()
  168. {
  169. application::state next_state;
  170. next_state.name = "options_menu";
  171. next_state.enter = std::bind(game::state::options_menu::enter, ctx);
  172. next_state.exit = std::bind(game::state::options_menu::exit, ctx);
  173. ctx->app->change_state(next_state);
  174. };
  175. auto increase_volume_callback = [ctx](float* volume, scene::text* value_text)
  176. {
  177. // Increase volume
  178. if (ctx->controls["menu_modifier"]->is_active())
  179. *volume += 0.01f;
  180. else
  181. *volume += 0.1f;
  182. // Limit volume
  183. if (*volume > 1.0f)
  184. *volume = 1.0f;
  185. // Update volume value text
  186. value_text->set_content(std::to_string(static_cast<int>(std::round(*volume * 100.0f))) + "%");
  187. // Realign text
  188. align_texts(ctx);
  189. value_text->update_tweens();
  190. };
  191. auto decrease_volume_callback = [ctx](float* volume, scene::text* value_text)
  192. {
  193. // Decrease volume
  194. if (ctx->controls["menu_modifier"]->is_active())
  195. *volume -= 0.01f;
  196. else
  197. *volume -= 0.1f;
  198. // Limit volume
  199. if (*volume < 0.0f)
  200. *volume = 0.0f;
  201. // Update volume value text
  202. value_text->set_content(std::to_string(static_cast<int>(std::round(*volume * 100.0f))) + "%");
  203. // Realign text
  204. align_texts(ctx);
  205. value_text->update_tweens();
  206. };
  207. auto toggle_mono_audio_callback = [ctx]()
  208. {
  209. ctx->mono_audio = !ctx->mono_audio;
  210. const std::string string_on = (*ctx->strings)["on"];
  211. const std::string string_off = (*ctx->strings)["off"];
  212. ctx->sound_menu_mono_audio_value_text->set_content((ctx->mono_audio) ? string_on : string_off);
  213. align_texts(ctx);
  214. ctx->sound_menu_mono_audio_value_text->update_tweens();
  215. };
  216. auto toggle_captions_callback = [ctx]()
  217. {
  218. ctx->captions = !ctx->captions;
  219. const std::string string_on = (*ctx->strings)["on"];
  220. const std::string string_off = (*ctx->strings)["off"];
  221. ctx->sound_menu_captions_value_text->set_content((ctx->captions) ? string_on : string_off);
  222. align_texts(ctx);
  223. ctx->sound_menu_captions_value_text->update_tweens();
  224. };
  225. auto increase_captions_size_callback = [ctx]()
  226. {
  227. // Increase size
  228. if (ctx->controls["menu_modifier"]->is_active())
  229. ctx->captions_size += 0.01f;
  230. else
  231. ctx->captions_size += 0.1f;
  232. // Limit size
  233. if (ctx->captions_size > 2.0f)
  234. ctx->captions_size = 2.0f;
  235. // Update volume value text
  236. ctx->sound_menu_captions_size_value_text->set_content(std::to_string(static_cast<int>(std::round(ctx->captions_size * 100.0f))) + "%");
  237. // Realign text
  238. align_texts(ctx);
  239. ctx->sound_menu_captions_size_value_text->update_tweens();
  240. };
  241. auto decrease_captions_size_callback = [ctx]()
  242. {
  243. // Decrease size
  244. if (ctx->controls["menu_modifier"]->is_active())
  245. ctx->captions_size -= 0.01f;
  246. else
  247. ctx->captions_size -= 0.1f;
  248. // Limit size
  249. if (ctx->captions_size < 0.1f)
  250. ctx->captions_size = 0.1f;
  251. // Update volume value text
  252. ctx->sound_menu_captions_size_value_text->set_content(std::to_string(static_cast<int>(std::round(ctx->captions_size * 100.0f))) + "%");
  253. // Realign text
  254. align_texts(ctx);
  255. ctx->sound_menu_captions_size_value_text->update_tweens();
  256. };
  257. ctx->controls["menu_down"]->set_activated_callback
  258. (
  259. [ctx]()
  260. {
  261. ++ctx->sound_menu_index;
  262. if (ctx->sound_menu_index >= ctx->sound_menu_label_texts.size())
  263. ctx->sound_menu_index = 0;
  264. update_text_color(ctx);
  265. }
  266. );
  267. ctx->controls["menu_up"]->set_activated_callback
  268. (
  269. [ctx]()
  270. {
  271. --ctx->sound_menu_index;
  272. if (ctx->sound_menu_index < 0)
  273. ctx->sound_menu_index = ctx->sound_menu_label_texts.size() - 1;
  274. update_text_color(ctx);
  275. }
  276. );
  277. ctx->controls["menu_left"]->set_activated_callback
  278. (
  279. [ctx]()
  280. {
  281. if (ctx->sound_menu_left_callbacks[ctx->sound_menu_index])
  282. ctx->sound_menu_left_callbacks[ctx->sound_menu_index]();
  283. }
  284. );
  285. ctx->controls["menu_right"]->set_activated_callback
  286. (
  287. [ctx]()
  288. {
  289. if (ctx->sound_menu_right_callbacks[ctx->sound_menu_index])
  290. ctx->sound_menu_right_callbacks[ctx->sound_menu_index]();
  291. }
  292. );
  293. ctx->controls["menu_select"]->set_activated_callback
  294. (
  295. [ctx]()
  296. {
  297. if (ctx->sound_menu_select_callbacks[ctx->sound_menu_index])
  298. ctx->sound_menu_select_callbacks[ctx->sound_menu_index]();
  299. }
  300. );
  301. ctx->controls["menu_back"]->set_activated_callback(menu_back_callback);
  302. // Build list of sound menu callbacks
  303. ctx->sound_menu_select_callbacks.push_back(std::bind(increase_volume_callback, &ctx->master_volume, ctx->sound_menu_master_volume_value_text));
  304. ctx->sound_menu_select_callbacks.push_back(std::bind(increase_volume_callback, &ctx->ambience_volume, ctx->sound_menu_ambience_volume_value_text));
  305. ctx->sound_menu_select_callbacks.push_back(std::bind(increase_volume_callback, &ctx->effects_volume, ctx->sound_menu_effects_volume_value_text));
  306. ctx->sound_menu_select_callbacks.push_back(toggle_mono_audio_callback);
  307. ctx->sound_menu_select_callbacks.push_back(toggle_captions_callback);
  308. ctx->sound_menu_select_callbacks.push_back(increase_captions_size_callback);
  309. ctx->sound_menu_select_callbacks.push_back(menu_back_callback);
  310. ctx->sound_menu_right_callbacks.push_back(std::bind(increase_volume_callback, &ctx->master_volume, ctx->sound_menu_master_volume_value_text));
  311. ctx->sound_menu_right_callbacks.push_back(std::bind(increase_volume_callback, &ctx->ambience_volume, ctx->sound_menu_ambience_volume_value_text));
  312. ctx->sound_menu_right_callbacks.push_back(std::bind(increase_volume_callback, &ctx->effects_volume, ctx->sound_menu_effects_volume_value_text));
  313. ctx->sound_menu_right_callbacks.push_back(toggle_mono_audio_callback);
  314. ctx->sound_menu_right_callbacks.push_back(toggle_captions_callback);
  315. ctx->sound_menu_right_callbacks.push_back(increase_captions_size_callback);
  316. ctx->sound_menu_right_callbacks.push_back(nullptr);
  317. ctx->sound_menu_left_callbacks.push_back(std::bind(decrease_volume_callback, &ctx->master_volume, ctx->sound_menu_master_volume_value_text));
  318. ctx->sound_menu_left_callbacks.push_back(std::bind(decrease_volume_callback, &ctx->ambience_volume, ctx->sound_menu_ambience_volume_value_text));
  319. ctx->sound_menu_left_callbacks.push_back(std::bind(decrease_volume_callback, &ctx->effects_volume, ctx->sound_menu_effects_volume_value_text));
  320. ctx->sound_menu_left_callbacks.push_back(toggle_mono_audio_callback);
  321. ctx->sound_menu_left_callbacks.push_back(toggle_captions_callback);
  322. ctx->sound_menu_left_callbacks.push_back(decrease_captions_size_callback);
  323. ctx->sound_menu_left_callbacks.push_back(nullptr);
  324. // Add text objects to UI
  325. for (std::size_t i = 0; i < ctx->sound_menu_label_texts.size(); ++i)
  326. {
  327. scene::text* label_text = ctx->sound_menu_label_texts[i];
  328. scene::text* value_text = ctx->sound_menu_value_texts[i];
  329. ctx->ui_scene->add_object(label_text);
  330. if (value_text)
  331. ctx->ui_scene->add_object(value_text);
  332. }
  333. update_text_color(ctx);
  334. update_text_tweens(ctx);
  335. }
  336. void exit(game::context* ctx)
  337. {
  338. // Clear control callbacks
  339. ctx->controls["menu_down"]->set_activated_callback(nullptr);
  340. ctx->controls["menu_up"]->set_activated_callback(nullptr);
  341. ctx->controls["menu_left"]->set_activated_callback(nullptr);
  342. ctx->controls["menu_right"]->set_activated_callback(nullptr);
  343. ctx->controls["menu_select"]->set_activated_callback(nullptr);
  344. ctx->controls["menu_back"]->set_activated_callback(nullptr);
  345. // Clear menu callbacks
  346. ctx->sound_menu_select_callbacks.clear();
  347. ctx->sound_menu_left_callbacks.clear();
  348. ctx->sound_menu_right_callbacks.clear();
  349. // Destruct sound menu texts
  350. for (std::size_t i = 0; i < ctx->sound_menu_label_texts.size(); ++i)
  351. {
  352. scene::text* label_text = ctx->sound_menu_label_texts[i];
  353. ctx->ui_scene->remove_object(label_text);
  354. delete label_text;
  355. scene::text* value_text = ctx->sound_menu_value_texts[i];
  356. if (value_text)
  357. {
  358. ctx->ui_scene->remove_object(value_text);
  359. delete value_text;
  360. }
  361. }
  362. ctx->sound_menu_label_texts.clear();
  363. ctx->sound_menu_value_texts.clear();
  364. // Update volumes in config
  365. (*ctx->config)["master_volume"] = ctx->master_volume;
  366. (*ctx->config)["ambience_volume"] = ctx->ambience_volume;
  367. (*ctx->config)["effects_volume"] = ctx->effects_volume;
  368. (*ctx->config)["mono_audio"] = ctx->mono_audio;
  369. (*ctx->config)["captions"] = ctx->captions;
  370. (*ctx->config)["captions_size"] = ctx->captions_size;
  371. ctx->ui_clear_pass->set_cleared_buffers(false, true, false);
  372. }
  373. } // namespace sound_menu
  374. } // namespace state
  375. } // namespace game