settings_scene.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. #include "../minesweeper.h"
  2. #include "../views/minesweeper_game_screen.h"
  3. typedef enum {
  4. MineSweeperSettingsScreenDifficultyTypeEasy,
  5. MineSweeperSettingsScreenDifficultyTypeMedium,
  6. MineSweeperSettingsScreenDifficultyTypeHard,
  7. MineSweeperSettingsScreenDifficultyTypeNum,
  8. } MineSweeperSettingsScreenDifficultyType;
  9. typedef enum {
  10. MineSweeperSettingsScreenIndexDifficulty,
  11. MineSweeperSettingsScreenIndexWidth,
  12. MineSweeperSettingsScreenIndexHeight,
  13. MineSweeperSettingsScreenIndexNum,
  14. } MineSweeperSettingsScreenIndex;
  15. typedef enum {
  16. MineSweeperSettingsScreenEventDifficultyChange,
  17. MineSweeperSettingsScreenEventWidthChange,
  18. MineSweeperSettingsScreenEventHeightChange,
  19. MineSweeperSettingsScreenEventSolvableChange,
  20. MineSweeperSettingsScreenEventInfoChange,
  21. MineSweeperSettingsScreenEventFeedbackChange,
  22. } MineSweeperSettingsScreenEvent;
  23. static const char* settings_screen_difficulty_text[MineSweeperSettingsScreenDifficultyTypeNum] = {
  24. "Easy",
  25. "Medium",
  26. "Hard",
  27. };
  28. static const char* settings_screen_verifier_text[2] = {
  29. "False",
  30. "True",
  31. };
  32. static void minesweeper_scene_settings_screen_set_difficulty(VariableItem* item) {
  33. furi_assert(item);
  34. MineSweeperApp* app = variable_item_get_context(item);
  35. app->t_settings_info.difficulty_item = item;
  36. uint8_t index = variable_item_get_current_value_index(app->t_settings_info.difficulty_item);
  37. app->t_settings_info.difficulty = index;
  38. variable_item_set_current_value_text(
  39. app->t_settings_info.difficulty_item, settings_screen_difficulty_text[index]);
  40. view_dispatcher_send_custom_event(
  41. app->view_dispatcher, MineSweeperSettingsScreenEventDifficultyChange);
  42. }
  43. static void minesweeper_scene_settings_screen_set_width(VariableItem* item) {
  44. char source[5];
  45. uint8_t index = 0;
  46. uint8_t curr_board_height = 7;
  47. bool is_over_max_tiles = false;
  48. furi_assert(item);
  49. MineSweeperApp* app = variable_item_get_context(item);
  50. app->t_settings_info.width_item = item;
  51. index = variable_item_get_current_value_index(app->t_settings_info.width_item);
  52. app->t_settings_info.board_width = index + 16;
  53. curr_board_height = app->t_settings_info.board_height;
  54. is_over_max_tiles = (app->t_settings_info.board_width * curr_board_height) >
  55. MINESWEEPER_BOARD_MAX_TILES;
  56. if(is_over_max_tiles) {
  57. do {
  58. is_over_max_tiles = (app->t_settings_info.board_width * --curr_board_height) >
  59. MINESWEEPER_BOARD_MAX_TILES;
  60. } while(is_over_max_tiles);
  61. app->t_settings_info.board_height = curr_board_height;
  62. snprintf(source, 5, "%" PRIu8, curr_board_height);
  63. source[4] = '\0';
  64. furi_string_set_strn(app->t_settings_info.height_str, source, 5);
  65. variable_item_set_current_value_index(
  66. app->t_settings_info.height_item, app->t_settings_info.board_height - 7);
  67. variable_item_set_current_value_text(
  68. app->t_settings_info.height_item,
  69. furi_string_get_cstr(app->t_settings_info.height_str));
  70. }
  71. snprintf(source, 5, "%" PRIu8, index + 16);
  72. source[4] = '\0';
  73. furi_string_set_strn(app->t_settings_info.width_str, source, 5);
  74. variable_item_set_current_value_text(
  75. app->t_settings_info.width_item, furi_string_get_cstr(app->t_settings_info.width_str));
  76. view_dispatcher_send_custom_event(
  77. app->view_dispatcher, MineSweeperSettingsScreenEventHeightChange);
  78. }
  79. static void minesweeper_scene_settings_screen_set_height(VariableItem* item) {
  80. char source[5];
  81. uint8_t index = 0;
  82. uint8_t curr_board_width = 16;
  83. bool is_over_max_tiles = false;
  84. furi_assert(item);
  85. MineSweeperApp* app = variable_item_get_context(item);
  86. app->t_settings_info.height_item = item;
  87. index = variable_item_get_current_value_index(app->t_settings_info.height_item);
  88. app->t_settings_info.board_height = index + 7;
  89. curr_board_width = app->t_settings_info.board_width;
  90. is_over_max_tiles = (app->t_settings_info.board_height * curr_board_width) >
  91. MINESWEEPER_BOARD_MAX_TILES;
  92. if(is_over_max_tiles) {
  93. do {
  94. is_over_max_tiles = (app->t_settings_info.board_height * --curr_board_width) >
  95. MINESWEEPER_BOARD_MAX_TILES;
  96. } while(is_over_max_tiles);
  97. app->t_settings_info.board_width = curr_board_width;
  98. snprintf(source, 5, "%" PRIu8, curr_board_width);
  99. source[4] = '\0';
  100. furi_string_set_strn(app->t_settings_info.width_str, source, 5);
  101. variable_item_set_current_value_index(
  102. app->t_settings_info.width_item, app->t_settings_info.board_width - 16);
  103. variable_item_set_current_value_text(
  104. app->t_settings_info.width_item, furi_string_get_cstr(app->t_settings_info.width_str));
  105. }
  106. snprintf(source, 5, "%" PRIu8, index + 7);
  107. source[4] = '\0';
  108. furi_string_set_strn(app->t_settings_info.height_str, source, 5);
  109. variable_item_set_current_value_text(
  110. app->t_settings_info.height_item, furi_string_get_cstr(app->t_settings_info.height_str));
  111. view_dispatcher_send_custom_event(
  112. app->view_dispatcher, MineSweeperSettingsScreenEventWidthChange);
  113. }
  114. static void minesweeper_scene_settings_screen_set_solvable(VariableItem* item) {
  115. furi_assert(item);
  116. MineSweeperApp* app = variable_item_get_context(item);
  117. uint8_t index = variable_item_get_current_value_index(app->t_settings_info.solvable_item);
  118. app->t_settings_info.ensure_solvable_board = (index == 1) ? true : false;
  119. variable_item_set_current_value_text(item, settings_screen_verifier_text[index]);
  120. view_dispatcher_send_custom_event(
  121. app->view_dispatcher, MineSweeperSettingsScreenEventSolvableChange);
  122. }
  123. static void minesweeper_scene_settings_screen_set_feedback(VariableItem* item) {
  124. furi_assert(item);
  125. MineSweeperApp* app = variable_item_get_context(item);
  126. uint8_t index = variable_item_get_current_value_index(item);
  127. app->feedback_enabled = index;
  128. FURI_LOG_I(TAG, "FEEDBACK CALLBACK INDEX %d", app->feedback_enabled);
  129. variable_item_set_current_value_text(item, ((index) ? "Enabled" : "Disabled"));
  130. view_dispatcher_send_custom_event(
  131. app->view_dispatcher, MineSweeperSettingsScreenEventFeedbackChange);
  132. }
  133. static void minesweeper_scene_settings_screen_set_info(VariableItem* item) {
  134. furi_assert(item);
  135. MineSweeperApp* app = variable_item_get_context(item);
  136. view_dispatcher_send_custom_event(
  137. app->view_dispatcher, MineSweeperSettingsScreenEventInfoChange);
  138. }
  139. void minesweeper_scene_settings_screen_on_enter(void* context) {
  140. furi_assert(context);
  141. MineSweeperApp* app = (MineSweeperApp*)context;
  142. VariableItemList* va = app->settings_screen;
  143. VariableItem* item;
  144. // If we are accessing the scene and have not changed the settings
  145. if(!app->is_settings_changed) {
  146. // Set temp setting buffer to current state
  147. app->t_settings_info = app->settings_info;
  148. }
  149. // Set Difficulty Item
  150. item = variable_item_list_add(
  151. va,
  152. "Difficulty",
  153. MineSweeperSettingsScreenDifficultyTypeNum,
  154. minesweeper_scene_settings_screen_set_difficulty,
  155. app);
  156. app->t_settings_info.difficulty_item = item;
  157. variable_item_set_current_value_index(item, app->t_settings_info.difficulty);
  158. variable_item_set_current_value_text(
  159. item, settings_screen_difficulty_text[app->t_settings_info.difficulty]);
  160. // Set Width Item
  161. item = variable_item_list_add(
  162. va, "Board Width", 33 - 16, minesweeper_scene_settings_screen_set_width, app);
  163. app->t_settings_info.width_item = item;
  164. variable_item_set_current_value_index(item, app->t_settings_info.board_width - 16);
  165. char source[5];
  166. snprintf(source, 5, "%" PRIu8, app->t_settings_info.board_width);
  167. source[4] = '\0';
  168. furi_string_set_strn(app->t_settings_info.width_str, source, 5);
  169. variable_item_set_current_value_text(
  170. item, furi_string_get_cstr(app->t_settings_info.width_str));
  171. // Set Height Item
  172. item = variable_item_list_add(
  173. va, "Board Height", 33 - 7, minesweeper_scene_settings_screen_set_height, app);
  174. app->t_settings_info.height_item = item;
  175. variable_item_set_current_value_index(item, app->t_settings_info.board_height - 7);
  176. snprintf(source, 5, "%" PRIu8, app->t_settings_info.board_height);
  177. source[4] = '\0';
  178. furi_string_set_strn(app->t_settings_info.height_str, source, 5);
  179. variable_item_set_current_value_text(
  180. item, furi_string_get_cstr(app->t_settings_info.height_str));
  181. // Set solvable item
  182. item = variable_item_list_add(
  183. va, "Ensure Solvable", 2, minesweeper_scene_settings_screen_set_solvable, app);
  184. app->t_settings_info.solvable_item = item;
  185. uint8_t idx = (app->t_settings_info.ensure_solvable_board) ? 1 : 0;
  186. variable_item_set_current_value_index(item, idx);
  187. variable_item_set_current_value_text(item, settings_screen_verifier_text[idx]);
  188. variable_item_set_current_value_text(item, settings_screen_verifier_text[idx]);
  189. // Set sound feedback item
  190. item = variable_item_list_add(
  191. va, "Feedback", 2, minesweeper_scene_settings_screen_set_feedback, app);
  192. variable_item_set_current_value_index(item, app->feedback_enabled);
  193. variable_item_set_current_value_text(item, ((app->feedback_enabled) ? "Enabled" : "Disabled"));
  194. // Set info item
  195. item = variable_item_list_add(
  196. va, "Right For Info", 2, minesweeper_scene_settings_screen_set_info, app);
  197. variable_item_set_current_value_index(item, 0);
  198. variable_item_set_current_value_text(item, "-------");
  199. view_dispatcher_switch_to_view(app->view_dispatcher, MineSweeperSettingsView);
  200. }
  201. bool minesweeper_scene_settings_screen_on_event(void* context, SceneManagerEvent event) {
  202. furi_assert(context);
  203. MineSweeperApp* app = context;
  204. bool consumed = false;
  205. if(event.type == SceneManagerEventTypeCustom) {
  206. app->is_settings_changed =
  207. (app->settings_info.board_width != app->t_settings_info.board_width ||
  208. app->settings_info.board_height != app->t_settings_info.board_height ||
  209. app->settings_info.difficulty != app->t_settings_info.difficulty ||
  210. app->settings_info.ensure_solvable_board !=
  211. app->t_settings_info.ensure_solvable_board);
  212. switch(event.event) {
  213. case MineSweeperSettingsScreenEventDifficultyChange:
  214. break;
  215. case MineSweeperSettingsScreenEventWidthChange:
  216. break;
  217. case MineSweeperSettingsScreenEventHeightChange:
  218. break;
  219. case MineSweeperSettingsScreenEventSolvableChange:
  220. break;
  221. case MineSweeperSettingsScreenEventInfoChange:
  222. case MineSweeperSettingsScreenEventFeedbackChange:
  223. // If only the feedback option is changed we can just save without restarting
  224. mine_sweeper_save_settings(app);
  225. break;
  226. default:
  227. break;
  228. };
  229. consumed = true;
  230. } else if(event.type == SceneManagerEventTypeBack) {
  231. if(app->is_settings_changed) {
  232. // If there are changes in the width, height, or difficulty go to confirmation screen for restart
  233. scene_manager_next_scene(app->scene_manager, MineSweeperSceneConfirmationScreen);
  234. } else {
  235. // Otherwise just go back
  236. memset(&app->t_settings_info, 0, sizeof(app->t_settings_info));
  237. if(!scene_manager_search_and_switch_to_previous_scene(
  238. app->scene_manager, MineSweeperSceneMenuScreen)) {
  239. scene_manager_stop(app->scene_manager);
  240. view_dispatcher_stop(app->view_dispatcher);
  241. }
  242. }
  243. consumed = true;
  244. }
  245. return consumed;
  246. }
  247. void minesweeper_scene_settings_screen_on_exit(void* context) {
  248. furi_assert(context);
  249. MineSweeperApp* app = (MineSweeperApp*)context;
  250. VariableItemList* va = app->settings_screen;
  251. variable_item_list_reset(va);
  252. }