scene_manager.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #include "scene_manager_i.h"
  2. #include <furi.h>
  3. SceneManager* scene_manager_alloc(const SceneManagerHandlers* app_scene_handlers, void* context) {
  4. furi_assert(context);
  5. SceneManager* scene_manager = furi_alloc(sizeof(SceneManager));
  6. // Set SceneManager context and scene handlers
  7. scene_manager->context = context;
  8. scene_manager->scene_handlers = app_scene_handlers;
  9. // Allocate all scenes
  10. scene_manager->scene = furi_alloc(sizeof(AppScene) * app_scene_handlers->scene_num);
  11. // Initialize ScaneManager array for navigation
  12. SceneManagerIdStack_init(scene_manager->scene_id_stack);
  13. return scene_manager;
  14. }
  15. void scene_manager_free(SceneManager* scene_manager) {
  16. furi_assert(scene_manager);
  17. // Clear ScaneManager array
  18. SceneManagerIdStack_clear(scene_manager->scene_id_stack);
  19. // Clear allocated scenes
  20. free(scene_manager->scene);
  21. // Free SceneManager structure
  22. free(scene_manager);
  23. }
  24. void scene_manager_set_scene_state(SceneManager* scene_manager, uint32_t scene_id, uint32_t state) {
  25. furi_assert(scene_manager);
  26. furi_assert(scene_id < scene_manager->scene_handlers->scene_num);
  27. scene_manager->scene[scene_id].state = state;
  28. }
  29. uint32_t scene_manager_get_scene_state(SceneManager* scene_manager, uint32_t scene_id) {
  30. furi_assert(scene_manager);
  31. furi_assert(scene_id < scene_manager->scene_handlers->scene_num);
  32. return scene_manager->scene[scene_id].state;
  33. }
  34. bool scene_manager_handle_custom_event(SceneManager* scene_manager, uint32_t custom_event) {
  35. furi_assert(scene_manager);
  36. SceneManagerEvent event = {
  37. .type = SceneManagerEventTypeCustom,
  38. .event = custom_event,
  39. };
  40. uint32_t scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
  41. return scene_manager->scene_handlers->on_event_handlers[scene_id](
  42. scene_manager->context, event);
  43. }
  44. bool scene_manager_handle_navigation_event(SceneManager* scene_manager) {
  45. furi_assert(scene_manager);
  46. SceneManagerEvent event = {
  47. .type = SceneManagerEventTypeNavigation,
  48. };
  49. uint32_t scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
  50. bool consumed =
  51. scene_manager->scene_handlers->on_event_handlers[scene_id](scene_manager->context, event);
  52. if(!consumed) {
  53. consumed = scene_manager_previous_scene(scene_manager);
  54. }
  55. return consumed;
  56. }
  57. void scene_manager_handle_tick_event(SceneManager* scene_manager) {
  58. furi_assert(scene_manager);
  59. SceneManagerEvent event = {
  60. .type = SceneManagerEventTypeTick,
  61. };
  62. uint32_t scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
  63. scene_manager->scene_handlers->on_event_handlers[scene_id](scene_manager->context, event);
  64. }
  65. void scene_manager_next_scene(SceneManager* scene_manager, uint32_t next_scene_id) {
  66. furi_assert(scene_manager);
  67. furi_assert(next_scene_id < scene_manager->scene_handlers->scene_num);
  68. // Check if it is not the first scene
  69. if(SceneManagerIdStack_size(scene_manager->scene_id_stack)) {
  70. uint32_t cur_scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
  71. scene_manager->scene_handlers->on_exit_handlers[cur_scene_id](scene_manager->context);
  72. }
  73. // Add next scene and run on_enter
  74. SceneManagerIdStack_push_back(scene_manager->scene_id_stack, next_scene_id);
  75. scene_manager->scene_handlers->on_enter_handlers[next_scene_id](scene_manager->context);
  76. }
  77. bool scene_manager_previous_scene(SceneManager* scene_manager) {
  78. furi_assert(scene_manager);
  79. uint32_t cur_scene_id = 0;
  80. SceneManagerIdStack_pop_back(&cur_scene_id, scene_manager->scene_id_stack);
  81. // Handle exit from start scene separately
  82. if(SceneManagerIdStack_size(scene_manager->scene_id_stack) == 0) {
  83. scene_manager->scene_handlers->on_exit_handlers[cur_scene_id](scene_manager->context);
  84. return false;
  85. }
  86. uint32_t prev_scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
  87. scene_manager->scene_handlers->on_exit_handlers[cur_scene_id](scene_manager->context);
  88. scene_manager->scene_handlers->on_enter_handlers[prev_scene_id](scene_manager->context);
  89. return true;
  90. }
  91. bool scene_manager_search_previous_scene(SceneManager* scene_manager, uint32_t scene_id) {
  92. furi_assert(scene_manager);
  93. uint32_t prev_scene_id = 0;
  94. uint32_t cur_scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
  95. SceneManagerIdStack_it_t scene_it;
  96. SceneManagerIdStack_it_last(scene_it, scene_manager->scene_id_stack);
  97. // Search scene with given id in navigation stack
  98. bool scene_found = false;
  99. while(!scene_found) {
  100. SceneManagerIdStack_previous(scene_it);
  101. if(SceneManagerIdStack_end_p(scene_it)) {
  102. return false;
  103. }
  104. prev_scene_id = *SceneManagerIdStack_ref(scene_it);
  105. if(prev_scene_id == scene_id) {
  106. scene_found = true;
  107. }
  108. }
  109. // Remove all scene id from navigation stack
  110. SceneManagerIdStack_next(scene_it);
  111. SceneManagerIdStack_pop_until(scene_manager->scene_id_stack, scene_it);
  112. scene_manager->scene_handlers->on_exit_handlers[cur_scene_id](scene_manager->context);
  113. scene_manager->scene_handlers->on_enter_handlers[prev_scene_id](scene_manager->context);
  114. return true;
  115. }