one_shot_animation_view.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #include "one_shot_animation_view.h"
  2. #include <furi.h>
  3. #include <portmacro.h>
  4. #include <gui/canvas.h>
  5. #include <gui/view.h>
  6. #include <gui/icon_i.h>
  7. #include <stdint.h>
  8. typedef void (*OneShotInteractCallback)(void*);
  9. struct OneShotView {
  10. View* view;
  11. TimerHandle_t update_timer;
  12. OneShotInteractCallback interact_callback;
  13. void* interact_callback_context;
  14. };
  15. typedef struct {
  16. const Icon* icon;
  17. uint32_t index;
  18. bool block_input;
  19. } OneShotViewModel;
  20. static void one_shot_view_update_timer_callback(TimerHandle_t xTimer) {
  21. OneShotView* view = (void*)pvTimerGetTimerID(xTimer);
  22. OneShotViewModel* model = view_get_model(view->view);
  23. if((model->index + 1) < model->icon->frame_count) {
  24. ++model->index;
  25. } else {
  26. model->block_input = false;
  27. model->index = model->icon->frame_count - 2;
  28. }
  29. view_commit_model(view->view, true);
  30. }
  31. static void one_shot_view_draw(Canvas* canvas, void* model_) {
  32. furi_assert(canvas);
  33. furi_assert(model_);
  34. OneShotViewModel* model = model_;
  35. furi_check(model->index < model->icon->frame_count);
  36. uint8_t y_offset = canvas_height(canvas) - model->icon->height;
  37. canvas_draw_bitmap(
  38. canvas,
  39. 0,
  40. y_offset,
  41. model->icon->width,
  42. model->icon->height,
  43. model->icon->frames[model->index]);
  44. }
  45. static bool one_shot_view_input(InputEvent* event, void* context) {
  46. furi_assert(context);
  47. furi_assert(event);
  48. OneShotView* view = context;
  49. bool consumed = false;
  50. OneShotViewModel* model = view_get_model(view->view);
  51. consumed = model->block_input;
  52. view_commit_model(view->view, false);
  53. if(!consumed) {
  54. if(event->key == InputKeyRight) {
  55. /* Right button reserved for animation activation, so consume */
  56. consumed = true;
  57. if(event->type == InputTypeShort) {
  58. if(view->interact_callback) {
  59. view->interact_callback(view->interact_callback_context);
  60. }
  61. }
  62. }
  63. }
  64. return consumed;
  65. }
  66. OneShotView* one_shot_view_alloc(void) {
  67. OneShotView* view = malloc(sizeof(OneShotView));
  68. view->view = view_alloc();
  69. view->update_timer =
  70. xTimerCreate(NULL, 1000, pdTRUE, view, one_shot_view_update_timer_callback);
  71. view_allocate_model(view->view, ViewModelTypeLocking, sizeof(OneShotViewModel));
  72. view_set_context(view->view, view);
  73. view_set_draw_callback(view->view, one_shot_view_draw);
  74. view_set_input_callback(view->view, one_shot_view_input);
  75. return view;
  76. }
  77. void one_shot_view_free(OneShotView* view) {
  78. furi_assert(view);
  79. xTimerDelete(view->update_timer, portMAX_DELAY);
  80. view_free(view->view);
  81. view->view = NULL;
  82. free(view);
  83. }
  84. void one_shot_view_set_interact_callback(
  85. OneShotView* view,
  86. OneShotInteractCallback callback,
  87. void* context) {
  88. furi_assert(view);
  89. view->interact_callback_context = context;
  90. view->interact_callback = callback;
  91. }
  92. void one_shot_view_start_animation(OneShotView* view, const Icon* icon) {
  93. furi_assert(view);
  94. furi_assert(icon);
  95. furi_check(icon->frame_count >= 2);
  96. OneShotViewModel* model = view_get_model(view->view);
  97. model->index = 0;
  98. model->icon = icon;
  99. model->block_input = true;
  100. view_commit_model(view->view, true);
  101. xTimerChangePeriod(view->update_timer, 1000 / model->icon->frame_rate, portMAX_DELAY);
  102. }
  103. View* one_shot_view_get_view(OneShotView* view) {
  104. furi_assert(view);
  105. return view->view;
  106. }