[FL-1019] New main screen and graphics (#389)
* new status bar, lock menu and dolphin activities screen * lock icon indication * main screen animation, basic scene switching * level progression calculations based on icounter value Co-authored-by: rusdacent <rusdacentx0x08@gmail.com> Co-authored-by: あく <alleteam@gmail.com>
							
								
								
									
										6
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						| @ -20,7 +20,11 @@ jobs: | ||||
|         uses: actions/checkout@v2 | ||||
|         with: | ||||
|           fetch-depth: 0 | ||||
|           submodules: true | ||||
|       - name: Checkout submodules | ||||
|         run: git submodule update --init --recursive | ||||
|       - name: Checkout submodules | ||||
|         run: git submodule sync | ||||
| 
 | ||||
|       - uses: satackey/action-docker-layer-caching@v0.0.11 | ||||
|         continue-on-error: true | ||||
|         with: | ||||
|  | ||||
| @ -1,4 +1,27 @@ | ||||
| #include "dolphin_i.h" | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| // temporary main screen animation managment
 | ||||
| void dolphin_scene_handler_set_scene(Dolphin* dolphin, IconName icon) { | ||||
|     with_view_model( | ||||
|         dolphin->idle_view_main, (DolphinViewMainModel * model) { | ||||
|             model->animation = assets_icons_get(icon); | ||||
|             icon_start_animation(model->animation); | ||||
|             return true; | ||||
|         }); | ||||
| } | ||||
| 
 | ||||
| void dolphin_scene_handler_switch_scene(Dolphin* dolphin) { | ||||
|     with_view_model( | ||||
|         dolphin->idle_view_main, (DolphinViewMainModel * model) { | ||||
|             if(icon_is_last_frame(model->animation)) { | ||||
|                 model->animation = assets_icons_get(idle_scenes[model->scene_num]); | ||||
|                 icon_start_animation(model->animation); | ||||
|                 model->scene_num = random() % sizeof(idle_scenes); | ||||
|             } | ||||
|             return true; | ||||
|         }); | ||||
| } | ||||
| 
 | ||||
| bool dolphin_view_first_start_input(InputEvent* event, void* context) { | ||||
|     furi_assert(event); | ||||
| @ -34,15 +57,38 @@ bool dolphin_view_idle_main_input(InputEvent* event, void* context) { | ||||
|     Dolphin* dolphin = context; | ||||
| 
 | ||||
|     if(event->type == InputTypeShort) { | ||||
|         if(!dolphin->locked) { | ||||
|             if(event->key == InputKeyOk) { | ||||
|                 with_value_mutex( | ||||
|                     dolphin->menu_vm, (Menu * menu) { menu_ok(menu); }); | ||||
|             } else if(event->key == InputKeyUp) { | ||||
|                 view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewLockMenu); | ||||
|             } else if(event->key == InputKeyLeft) { | ||||
|                 view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewIdleUp); | ||||
|             } else if(event->key == InputKeyRight) { | ||||
|                 view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewIdleMeta); | ||||
|             } else if(event->key == InputKeyDown) { | ||||
|                 view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewIdleDown); | ||||
|             } | ||||
| 
 | ||||
|             if(event->key == InputKeyBack) { | ||||
|                 view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewIdleMain); | ||||
|             } | ||||
|         } else { | ||||
|             if(event->key == InputKeyBack) { | ||||
|                 dolphin->lock_count++; | ||||
|                 if(dolphin->lock_count == 3) { | ||||
|                     dolphin->locked = false; | ||||
|                     dolphin->lock_count = 0; | ||||
|                     view_dispatcher_switch_to_view( | ||||
|                         dolphin->idle_view_dispatcher, DolphinViewIdleMain); | ||||
|                     view_port_enabled_set(dolphin->lock_viewport, false); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         dolphin_scene_handler_switch_scene(dolphin); | ||||
|     } | ||||
| 
 | ||||
|     // All events consumed
 | ||||
|     return true; | ||||
| } | ||||
| @ -67,6 +113,182 @@ bool dolphin_view_idle_up_input(InputEvent* event, void* context) { | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| static void lock_menu_callback(void* context, uint8_t index) { | ||||
|     Dolphin* dolphin = context; | ||||
|     switch(index) { | ||||
|     case 0: | ||||
|         dolphin->locked = true; | ||||
|         view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewIdleMain); | ||||
|         view_port_enabled_set(dolphin->lock_viewport, true); | ||||
|         break; | ||||
| 
 | ||||
|     default: | ||||
|         break; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void meta_menu_callback(void* context, uint8_t index) { | ||||
|     Dolphin* dolphin = context; | ||||
|     switch(index) { | ||||
|     case 0: | ||||
|         view_port_enabled_set(dolphin->passport, true); | ||||
|         break; | ||||
| 
 | ||||
|     default: | ||||
|         break; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| static void lock_icon_callback(Canvas* canvas, void* context) { | ||||
|     assert(context); | ||||
|     Dolphin* dolphin = context; | ||||
|     canvas_draw_icon(canvas, 0, 0, dolphin->lock_icon); | ||||
| } | ||||
| 
 | ||||
| static void draw_passport_callback(Canvas* canvas, void* context) { | ||||
|     assert(context); | ||||
|     Dolphin* dolphin = context; | ||||
| 
 | ||||
|     char level[20]; | ||||
|     uint32_t current_level = dolphin_state_get_level(dolphin->state); | ||||
|     uint32_t prev_cap = dolphin_state_xp_to_levelup(dolphin->state, current_level - 1, false); | ||||
|     uint32_t exp = (dolphin_state_xp_to_levelup(dolphin->state, current_level, true) * 63) / | ||||
|                    (dolphin_state_xp_to_levelup(dolphin->state, current_level, false) - prev_cap); | ||||
| 
 | ||||
|     canvas_clear(canvas); | ||||
| 
 | ||||
|     // multipass
 | ||||
|     canvas_draw_icon_name(canvas, 0, 0, I_PassportLeft_6x47); | ||||
|     canvas_draw_icon_name(canvas, 0, 47, I_PassportBottom_128x17); | ||||
|     canvas_draw_line(canvas, 6, 0, 125, 0); | ||||
|     canvas_draw_line(canvas, 127, 2, 127, 47); | ||||
|     canvas_draw_dot(canvas, 126, 1); | ||||
| 
 | ||||
|     //portrait frame
 | ||||
|     canvas_draw_line(canvas, 9, 6, 9, 53); | ||||
|     canvas_draw_line(canvas, 10, 5, 52, 5); | ||||
|     canvas_draw_line(canvas, 55, 8, 55, 53); | ||||
|     canvas_draw_line(canvas, 10, 54, 54, 54); | ||||
|     canvas_draw_line(canvas, 53, 5, 55, 7); | ||||
| 
 | ||||
|     // portrait
 | ||||
|     canvas_draw_icon_name(canvas, 14, 11, I_DolphinOkay_41x43); | ||||
|     canvas_draw_line(canvas, 59, 18, 124, 18); | ||||
|     canvas_draw_line(canvas, 59, 31, 124, 31); | ||||
|     canvas_draw_line(canvas, 59, 44, 124, 44); | ||||
| 
 | ||||
|     canvas_draw_str(canvas, 59, 15, api_hal_version_get_name_ptr()); | ||||
|     canvas_draw_str(canvas, 59, 28, "Mood: OK"); | ||||
| 
 | ||||
|     snprintf(level, 20, "Level: %ld", current_level); | ||||
| 
 | ||||
|     canvas_draw_str(canvas, 59, 41, level); | ||||
|     canvas_set_color(canvas, ColorWhite); | ||||
|     canvas_draw_box(canvas, 123 - exp, 48, exp + 1, 6); | ||||
|     canvas_set_color(canvas, ColorBlack); | ||||
|     canvas_draw_line(canvas, 123 - exp, 48, 123 - exp, 54); | ||||
| } | ||||
| 
 | ||||
| static void passport_input_callback(InputEvent* event, void* context) { | ||||
|     Dolphin* dolphin = context; | ||||
|     if(event->type == InputTypeShort) { | ||||
|         if(event->key == InputKeyBack) { | ||||
|             view_port_enabled_set(dolphin->passport, false); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| bool dolphin_view_lockmenu_input(InputEvent* event, void* context) { | ||||
|     furi_assert(event); | ||||
|     furi_assert(context); | ||||
|     Dolphin* dolphin = context; | ||||
| 
 | ||||
|     if(event->type != InputTypeShort) return false; | ||||
| 
 | ||||
|     if(event->key == InputKeyUp) { | ||||
|         with_view_model( | ||||
|             dolphin->view_lockmenu, (DolphinViewMenuModel * model) { | ||||
|                 if(model->idx <= 0) | ||||
|                     model->idx = 0; | ||||
|                 else | ||||
|                     --model->idx; | ||||
|                 return true; | ||||
|             }); | ||||
|     } else if(event->key == InputKeyDown) { | ||||
|         with_view_model( | ||||
|             dolphin->view_lockmenu, (DolphinViewMenuModel * model) { | ||||
|                 if(model->idx >= 2) | ||||
|                     model->idx = 2; | ||||
|                 else | ||||
|                     ++model->idx; | ||||
|                 return true; | ||||
|             }); | ||||
|     } else if(event->key == InputKeyOk) { | ||||
|         with_view_model( | ||||
|             dolphin->view_lockmenu, (DolphinViewMenuModel * model) { | ||||
|                 lock_menu_callback(context, model->idx); | ||||
|                 return true; | ||||
|             }); | ||||
|     } else if(event->key == InputKeyBack) { | ||||
|         with_view_model( | ||||
|             dolphin->view_lockmenu, (DolphinViewMenuModel * model) { | ||||
|                 model->idx = 0; | ||||
|                 return true; | ||||
|             }); | ||||
|         view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewIdleMain); | ||||
| 
 | ||||
|         if(random() % 100 > 50) | ||||
|             dolphin_scene_handler_set_scene(dolphin, idle_scenes[random() % sizeof(idle_scenes)]); | ||||
|     } | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| bool dolphin_view_idle_meta_input(InputEvent* event, void* context) { | ||||
|     furi_assert(event); | ||||
|     furi_assert(context); | ||||
|     Dolphin* dolphin = context; | ||||
| 
 | ||||
|     if(event->type != InputTypeShort) return false; | ||||
| 
 | ||||
|     if(event->key == InputKeyLeft) { | ||||
|         with_view_model( | ||||
|             dolphin->idle_view_meta, (DolphinViewMenuModel * model) { | ||||
|                 if(model->idx <= 0) | ||||
|                     model->idx = 0; | ||||
|                 else | ||||
|                     --model->idx; | ||||
|                 return true; | ||||
|             }); | ||||
|     } else if(event->key == InputKeyRight) { | ||||
|         with_view_model( | ||||
|             dolphin->idle_view_meta, (DolphinViewMenuModel * model) { | ||||
|                 if(model->idx >= 2) | ||||
|                     model->idx = 2; | ||||
|                 else | ||||
|                     ++model->idx; | ||||
|                 return true; | ||||
|             }); | ||||
|     } else if(event->key == InputKeyOk) { | ||||
|         with_view_model( | ||||
|             dolphin->idle_view_meta, (DolphinViewMenuModel * model) { | ||||
|                 meta_menu_callback(context, model->idx); | ||||
|                 return true; | ||||
|             }); | ||||
|     } else if(event->key == InputKeyBack) { | ||||
|         with_view_model( | ||||
|             dolphin->idle_view_meta, (DolphinViewMenuModel * model) { | ||||
|                 model->idx = 0; | ||||
|                 return true; | ||||
|             }); | ||||
|         view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewIdleMain); | ||||
|         if(random() % 100 > 50) | ||||
|             dolphin_scene_handler_set_scene(dolphin, idle_scenes[random() % sizeof(idle_scenes)]); | ||||
|     } | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| Dolphin* dolphin_alloc() { | ||||
|     Dolphin* dolphin = furi_alloc(sizeof(Dolphin)); | ||||
|     // Message queue
 | ||||
| @ -90,6 +312,9 @@ Dolphin* dolphin_alloc() { | ||||
|     // Main Idle View
 | ||||
|     dolphin->idle_view_main = view_alloc(); | ||||
|     view_set_context(dolphin->idle_view_main, dolphin); | ||||
|     view_allocate_model( | ||||
|         dolphin->idle_view_main, ViewModelTypeLockFree, sizeof(DolphinViewIdleUpModel)); | ||||
| 
 | ||||
|     view_set_draw_callback(dolphin->idle_view_main, dolphin_view_idle_main_draw); | ||||
|     view_set_input_callback(dolphin->idle_view_main, dolphin_view_idle_main_input); | ||||
|     view_dispatcher_add_view( | ||||
| @ -97,13 +322,34 @@ Dolphin* dolphin_alloc() { | ||||
|     // Stats Idle View
 | ||||
|     dolphin->idle_view_up = view_alloc(); | ||||
|     view_set_context(dolphin->idle_view_up, dolphin); | ||||
| 
 | ||||
|     view_allocate_model( | ||||
|         dolphin->idle_view_up, ViewModelTypeLockFree, sizeof(DolphinViewIdleUpModel)); | ||||
|         dolphin->idle_view_up, ViewModelTypeLockFree, sizeof(DolphinViewMainModel)); | ||||
|     view_set_draw_callback(dolphin->idle_view_up, dolphin_view_idle_up_draw); | ||||
|     view_set_input_callback(dolphin->idle_view_up, dolphin_view_idle_up_input); | ||||
|     view_set_previous_callback(dolphin->idle_view_up, dolphin_view_idle_back); | ||||
|     view_dispatcher_add_view( | ||||
|         dolphin->idle_view_dispatcher, DolphinViewIdleUp, dolphin->idle_view_up); | ||||
|     // Lock Menu View
 | ||||
|     dolphin->view_lockmenu = view_alloc(); | ||||
|     view_set_context(dolphin->view_lockmenu, dolphin); | ||||
|     view_allocate_model( | ||||
|         dolphin->view_lockmenu, ViewModelTypeLockFree, sizeof(DolphinViewMenuModel)); | ||||
|     view_set_draw_callback(dolphin->view_lockmenu, dolphin_view_lockmenu_draw); | ||||
|     view_set_input_callback(dolphin->view_lockmenu, dolphin_view_lockmenu_input); | ||||
|     view_set_previous_callback(dolphin->view_lockmenu, dolphin_view_idle_back); | ||||
|     view_dispatcher_add_view( | ||||
|         dolphin->idle_view_dispatcher, DolphinViewLockMenu, dolphin->view_lockmenu); | ||||
|     // Meta View
 | ||||
|     dolphin->idle_view_meta = view_alloc(); | ||||
|     view_set_context(dolphin->idle_view_meta, dolphin); | ||||
|     view_allocate_model( | ||||
|         dolphin->idle_view_meta, ViewModelTypeLockFree, sizeof(DolphinViewMenuModel)); | ||||
|     view_set_draw_callback(dolphin->idle_view_meta, dolphin_view_idle_meta_draw); | ||||
|     view_set_input_callback(dolphin->idle_view_meta, dolphin_view_idle_meta_input); | ||||
|     view_set_previous_callback(dolphin->idle_view_meta, dolphin_view_idle_back); | ||||
|     view_dispatcher_add_view( | ||||
|         dolphin->idle_view_dispatcher, DolphinViewIdleMeta, dolphin->idle_view_meta); | ||||
|     // Down Idle View
 | ||||
|     dolphin->idle_view_down = view_alloc(); | ||||
|     view_set_draw_callback(dolphin->idle_view_down, dolphin_view_idle_down_draw); | ||||
| @ -117,6 +363,22 @@ Dolphin* dolphin_alloc() { | ||||
|     view_dispatcher_add_view( | ||||
|         dolphin->idle_view_dispatcher, DolphinViewHwMismatch, dolphin->view_hw_mismatch); | ||||
| 
 | ||||
|     // Lock icon
 | ||||
|     dolphin->lock_icon = assets_icons_get(I_Lock_8x8); | ||||
|     dolphin->lock_viewport = view_port_alloc(); | ||||
|     view_port_set_width(dolphin->lock_viewport, icon_get_width(dolphin->lock_icon)); | ||||
|     view_port_draw_callback_set(dolphin->lock_viewport, lock_icon_callback, dolphin); | ||||
|     view_port_enabled_set(dolphin->lock_viewport, false); | ||||
| 
 | ||||
|     // Passport
 | ||||
|     dolphin->passport = view_port_alloc(); | ||||
|     view_port_draw_callback_set(dolphin->passport, draw_passport_callback, dolphin); | ||||
|     view_port_input_callback_set(dolphin->passport, passport_input_callback, dolphin); | ||||
|     view_port_enabled_set(dolphin->passport, false); | ||||
| 
 | ||||
|     // Main screen animation
 | ||||
|     dolphin_scene_handler_set_scene(dolphin, idle_scenes[random() % sizeof(idle_scenes)]); | ||||
| 
 | ||||
|     return dolphin; | ||||
| } | ||||
| 
 | ||||
| @ -139,7 +401,12 @@ int32_t dolphin_task() { | ||||
|     Dolphin* dolphin = dolphin_alloc(); | ||||
| 
 | ||||
|     Gui* gui = furi_record_open("gui"); | ||||
| 
 | ||||
|     view_dispatcher_attach_to_gui(dolphin->idle_view_dispatcher, gui, ViewDispatcherTypeWindow); | ||||
|     gui_add_view_port(gui, dolphin->lock_viewport, GuiLayerStatusBarLeft); | ||||
| 
 | ||||
|     gui_add_view_port(gui, dolphin->passport, GuiLayerFullscreen); | ||||
| 
 | ||||
|     if(dolphin_state_load(dolphin->state)) { | ||||
|         view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewIdleMain); | ||||
|     } else { | ||||
| @ -157,7 +424,6 @@ int32_t dolphin_task() { | ||||
|     if(!api_hal_version_do_i_belong_here()) { | ||||
|         view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewHwMismatch); | ||||
|     } | ||||
| 
 | ||||
|     DolphinEvent event; | ||||
|     while(1) { | ||||
|         furi_check(osMessageQueueGet(dolphin->event_queue, &event, NULL, osWaitForever) == osOK); | ||||
| @ -173,6 +439,5 @@ int32_t dolphin_task() { | ||||
|             dolphin_state_save(dolphin->state); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| @ -39,9 +39,20 @@ struct Dolphin { | ||||
|     View* idle_view_main; | ||||
|     View* idle_view_up; | ||||
|     View* idle_view_down; | ||||
|     View* idle_view_meta; | ||||
|     View* view_hw_mismatch; | ||||
|     View* view_lockmenu; | ||||
|     ViewPort* passport; | ||||
|     ViewPort* lock_viewport; | ||||
|     Icon* lock_icon; | ||||
| 
 | ||||
|     bool locked; | ||||
|     uint8_t lock_count; | ||||
| }; | ||||
| 
 | ||||
| // Temporary
 | ||||
| const IconName idle_scenes[] = {A_Wink_128x64, A_WatchingTV_128x64}; | ||||
| 
 | ||||
| Dolphin* dolphin_alloc(); | ||||
| 
 | ||||
| /* Save Dolphin state (write to permanent memory)
 | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| #include "dolphin_state.h" | ||||
| #include <furi.h> | ||||
| #include <api-hal.h> | ||||
| #include <math.h> | ||||
| 
 | ||||
| typedef struct { | ||||
|     uint8_t magic; | ||||
| @ -17,6 +18,8 @@ typedef struct { | ||||
| #define DOLPHIN_DATA_HEADER_MAGIC 0xD0 | ||||
| #define DOLPHIN_DATA_HEADER_VERSION 0x01 | ||||
| 
 | ||||
| #define DOLPHIN_LVL_THRESHOLD 20.0f | ||||
| 
 | ||||
| typedef struct { | ||||
|     uint32_t limit_ibutton; | ||||
|     uint32_t limit_nfc; | ||||
| @ -119,3 +122,14 @@ uint32_t dolphin_state_get_icounter(DolphinState* dolphin_state) { | ||||
| uint32_t dolphin_state_get_butthurt(DolphinState* dolphin_state) { | ||||
|     return dolphin_state->data.butthurt; | ||||
| } | ||||
| 
 | ||||
| uint32_t dolphin_state_get_level(DolphinState* dolphin_state) { | ||||
|     return 0.5f + | ||||
|            sqrtf(1.0f + 8.0f * ((float)dolphin_state->data.icounter / DOLPHIN_LVL_THRESHOLD)) / | ||||
|                2.0f; | ||||
| } | ||||
| 
 | ||||
| uint32_t dolphin_state_xp_to_levelup(DolphinState* dolphin_state, uint32_t level, bool remaining) { | ||||
|     return (DOLPHIN_LVL_THRESHOLD * level * (level + 1) / 2) - | ||||
|            (remaining ? dolphin_state->data.icounter : 0); | ||||
| } | ||||
| @ -21,3 +21,7 @@ void dolphin_state_on_deed(DolphinState* dolphin_state, DolphinDeed deed); | ||||
| uint32_t dolphin_state_get_icounter(DolphinState* dolphin_state); | ||||
| 
 | ||||
| uint32_t dolphin_state_get_butthurt(DolphinState* dolphin_state); | ||||
| 
 | ||||
| uint32_t dolphin_state_get_level(DolphinState* dolphin_state); | ||||
| 
 | ||||
| uint32_t dolphin_state_xp_to_levelup(DolphinState* dolphin_state, uint32_t level, bool remaining); | ||||
| @ -2,9 +2,11 @@ | ||||
| #include <gui/view.h> | ||||
| #include <gui/gui.h> | ||||
| #include <gui/elements.h> | ||||
| 
 | ||||
| #include <api-hal.h> | ||||
| 
 | ||||
| static char* Lockmenu_Items[3] = {"Lock", "Set PIN", "DUMB mode"}; | ||||
| static char* Meta_Items[3] = {"Passport", "Games", "???"}; | ||||
| 
 | ||||
| void dolphin_view_first_start_draw(Canvas* canvas, void* model) { | ||||
|     DolphinViewFirstStartModel* m = model; | ||||
|     canvas_clear(canvas); | ||||
| @ -57,40 +59,73 @@ void dolphin_view_first_start_draw(Canvas* canvas, void* model) { | ||||
| 
 | ||||
| void dolphin_view_idle_main_draw(Canvas* canvas, void* model) { | ||||
|     canvas_clear(canvas); | ||||
|     canvas_set_color(canvas, ColorBlack); | ||||
|     canvas_draw_icon_name( | ||||
|         canvas, canvas_width(canvas) - 80, canvas_height(canvas) - 60 + 6, I_Flipper_young_80x60); | ||||
|     canvas_set_font(canvas, FontSecondary); | ||||
|     canvas_draw_str(canvas, 2, 10, "/\\: Stats"); | ||||
|     canvas_draw_str(canvas, 5, 32, "OK: Menu"); | ||||
|     canvas_draw_str(canvas, 2, 52, "\\/: Version"); | ||||
|     DolphinViewMainModel* m = model; | ||||
|     if(m->animation) canvas_draw_icon(canvas, 0, 0, m->animation); | ||||
| } | ||||
| 
 | ||||
| void dolphin_view_idle_up_draw(Canvas* canvas, void* model) { | ||||
|     DolphinViewIdleUpModel* m = model; | ||||
|     canvas_clear(canvas); | ||||
| 
 | ||||
|     canvas_set_color(canvas, ColorBlack); | ||||
|     canvas_set_font(canvas, FontPrimary); | ||||
|     canvas_draw_str(canvas, 2, 10, "Dolphin stats:"); | ||||
|     canvas_draw_str(canvas, 2, 15, "Dolphin stats:"); | ||||
| 
 | ||||
|     char buffer[64]; | ||||
|     canvas_set_font(canvas, FontSecondary); | ||||
|     snprintf(buffer, 64, "Icounter: %ld", m->icounter); | ||||
|     canvas_draw_str(canvas, 5, 22, buffer); | ||||
|     canvas_draw_str(canvas, 5, 30, buffer); | ||||
|     snprintf(buffer, 64, "Butthurt: %ld", m->butthurt); | ||||
|     canvas_draw_str(canvas, 5, 32, buffer); | ||||
|     canvas_draw_str(canvas, 5, 40, "< > change icounter"); | ||||
|     canvas_draw_str(canvas, 5, 40, buffer); | ||||
|     canvas_draw_str(canvas, 0, 53, "[< >] icounter value   [ok] save"); | ||||
| } | ||||
| 
 | ||||
| void dolphin_view_lockmenu_draw(Canvas* canvas, void* model) { | ||||
|     DolphinViewMenuModel* m = model; | ||||
|     canvas_clear(canvas); | ||||
|     canvas_set_color(canvas, ColorBlack); | ||||
|     canvas_draw_icon_name(canvas, 5, 0, I_DoorLeft_8x56); | ||||
|     canvas_draw_icon_name(canvas, 115, 0, I_DoorRight_8x56); | ||||
|     canvas_set_font(canvas, FontSecondary); | ||||
|     for(uint8_t i = 0; i < 3; ++i) { | ||||
|         canvas_draw_str_aligned( | ||||
|             canvas, 64, 13 + (i * 17), AlignCenter, AlignCenter, Lockmenu_Items[i]); | ||||
|         if(m->idx == i) elements_frame(canvas, 15, 5 + (i * 17), 98, 15); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void dolphin_view_idle_meta_draw(Canvas* canvas, void* model) { | ||||
|     DolphinViewMenuModel* m = model; | ||||
|     canvas_clear(canvas); | ||||
|     canvas_set_color(canvas, ColorBlack); | ||||
|     canvas_set_font(canvas, FontSecondary); | ||||
| 
 | ||||
|     canvas_draw_icon_name(canvas, 20, 23, I_BigProfile_24x24); | ||||
|     canvas_draw_icon_name(canvas, 55, 23, I_BigGames_24x24); | ||||
|     canvas_draw_icon_name(canvas, 90, 23, I_BigBurger_24x24); | ||||
| 
 | ||||
|     canvas_draw_str_aligned(canvas, 66, 12, AlignCenter, AlignCenter, Meta_Items[m->idx]); | ||||
| 
 | ||||
|     canvas_draw_frame(canvas, 17 + (35 * m->idx), 20, 30, 30); | ||||
|     canvas_set_color(canvas, ColorWhite); | ||||
| 
 | ||||
|     canvas_draw_dot(canvas, 17 + (35 * m->idx), 20); | ||||
|     canvas_draw_dot(canvas, 17 + (35 * m->idx), 49); | ||||
|     canvas_draw_dot(canvas, 46 + (35 * m->idx), 20); | ||||
|     canvas_draw_dot(canvas, 46 + (35 * m->idx), 49); | ||||
| 
 | ||||
|     canvas_set_color(canvas, ColorBlack); | ||||
| } | ||||
| 
 | ||||
| void dolphin_view_idle_down_draw(Canvas* canvas, void* model) { | ||||
|     canvas_clear(canvas); | ||||
|     canvas_set_color(canvas, ColorBlack); | ||||
|     canvas_set_font(canvas, FontPrimary); | ||||
|     canvas_draw_str(canvas, 2, 10, "Version info:"); | ||||
|     canvas_draw_str(canvas, 2, 15, "Version info:"); | ||||
|     canvas_set_font(canvas, FontSecondary); | ||||
|     canvas_draw_str(canvas, 5, 22, TARGET " " BUILD_DATE); | ||||
|     canvas_draw_str(canvas, 5, 32, GIT_BRANCH); | ||||
|     canvas_draw_str(canvas, 5, 42, GIT_BRANCH_NUM " " GIT_COMMIT); | ||||
|     canvas_draw_str(canvas, 5, 25, TARGET " " BUILD_DATE); | ||||
|     canvas_draw_str(canvas, 5, 35, GIT_BRANCH); | ||||
|     canvas_draw_str(canvas, 5, 45, GIT_BRANCH_NUM " " GIT_COMMIT); | ||||
| 
 | ||||
|     char buffer[64]; | ||||
|     snprintf( | ||||
| @ -101,7 +136,7 @@ void dolphin_view_idle_down_draw(Canvas* canvas, void* model) { | ||||
|         api_hal_version_get_hw_target(), | ||||
|         api_hal_version_get_hw_body(), | ||||
|         api_hal_version_get_hw_connect()); | ||||
|     canvas_draw_str(canvas, 5, 52, buffer); | ||||
|     canvas_draw_str(canvas, 5, 55, buffer); | ||||
| } | ||||
| 
 | ||||
| void dolphin_view_hw_mismatch_draw(Canvas* canvas, void* model) { | ||||
|  | ||||
| @ -13,6 +13,8 @@ typedef enum { | ||||
|     DolphinViewIdleUp, | ||||
|     DolphinViewIdleDown, | ||||
|     DolphinViewHwMismatch, | ||||
|     DolphinViewLockMenu, | ||||
|     DolphinViewIdleMeta, | ||||
| } DolphinViewIdle; | ||||
| 
 | ||||
| typedef struct { | ||||
| @ -27,12 +29,27 @@ typedef struct { | ||||
|     uint32_t butthurt; | ||||
| } DolphinViewIdleUpModel; | ||||
| 
 | ||||
| typedef struct { | ||||
|     uint8_t idx; | ||||
| } DolphinViewMenuModel; | ||||
| 
 | ||||
| typedef struct { | ||||
|     Icon* animation; | ||||
|     uint8_t scene_num; | ||||
| 
 | ||||
| } DolphinViewMainModel; | ||||
| 
 | ||||
| void dolphin_view_idle_main_draw(Canvas* canvas, void* model); | ||||
| bool dolphin_view_idle_main_input(InputEvent* event, void* context); | ||||
| 
 | ||||
| void dolphin_view_idle_up_draw(Canvas* canvas, void* model); | ||||
| 
 | ||||
| void dolphin_view_lockmenu_draw(Canvas* canvas, void* model); | ||||
| 
 | ||||
| void dolphin_view_idle_down_draw(Canvas* canvas, void* model); | ||||
| 
 | ||||
| void dolphin_view_idle_meta_draw(Canvas* canvas, void* model); | ||||
| 
 | ||||
| void dolphin_view_hw_mismatch_draw(Canvas* canvas, void* model); | ||||
| 
 | ||||
| uint32_t dolphin_view_idle_back(void* context); | ||||
|  | ||||
| @ -46,8 +46,12 @@ void gui_redraw_status_bar(Gui* gui) { | ||||
|     uint8_t x_used = 0; | ||||
|     uint8_t width; | ||||
|     ViewPort* view_port; | ||||
|     canvas_frame_set( | ||||
|         gui->canvas, GUI_STATUS_BAR_X, GUI_STATUS_BAR_Y, GUI_DISPLAY_WIDTH, GUI_STATUS_BAR_HEIGHT); | ||||
|     canvas_draw_icon_name(gui->canvas, 0, 0, I_Background_128x11); | ||||
| 
 | ||||
|     // Right side
 | ||||
|     x = GUI_DISPLAY_WIDTH + 2; | ||||
|     x = GUI_DISPLAY_WIDTH; | ||||
|     ViewPortArray_it(it, gui->layers[GuiLayerStatusBarRight]); | ||||
|     while(!ViewPortArray_end_p(it) && x_used < GUI_STATUS_BAR_WIDTH) { | ||||
|         // Render view_port;
 | ||||
| @ -57,7 +61,28 @@ void gui_redraw_status_bar(Gui* gui) { | ||||
|             if(!width) width = 8; | ||||
|             x_used += width; | ||||
|             x -= (width + 2); | ||||
|             canvas_frame_set(gui->canvas, x, GUI_STATUS_BAR_Y, width, GUI_STATUS_BAR_HEIGHT); | ||||
|             canvas_frame_set(gui->canvas, x - 3, GUI_STATUS_BAR_Y, width, GUI_STATUS_BAR_HEIGHT); | ||||
| 
 | ||||
|             canvas_set_color(gui->canvas, ColorWhite); | ||||
|             canvas_draw_box(gui->canvas, 1, 1, width + 3, 11); | ||||
| 
 | ||||
|             canvas_set_color(gui->canvas, ColorBlack); | ||||
| 
 | ||||
|             canvas_draw_box(gui->canvas, 1, 0, 1, 12); | ||||
|             canvas_draw_box(gui->canvas, 0, 1, 1, 11); | ||||
| 
 | ||||
|             canvas_draw_box(gui->canvas, 1, 11, width + 4, 2); | ||||
|             canvas_draw_box(gui->canvas, 1, 0, width + 4, 1); | ||||
|             canvas_draw_box(gui->canvas, width + 4, 1, 1, 11); | ||||
| 
 | ||||
|             canvas_set_color(gui->canvas, ColorWhite); | ||||
|             canvas_draw_dot(gui->canvas, width + 4, 0); | ||||
|             canvas_draw_dot(gui->canvas, width + 4, 12); | ||||
| 
 | ||||
|             canvas_set_color(gui->canvas, ColorBlack); | ||||
| 
 | ||||
|             canvas_frame_set(gui->canvas, x, GUI_STATUS_BAR_Y + 2, width, GUI_STATUS_BAR_HEIGHT); | ||||
| 
 | ||||
|             view_port_draw(view_port, gui->canvas); | ||||
|         } | ||||
|         ViewPortArray_next(it); | ||||
| @ -73,7 +98,31 @@ void gui_redraw_status_bar(Gui* gui) { | ||||
|             if(!width) width = 8; | ||||
|             x_used += width; | ||||
|             canvas_frame_set(gui->canvas, x, GUI_STATUS_BAR_Y, width, GUI_STATUS_BAR_HEIGHT); | ||||
| 
 | ||||
|             canvas_set_color(gui->canvas, ColorWhite); | ||||
|             canvas_draw_box(gui->canvas, 1, 1, width + 3, 11); | ||||
| 
 | ||||
|             canvas_set_color(gui->canvas, ColorBlack); | ||||
| 
 | ||||
|             if(x == 0) { // Frame start
 | ||||
|                 canvas_draw_box(gui->canvas, 1, 0, 1, 12); | ||||
|                 canvas_draw_box(gui->canvas, 0, 1, 1, 11); | ||||
|             } | ||||
| 
 | ||||
|             canvas_draw_box(gui->canvas, 1, 11, width + 4, 2); | ||||
|             canvas_draw_box(gui->canvas, 1, 0, width + 4, 1); | ||||
|             canvas_draw_box(gui->canvas, width + 4, 0, 1, 12); | ||||
| 
 | ||||
|             canvas_set_color(gui->canvas, ColorWhite); | ||||
|             canvas_draw_dot(gui->canvas, width + 4, 0); | ||||
|             canvas_draw_dot(gui->canvas, width + 4, 12); | ||||
| 
 | ||||
|             canvas_set_color(gui->canvas, ColorBlack); | ||||
| 
 | ||||
|             canvas_frame_set( | ||||
|                 gui->canvas, x + 3, GUI_STATUS_BAR_Y + 2, width, GUI_STATUS_BAR_HEIGHT); | ||||
|             view_port_draw(view_port, gui->canvas); | ||||
| 
 | ||||
|             x += (width + 2); | ||||
|         } | ||||
|         ViewPortArray_next(it); | ||||
|  | ||||
| @ -58,3 +58,13 @@ void icon_stop_animation(Icon* icon) { | ||||
|     icon->tick = 0; | ||||
|     icon->frame = 0; | ||||
| } | ||||
| 
 | ||||
| uint8_t icon_get_current_frame(Icon* icon) { | ||||
|     furi_assert(icon); | ||||
|     return icon->frame; | ||||
| } | ||||
| 
 | ||||
| bool icon_is_last_frame(Icon* icon) { | ||||
|     furi_assert(icon); | ||||
|     return icon->data->frame_count - icon->frame <= 1; | ||||
| } | ||||
| @ -46,6 +46,16 @@ void icon_start_animation(Icon* icon); | ||||
|  */ | ||||
| void icon_stop_animation(Icon* icon); | ||||
| 
 | ||||
| /*
 | ||||
|  * Get current frame | ||||
|  */ | ||||
| uint8_t icon_get_current_frame(Icon* icon); | ||||
| 
 | ||||
| /*
 | ||||
|  * Returns true if current frame is a last one | ||||
|  */ | ||||
| bool icon_is_last_frame(Icon* icon); | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| @ -42,11 +42,10 @@ void power_draw_usb_callback(Canvas* canvas, void* context) { | ||||
| void power_draw_battery_callback(Canvas* canvas, void* context) { | ||||
|     assert(context); | ||||
|     Power* power = context; | ||||
| 
 | ||||
|     canvas_draw_icon(canvas, 0, 0, power->battery_icon); | ||||
|     with_view_model( | ||||
|         power->info_view, (PowerInfoModel * model) { | ||||
|             canvas_draw_box(canvas, 2, 2, (float)model->charge / 100 * 14, 4); | ||||
|             canvas_draw_box(canvas, 2, 2, (float)model->charge / 100 * 20, 4); | ||||
|             return false; | ||||
|         }); | ||||
| } | ||||
| @ -130,11 +129,11 @@ Power* power_alloc() { | ||||
|     view_port_set_width(power->usb_view_port, icon_get_width(power->usb_icon)); | ||||
|     view_port_draw_callback_set(power->usb_view_port, power_draw_usb_callback, power); | ||||
| 
 | ||||
|     power->battery_icon = assets_icons_get(I_Battery_19x8); | ||||
|     power->battery_icon = assets_icons_get(I_Battery_26x8); | ||||
|     power->battery_view_port = view_port_alloc(); | ||||
| 
 | ||||
|     view_port_set_width(power->battery_view_port, icon_get_width(power->battery_icon)); | ||||
|     view_port_draw_callback_set(power->battery_view_port, power_draw_battery_callback, power); | ||||
| 
 | ||||
|     return power; | ||||
| } | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Animations/WatchingTV_128x64/frame_01.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 809 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Animations/WatchingTV_128x64/frame_02.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 833 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Animations/WatchingTV_128x64/frame_03.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 818 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Animations/WatchingTV_128x64/frame_04.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 830 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Animations/WatchingTV_128x64/frame_05.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 830 B | 
							
								
								
									
										1
									
								
								assets/icons/Animations/WatchingTV_128x64/frame_rate
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1 @@ | ||||
| 10 | ||||
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Animations/Wink_128x64/frame_01.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 674 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Animations/Wink_128x64/frame_02.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 673 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Animations/Wink_128x64/frame_03.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 667 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Animations/Wink_128x64/frame_04.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 673 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Animations/Wink_128x64/frame_05.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 674 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Animations/Wink_128x64/frame_06.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 667 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Animations/Wink_128x64/frame_07.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 673 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Animations/Wink_128x64/frame_08.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 677 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Animations/Wink_128x64/frame_09.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 674 B | 
							
								
								
									
										1
									
								
								assets/icons/Animations/Wink_128x64/frame_rate
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1 @@ | ||||
| 10 | ||||
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Dolphin/BigBurger_24x24.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 356 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Dolphin/BigGames_24x24.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 338 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Dolphin/BigProfile_24x24.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 340 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Dolphin/DolphinOkay_41x43.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 423 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Interface/DoorLeft_8x56.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 328 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Interface/DoorLocked_10x56.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 372 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Interface/DoorRight_8x56.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 317 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Interface/PassportBottom_128x17.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 364 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/Interface/PassportLeft_6x47.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 298 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/StatusBar/Background_128x11.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 410 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/StatusBar/Background_128x8.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 374 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/StatusBar/Battery_26x8.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 313 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/StatusBar/Lock_8x8.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 303 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/StatusBar/PlaceholderL_11x13.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 312 B | 
							
								
								
									
										
											BIN
										
									
								
								assets/icons/StatusBar/PlaceholderR_30x13.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 318 B | 
 its your bedtime
						its your bedtime