settings_scene.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  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,
  40. settings_screen_difficulty_text[index]);
  41. view_dispatcher_send_custom_event(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) > MINESWEEPER_BOARD_MAX_TILES;
  55. if (is_over_max_tiles) {
  56. do {
  57. is_over_max_tiles = (app->t_settings_info.board_width * --curr_board_height) > MINESWEEPER_BOARD_MAX_TILES;
  58. } while (is_over_max_tiles);
  59. app->t_settings_info.board_height = curr_board_height;
  60. snprintf(source, 5, "%" PRIu8, curr_board_height);
  61. source[4] = '\0';
  62. furi_string_set_strn(app->t_settings_info.height_str, source, 5);
  63. variable_item_set_current_value_index(
  64. app->t_settings_info.height_item,
  65. app->t_settings_info.board_height-7);
  66. variable_item_set_current_value_text(app->t_settings_info.height_item, furi_string_get_cstr(app->t_settings_info.height_str));
  67. }
  68. snprintf(source, 5, "%" PRIu8, index+16);
  69. source[4] = '\0';
  70. furi_string_set_strn(app->t_settings_info.width_str, source, 5);
  71. variable_item_set_current_value_text(app->t_settings_info.width_item, furi_string_get_cstr(app->t_settings_info.width_str));
  72. view_dispatcher_send_custom_event(app->view_dispatcher, MineSweeperSettingsScreenEventHeightChange);
  73. }
  74. static void minesweeper_scene_settings_screen_set_height(VariableItem* item) {
  75. char source[5];
  76. uint8_t index = 0;
  77. uint8_t curr_board_width = 16;
  78. bool is_over_max_tiles = false;
  79. furi_assert(item);
  80. MineSweeperApp* app = variable_item_get_context(item);
  81. app->t_settings_info.height_item = item;
  82. index = variable_item_get_current_value_index(app->t_settings_info.height_item);
  83. app->t_settings_info.board_height = index+7;
  84. curr_board_width = app->t_settings_info.board_width;
  85. is_over_max_tiles = (app->t_settings_info.board_height * curr_board_width) > MINESWEEPER_BOARD_MAX_TILES;
  86. if (is_over_max_tiles) {
  87. do {
  88. is_over_max_tiles = (app->t_settings_info.board_height * --curr_board_width) > MINESWEEPER_BOARD_MAX_TILES;
  89. } while (is_over_max_tiles);
  90. app->t_settings_info.board_width = curr_board_width;
  91. snprintf(source, 5, "%" PRIu8, curr_board_width);
  92. source[4] = '\0';
  93. furi_string_set_strn(app->t_settings_info.width_str, source, 5);
  94. variable_item_set_current_value_index(
  95. app->t_settings_info.width_item,
  96. app->t_settings_info.board_width-16);
  97. variable_item_set_current_value_text(app->t_settings_info.width_item, furi_string_get_cstr(app->t_settings_info.width_str));
  98. }
  99. snprintf(source, 5, "%" PRIu8, index+7);
  100. source[4] = '\0';
  101. furi_string_set_strn(app->t_settings_info.height_str, source, 5);
  102. variable_item_set_current_value_text(app->t_settings_info.height_item, furi_string_get_cstr(app->t_settings_info.height_str));
  103. view_dispatcher_send_custom_event(app->view_dispatcher, MineSweeperSettingsScreenEventWidthChange);
  104. }
  105. static void minesweeper_scene_settings_screen_set_solvable(VariableItem* item) {
  106. furi_assert(item);
  107. MineSweeperApp* app = variable_item_get_context(item);
  108. uint8_t index = variable_item_get_current_value_index(app->t_settings_info.solvable_item);
  109. app->t_settings_info.ensure_solvable_board = (index == 1) ? true : false;
  110. variable_item_set_current_value_text(item, settings_screen_verifier_text[index]);
  111. view_dispatcher_send_custom_event(app->view_dispatcher, MineSweeperSettingsScreenEventSolvableChange);
  112. }
  113. static void minesweeper_scene_settings_screen_set_feedback(VariableItem* item) {
  114. furi_assert(item);
  115. MineSweeperApp* app = variable_item_get_context(item);
  116. uint8_t index = variable_item_get_current_value_index(item);
  117. app->feedback_enabled = index;
  118. FURI_LOG_I(TAG, "FEEDBACK CALLBACK INDEX %d", app->feedback_enabled);
  119. variable_item_set_current_value_text(
  120. item,
  121. ((index) ? "Enabled" : "Disabled"));
  122. view_dispatcher_send_custom_event(app->view_dispatcher, MineSweeperSettingsScreenEventFeedbackChange);
  123. }
  124. static void minesweeper_scene_settings_screen_set_info(VariableItem* item) {
  125. furi_assert(item);
  126. MineSweeperApp* app = variable_item_get_context(item);
  127. view_dispatcher_send_custom_event(app->view_dispatcher, MineSweeperSettingsScreenEventInfoChange);
  128. }
  129. void minesweeper_scene_settings_screen_on_enter(void* context) {
  130. furi_assert(context);
  131. MineSweeperApp* app = (MineSweeperApp*)context;
  132. VariableItemList* va = app->settings_screen;
  133. VariableItem* item;
  134. // If we are accessing the scene and have not changed the settings
  135. if (!app->is_settings_changed) {
  136. // Set temp setting buffer to current state
  137. app->t_settings_info = app->settings_info;
  138. }
  139. // Set Difficulty Item
  140. item = variable_item_list_add(
  141. va,
  142. "Difficulty",
  143. MineSweeperSettingsScreenDifficultyTypeNum,
  144. minesweeper_scene_settings_screen_set_difficulty,
  145. app);
  146. app->t_settings_info.difficulty_item = item;
  147. variable_item_set_current_value_index(
  148. item,
  149. app->t_settings_info.difficulty);
  150. variable_item_set_current_value_text(
  151. item,
  152. settings_screen_difficulty_text[app->t_settings_info.difficulty]);
  153. // Set Width Item
  154. item = variable_item_list_add(
  155. va,
  156. "Board Width",
  157. 33-16,
  158. minesweeper_scene_settings_screen_set_width,
  159. app);
  160. app->t_settings_info.width_item = item;
  161. variable_item_set_current_value_index(
  162. item,
  163. app->t_settings_info.board_width-16);
  164. char source[5];
  165. snprintf(source, 5, "%" PRIu8, app->t_settings_info.board_width);
  166. source[4] = '\0';
  167. furi_string_set_strn(app->t_settings_info.width_str, source, 5);
  168. variable_item_set_current_value_text(
  169. item,
  170. furi_string_get_cstr(app->t_settings_info.width_str));
  171. // Set Height Item
  172. item = variable_item_list_add(
  173. va,
  174. "Board Height",
  175. 33-7,
  176. minesweeper_scene_settings_screen_set_height,
  177. app);
  178. app->t_settings_info.height_item = item;
  179. variable_item_set_current_value_index(
  180. item,
  181. app->t_settings_info.board_height-7);
  182. snprintf(source, 5, "%" PRIu8, app->t_settings_info.board_height);
  183. source[4] = '\0';
  184. furi_string_set_strn(app->t_settings_info.height_str, source, 5);
  185. variable_item_set_current_value_text(
  186. item,
  187. furi_string_get_cstr(app->t_settings_info.height_str));
  188. // Set solvable item
  189. item = variable_item_list_add(
  190. va,
  191. "Ensure Solvable",
  192. 2,
  193. minesweeper_scene_settings_screen_set_solvable,
  194. app);
  195. app->t_settings_info.solvable_item = item;
  196. uint8_t idx = (app->t_settings_info.ensure_solvable_board) ? 1 : 0;
  197. variable_item_set_current_value_index(
  198. item,
  199. idx);
  200. variable_item_set_current_value_text(
  201. item,
  202. settings_screen_verifier_text[idx]);
  203. // Set sound feedback item
  204. item = variable_item_list_add(
  205. va,
  206. "Feedback",
  207. 2,
  208. minesweeper_scene_settings_screen_set_feedback,
  209. app);
  210. variable_item_set_current_value_index(
  211. item,
  212. app->feedback_enabled);
  213. variable_item_set_current_value_text(
  214. item,
  215. ((app->feedback_enabled) ? "Enabled" : "Disabled"));
  216. // Set info item
  217. item = variable_item_list_add(
  218. va,
  219. "Right For Info",
  220. 2,
  221. minesweeper_scene_settings_screen_set_info,
  222. app);
  223. variable_item_set_current_value_index(
  224. item,
  225. 0);
  226. variable_item_set_current_value_text(
  227. item,
  228. "-------");
  229. view_dispatcher_switch_to_view(app->view_dispatcher, MineSweeperSettingsView);
  230. }
  231. bool minesweeper_scene_settings_screen_on_event(void* context, SceneManagerEvent event) {
  232. furi_assert(context);
  233. MineSweeperApp* app = context;
  234. bool consumed = false;
  235. if (event.type == SceneManagerEventTypeCustom) {
  236. app->is_settings_changed = (app->settings_info.board_width != app->t_settings_info.board_width ||
  237. app->settings_info.board_height != app->t_settings_info.board_height ||
  238. app->settings_info.difficulty != app->t_settings_info.difficulty ||
  239. app->settings_info.ensure_solvable_board != app->t_settings_info.ensure_solvable_board);
  240. switch (event.event) {
  241. case MineSweeperSettingsScreenEventDifficultyChange :
  242. break;
  243. case MineSweeperSettingsScreenEventWidthChange :
  244. break;
  245. case MineSweeperSettingsScreenEventHeightChange :
  246. break;
  247. case MineSweeperSettingsScreenEventSolvableChange :
  248. break;
  249. case MineSweeperSettingsScreenEventInfoChange :
  250. scene_manager_next_scene(app->scene_manager, MineSweeperSceneInfoScreen);
  251. break;
  252. case MineSweeperSettingsScreenEventFeedbackChange :
  253. // If only the feedback option is changed we can just save without restarting
  254. mine_sweeper_save_settings(app);
  255. break;
  256. default :
  257. break;
  258. };
  259. consumed = true;
  260. } else if (event.type == SceneManagerEventTypeBack) {
  261. if (app->is_settings_changed) {
  262. // If there are changes in the width, height, or difficulty go to confirmation screen for restart
  263. scene_manager_next_scene(app->scene_manager, MineSweeperSceneConfirmationScreen);
  264. } else {
  265. // Otherwise just go back
  266. memset(&app->t_settings_info, 0, sizeof(app->t_settings_info));
  267. if (!scene_manager_search_and_switch_to_previous_scene(
  268. app->scene_manager, MineSweeperSceneMenuScreen)) {
  269. scene_manager_stop(app->scene_manager);
  270. view_dispatcher_stop(app->view_dispatcher);
  271. }
  272. }
  273. consumed = true;
  274. }
  275. return consumed;
  276. }
  277. void minesweeper_scene_settings_screen_on_exit(void* context) {
  278. furi_assert(context);
  279. MineSweeperApp* app = (MineSweeperApp*)context;
  280. VariableItemList* va = app->settings_screen;
  281. variable_item_list_reset(va);
  282. }