diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ae75fc8c..fb09b35f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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: diff --git a/applications/dolphin/dolphin.c b/applications/dolphin/dolphin.c index 31a15390..b12c4d14 100644 --- a/applications/dolphin/dolphin.c +++ b/applications/dolphin/dolphin.c @@ -1,4 +1,27 @@ #include "dolphin_i.h" +#include + +// 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(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, DolphinViewIdleUp); - } else if(event->key == InputKeyDown) { - view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewIdleDown); + 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; } diff --git a/applications/dolphin/dolphin_i.h b/applications/dolphin/dolphin_i.h index a0cd8e40..ff257921 100644 --- a/applications/dolphin/dolphin_i.h +++ b/applications/dolphin/dolphin_i.h @@ -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) diff --git a/applications/dolphin/dolphin_state.c b/applications/dolphin/dolphin_state.c index 8bff0c01..cbe5e117 100644 --- a/applications/dolphin/dolphin_state.c +++ b/applications/dolphin/dolphin_state.c @@ -1,6 +1,7 @@ #include "dolphin_state.h" #include #include +#include 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); +} \ No newline at end of file diff --git a/applications/dolphin/dolphin_state.h b/applications/dolphin/dolphin_state.h index 33433b2b..6e5a94e0 100644 --- a/applications/dolphin/dolphin_state.h +++ b/applications/dolphin/dolphin_state.h @@ -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); \ No newline at end of file diff --git a/applications/dolphin/dolphin_views.c b/applications/dolphin/dolphin_views.c index 7f9b3525..1cad7cd4 100644 --- a/applications/dolphin/dolphin_views.c +++ b/applications/dolphin/dolphin_views.c @@ -2,9 +2,11 @@ #include #include #include - #include +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) { diff --git a/applications/dolphin/dolphin_views.h b/applications/dolphin/dolphin_views.h index 6433080c..2be3b14f 100644 --- a/applications/dolphin/dolphin_views.h +++ b/applications/dolphin/dolphin_views.h @@ -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); diff --git a/applications/gui/gui.c b/applications/gui/gui.c index bc541d0a..40ae8078 100644 --- a/applications/gui/gui.c +++ b/applications/gui/gui.c @@ -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); diff --git a/applications/gui/icon.c b/applications/gui/icon.c index 37c6eba0..a0cc2505 100644 --- a/applications/gui/icon.c +++ b/applications/gui/icon.c @@ -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; +} \ No newline at end of file diff --git a/applications/gui/icon.h b/applications/gui/icon.h index 72acabd5..d9d14c94 100644 --- a/applications/gui/icon.h +++ b/applications/gui/icon.h @@ -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 diff --git a/applications/power/power.c b/applications/power/power.c index e8b58049..10d6256d 100644 --- a/applications/power/power.c +++ b/applications/power/power.c @@ -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; } diff --git a/assets/icons/Animations/WatchingTV_128x64/frame_01.png b/assets/icons/Animations/WatchingTV_128x64/frame_01.png new file mode 100644 index 00000000..221cfbba Binary files /dev/null and b/assets/icons/Animations/WatchingTV_128x64/frame_01.png differ diff --git a/assets/icons/Animations/WatchingTV_128x64/frame_02.png b/assets/icons/Animations/WatchingTV_128x64/frame_02.png new file mode 100644 index 00000000..c1ce095a Binary files /dev/null and b/assets/icons/Animations/WatchingTV_128x64/frame_02.png differ diff --git a/assets/icons/Animations/WatchingTV_128x64/frame_03.png b/assets/icons/Animations/WatchingTV_128x64/frame_03.png new file mode 100644 index 00000000..672cd1e8 Binary files /dev/null and b/assets/icons/Animations/WatchingTV_128x64/frame_03.png differ diff --git a/assets/icons/Animations/WatchingTV_128x64/frame_04.png b/assets/icons/Animations/WatchingTV_128x64/frame_04.png new file mode 100644 index 00000000..a4ea47e5 Binary files /dev/null and b/assets/icons/Animations/WatchingTV_128x64/frame_04.png differ diff --git a/assets/icons/Animations/WatchingTV_128x64/frame_05.png b/assets/icons/Animations/WatchingTV_128x64/frame_05.png new file mode 100644 index 00000000..15fa1601 Binary files /dev/null and b/assets/icons/Animations/WatchingTV_128x64/frame_05.png differ diff --git a/assets/icons/Animations/WatchingTV_128x64/frame_rate b/assets/icons/Animations/WatchingTV_128x64/frame_rate new file mode 100644 index 00000000..9a037142 --- /dev/null +++ b/assets/icons/Animations/WatchingTV_128x64/frame_rate @@ -0,0 +1 @@ +10 \ No newline at end of file diff --git a/assets/icons/Animations/Wink_128x64/frame_01.png b/assets/icons/Animations/Wink_128x64/frame_01.png new file mode 100644 index 00000000..3eff7d9a Binary files /dev/null and b/assets/icons/Animations/Wink_128x64/frame_01.png differ diff --git a/assets/icons/Animations/Wink_128x64/frame_02.png b/assets/icons/Animations/Wink_128x64/frame_02.png new file mode 100644 index 00000000..bfbfecb2 Binary files /dev/null and b/assets/icons/Animations/Wink_128x64/frame_02.png differ diff --git a/assets/icons/Animations/Wink_128x64/frame_03.png b/assets/icons/Animations/Wink_128x64/frame_03.png new file mode 100644 index 00000000..6e63bff7 Binary files /dev/null and b/assets/icons/Animations/Wink_128x64/frame_03.png differ diff --git a/assets/icons/Animations/Wink_128x64/frame_04.png b/assets/icons/Animations/Wink_128x64/frame_04.png new file mode 100644 index 00000000..0e3c4f23 Binary files /dev/null and b/assets/icons/Animations/Wink_128x64/frame_04.png differ diff --git a/assets/icons/Animations/Wink_128x64/frame_05.png b/assets/icons/Animations/Wink_128x64/frame_05.png new file mode 100644 index 00000000..42cfee7b Binary files /dev/null and b/assets/icons/Animations/Wink_128x64/frame_05.png differ diff --git a/assets/icons/Animations/Wink_128x64/frame_06.png b/assets/icons/Animations/Wink_128x64/frame_06.png new file mode 100644 index 00000000..ccf84a0a Binary files /dev/null and b/assets/icons/Animations/Wink_128x64/frame_06.png differ diff --git a/assets/icons/Animations/Wink_128x64/frame_07.png b/assets/icons/Animations/Wink_128x64/frame_07.png new file mode 100644 index 00000000..3da34c70 Binary files /dev/null and b/assets/icons/Animations/Wink_128x64/frame_07.png differ diff --git a/assets/icons/Animations/Wink_128x64/frame_08.png b/assets/icons/Animations/Wink_128x64/frame_08.png new file mode 100644 index 00000000..7c4a31c0 Binary files /dev/null and b/assets/icons/Animations/Wink_128x64/frame_08.png differ diff --git a/assets/icons/Animations/Wink_128x64/frame_09.png b/assets/icons/Animations/Wink_128x64/frame_09.png new file mode 100644 index 00000000..bf43cbd4 Binary files /dev/null and b/assets/icons/Animations/Wink_128x64/frame_09.png differ diff --git a/assets/icons/Animations/Wink_128x64/frame_rate b/assets/icons/Animations/Wink_128x64/frame_rate new file mode 100644 index 00000000..9a037142 --- /dev/null +++ b/assets/icons/Animations/Wink_128x64/frame_rate @@ -0,0 +1 @@ +10 \ No newline at end of file diff --git a/assets/icons/Dolphin/BigBurger_24x24.png b/assets/icons/Dolphin/BigBurger_24x24.png new file mode 100644 index 00000000..5533147c Binary files /dev/null and b/assets/icons/Dolphin/BigBurger_24x24.png differ diff --git a/assets/icons/Dolphin/BigGames_24x24.png b/assets/icons/Dolphin/BigGames_24x24.png new file mode 100644 index 00000000..a6e096f4 Binary files /dev/null and b/assets/icons/Dolphin/BigGames_24x24.png differ diff --git a/assets/icons/Dolphin/BigProfile_24x24.png b/assets/icons/Dolphin/BigProfile_24x24.png new file mode 100644 index 00000000..61b796e2 Binary files /dev/null and b/assets/icons/Dolphin/BigProfile_24x24.png differ diff --git a/assets/icons/Dolphin/DolphinOkay_41x43.png b/assets/icons/Dolphin/DolphinOkay_41x43.png new file mode 100644 index 00000000..52cc98b1 Binary files /dev/null and b/assets/icons/Dolphin/DolphinOkay_41x43.png differ diff --git a/assets/icons/Interface/DoorLeft_8x56.png b/assets/icons/Interface/DoorLeft_8x56.png new file mode 100644 index 00000000..f8eab132 Binary files /dev/null and b/assets/icons/Interface/DoorLeft_8x56.png differ diff --git a/assets/icons/Interface/DoorLocked_10x56.png b/assets/icons/Interface/DoorLocked_10x56.png new file mode 100644 index 00000000..d83d28a8 Binary files /dev/null and b/assets/icons/Interface/DoorLocked_10x56.png differ diff --git a/assets/icons/Interface/DoorRight_8x56.png b/assets/icons/Interface/DoorRight_8x56.png new file mode 100644 index 00000000..4828ebc6 Binary files /dev/null and b/assets/icons/Interface/DoorRight_8x56.png differ diff --git a/assets/icons/Interface/PassportBottom_128x17.png b/assets/icons/Interface/PassportBottom_128x17.png new file mode 100644 index 00000000..e4caa754 Binary files /dev/null and b/assets/icons/Interface/PassportBottom_128x17.png differ diff --git a/assets/icons/Interface/PassportLeft_6x47.png b/assets/icons/Interface/PassportLeft_6x47.png new file mode 100644 index 00000000..fc854c4a Binary files /dev/null and b/assets/icons/Interface/PassportLeft_6x47.png differ diff --git a/assets/icons/StatusBar/Background_128x11.png b/assets/icons/StatusBar/Background_128x11.png new file mode 100644 index 00000000..78ef029a Binary files /dev/null and b/assets/icons/StatusBar/Background_128x11.png differ diff --git a/assets/icons/StatusBar/Background_128x8.png b/assets/icons/StatusBar/Background_128x8.png new file mode 100644 index 00000000..c71b5a99 Binary files /dev/null and b/assets/icons/StatusBar/Background_128x8.png differ diff --git a/assets/icons/StatusBar/Battery_26x8.png b/assets/icons/StatusBar/Battery_26x8.png new file mode 100644 index 00000000..5fc1b0cd Binary files /dev/null and b/assets/icons/StatusBar/Battery_26x8.png differ diff --git a/assets/icons/StatusBar/Lock_8x8.png b/assets/icons/StatusBar/Lock_8x8.png new file mode 100644 index 00000000..01fb0eb6 Binary files /dev/null and b/assets/icons/StatusBar/Lock_8x8.png differ diff --git a/assets/icons/StatusBar/PlaceholderL_11x13.png b/assets/icons/StatusBar/PlaceholderL_11x13.png new file mode 100644 index 00000000..a6a56127 Binary files /dev/null and b/assets/icons/StatusBar/PlaceholderL_11x13.png differ diff --git a/assets/icons/StatusBar/PlaceholderR_30x13.png b/assets/icons/StatusBar/PlaceholderR_30x13.png new file mode 100644 index 00000000..bc1c9367 Binary files /dev/null and b/assets/icons/StatusBar/PlaceholderR_30x13.png differ