scene.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. #include <furi.h>
  2. #include <furi-hal.h>
  3. #include "scene.h"
  4. static SceneAppGui* scene_app_gui = NULL;
  5. static ValueMutex* scene_state_mutex = NULL;
  6. void dolphin_scene_redraw(Canvas* canvas, void* ctx) {
  7. furi_assert(canvas);
  8. furi_assert(ctx);
  9. SceneState* state = (SceneState*)acquire_mutex((ValueMutex*)ctx, 25);
  10. if(state == NULL) return; // redraw fail
  11. uint32_t t = xTaskGetTickCount();
  12. canvas_clear(canvas);
  13. dolphin_scene_render(state, canvas, t);
  14. dolphin_scene_render_state(state, canvas);
  15. release_mutex((ValueMutex*)ctx, state);
  16. }
  17. void dolphin_scene_handle_input(SceneState* state, InputEvent* input) {
  18. // printf("[kb] event: %02x %s\n", input->key, input->state ? "pressed" : "released");
  19. dolphin_scene_handle_user_input(state, input);
  20. }
  21. void dolphin_scene_tick_handler(SceneState* state, uint32_t t, uint32_t dt) {
  22. // printf("t: %d, dt: %d\n", t, dt);
  23. dolphin_scene_coordinates(state, dt);
  24. dolphin_scene_update_state(state, t, dt);
  25. }
  26. static void scene_engine_tick_callback(void* p) {
  27. osMessageQueueId_t event_queue = p;
  28. AppEvent event;
  29. event.type = EventTypeTick;
  30. osMessageQueuePut(event_queue, (void*)&event, 0, 0);
  31. }
  32. static void scene_engine_input_callback(InputEvent* input_event, void* ctx) {
  33. osMessageQueueId_t event_queue = ctx;
  34. AppEvent event;
  35. event.type = EventTypeKey;
  36. event.value.input = *input_event;
  37. osMessageQueuePut(event_queue, (void*)&event, 0, osWaitForever);
  38. }
  39. void scene_alloc() {
  40. printf("scene_alloc: start\r\n");
  41. furi_assert(scene_app_gui == NULL);
  42. furi_assert(scene_state_mutex == NULL);
  43. // SceneAppGui
  44. scene_app_gui = furi_alloc(sizeof(SceneAppGui));
  45. scene_app_gui->mqueue = osMessageQueueNew(8, sizeof(AppEvent), NULL);
  46. scene_app_gui->gui = furi_record_open("gui");
  47. scene_app_gui->view_port = view_port_alloc();
  48. scene_app_gui->timer =
  49. osTimerNew(scene_engine_tick_callback, osTimerPeriodic, scene_app_gui->mqueue, NULL);
  50. printf("scene_alloc: timer %p\r\n", scene_app_gui->timer);
  51. // Scene State
  52. SceneState* scene_state = furi_alloc(sizeof(SceneState));
  53. scene_state->player.y = DOLPHIN_DEFAULT_Y;
  54. scene_state->player.x = DOLPHIN_CENTER;
  55. scene_state->player_global.x = 160;
  56. scene_state->player_global.y = WORLD_HEIGHT;
  57. scene_state->frame_group = DirRight;
  58. scene_state->frame_type = DirRight;
  59. scene_state->frame_pending = DirRight;
  60. scene_state->last_group = DirRight;
  61. scene_state->screen.x = scene_state->player.x;
  62. scene_state->screen.y = scene_state->player.y;
  63. // scene_state->debug = true;
  64. scene_state_mutex = furi_alloc(sizeof(ValueMutex));
  65. furi_check(init_mutex(scene_state_mutex, scene_state, sizeof(SceneState)));
  66. // Open GUI and register fullscreen view_port
  67. view_port_draw_callback_set(scene_app_gui->view_port, dolphin_scene_redraw, scene_state_mutex);
  68. view_port_input_callback_set(
  69. scene_app_gui->view_port, scene_engine_input_callback, scene_app_gui->mqueue);
  70. gui_add_view_port(scene_app_gui->gui, scene_app_gui->view_port, GuiLayerFullscreen);
  71. view_port_enabled_set(scene_app_gui->view_port, true);
  72. printf("scene_alloc: complete\r\n");
  73. }
  74. void scene_free() {
  75. printf("scene_free: start\r\n");
  76. view_port_enabled_set(scene_app_gui->view_port, false);
  77. gui_remove_view_port(scene_app_gui->gui, scene_app_gui->view_port);
  78. SceneState* scene_state = (SceneState*)acquire_mutex_block(scene_state_mutex);
  79. furi_assert(scene_state);
  80. free(scene_state);
  81. release_mutex(scene_state_mutex, scene_state);
  82. delete_mutex(scene_state_mutex);
  83. free(scene_state_mutex);
  84. scene_state_mutex = NULL;
  85. furi_check(osTimerDelete(scene_app_gui->timer) == osOK);
  86. furi_record_close("gui");
  87. view_port_free(scene_app_gui->view_port);
  88. furi_check(osMessageQueueDelete(scene_app_gui->mqueue) == osOK);
  89. free(scene_app_gui);
  90. scene_app_gui = NULL;
  91. printf("scene_free: complete\r\n");
  92. }
  93. int32_t scene_app(void* p) {
  94. furi_hal_power_insomnia_enter();
  95. scene_alloc();
  96. osTimerStart(scene_app_gui->timer, 40);
  97. uint32_t t = xTaskGetTickCount();
  98. uint32_t prev_t = 0;
  99. while(1) {
  100. AppEvent event;
  101. if(osMessageQueueGet(scene_app_gui->mqueue, &event, 0, osWaitForever) == osOK) {
  102. SceneState* scene_state = (SceneState*)acquire_mutex_block(scene_state_mutex);
  103. if(event.type == EventTypeTick) {
  104. t = xTaskGetTickCount();
  105. dolphin_scene_tick_handler(scene_state, t, (t - prev_t) % 1024);
  106. prev_t = t;
  107. } else if(event.type == EventTypeKey) {
  108. if(event.value.input.key == InputKeyBack &&
  109. event.value.input.type == InputTypeShort) {
  110. release_mutex(scene_state_mutex, scene_state);
  111. break;
  112. } else {
  113. dolphin_scene_handle_input(scene_state, &event.value.input);
  114. }
  115. }
  116. release_mutex(scene_state_mutex, scene_state);
  117. view_port_update(scene_app_gui->view_port);
  118. }
  119. }
  120. osTimerStop(scene_app_gui->timer);
  121. // CMSIS + FreeRTOS = Enterprise
  122. osDelay(15);
  123. scene_free();
  124. furi_hal_power_insomnia_exit();
  125. return 0;
  126. }