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

206 lines
5.6 KiB

  1. /*
  2. * Copyright (C) 2023 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/language-menu-state.hpp"
  20. #include "game/states/options-menu-state.hpp"
  21. #include "game/controls.hpp"
  22. #include <engine/scene/text.hpp>
  23. #include <engine/debug/log.hpp>
  24. #include "game/fonts.hpp"
  25. #include "game/menu.hpp"
  26. #include "game/strings.hpp"
  27. #include <engine/utility/hash/fnv1a.hpp>
  28. #include <engine/resources/resource-manager.hpp>
  29. #include <algorithm>
  30. #include <cctype>
  31. using namespace hash::literals;
  32. language_menu_state::language_menu_state(::game& ctx):
  33. game_state(ctx)
  34. {
  35. debug::log_trace("Entering language menu state...");
  36. // Load language manifest
  37. language_manifest = ctx.resource_manager->load<text_file>("languages.txt");
  38. if (!language_manifest)
  39. {
  40. throw std::runtime_error("Failed to load language manifest");
  41. }
  42. // Determine index of current language
  43. language_index = 0;
  44. for (std::size_t i = 0; i < language_manifest->lines.size(); ++i)
  45. {
  46. if (ctx.language_tag == language_manifest->lines[i])
  47. {
  48. language_index = i;
  49. break;
  50. }
  51. }
  52. // Construct menu item texts
  53. language_name_text = std::make_unique<scene::text>();
  54. language_value_text = std::make_unique<scene::text>();
  55. back_text = std::make_unique<scene::text>();
  56. // Build list of menu item texts
  57. ctx.menu_item_texts.push_back({language_name_text.get(), language_value_text.get()});
  58. ctx.menu_item_texts.push_back({back_text.get(), nullptr});
  59. // Set content of menu item texts
  60. update_text_content();
  61. // Init menu item index
  62. ::menu::init_menu_item_index(ctx, "language");
  63. ::menu::update_text_color(ctx);
  64. ::menu::update_text_font(ctx);
  65. ::menu::align_text(ctx);
  66. ::menu::add_text_to_ui(ctx);
  67. ::menu::setup_animations(ctx);
  68. auto change_language = [this, &ctx]()
  69. {
  70. const std::string& language_tag = this->language_manifest->lines[this->language_index];
  71. // Slugify language tag
  72. std::string language_slug = language_tag;
  73. std::transform
  74. (
  75. language_slug.begin(),
  76. language_slug.end(),
  77. language_slug.begin(),
  78. [](unsigned char c)
  79. {
  80. return std::tolower(c);
  81. }
  82. );
  83. // Load language strings
  84. ctx.string_map = ctx.resource_manager->load<i18n::string_map>(language_slug + ".str");
  85. // Update language settings
  86. ctx.language_tag = language_tag;
  87. (*ctx.settings)["language_tag"] = ctx.language_tag;
  88. // Log language change
  89. debug::log_info("Language tag: {}", ctx.language_tag);
  90. // Reload fonts
  91. debug::log_trace("Reloading fonts...");
  92. ::load_fonts(ctx);
  93. debug::log_trace("Reloaded fonts");
  94. // Update menus
  95. ::menu::update_text_font(ctx);
  96. this->update_text_content();
  97. ::menu::refresh_text(ctx);
  98. ::menu::align_text(ctx);
  99. };
  100. // Construct menu item callbacks
  101. auto next_language_callback = [this, &ctx, change_language]()
  102. {
  103. this->language_index = (this->language_index + 1) % this->language_manifest->lines.size();
  104. change_language();
  105. };
  106. auto previous_language_callback = [this, &ctx, change_language]()
  107. {
  108. if (this->language_index > 0)
  109. {
  110. --this->language_index;
  111. }
  112. else
  113. {
  114. this->language_index = this->language_manifest->lines.size() - 1;
  115. }
  116. change_language();
  117. };
  118. auto select_back_callback = [&ctx]()
  119. {
  120. // Disable menu controls
  121. ctx.function_queue.push(std::bind(::disable_menu_controls, std::ref(ctx)));
  122. ::menu::fade_out
  123. (
  124. ctx,
  125. [&ctx]()
  126. {
  127. // Queue change to options menu state
  128. ctx.function_queue.push
  129. (
  130. [&ctx]()
  131. {
  132. ctx.state_machine.pop();
  133. ctx.state_machine.emplace(std::make_unique<options_menu_state>(ctx));
  134. }
  135. );
  136. }
  137. );
  138. };
  139. // Build list of menu select callbacks
  140. ctx.menu_select_callbacks.push_back(next_language_callback);
  141. ctx.menu_select_callbacks.push_back(select_back_callback);
  142. // Build list of menu left callbacks
  143. ctx.menu_left_callbacks.push_back(previous_language_callback);
  144. ctx.menu_left_callbacks.push_back(nullptr);
  145. // Build list of menu right callbacks
  146. ctx.menu_right_callbacks.push_back(next_language_callback);
  147. ctx.menu_right_callbacks.push_back(nullptr);
  148. // Set menu back callback
  149. ctx.menu_back_callback = select_back_callback;
  150. // Enable menu controls next frame
  151. ctx.function_queue.push(std::bind(::enable_menu_controls, std::ref(ctx)));
  152. // Fade in menu
  153. ::menu::fade_in(ctx, nullptr);
  154. debug::log_trace("Entered language menu state");
  155. }
  156. language_menu_state::~language_menu_state()
  157. {
  158. debug::log_trace("Exiting language menu state...");
  159. // Destruct menu
  160. ::disable_menu_controls(ctx);
  161. ::menu::clear_callbacks(ctx);
  162. ::menu::delete_animations(ctx);
  163. ::menu::remove_text_from_ui(ctx);
  164. ::menu::delete_text(ctx);
  165. debug::log_trace("Exited language menu state");
  166. }
  167. void language_menu_state::update_text_content()
  168. {
  169. auto [language_name, language_value] = ctx.menu_item_texts[0];
  170. auto [back_name, back_value] = ctx.menu_item_texts[1];
  171. language_name->set_content(get_string(ctx, "language_menu_language"));
  172. language_value->set_content(get_string(ctx, "language_name_native"));
  173. back_name->set_content(get_string(ctx, "back"));
  174. }