Просмотр исходного кода

[FL-1908] New animation update scheme (#737)

* Assets: update desktop animation frame rate and cleanup.

* Power: update ViewPort only if changed.

* Gui: tie IconAnimation with View, new update event generation scheme. Desktop: update IconAnimation usage.

Co-authored-by: DrZlo13 <who.just.the.doctor@gmail.com>
あく 4 лет назад
Родитель
Сommit
61aaed8abb

+ 1 - 2
applications/desktop/scenes/desktop_scene_locked.c

@@ -45,7 +45,6 @@ bool desktop_scene_locked_on_event(void* context, SceneManagerEvent event) {
 
 void desktop_scene_locked_on_exit(void* context) {
     Desktop* desktop = (Desktop*)context;
-    DesktopLockedView* locked_view = desktop->locked_view;
     desktop_locked_reset_counter(desktop->locked_view);
-    osTimerStop(locked_view->timer);
+    osTimerStop(desktop->locked_view->timer);
 }

+ 1 - 0
applications/desktop/scenes/desktop_scene_main.c

@@ -67,6 +67,7 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) {
             desktop_switch_to_app(desktop, &FLIPPER_ARCHIVE);
             consumed = true;
             break;
+
         case DesktopMainEventOpenFavorite:
             desktop_settings_load(&desktop->settings);
             desktop_switch_to_app(desktop, &FLIPPER_APPS[desktop->settings.favorite]);

+ 24 - 4
applications/desktop/views/desktop_locked.c

@@ -20,13 +20,12 @@ void locked_view_timer_callback(void* context) {
 }
 
 // temporary locked screen animation managment
-static void
-    desktop_scene_handler_set_scene(DesktopLockedView* locked_view, const Icon* icon_data) {
+static void desktop_locked_set_scene(DesktopLockedView* locked_view, const Icon* icon_data) {
     with_view_model(
         locked_view->view, (DesktopLockedViewModel * model) {
             if(model->animation) icon_animation_free(model->animation);
             model->animation = icon_animation_alloc(icon_data);
-            icon_animation_start(model->animation);
+            view_tie_icon_animation(locked_view->view, model->animation);
             return true;
         });
 }
@@ -148,6 +147,25 @@ bool desktop_locked_input(InputEvent* event, void* context) {
     return true;
 }
 
+void desktop_locked_enter(void* context) {
+    DesktopLockedView* locked_view = context;
+
+    with_view_model(
+        locked_view->view, (DesktopLockedViewModel * model) {
+            if(model->animation) icon_animation_start(model->animation);
+            return false;
+        });
+}
+
+void desktop_locked_exit(void* context) {
+    DesktopLockedView* locked_view = context;
+    with_view_model(
+        locked_view->view, (DesktopLockedViewModel * model) {
+            if(model->animation) icon_animation_stop(model->animation);
+            return false;
+        });
+}
+
 DesktopLockedView* desktop_locked_alloc() {
     DesktopLockedView* locked_view = furi_alloc(sizeof(DesktopLockedView));
     locked_view->view = view_alloc();
@@ -158,8 +176,10 @@ DesktopLockedView* desktop_locked_alloc() {
     view_set_context(locked_view->view, locked_view);
     view_set_draw_callback(locked_view->view, (ViewDrawCallback)desktop_locked_render);
     view_set_input_callback(locked_view->view, desktop_locked_input);
+    view_set_enter_callback(locked_view->view, desktop_locked_enter);
+    view_set_exit_callback(locked_view->view, desktop_locked_exit);
 
-    desktop_scene_handler_set_scene(locked_view, idle_scenes[random() % COUNT_OF(idle_scenes)]);
+    desktop_locked_set_scene(locked_view, idle_scenes[random() % COUNT_OF(idle_scenes)]);
     return locked_view;
 }
 

+ 28 - 9
applications/desktop/views/desktop_main.c

@@ -17,17 +17,18 @@ void desktop_main_set_callback(
 void desktop_main_reset_hint(DesktopMainView* main_view) {
     with_view_model(
         main_view->view, (DesktopMainViewModel * model) {
-            model->hint_timeout = 0;
+            model->hint_expire_at = 0;
             return true;
         });
 }
+
 // temporary main screen animation managment
-void desktop_scene_handler_set_scene(DesktopMainView* main_view, const Icon* icon_data) {
+static void desktop_main_set_scene(DesktopMainView* main_view, const Icon* icon_data) {
     with_view_model(
         main_view->view, (DesktopMainViewModel * model) {
             if(model->animation) icon_animation_free(model->animation);
             model->animation = icon_animation_alloc(icon_data);
-            icon_animation_start(model->animation);
+            view_tie_icon_animation(main_view->view, model->animation);
             return true;
         });
 }
@@ -38,7 +39,6 @@ void desktop_scene_handler_switch_scene(DesktopMainView* main_view) {
             if(icon_animation_is_last_frame(model->animation)) {
                 if(model->animation) icon_animation_free(model->animation);
                 model->animation = icon_animation_alloc(idle_scenes[model->scene_num]);
-                icon_animation_start(model->animation);
                 model->scene_num = random() % COUNT_OF(idle_scenes);
             }
             return true;
@@ -53,8 +53,7 @@ void desktop_main_render(Canvas* canvas, void* model) {
         canvas_draw_icon_animation(canvas, 0, -3, m->animation);
     }
 
-    if(m->unlocked && m->hint_timeout) {
-        m->hint_timeout = CLAMP(m->hint_timeout - 1, 2, 0);
+    if(osKernelGetTickCount() < m->hint_expire_at) {
         canvas_set_font(canvas, FontPrimary);
         elements_multiline_text_framed(canvas, 42, 30, "Unlocked");
     }
@@ -87,6 +86,25 @@ bool desktop_main_input(InputEvent* event, void* context) {
     return true;
 }
 
+void desktop_main_enter(void* context) {
+    DesktopMainView* main_view = context;
+
+    with_view_model(
+        main_view->view, (DesktopMainViewModel * model) {
+            if(model->animation) icon_animation_start(model->animation);
+            return false;
+        });
+}
+
+void desktop_main_exit(void* context) {
+    DesktopMainView* main_view = context;
+    with_view_model(
+        main_view->view, (DesktopMainViewModel * model) {
+            if(model->animation) icon_animation_stop(model->animation);
+            return false;
+        });
+}
+
 DesktopMainView* desktop_main_alloc() {
     DesktopMainView* main_view = furi_alloc(sizeof(DesktopMainView));
     main_view->view = view_alloc();
@@ -94,8 +112,10 @@ DesktopMainView* desktop_main_alloc() {
     view_set_context(main_view->view, main_view);
     view_set_draw_callback(main_view->view, (ViewDrawCallback)desktop_main_render);
     view_set_input_callback(main_view->view, desktop_main_input);
+    view_set_enter_callback(main_view->view, desktop_main_enter);
+    view_set_exit_callback(main_view->view, desktop_main_exit);
 
-    desktop_scene_handler_set_scene(main_view, idle_scenes[random() % COUNT_OF(idle_scenes)]);
+    desktop_main_set_scene(main_view, idle_scenes[random() % COUNT_OF(idle_scenes)]);
 
     return main_view;
 }
@@ -109,8 +129,7 @@ void desktop_main_free(DesktopMainView* main_view) {
 void desktop_main_unlocked(DesktopMainView* main_view) {
     with_view_model(
         main_view->view, (DesktopMainViewModel * model) {
-            model->unlocked = true;
-            model->hint_timeout = 2;
+            model->hint_expire_at = osKernelGetTickCount() + osKernelGetTickFreq();
             return true;
         });
 }

+ 2 - 2
applications/desktop/views/desktop_main.h

@@ -28,8 +28,7 @@ struct DesktopMainView {
 typedef struct {
     IconAnimation* animation;
     uint8_t scene_num;
-    uint8_t hint_timeout;
-    bool unlocked;
+    uint32_t hint_expire_at;
 } DesktopMainViewModel;
 
 void desktop_main_set_callback(
@@ -40,4 +39,5 @@ void desktop_main_set_callback(
 View* desktop_main_get_view(DesktopMainView* main_view);
 
 DesktopMainView* desktop_main_alloc();
+
 void desktop_main_free(DesktopMainView* main_view);

+ 36 - 30
applications/gui/icon_animation.c

@@ -7,26 +7,26 @@ IconAnimation* icon_animation_alloc(const Icon* icon) {
     furi_assert(icon);
     IconAnimation* instance = furi_alloc(sizeof(IconAnimation));
     instance->icon = icon;
+    instance->timer = osTimerNew(icon_animation_timer_callback, osTimerPeriodic, instance, NULL);
     return instance;
 }
 
 void icon_animation_free(IconAnimation* instance) {
     furi_assert(instance);
+    furi_check(osTimerDelete(instance->timer) == osOK);
     free(instance);
 }
 
-const uint8_t* icon_animation_get_data(IconAnimation* instance) {
+void icon_animation_set_update_callback(
+    IconAnimation* instance,
+    IconAnimationCallback callback,
+    void* context) {
     furi_assert(instance);
-    if(instance->tick) {
-        uint32_t now = osKernelGetTickCount();
-        if(now < instance->tick) {
-            instance->tick = now;
-            icon_animation_next_frame(instance);
-        } else if(now - instance->tick > osKernelGetTickFreq() / instance->icon->frame_rate) {
-            instance->tick = now;
-            icon_animation_next_frame(instance);
-        }
-    }
+    instance->callback = callback;
+    instance->callback_context = context;
+}
+
+const uint8_t* icon_animation_get_data(IconAnimation* instance) {
     return instance->icon->frames[instance->frame];
 }
 
@@ -35,6 +35,19 @@ void icon_animation_next_frame(IconAnimation* instance) {
     instance->frame = (instance->frame + 1) % instance->icon->frame_count;
 }
 
+void icon_animation_timer_callback(void* context) {
+    furi_assert(context);
+
+    IconAnimation* instance = context;
+
+    if(!instance->animating) return;
+
+    icon_animation_next_frame(instance);
+    if(instance->callback) {
+        instance->callback(instance, instance->callback_context);
+    }
+}
+
 uint8_t icon_animation_get_width(IconAnimation* instance) {
     furi_assert(instance);
     return instance->icon->width;
@@ -45,33 +58,26 @@ uint8_t icon_animation_get_height(IconAnimation* instance) {
     return instance->icon->height;
 }
 
-bool icon_animation_is_animated(IconAnimation* instance) {
-    furi_assert(instance);
-    return instance->icon->frame_count > 1;
-}
-
-bool icon_animation_is_animating(IconAnimation* instance) {
-    furi_assert(instance);
-    return instance->tick > 0;
-}
-
 void icon_animation_start(IconAnimation* instance) {
     furi_assert(instance);
-    instance->tick = osKernelGetTickCount();
+    if(!instance->animating) {
+        instance->animating = true;
+        furi_check(
+            osTimerStart(instance->timer, (osKernelGetTickFreq() / instance->icon->frame_rate)) ==
+            osOK);
+    }
 }
 
 void icon_animation_stop(IconAnimation* instance) {
     furi_assert(instance);
-    instance->tick = 0;
-    instance->frame = 0;
-}
-
-uint8_t icon_animation_get_current_frame(IconAnimation* instance) {
-    furi_assert(instance);
-    return instance->frame;
+    if(instance->animating) {
+        instance->animating = false;
+        furi_check(osTimerStop(instance->timer) == osOK);
+        instance->frame = 0;
+    }
 }
 
 bool icon_animation_is_last_frame(IconAnimation* instance) {
     furi_assert(instance);
     return instance->icon->frame_count - instance->frame <= 1;
-}
+}

+ 16 - 29
applications/gui/icon_animation.h

@@ -11,54 +11,41 @@ extern "C" {
 
 typedef struct IconAnimation IconAnimation;
 
-/*
- * Allocate icon animation instance with const icon data.
+typedef void (*IconAnimationCallback)(IconAnimation* instance, void* context);
+
+/** Allocate icon animation instance with const icon data.
  * always returns Icon or stops system if not enough memory
  */
 IconAnimation* icon_animation_alloc(const Icon* icon);
 
-/*
- * Release icon animation instance
+/** Release icon animation instance
  */
 void icon_animation_free(IconAnimation* instance);
 
-/*
- * Get icon animation width
+/** Get icon animation width
  */
-uint8_t icon_animation_get_width(IconAnimation* instance);
-
-/*
- * Get icon animation height
- */
-uint8_t icon_animation_get_height(IconAnimation* instance);
+void icon_animation_set_update_callback(
+    IconAnimation* instance,
+    IconAnimationCallback callback,
+    void* context);
 
-/*
- * Check if icon is animated
+/** Get icon animation width
  */
-bool icon_animation_is_animated(IconAnimation* instance);
+uint8_t icon_animation_get_width(IconAnimation* instance);
 
-/*
- * Check if icon animation is active
+/** Get icon animation height
  */
-bool icon_animation_is_animating(IconAnimation* instance);
+uint8_t icon_animation_get_height(IconAnimation* instance);
 
-/*
- * Start icon animation
+/** Start icon animation
  */
 void icon_animation_start(IconAnimation* instance);
 
-/*
- * Stop icon animation
+/** Stop icon animation
  */
 void icon_animation_stop(IconAnimation* instance);
 
-/*
- * Get current frame
- */
-uint8_t icon_animation_get_current_frame(IconAnimation* instance);
-
-/*
- * Returns true if current frame is a last one
+/** Returns true if current frame is a last one
  */
 bool icon_animation_is_last_frame(IconAnimation* instance);
 

+ 10 - 8
applications/gui/icon_animation_i.h

@@ -2,20 +2,22 @@
 
 #include "icon_animation.h"
 
-#include <stdint.h>
+#include <furi.h>
 
 struct IconAnimation {
     const Icon* icon;
     uint8_t frame;
-    uint32_t tick;
+    bool animating;
+    osTimerId_t timer;
+    IconAnimationCallback callback;
+    void* callback_context;
 };
 
-/*
- * Get pointer to current frame data
- */
+/** Get pointer to current frame data */
 const uint8_t* icon_animation_get_data(IconAnimation* instance);
 
-/*
- * Advance to next frame
- */
+/** Advance to next frame */
 void icon_animation_next_frame(IconAnimation* instance);
+
+/** IconAnimation timer callback */
+void icon_animation_timer_callback(void* context);

+ 49 - 5
applications/gui/modules/menu.c

@@ -20,7 +20,7 @@ ARRAY_DEF(MenuItemArray, MenuItem, M_POD_OPLIST);
 
 typedef struct {
     MenuItemArray_t items;
-    uint8_t position;
+    size_t position;
 } MenuModel;
 
 static void menu_process_up(Menu* menu);
@@ -32,7 +32,7 @@ static void menu_draw_callback(Canvas* canvas, void* _model) {
 
     canvas_clear(canvas);
 
-    uint8_t position = model->position;
+    size_t position = model->position;
     size_t items_count = MenuItemArray_size(model->items);
     if(items_count) {
         MenuItem* item;
@@ -43,7 +43,6 @@ static void menu_draw_callback(Canvas* canvas, void* _model) {
         item = MenuItemArray_get(model->items, shift_position);
         if(item->icon) {
             canvas_draw_icon_animation(canvas, 4, 3, item->icon);
-            icon_animation_stop(item->icon);
         }
         canvas_draw_str(canvas, 22, 14, item->label);
         // Second line main
@@ -52,7 +51,6 @@ static void menu_draw_callback(Canvas* canvas, void* _model) {
         item = MenuItemArray_get(model->items, shift_position);
         if(item->icon) {
             canvas_draw_icon_animation(canvas, 4, 25, item->icon);
-            icon_animation_start(item->icon);
         }
         canvas_draw_str(canvas, 22, 36, item->label);
         // Third line
@@ -61,7 +59,6 @@ static void menu_draw_callback(Canvas* canvas, void* _model) {
         item = MenuItemArray_get(model->items, shift_position);
         if(item->icon) {
             canvas_draw_icon_animation(canvas, 4, 47, item->icon);
-            icon_animation_stop(item->icon);
         }
         canvas_draw_str(canvas, 22, 58, item->label);
         // Frame and scrollbar
@@ -93,6 +90,30 @@ static bool menu_input_callback(InputEvent* event, void* context) {
     return consumed;
 }
 
+static void menu_enter(void* context) {
+    Menu* menu = context;
+    with_view_model(
+        menu->view, (MenuModel * model) {
+            MenuItem* item = MenuItemArray_get(model->items, model->position);
+            if(item && item->icon) {
+                icon_animation_start(item->icon);
+            }
+            return false;
+        });
+}
+
+static void menu_exit(void* context) {
+    Menu* menu = context;
+    with_view_model(
+        menu->view, (MenuModel * model) {
+            MenuItem* item = MenuItemArray_get(model->items, model->position);
+            if(item && item->icon) {
+                icon_animation_stop(item->icon);
+            }
+            return false;
+        });
+}
+
 Menu* menu_alloc() {
     Menu* menu = furi_alloc(sizeof(Menu));
     menu->view = view_alloc(menu->view);
@@ -100,6 +121,8 @@ Menu* menu_alloc() {
     view_allocate_model(menu->view, ViewModelTypeLocking, sizeof(MenuModel));
     view_set_draw_callback(menu->view, menu_draw_callback);
     view_set_input_callback(menu->view, menu_input_callback);
+    view_set_enter_callback(menu->view, menu_enter);
+    view_set_exit_callback(menu->view, menu_exit);
 
     with_view_model(
         menu->view, (MenuModel * model) {
@@ -143,6 +166,7 @@ void menu_add_item(
             item = MenuItemArray_push_new(model->items);
             item->label = label;
             item->icon = icon;
+            view_tie_icon_animation(menu->view, item->icon);
             item->index = index;
             item->callback = callback;
             item->callback_context = context;
@@ -175,11 +199,21 @@ void menu_set_selected_item(Menu* menu, uint32_t index) {
 static void menu_process_up(Menu* menu) {
     with_view_model(
         menu->view, (MenuModel * model) {
+            MenuItem* item = MenuItemArray_get(model->items, model->position);
+            if(item && item->icon) {
+                icon_animation_stop(item->icon);
+            }
+
             if(model->position > 0) {
                 model->position--;
             } else {
                 model->position = MenuItemArray_size(model->items) - 1;
             }
+
+            item = MenuItemArray_get(model->items, model->position);
+            if(item && item->icon) {
+                icon_animation_start(item->icon);
+            }
             return true;
         });
 }
@@ -187,11 +221,21 @@ static void menu_process_up(Menu* menu) {
 static void menu_process_down(Menu* menu) {
     with_view_model(
         menu->view, (MenuModel * model) {
+            MenuItem* item = MenuItemArray_get(model->items, model->position);
+            if(item && item->icon) {
+                icon_animation_stop(item->icon);
+            }
+
             if(model->position < MenuItemArray_size(model->items) - 1) {
                 model->position++;
             } else {
                 model->position = 0;
             }
+
+            item = MenuItemArray_get(model->items, model->position);
+            if(item && item->icon) {
+                icon_animation_start(item->icon);
+            }
             return true;
         });
 }

+ 13 - 0
applications/gui/view.c

@@ -12,6 +12,11 @@ void view_free(View* view) {
     free(view);
 }
 
+void view_tie_icon_animation(View* view, IconAnimation* icon_animation) {
+    furi_assert(view);
+    icon_animation_set_update_callback(icon_animation, view_icon_animation_callback, view);
+}
+
 void view_set_draw_callback(View* view, ViewDrawCallback callback) {
     furi_assert(view);
     furi_assert(view->draw_callback == NULL);
@@ -120,6 +125,14 @@ void view_commit_model(View* view, bool update) {
     }
 }
 
+void view_icon_animation_callback(IconAnimation* instance, void* context) {
+    furi_assert(context);
+    View* view = context;
+    if(view->update_callback) {
+        view->update_callback(view, view->update_callback_context);
+    }
+}
+
 void view_unlock_model(View* view) {
     furi_assert(view);
     if(view->model_type == ViewModelTypeLocking) {

+ 52 - 43
applications/gui/view.h

@@ -1,6 +1,8 @@
 #pragma once
 
 #include <input/input.h>
+
+#include "icon_animation.h"
 #include "canvas.h"
 
 #include <stddef.h>
@@ -10,9 +12,10 @@
 extern "C" {
 #endif
 
-/* Hides drawing view_port */
+/** Hides drawing view_port */
 #define VIEW_NONE 0xFFFFFFFF
-/* Ignore navigation event */
+
+/** Ignore navigation event */
 #define VIEW_IGNORE 0xFFFFFFFE
 
 typedef enum {
@@ -20,17 +23,17 @@ typedef enum {
     ViewOrientationVertical,
 } ViewOrientation;
 
-/* View, anonymous type */
+/** View, anonymous type */
 typedef struct View View;
 
-/* View Draw callback
+/** View Draw callback
  * @param canvas, pointer to canvas
  * @param view_model, pointer to context
  * @warning called from GUI thread
  */
 typedef void (*ViewDrawCallback)(Canvas* canvas, void* model);
 
-/* View Input callback
+/** View Input callback
  * @param event, pointer to input event data
  * @param context, pointer to context
  * @return true if event handled, false if event ignored
@@ -38,27 +41,27 @@ typedef void (*ViewDrawCallback)(Canvas* canvas, void* model);
  */
 typedef bool (*ViewInputCallback)(InputEvent* event, void* context);
 
-/* View Custom callback
+/** View Custom callback
  * @param event, number of custom event
  * @param context, pointer to context
  * @return true if event handled, false if event ignored
  */
 typedef bool (*ViewCustomCallback)(uint32_t event, void* context);
 
-/* View navigation callback
+/** View navigation callback
  * @param context, pointer to context
  * @return next view id
  * @warning called from GUI thread
  */
 typedef uint32_t (*ViewNavigationCallback)(void* context);
 
-/* View callback
+/** View callback
  * @param context, pointer to context
  * @warning called from GUI thread
  */
 typedef void (*ViewCallback)(void* context);
 
-/* View Update Callback
+/** View Update Callback
  * Called upon model change, need to be propagated to GUI throw ViewPort update
  * @param view, pointer to view
  * @param context, pointer to context
@@ -66,7 +69,7 @@ typedef void (*ViewCallback)(void* context);
  */
 typedef void (*ViewUpdateCallback)(View* view, void* context);
 
-/* View model types */
+/** View model types */
 typedef enum {
     /* Model is not allocated */
     ViewModelTypeNone,
@@ -80,97 +83,103 @@ typedef enum {
     ViewModelTypeLocking,
 } ViewModelType;
 
-/* Allocate and init View
- * @return pointer to View
+/** Allocate and init View
+ * @return View instance
  */
 View* view_alloc();
 
-/* Free View
- * @param pointer to View
+/** Free View
+ * @param View instance
  */
 void view_free(View* view);
 
-/* Set View Draw callback
- * @param view, pointer to View
+/** Tie IconAnimation with View
+ * @param view, View instance
+ * @param icon_animation, IconAnimation instance
+ */
+void view_tie_icon_animation(View* view, IconAnimation* icon_animation);
+
+/** Set View Draw callback
+ * @param view, View instance
  * @param callback, draw callback
  */
 void view_set_draw_callback(View* view, ViewDrawCallback callback);
 
-/* Set View Input callback
- * @param view, pointer to View
+/** Set View Input callback
+ * @param view, View instance
  * @param callback, input callback
  */
 void view_set_input_callback(View* view, ViewInputCallback callback);
 
-/* Set View Custom callback
- * @param view, pointer to View
+/** Set View Custom callback
+ * @param view, View instance
  * @param callback, input callback
  */
 void view_set_custom_callback(View* view, ViewCustomCallback callback);
 
-/* Set Navigation Previous callback
- * @param view, pointer to View
+/** Set Navigation Previous callback
+ * @param view, View instance
  * @param callback, input callback
  */
 void view_set_previous_callback(View* view, ViewNavigationCallback callback);
 
-/* Set Enter callback
- * @param view, pointer to View
+/** Set Enter callback
+ * @param view, View instance
  * @param callback, callback
  */
 void view_set_enter_callback(View* view, ViewCallback callback);
 
-/* Set Exit callback
- * @param view, pointer to View
+/** Set Exit callback
+ * @param view, View instance
  * @param callback, callback
  */
 void view_set_exit_callback(View* view, ViewCallback callback);
 
-/* Set Update callback
- * @param view, pointer to View
+/** Set Update callback
+ * @param view, View instance
  * @param callback, callback
  */
 void view_set_update_callback(View* view, ViewUpdateCallback callback);
 
-/* Set View Draw callback
- * @param view, pointer to View
+/** Set View Draw callback
+ * @param view, View instance
  * @param context, context for callbacks
  */
 void view_set_update_callback_context(View* view, void* context);
 
-/* Set View Draw callback
- * @param view, pointer to View
+/** Set View Draw callback
+ * @param view, View instance
  * @param context, context for callbacks
  */
 void view_set_context(View* view, void* context);
 
-/* Set View Orientation
- * @param view, pointer to View
+/** Set View Orientation
+ * @param view, View instance
  * @param orientation, either vertical or horizontal
  */
 void view_set_orientation(View* view, ViewOrientation orientation);
 
-/* Allocate view model.
- * @param view, pointer to View
+/** Allocate view model.
+ * @param view, View instance
  * @param type, View Model Type
  * @param size, size
  */
 void view_allocate_model(View* view, ViewModelType type, size_t size);
 
-/* Free view model data memory.
- * @param view, pointer to View
+/** Free view model data memory.
+ * @param view, View instance
  */
 void view_free_model(View* view);
 
-/* Get view model data
- * @param view, pointer to View
+/** Get view model data
+ * @param view, View instance
  * @return pointer to model data
  * @warning Don't forget to commit model changes
  */
 void* view_get_model(View* view);
 
-/* Commit view model
- * @param view, pointer to View
+/** Commit view model
+ * @param view, View instance
  * @param update, true if you want to emit view update, false otherwise
  */
 void view_commit_model(View* view, bool update);
@@ -187,7 +196,7 @@ void view_commit_model(View* view, bool update);
         view_commit_model(view, update);                    \
     }
 #else
-/* 
+/** 
  * With clause for view model
  * @param view, View instance pointer
  * @param function_body a (){} lambda declaration, executed within you parent function context

+ 3 - 0
applications/gui/view_i.h

@@ -26,6 +26,9 @@ struct View {
     void* context;
 };
 
+/* IconAnimation tie callback */
+void view_icon_animation_callback(IconAnimation* instance, void* context);
+
 /* Unlock model */
 void view_unlock_model(View* view);
 

+ 10 - 20
applications/gui/view_port.h

@@ -14,48 +14,41 @@ typedef enum {
     ViewPortOrientationVertical,
 } ViewPortOrientation;
 
-/*
- * ViewPort Draw callback
+/** ViewPort Draw callback
  * @warning called from GUI thread
  */
 typedef void (*ViewPortDrawCallback)(Canvas* canvas, void* context);
 
-/*
- * ViewPort Input callback
+/** ViewPort Input callback
  * @warning called from GUI thread
  */
 typedef void (*ViewPortInputCallback)(InputEvent* event, void* context);
 
-/*
- * ViewPort allocator
+/** ViewPort allocator
  * always returns view_port or stops system if not enough memory.
  */
 ViewPort* view_port_alloc();
 
-/*
- * ViewPort deallocator
+/** ViewPort deallocator
  * Ensure that view_port was unregistered in GUI system before use.
  */
 void view_port_free(ViewPort* view_port);
 
-/*
- * Set view_port width.
+/** Set view_port width.
  * Will be used to limit canvas drawing area and autolayout feature.
  * @param width - wanted width, 0 - auto.
  */
 void view_port_set_width(ViewPort* view_port, uint8_t width);
 uint8_t view_port_get_width(ViewPort* view_port);
 
-/*
- * Set view_port height.
+/** Set view_port height.
  * Will be used to limit canvas drawing area and autolayout feature.
  * @param height - wanted height, 0 - auto.
  */
 void view_port_set_height(ViewPort* view_port, uint8_t height);
 uint8_t view_port_get_height(ViewPort* view_port);
 
-/*
- * Enable or disable view_port rendering.
+/** Enable or disable view_port rendering.
  * @param view_port - ViewPort instance
  * @param enabled
  * @warning automatically dispatches update event
@@ -63,8 +56,7 @@ uint8_t view_port_get_height(ViewPort* view_port);
 void view_port_enabled_set(ViewPort* view_port, bool enabled);
 bool view_port_is_enabled(ViewPort* view_port);
 
-/*
- * ViewPort event callbacks
+/** ViewPort event callbacks
  * @param callback - appropriate callback function
  * @param context - context to pass to callback
  */
@@ -74,14 +66,12 @@ void view_port_input_callback_set(
     ViewPortInputCallback callback,
     void* context);
 
-/*
- * Emit update signal to GUI system.
+/** Emit update signal to GUI system.
  * Rendering will happen later after GUI system process signal.
  */
 void view_port_update(ViewPort* view_port);
 
-/*
- * Set ViewPort orientation.
+/** Set ViewPort orientation.
  * @param   orientation, display orientation, horizontal or vertical.
  */
 void view_port_set_orientation(ViewPort* view_port, ViewPortOrientation orientation);

+ 21 - 17
applications/power/power_service/power.c

@@ -97,23 +97,27 @@ static void power_check_charging_state(Power* power) {
     }
 }
 
-static void power_update_info(Power* power) {
-    osMutexAcquire(power->info_mtx, osWaitForever);
-    PowerInfo* info = &power->info;
-
-    info->charge = furi_hal_power_get_pct();
-    info->health = furi_hal_power_get_bat_health_pct();
-    info->capacity_remaining = furi_hal_power_get_battery_remaining_capacity();
-    info->capacity_full = furi_hal_power_get_battery_full_capacity();
-    info->current_charger = furi_hal_power_get_battery_current(FuriHalPowerICCharger);
-    info->current_gauge = furi_hal_power_get_battery_current(FuriHalPowerICFuelGauge);
-    info->voltage_charger = furi_hal_power_get_battery_voltage(FuriHalPowerICCharger);
-    info->voltage_gauge = furi_hal_power_get_battery_voltage(FuriHalPowerICFuelGauge);
-    info->voltage_vbus = furi_hal_power_get_usb_voltage();
-    info->temperature_charger = furi_hal_power_get_battery_temperature(FuriHalPowerICCharger);
-    info->temperature_gauge = furi_hal_power_get_battery_temperature(FuriHalPowerICFuelGauge);
+static bool power_update_info(Power* power) {
+    PowerInfo info;
+
+    info.charge = furi_hal_power_get_pct();
+    info.health = furi_hal_power_get_bat_health_pct();
+    info.capacity_remaining = furi_hal_power_get_battery_remaining_capacity();
+    info.capacity_full = furi_hal_power_get_battery_full_capacity();
+    info.current_charger = furi_hal_power_get_battery_current(FuriHalPowerICCharger);
+    info.current_gauge = furi_hal_power_get_battery_current(FuriHalPowerICFuelGauge);
+    info.voltage_charger = furi_hal_power_get_battery_voltage(FuriHalPowerICCharger);
+    info.voltage_gauge = furi_hal_power_get_battery_voltage(FuriHalPowerICFuelGauge);
+    info.voltage_vbus = furi_hal_power_get_usb_voltage();
+    info.temperature_charger = furi_hal_power_get_battery_temperature(FuriHalPowerICCharger);
+    info.temperature_gauge = furi_hal_power_get_battery_temperature(FuriHalPowerICFuelGauge);
 
+    osMutexAcquire(power->info_mtx, osWaitForever);
+    bool need_refresh = power->info.charge != info.charge;
+    power->info = info;
     osMutexRelease(power->info_mtx);
+
+    return need_refresh;
 }
 
 static void power_check_low_battery(Power* power) {
@@ -156,7 +160,7 @@ int32_t power_srv(void* p) {
 
     while(1) {
         // Update data from gauge and charger
-        power_update_info(power);
+        bool need_refresh = power_update_info(power);
 
         // Check low battery level
         power_check_low_battery(power);
@@ -168,7 +172,7 @@ int32_t power_srv(void* p) {
         power_check_battery_level_change(power);
 
         // Update battery view port
-        view_port_update(power->battery_view_port);
+        if(need_refresh) view_port_update(power->battery_view_port);
 
         osDelay(1000);
     }

Разница между файлами не показана из-за своего большого размера
+ 0 - 0
assets/compiled/assets_icons.c


BIN
assets/icons/Animations/WatchingTV_128x64/frame_05.png


+ 1 - 1
assets/icons/Animations/WatchingTV_128x64/frame_rate

@@ -1 +1 @@
-10
+1

+ 1 - 1
assets/icons/Animations/Wink_128x64/frame_rate

@@ -1 +1 @@
-10
+1

Некоторые файлы не были показаны из-за большого количества измененных файлов