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

376 lines
11 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/state/gamepad-config-menu.hpp"
  20. #include "game/state/controls-menu.hpp"
  21. #include "game/context.hpp"
  22. #include "scene/text.hpp"
  23. #include "debug/log.hpp"
  24. #include "resources/resource-manager.hpp"
  25. #include "game/menu.hpp"
  26. #include "game/controls.hpp"
  27. #include "game/strings.hpp"
  28. #include "utility/hash/fnv1a.hpp"
  29. using namespace hash::literals;
  30. namespace game {
  31. namespace state {
  32. gamepad_config_menu::gamepad_config_menu(game::context& ctx):
  33. game::state::base(ctx)
  34. {
  35. debug::log::trace("Entering gamepad config menu state...");
  36. // Add camera control menu items
  37. add_control_item("move_forward");
  38. add_control_item("move_back");
  39. add_control_item("move_left");
  40. add_control_item("move_right");
  41. add_control_item("move_up");
  42. add_control_item("move_down");
  43. // Add application control menu items
  44. add_control_item("toggle_fullscreen");
  45. add_control_item("screenshot");
  46. // Construct menu item texts
  47. scene::text* back_text = new scene::text();
  48. // Build list of menu item texts
  49. ctx.menu_item_texts.push_back({back_text, nullptr});
  50. // Set content of menu item texts
  51. back_text->set_content(get_string(ctx, "back"_fnv1a32));
  52. // Init menu item index
  53. game::menu::init_menu_item_index(ctx, "gamepad_config");
  54. game::menu::update_text_color(ctx);
  55. game::menu::update_text_font(ctx);
  56. game::menu::align_text(ctx);
  57. game::menu::update_text_tweens(ctx);
  58. game::menu::add_text_to_ui(ctx);
  59. game::menu::setup_animations(ctx);
  60. // Construct menu item callbacks
  61. auto select_back_callback = [&ctx]()
  62. {
  63. // Disable controls
  64. game::menu::clear_controls(ctx);
  65. game::menu::fade_out
  66. (
  67. ctx,
  68. [&ctx]()
  69. {
  70. // Queue change to controls menu state
  71. ctx.function_queue.push
  72. (
  73. [&ctx]()
  74. {
  75. ctx.state_machine.pop();
  76. ctx.state_machine.emplace(new game::state::controls_menu(ctx));
  77. }
  78. );
  79. }
  80. );
  81. };
  82. // Build list of menu select callbacks
  83. ctx.menu_select_callbacks.push_back(select_back_callback);
  84. // Build list of menu left callbacks
  85. ctx.menu_left_callbacks.push_back(nullptr);
  86. // Build list of menu right callbacks
  87. ctx.menu_right_callbacks.push_back(nullptr);
  88. // Set menu back callback
  89. ctx.menu_back_callback = select_back_callback;
  90. // Queue menu control setup
  91. ctx.function_queue.push(std::bind(game::menu::setup_controls, std::ref(ctx)));
  92. // Fade in menu
  93. game::menu::fade_in(ctx, nullptr);
  94. debug::log::trace("Entered gamepad config menu state");
  95. }
  96. gamepad_config_menu::~gamepad_config_menu()
  97. {
  98. debug::log::trace("Exiting gamepad config menu state...");
  99. // Destruct menu
  100. game::menu::clear_controls(ctx);
  101. game::menu::clear_callbacks(ctx);
  102. game::menu::delete_animations(ctx);
  103. game::menu::remove_text_from_ui(ctx);
  104. game::menu::delete_text(ctx);
  105. // Save control profile
  106. game::save_control_profile(ctx);
  107. debug::log::trace("Exited gamepad config menu state");
  108. }
  109. std::string gamepad_config_menu::get_binding_string(input::control* control)
  110. {
  111. std::string binding_string;
  112. /*
  113. auto mappings = ctx.input_event_router->get_mappings(control);
  114. for (input::mapping* mapping: *mappings)
  115. {
  116. std::string mapping_string;
  117. switch (mapping->get_type())
  118. {
  119. case input::mapping_type::gamepad_axis:
  120. {
  121. const input::gamepad_axis_mapping* axis_mapping = static_cast<const input::gamepad_axis_mapping*>(mapping);
  122. switch (axis_mapping->axis)
  123. {
  124. case input::gamepad_axis::left_x:
  125. if (axis_mapping->negative)
  126. mapping_string = (*ctx.strings)["gamepad_left_stick_left"];
  127. else
  128. mapping_string = (*ctx.strings)["gamepad_left_stick_right"];
  129. break;
  130. case input::gamepad_axis::left_y:
  131. if (axis_mapping->negative)
  132. mapping_string = (*ctx.strings)["gamepad_left_stick_up"];
  133. else
  134. mapping_string = (*ctx.strings)["gamepad_left_stick_down"];
  135. break;
  136. case input::gamepad_axis::right_x:
  137. if (axis_mapping->negative)
  138. mapping_string = (*ctx.strings)["gamepad_right_stick_left"];
  139. else
  140. mapping_string = (*ctx.strings)["gamepad_right_stick_right"];
  141. break;
  142. case input::gamepad_axis::right_y:
  143. if (axis_mapping->negative)
  144. mapping_string = (*ctx.strings)["gamepad_right_stick_up"];
  145. else
  146. mapping_string = (*ctx.strings)["gamepad_right_stick_down"];
  147. break;
  148. case input::gamepad_axis::left_trigger:
  149. mapping_string = (*ctx.strings)["gamepad_left_trigger"];
  150. break;
  151. case input::gamepad_axis::right_trigger:
  152. mapping_string = (*ctx.strings)["gamepad_right_trigger"];
  153. break;
  154. default:
  155. break;
  156. }
  157. break;
  158. }
  159. case input::mapping_type::gamepad_button:
  160. {
  161. const input::gamepad_button_mapping* button_mapping = static_cast<const input::gamepad_button_mapping*>(mapping);
  162. switch (button_mapping->button)
  163. {
  164. case input::gamepad_button::a:
  165. mapping_string = (*ctx.strings)["gamepad_button_a"];
  166. break;
  167. case input::gamepad_button::b:
  168. mapping_string = (*ctx.strings)["gamepad_button_b"];
  169. break;
  170. case input::gamepad_button::x:
  171. mapping_string = (*ctx.strings)["gamepad_button_x"];
  172. break;
  173. case input::gamepad_button::y:
  174. mapping_string = (*ctx.strings)["gamepad_button_y"];
  175. break;
  176. case input::gamepad_button::back:
  177. mapping_string = (*ctx.strings)["gamepad_button_back"];
  178. break;
  179. case input::gamepad_button::guide:
  180. mapping_string = (*ctx.strings)["gamepad_button_guide"];
  181. break;
  182. case input::gamepad_button::start:
  183. mapping_string = (*ctx.strings)["gamepad_button_start"];
  184. break;
  185. case input::gamepad_button::left_stick:
  186. mapping_string = (*ctx.strings)["gamepad_button_left_stick"];
  187. break;
  188. case input::gamepad_button::right_stick:
  189. mapping_string = (*ctx.strings)["gamepad_button_right_stick"];
  190. break;
  191. case input::gamepad_button::left_shoulder:
  192. mapping_string = (*ctx.strings)["gamepad_button_left_shoulder"];
  193. break;
  194. case input::gamepad_button::right_shoulder:
  195. mapping_string = (*ctx.strings)["gamepad_button_right_shoulder"];
  196. break;
  197. case input::gamepad_button::dpad_up:
  198. mapping_string = (*ctx.strings)["gamepad_button_dpad_up"];
  199. break;
  200. case input::gamepad_button::dpad_down:
  201. mapping_string = (*ctx.strings)["gamepad_button_dpad_down"];
  202. break;
  203. case input::gamepad_button::dpad_left:
  204. mapping_string = (*ctx.strings)["gamepad_button_dpad_left"];
  205. break;
  206. case input::gamepad_button::dpad_right:
  207. mapping_string = (*ctx.strings)["gamepad_button_dpad_right"];
  208. break;
  209. default:
  210. break;
  211. }
  212. break;
  213. }
  214. default:
  215. break;
  216. }
  217. if (!mapping_string.empty())
  218. {
  219. if (binding_string.empty())
  220. {
  221. binding_string = mapping_string;
  222. }
  223. else
  224. {
  225. binding_string += " " + mapping_string;
  226. }
  227. }
  228. }
  229. */
  230. return binding_string;
  231. }
  232. void gamepad_config_menu::add_control_item(const std::string& control_name)
  233. {
  234. // Get pointer to control
  235. //input::control* control = ctx.controls[control_name];
  236. // Construct texts
  237. scene::text* name_text = new scene::text();
  238. scene::text* value_text = new scene::text();
  239. // Add texts to list of menu item texts
  240. ctx.menu_item_texts.push_back({name_text, value_text});
  241. // Set content of name text
  242. name_text->set_content(control_name);
  243. // Set content of value text
  244. //value_text->set_content(get_binding_string(control));
  245. auto select_callback = [this, &ctx = this->ctx, value_text]()
  246. {
  247. // Clear binding string from value text
  248. value_text->set_content(get_string(ctx, "ellipsis"_fnv1a32));
  249. game::menu::align_text(ctx);
  250. game::menu::update_text_tweens(ctx);
  251. // Disable controls
  252. game::menu::clear_controls(ctx);
  253. /*
  254. // Remove gamepad event mappings from control
  255. ctx.input_event_router->remove_mappings(control, input::mapping_type::gamepad_axis);
  256. ctx.input_event_router->remove_mappings(control, input::mapping_type::gamepad_button);
  257. // Setup input binding listener
  258. ctx.input_listener->set_callback
  259. (
  260. [this, &ctx, control, value_text](const event_base& event)
  261. {
  262. auto id = event.get_event_type_id();
  263. if (id == gamepad_axis_moved_event::event_type_id)
  264. {
  265. // Map gamepad axis event to control
  266. const gamepad_axis_moved_event& axis_event = static_cast<const gamepad_axis_moved_event&>(event);
  267. if (std::abs(axis_event.value) < 0.5f)
  268. return;
  269. ctx.input_event_router->add_mapping(input::gamepad_axis_mapping(control, nullptr, axis_event.axis, (axis_event.value < 0)));
  270. }
  271. else if (id == gamepad_button_pressed_event::event_type_id)
  272. {
  273. // Map gamepad button event to control
  274. const gamepad_button_pressed_event& button_event = static_cast<const gamepad_button_pressed_event&>(event);
  275. ctx.input_event_router->add_mapping(input::gamepad_button_mapping(control, nullptr, button_event.button));
  276. }
  277. else if (id == key_pressed_event::event_type_id)
  278. {
  279. // Map key pressed event to control
  280. const key_pressed_event& key_event = static_cast<const key_pressed_event&>(event);
  281. if (key_event.scancode != input::scancode::escape && key_event.scancode != input::scancode::backspace)
  282. return;
  283. }
  284. else
  285. {
  286. return;
  287. }
  288. // Update menu text
  289. value_text->set_content(this->get_binding_string(control));
  290. game::menu::align_text(ctx);
  291. game::menu::update_text_tweens(ctx);
  292. // Disable input listener
  293. ctx.input_listener->set_enabled(false);
  294. ctx.input_listener->set_callback(nullptr);
  295. // Queue menu control setup
  296. ctx.function_queue.push(std::bind(game::menu::setup_controls, std::ref(ctx)));
  297. }
  298. );
  299. ctx.input_listener->set_enabled(true);
  300. */
  301. };
  302. // Register menu item callbacks
  303. ctx.menu_select_callbacks.push_back(select_callback);
  304. ctx.menu_left_callbacks.push_back(nullptr);
  305. ctx.menu_right_callbacks.push_back(nullptr);
  306. }
  307. } // namespace state
  308. } // namespace game