Assets, Icons, UI toolkit. Part 1. (#202)
* Assets: import from gdrive * Assets: fully working build pipeline and registry * NFC: menu icon * Gui: layers. Irukagotchi: base app to handle input on idle screen. Makefile: reboot after flash in dfu mode. * ValueMutex: with lambda * Assets: proper animation frames sorting * ValueMutex: proper furi_open usage * Assets,GUI: split icon into icon data and icon state. * Format source code * Docker: add python3 and imagemagic * Irukagotchi: cleanup * GUI: event lock moved to gui. * Rfid: proper gui layer * GUI: elements. Menu: frame and scroll * GUI, Menu: format code. * Menu: dual font main menu * Menu: format sources * GUI: 0 total scrollbar * CI: enable lfs * Menu: pixel perfect main menu Co-authored-by: Aleksandr Kutuzov <aku@plooks.com> Co-authored-by: aanper <mail@s3f.ru>
This commit is contained in:
		
							parent
							
								
									e699c4a31e
								
							
						
					
					
						commit
						665f6d7d9c
					
				
							
								
								
									
										1
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							| @ -16,6 +16,7 @@ jobs: | |||||||
|         uses: actions/checkout@v2 |         uses: actions/checkout@v2 | ||||||
|         with: |         with: | ||||||
|             submodules: true |             submodules: true | ||||||
|  |             lfs: true | ||||||
| 
 | 
 | ||||||
|       - uses: satackey/action-docker-layer-caching@v0.0.8 |       - uses: satackey/action-docker-layer-caching@v0.0.8 | ||||||
|         continue-on-error: true |         continue-on-error: true | ||||||
|  | |||||||
| @ -74,7 +74,7 @@ void app_loader(void* p) { | |||||||
|         printf("gui is not available\n"); |         printf("gui is not available\n"); | ||||||
|         furiac_exit(NULL); |         furiac_exit(NULL); | ||||||
|     } |     } | ||||||
|     gui->add_widget(gui, state.widget, WidgetLayerFullscreen); |     gui->add_widget(gui, state.widget, GuiLayerFullscreen); | ||||||
| 
 | 
 | ||||||
|     { |     { | ||||||
|         Menu* menu = acquire_mutex_block(menu_mutex); |         Menu* menu = acquire_mutex_block(menu_mutex); | ||||||
|  | |||||||
| @ -30,6 +30,7 @@ void app_loader(void* p); | |||||||
| void cc1101_workaround(void* p); | void cc1101_workaround(void* p); | ||||||
| void lf_rfid_workaround(void* p); | void lf_rfid_workaround(void* p); | ||||||
| void nfc_task(void* p); | void nfc_task(void* p); | ||||||
|  | void irukagotchi_task(void* p); | ||||||
| 
 | 
 | ||||||
| const FlipperStartupApp FLIPPER_STARTUP[] = { | const FlipperStartupApp FLIPPER_STARTUP[] = { | ||||||
| #ifdef APP_DISPLAY | #ifdef APP_DISPLAY | ||||||
| @ -54,6 +55,10 @@ const FlipperStartupApp FLIPPER_STARTUP[] = { | |||||||
|     {.app = app_loader, .name = "app_loader", .libs = {1, FURI_LIB{"menu_task"}}}, |     {.app = app_loader, .name = "app_loader", .libs = {1, FURI_LIB{"menu_task"}}}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | #ifdef APP_IRUKAGOTCHI | ||||||
|  |     {.app = irukagotchi_task, .name = "irukagotchi_task", .libs = {1, FURI_LIB{"menu_task"}}}, | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| #ifdef APP_CC1101 | #ifdef APP_CC1101 | ||||||
|     {.app = cc1101_workaround, .name = "cc1101 workaround", .libs = {1, FURI_LIB{"gui_task"}}}, |     {.app = cc1101_workaround, .name = "cc1101 workaround", .libs = {1, FURI_LIB{"gui_task"}}}, | ||||||
| #endif | #endif | ||||||
|  | |||||||
| @ -11,6 +11,7 @@ ifeq ($(APP_RELEASE), 1) | |||||||
| APP_MENU = 1 | APP_MENU = 1 | ||||||
| APP_NFC  = 1 | APP_NFC  = 1 | ||||||
| BUILD_IRDA  = 1 | BUILD_IRDA  = 1 | ||||||
|  | APP_IRUKAGOTCHI = 1 | ||||||
| BUILD_EXAMPLE_BLINK = 1 | BUILD_EXAMPLE_BLINK = 1 | ||||||
| BUILD_EXAMPLE_UART_WRITE = 1 | BUILD_EXAMPLE_UART_WRITE = 1 | ||||||
| BUILD_EXAMPLE_INPUT_DUMP = 1 | BUILD_EXAMPLE_INPUT_DUMP = 1 | ||||||
| @ -26,6 +27,13 @@ CFLAGS		+= -DAPP_NFC | |||||||
| C_SOURCES	+= $(wildcard $(APP_DIR)/nfc/*.c) | C_SOURCES	+= $(wildcard $(APP_DIR)/nfc/*.c) | ||||||
| endif | endif | ||||||
| 
 | 
 | ||||||
|  | APP_IRUKAGOTCHI ?= 0 | ||||||
|  | ifeq ($(APP_IRUKAGOTCHI), 1) | ||||||
|  | APP_MENU	= 1 | ||||||
|  | CFLAGS		+= -DAPP_IRUKAGOTCHI | ||||||
|  | C_SOURCES	+= $(wildcard $(APP_DIR)/irukagotchi/*.c) | ||||||
|  | endif | ||||||
|  | 
 | ||||||
| APP_MENU ?= 0 | APP_MENU ?= 0 | ||||||
| ifeq ($(APP_MENU), 1) | ifeq ($(APP_MENU), 1) | ||||||
| CFLAGS += -DAPP_MENU | CFLAGS += -DAPP_MENU | ||||||
|  | |||||||
| @ -229,7 +229,7 @@ extern "C" void cc1101_workaround(void* p) { | |||||||
|         printf("[cc1101] gui is not available\n"); |         printf("[cc1101] gui is not available\n"); | ||||||
|         furiac_exit(NULL); |         furiac_exit(NULL); | ||||||
|     } |     } | ||||||
|     gui->add_widget(gui, widget, WidgetLayerFullscreen); |     gui->add_widget(gui, widget, GuiLayerFullscreen); | ||||||
| 
 | 
 | ||||||
|     printf("[cc1101] creating device\n"); |     printf("[cc1101] creating device\n"); | ||||||
|     GpioPin cs_pin = {CC1101_CS_GPIO_Port, CC1101_CS_Pin}; |     GpioPin cs_pin = {CC1101_CS_GPIO_Port, CC1101_CS_Pin}; | ||||||
|  | |||||||
| @ -1,5 +1,7 @@ | |||||||
| #include "canvas.h" | #include "canvas.h" | ||||||
| #include "canvas_i.h" | #include "canvas_i.h" | ||||||
|  | #include "icon.h" | ||||||
|  | #include "icon_i.h" | ||||||
| 
 | 
 | ||||||
| #include <assert.h> | #include <assert.h> | ||||||
| #include <flipper.h> | #include <flipper.h> | ||||||
| @ -20,6 +22,11 @@ void canvas_clear(CanvasApi* api); | |||||||
| void canvas_color_set(CanvasApi* api, uint8_t color); | void canvas_color_set(CanvasApi* api, uint8_t color); | ||||||
| void canvas_font_set(CanvasApi* api, Font font); | void canvas_font_set(CanvasApi* api, Font font); | ||||||
| void canvas_str_draw(CanvasApi* api, uint8_t x, uint8_t y, const char* str); | void canvas_str_draw(CanvasApi* api, uint8_t x, uint8_t y, const char* str); | ||||||
|  | void canvas_icon_draw(CanvasApi* api, uint8_t x, uint8_t y, Icon* icon); | ||||||
|  | void canvas_dot_draw(CanvasApi* api, uint8_t x, uint8_t y); | ||||||
|  | void canvas_box_draw(CanvasApi* api, uint8_t x, uint8_t y, uint8_t width, uint8_t height); | ||||||
|  | void canvas_draw_frame(CanvasApi* api, uint8_t x, uint8_t y, uint8_t width, uint8_t height); | ||||||
|  | void canvas_draw_line(CanvasApi* api, uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2); | ||||||
| 
 | 
 | ||||||
| uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr); | uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr); | ||||||
| uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr); | uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr); | ||||||
| @ -43,6 +50,11 @@ CanvasApi* canvas_api_init() { | |||||||
|     canvas->api.set_color = canvas_color_set; |     canvas->api.set_color = canvas_color_set; | ||||||
|     canvas->api.set_font = canvas_font_set; |     canvas->api.set_font = canvas_font_set; | ||||||
|     canvas->api.draw_str = canvas_str_draw; |     canvas->api.draw_str = canvas_str_draw; | ||||||
|  |     canvas->api.draw_icon = canvas_icon_draw; | ||||||
|  |     canvas->api.draw_dot = canvas_dot_draw; | ||||||
|  |     canvas->api.draw_box = canvas_box_draw; | ||||||
|  |     canvas->api.draw_frame = canvas_draw_frame; | ||||||
|  |     canvas->api.draw_line = canvas_draw_line; | ||||||
| 
 | 
 | ||||||
|     return (CanvasApi*)canvas; |     return (CanvasApi*)canvas; | ||||||
| } | } | ||||||
| @ -112,8 +124,43 @@ void canvas_font_set(CanvasApi* api, Font font) { | |||||||
| 
 | 
 | ||||||
| void canvas_str_draw(CanvasApi* api, uint8_t x, uint8_t y, const char* str) { | void canvas_str_draw(CanvasApi* api, uint8_t x, uint8_t y, const char* str) { | ||||||
|     assert(api); |     assert(api); | ||||||
|  |     if(!str) return; | ||||||
|     Canvas* canvas = (Canvas*)api; |     Canvas* canvas = (Canvas*)api; | ||||||
|     x += canvas->offset_x; |     x += canvas->offset_x; | ||||||
|     y += canvas->offset_y; |     y += canvas->offset_y; | ||||||
|     u8g2_DrawStr(&canvas->fb, x, y, str); |     u8g2_DrawStr(&canvas->fb, x, y, str); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | void canvas_icon_draw(CanvasApi* api, uint8_t x, uint8_t y, Icon* icon) { | ||||||
|  |     assert(api); | ||||||
|  |     if(!icon) return; | ||||||
|  |     Canvas* canvas = (Canvas*)api; | ||||||
|  |     x += canvas->offset_x; | ||||||
|  |     y += canvas->offset_y; | ||||||
|  |     u8g2_DrawXBM( | ||||||
|  |         &canvas->fb, x, y, icon_get_width(icon), icon_get_height(icon), icon_get_data(icon)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void canvas_dot_draw(CanvasApi* api, uint8_t x, uint8_t y) { | ||||||
|  |     assert(api); | ||||||
|  |     Canvas* canvas = (Canvas*)api; | ||||||
|  |     u8g2_DrawPixel(&canvas->fb, x, y); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void canvas_box_draw(CanvasApi* api, uint8_t x, uint8_t y, uint8_t width, uint8_t height) { | ||||||
|  |     assert(api); | ||||||
|  |     Canvas* canvas = (Canvas*)api; | ||||||
|  |     u8g2_DrawBox(&canvas->fb, x, y, width, height); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void canvas_draw_frame(CanvasApi* api, uint8_t x, uint8_t y, uint8_t width, uint8_t height) { | ||||||
|  |     assert(api); | ||||||
|  |     Canvas* canvas = (Canvas*)api; | ||||||
|  |     u8g2_DrawFrame(&canvas->fb, x, y, width, height); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void canvas_draw_line(CanvasApi* api, uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) { | ||||||
|  |     assert(api); | ||||||
|  |     Canvas* canvas = (Canvas*)api; | ||||||
|  |     u8g2_DrawLine(&canvas->fb, x1, y1, x2, y2); | ||||||
|  | } | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ | |||||||
| 
 | 
 | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
| #include <u8g2.h> | #include <u8g2.h> | ||||||
|  | #include <gui/icon.h> | ||||||
| 
 | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
|     ColorWhite = 0x00, |     ColorWhite = 0x00, | ||||||
| @ -24,4 +25,9 @@ struct CanvasApi { | |||||||
|     void (*set_font)(CanvasApi* canvas, Font font); |     void (*set_font)(CanvasApi* canvas, Font font); | ||||||
| 
 | 
 | ||||||
|     void (*draw_str)(CanvasApi* canvas, uint8_t x, uint8_t y, const char* str); |     void (*draw_str)(CanvasApi* canvas, uint8_t x, uint8_t y, const char* str); | ||||||
|  |     void (*draw_icon)(CanvasApi* canvas, uint8_t x, uint8_t y, Icon* icon); | ||||||
|  |     void (*draw_dot)(CanvasApi* canvas, uint8_t x, uint8_t y); | ||||||
|  |     void (*draw_box)(CanvasApi* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height); | ||||||
|  |     void (*draw_frame)(CanvasApi* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height); | ||||||
|  |     void (*draw_line)(CanvasApi* canvas, uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2); | ||||||
| }; | }; | ||||||
|  | |||||||
							
								
								
									
										31
									
								
								applications/gui/elements.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								applications/gui/elements.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | |||||||
|  | #include "elements.h" | ||||||
|  | 
 | ||||||
|  | void elements_scrollbar(CanvasApi* canvas, uint8_t pos, uint8_t total) { | ||||||
|  |     uint8_t width = canvas->width(canvas); | ||||||
|  |     uint8_t height = canvas->height(canvas); | ||||||
|  |     // prevent overflows
 | ||||||
|  |     canvas->set_color(canvas, ColorWhite); | ||||||
|  |     canvas->draw_box(canvas, width - 3, 0, 3, height); | ||||||
|  |     // dot line
 | ||||||
|  |     canvas->set_color(canvas, ColorBlack); | ||||||
|  |     for(uint8_t i = 0; i < height; i += 2) { | ||||||
|  |         canvas->draw_dot(canvas, width - 2, i); | ||||||
|  |     } | ||||||
|  |     // Position block
 | ||||||
|  |     if(total) { | ||||||
|  |         uint8_t block_h = ((float)height) / total; | ||||||
|  |         canvas->draw_box(canvas, width - 3, block_h * pos, 3, block_h); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void elements_frame(CanvasApi* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height) { | ||||||
|  |     canvas->draw_line(canvas, x + 2, y, x + width - 2, y); | ||||||
|  |     canvas->draw_line(canvas, x + 1, y + height - 1, x + width, y + height - 1); | ||||||
|  |     canvas->draw_line(canvas, x + 2, y + height, x + width - 1, y + height); | ||||||
|  | 
 | ||||||
|  |     canvas->draw_line(canvas, x, y + 2, x, y + height - 2); | ||||||
|  |     canvas->draw_line(canvas, x + width - 1, y + 1, x + width - 1, y + height - 2); | ||||||
|  |     canvas->draw_line(canvas, x + width, y + 2, x + width, y + height - 2); | ||||||
|  | 
 | ||||||
|  |     canvas->draw_dot(canvas, x + 1, y + 1); | ||||||
|  | } | ||||||
							
								
								
									
										8
									
								
								applications/gui/elements.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								applications/gui/elements.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <stdint.h> | ||||||
|  | #include "canvas.h" | ||||||
|  | 
 | ||||||
|  | void elements_scrollbar(CanvasApi* canvas, uint8_t pos, uint8_t total); | ||||||
|  | 
 | ||||||
|  | void elements_frame(CanvasApi* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height); | ||||||
| @ -3,8 +3,8 @@ | |||||||
| 
 | 
 | ||||||
| #include <flipper.h> | #include <flipper.h> | ||||||
| #include <flipper_v2.h> | #include <flipper_v2.h> | ||||||
| #include <stdio.h> |  | ||||||
| #include <m-array.h> | #include <m-array.h> | ||||||
|  | #include <stdio.h> | ||||||
| 
 | 
 | ||||||
| #include "gui_event.h" | #include "gui_event.h" | ||||||
| #include "canvas.h" | #include "canvas.h" | ||||||
| @ -18,54 +18,10 @@ struct Gui { | |||||||
|     GuiApi api; |     GuiApi api; | ||||||
|     GuiEvent* event; |     GuiEvent* event; | ||||||
|     CanvasApi* canvas_api; |     CanvasApi* canvas_api; | ||||||
|     WidgetArray_t widgets_status_bar; |     WidgetArray_t layers[GuiLayerMAX]; | ||||||
|     WidgetArray_t widgets; |     osMutexId_t mutex; | ||||||
|     WidgetArray_t widgets_fs; |  | ||||||
|     WidgetArray_t widgets_dialog; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void gui_add_widget(GuiApi* gui_api, Widget* widget, WidgetLayer layer) { |  | ||||||
|     assert(gui_api); |  | ||||||
|     assert(widget); |  | ||||||
|     Gui* gui = (Gui*)gui_api; |  | ||||||
| 
 |  | ||||||
|     // TODO add mutex on widget array
 |  | ||||||
|     WidgetArray_t* widget_array = NULL; |  | ||||||
| 
 |  | ||||||
|     switch(layer) { |  | ||||||
|     case WidgetLayerStatusBar: |  | ||||||
|         widget_array = &gui->widgets_status_bar; |  | ||||||
|         break; |  | ||||||
|     case WidgetLayerMain: |  | ||||||
|         widget_array = &gui->widgets; |  | ||||||
|         break; |  | ||||||
|     case WidgetLayerFullscreen: |  | ||||||
|         widget_array = &gui->widgets_fs; |  | ||||||
|         break; |  | ||||||
|     case WidgetLayerDialog: |  | ||||||
|         widget_array = &gui->widgets_dialog; |  | ||||||
|         break; |  | ||||||
|     default: |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     assert(widget_array); |  | ||||||
| 
 |  | ||||||
|     gui_event_lock(gui->event); |  | ||||||
|     WidgetArray_push_back(*widget_array, widget); |  | ||||||
|     widget_gui_set(widget, gui); |  | ||||||
|     gui_event_unlock(gui->event); |  | ||||||
| 
 |  | ||||||
|     gui_update(gui); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void gui_update(Gui* gui) { |  | ||||||
|     assert(gui); |  | ||||||
|     GuiMessage message; |  | ||||||
|     message.type = GuiMessageTypeRedraw; |  | ||||||
|     gui_event_messsage_send(gui->event, &message); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| Widget* gui_widget_find_enabled(WidgetArray_t array) { | Widget* gui_widget_find_enabled(WidgetArray_t array) { | ||||||
|     size_t widgets_count = WidgetArray_size(array); |     size_t widgets_count = WidgetArray_size(array); | ||||||
|     for(size_t i = 0; i < widgets_count; i++) { |     for(size_t i = 0; i < widgets_count; i++) { | ||||||
| @ -77,9 +33,16 @@ Widget* gui_widget_find_enabled(WidgetArray_t array) { | |||||||
|     return NULL; |     return NULL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void gui_update(Gui* gui) { | ||||||
|  |     assert(gui); | ||||||
|  |     GuiMessage message; | ||||||
|  |     message.type = GuiMessageTypeRedraw; | ||||||
|  |     gui_event_messsage_send(gui->event, &message); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool gui_redraw_fs(Gui* gui) { | bool gui_redraw_fs(Gui* gui) { | ||||||
|     canvas_frame_set(gui->canvas_api, 0, 0, 128, 64); |     canvas_frame_set(gui->canvas_api, 0, 0, 128, 64); | ||||||
|     Widget* widget = gui_widget_find_enabled(gui->widgets_fs); |     Widget* widget = gui_widget_find_enabled(gui->layers[GuiLayerFullscreen]); | ||||||
|     if(widget) { |     if(widget) { | ||||||
|         widget_draw(widget, gui->canvas_api); |         widget_draw(widget, gui->canvas_api); | ||||||
|         return true; |         return true; | ||||||
| @ -88,64 +51,128 @@ bool gui_redraw_fs(Gui* gui) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void gui_redraw_status_bar(Gui* gui) { | bool gui_redraw_status_bar(Gui* gui) { | ||||||
|     canvas_frame_set(gui->canvas_api, 0, 0, 128, 64); |     canvas_frame_set(gui->canvas_api, 0, 0, 128, 64); | ||||||
|     Widget* widget = gui_widget_find_enabled(gui->widgets_status_bar); |     Widget* widget = gui_widget_find_enabled(gui->layers[GuiLayerStatusBar]); | ||||||
|     if(widget) widget_draw(widget, gui->canvas_api); |     if(widget) { | ||||||
|  |         widget_draw(widget, gui->canvas_api); | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |     return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void gui_redraw_normal(Gui* gui) { | bool gui_redraw_normal(Gui* gui) { | ||||||
|     canvas_frame_set(gui->canvas_api, 0, 9, 128, 55); |     canvas_frame_set(gui->canvas_api, 0, 9, 128, 55); | ||||||
|     Widget* widget = gui_widget_find_enabled(gui->widgets); |     Widget* widget = gui_widget_find_enabled(gui->layers[GuiLayerMain]); | ||||||
|     if(widget) widget_draw(widget, gui->canvas_api); |     if(widget) { | ||||||
|  |         widget_draw(widget, gui->canvas_api); | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |     return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void gui_redraw_dialogs(Gui* gui) { | bool gui_redraw_none(Gui* gui) { | ||||||
|     canvas_frame_set(gui->canvas_api, 10, 20, 118, 44); |     canvas_frame_set(gui->canvas_api, 0, 9, 118, 44); | ||||||
|     Widget* widget = gui_widget_find_enabled(gui->widgets_dialog); |     Widget* widget = gui_widget_find_enabled(gui->layers[GuiLayerNone]); | ||||||
|     if(widget) widget_draw(widget, gui->canvas_api); |     if(widget) { | ||||||
|  |         widget_draw(widget, gui->canvas_api); | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void gui_redraw(Gui* gui) { | void gui_redraw(Gui* gui) { | ||||||
|     assert(gui); |     assert(gui); | ||||||
|  |     gui_lock(gui); | ||||||
| 
 | 
 | ||||||
|     if(!gui_redraw_fs(gui)) { |     if(!gui_redraw_fs(gui)) { | ||||||
|         gui_redraw_status_bar(gui); |         if(!gui_redraw_normal(gui)) { | ||||||
|         gui_redraw_normal(gui); |             gui_redraw_none(gui); | ||||||
|  |         } | ||||||
|  |         gui_redraw_status_bar(gui); | ||||||
|     } |     } | ||||||
|     gui_redraw_dialogs(gui); |  | ||||||
| 
 | 
 | ||||||
|     canvas_commit(gui->canvas_api); |     canvas_commit(gui->canvas_api); | ||||||
|  |     gui_unlock(gui); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void gui_input(Gui* gui, InputEvent* input_event) { | void gui_input(Gui* gui, InputEvent* input_event) { | ||||||
|     assert(gui); |     assert(gui); | ||||||
|  |     gui_lock(gui); | ||||||
| 
 | 
 | ||||||
|     Widget* widget = gui_widget_find_enabled(gui->widgets_dialog); |     Widget* widget = gui_widget_find_enabled(gui->layers[GuiLayerFullscreen]); | ||||||
|     if(!widget) widget = gui_widget_find_enabled(gui->widgets_fs); |     if(!widget) widget = gui_widget_find_enabled(gui->layers[GuiLayerMain]); | ||||||
|     if(!widget) widget = gui_widget_find_enabled(gui->widgets); |     if(!widget) widget = gui_widget_find_enabled(gui->layers[GuiLayerNone]); | ||||||
| 
 | 
 | ||||||
|     if(widget) { |     if(widget) { | ||||||
|         widget_input(widget, input_event); |         widget_input(widget, input_event); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     gui_unlock(gui); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void gui_lock(Gui* gui) { | ||||||
|  |     assert(gui); | ||||||
|  |     assert(osMutexAcquire(gui->mutex, osWaitForever) == osOK); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void gui_unlock(Gui* gui) { | ||||||
|  |     assert(gui); | ||||||
|  |     assert(osMutexRelease(gui->mutex) == osOK); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void gui_add_widget(GuiApi* gui_api, Widget* widget, GuiLayer layer) { | ||||||
|  |     assert(gui_api); | ||||||
|  |     assert(widget); | ||||||
|  |     assert(layer < GuiLayerMAX); | ||||||
|  |     Gui* gui = (Gui*)gui_api; | ||||||
|  | 
 | ||||||
|  |     gui_lock(gui); | ||||||
|  |     WidgetArray_push_back(gui->layers[layer], widget); | ||||||
|  |     widget_gui_set(widget, gui); | ||||||
|  |     gui_unlock(gui); | ||||||
|  |     gui_update(gui); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void gui_remove_widget(GuiApi* gui_api, Widget* widget) { | ||||||
|  |     assert(gui_api); | ||||||
|  |     assert(widget); | ||||||
|  |     Gui* gui = (Gui*)gui_api; | ||||||
|  | 
 | ||||||
|  |     gui_lock(gui); | ||||||
|  | 
 | ||||||
|  |     widget_gui_set(widget, NULL); | ||||||
|  |     WidgetArray_it_t it; | ||||||
|  |     for(size_t i = 0; i < GuiLayerMAX; i++) { | ||||||
|  |         WidgetArray_it(it, gui->layers[i]); | ||||||
|  |         while(!WidgetArray_end_p(it)) { | ||||||
|  |             if(*WidgetArray_ref(it) == widget) { | ||||||
|  |                 WidgetArray_remove(gui->layers[i], it); | ||||||
|  |             } | ||||||
|  |             WidgetArray_next(it); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     gui_unlock(gui); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Gui* gui_alloc() { | Gui* gui_alloc() { | ||||||
|     Gui* gui = furi_alloc(sizeof(Gui)); |     Gui* gui = furi_alloc(sizeof(Gui)); | ||||||
| 
 |     // Set API functions
 | ||||||
|     // Initialize widget arrays
 |     gui->api.add_widget = gui_add_widget; | ||||||
|     WidgetArray_init(gui->widgets_status_bar); |     gui->api.remove_widget = gui_remove_widget; | ||||||
|     WidgetArray_init(gui->widgets); |     // Allocate mutex
 | ||||||
|     WidgetArray_init(gui->widgets_fs); |     gui->mutex = osMutexNew(NULL); | ||||||
|     WidgetArray_init(gui->widgets_dialog); |     assert(gui->mutex); | ||||||
| 
 |  | ||||||
|     // Event dispatcher
 |     // Event dispatcher
 | ||||||
|     gui->event = gui_event_alloc(); |     gui->event = gui_event_alloc(); | ||||||
| 
 |  | ||||||
|     // Drawing canvas api
 |     // Drawing canvas api
 | ||||||
|     gui->canvas_api = canvas_api_init(); |     gui->canvas_api = canvas_api_init(); | ||||||
| 
 |     // Compose Layers
 | ||||||
|     gui->api.add_widget = gui_add_widget; |     for(size_t i = 0; i < GuiLayerMAX; i++) { | ||||||
|  |         WidgetArray_init(gui->layers[i]); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     return gui; |     return gui; | ||||||
| } | } | ||||||
|  | |||||||
| @ -4,15 +4,17 @@ | |||||||
| #include "canvas.h" | #include "canvas.h" | ||||||
| 
 | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
|     WidgetLayerStatusBar, |     GuiLayerNone, /* Special layer for internal use only */ | ||||||
|     WidgetLayerMain, |  | ||||||
|     WidgetLayerFullscreen, |  | ||||||
|     WidgetLayerDialog |  | ||||||
| } WidgetLayer; |  | ||||||
| 
 | 
 | ||||||
| typedef struct Widget Widget; |     GuiLayerStatusBar, /* Status bar widget layer */ | ||||||
|  |     GuiLayerMain, /* Main widget layer, status bar is shown */ | ||||||
|  |     GuiLayerFullscreen, /* Fullscreen widget layer */ | ||||||
|  | 
 | ||||||
|  |     GuiLayerMAX /* Don't use or move, special value */ | ||||||
|  | } GuiLayer; | ||||||
| 
 | 
 | ||||||
| typedef struct GuiApi GuiApi; | typedef struct GuiApi GuiApi; | ||||||
| struct GuiApi { | struct GuiApi { | ||||||
|     void (*add_widget)(GuiApi* gui_api, Widget* widget, WidgetLayer layer); |     void (*add_widget)(GuiApi* gui_api, Widget* widget, GuiLayer layer); | ||||||
|  |     void (*remove_widget)(GuiApi* gui_api, Widget* widget); | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -8,7 +8,6 @@ | |||||||
| struct GuiEvent { | struct GuiEvent { | ||||||
|     PubSub* input_event_record; |     PubSub* input_event_record; | ||||||
|     osMessageQueueId_t mqueue; |     osMessageQueueId_t mqueue; | ||||||
|     osMutexId_t lock_mutex; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void gui_event_input_events_callback(const void* value, void* ctx) { | void gui_event_input_events_callback(const void* value, void* ctx) { | ||||||
| @ -33,37 +32,15 @@ GuiEvent* gui_event_alloc() { | |||||||
|     assert(gui_event->input_event_record != NULL); |     assert(gui_event->input_event_record != NULL); | ||||||
|     subscribe_pubsub(gui_event->input_event_record, gui_event_input_events_callback, gui_event); |     subscribe_pubsub(gui_event->input_event_record, gui_event_input_events_callback, gui_event); | ||||||
| 
 | 
 | ||||||
|     // Lock mutex
 |  | ||||||
|     gui_event->lock_mutex = osMutexNew(NULL); |  | ||||||
|     assert(gui_event->lock_mutex); |  | ||||||
|     gui_event_lock(gui_event); |  | ||||||
| 
 |  | ||||||
|     return gui_event; |     return gui_event; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void gui_event_free(GuiEvent* gui_event) { | void gui_event_free(GuiEvent* gui_event) { | ||||||
|     osStatus_t status; |  | ||||||
|     assert(gui_event); |     assert(gui_event); | ||||||
|     gui_event_unlock(gui_event); |     assert(osMessageQueueDelete(gui_event->mqueue) == osOK); | ||||||
|     status = osMessageQueueDelete(gui_event->mqueue); |  | ||||||
|     assert(status == osOK); |  | ||||||
|     free(gui_event); |     free(gui_event); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void gui_event_lock(GuiEvent* gui_event) { |  | ||||||
|     osStatus_t status; |  | ||||||
|     assert(gui_event); |  | ||||||
|     status = osMutexAcquire(gui_event->lock_mutex, osWaitForever); |  | ||||||
|     assert(status == osOK); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void gui_event_unlock(GuiEvent* gui_event) { |  | ||||||
|     osStatus_t status; |  | ||||||
|     assert(gui_event); |  | ||||||
|     status = osMutexRelease(gui_event->lock_mutex); |  | ||||||
|     assert(status == osOK); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void gui_event_messsage_send(GuiEvent* gui_event, GuiMessage* message) { | void gui_event_messsage_send(GuiEvent* gui_event, GuiMessage* message) { | ||||||
|     assert(gui_event); |     assert(gui_event); | ||||||
|     assert(message); |     assert(message); | ||||||
| @ -71,12 +48,10 @@ void gui_event_messsage_send(GuiEvent* gui_event, GuiMessage* message) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| GuiMessage gui_event_message_next(GuiEvent* gui_event) { | GuiMessage gui_event_message_next(GuiEvent* gui_event) { | ||||||
|     osStatus_t status; |  | ||||||
|     assert(gui_event); |     assert(gui_event); | ||||||
|     GuiMessage message; |     GuiMessage message; | ||||||
|     gui_event_unlock(gui_event); | 
 | ||||||
|     status = osMessageQueueGet(gui_event->mqueue, &message, NULL, osWaitForever); |     assert(osMessageQueueGet(gui_event->mqueue, &message, NULL, osWaitForever) == osOK); | ||||||
|     assert(status == osOK); | 
 | ||||||
|     gui_event_lock(gui_event); |  | ||||||
|     return message; |     return message; | ||||||
| } | } | ||||||
|  | |||||||
| @ -20,10 +20,6 @@ GuiEvent* gui_event_alloc(); | |||||||
| 
 | 
 | ||||||
| void gui_event_free(GuiEvent* gui_event); | void gui_event_free(GuiEvent* gui_event); | ||||||
| 
 | 
 | ||||||
| void gui_event_lock(GuiEvent* gui_event); |  | ||||||
| 
 |  | ||||||
| void gui_event_unlock(GuiEvent* gui_event); |  | ||||||
| 
 |  | ||||||
| void gui_event_messsage_send(GuiEvent* gui_event, GuiMessage* message); | void gui_event_messsage_send(GuiEvent* gui_event, GuiMessage* message); | ||||||
| 
 | 
 | ||||||
| GuiMessage gui_event_message_next(GuiEvent* gui_event); | GuiMessage gui_event_message_next(GuiEvent* gui_event); | ||||||
|  | |||||||
| @ -3,3 +3,5 @@ | |||||||
| typedef struct Gui Gui; | typedef struct Gui Gui; | ||||||
| 
 | 
 | ||||||
| void gui_update(Gui* gui); | void gui_update(Gui* gui); | ||||||
|  | void gui_lock(Gui* gui); | ||||||
|  | void gui_unlock(Gui* gui); | ||||||
							
								
								
									
										63
									
								
								applications/gui/icon.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								applications/gui/icon.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,63 @@ | |||||||
|  | #include "icon.h" | ||||||
|  | #include "icon_i.h" | ||||||
|  | 
 | ||||||
|  | #include <cmsis_os2.h> | ||||||
|  | #include <flipper.h> | ||||||
|  | #include <assert.h> | ||||||
|  | 
 | ||||||
|  | Icon* icon_alloc(const IconData* data) { | ||||||
|  |     Icon* icon = furi_alloc(sizeof(Icon)); | ||||||
|  |     icon->data = data; | ||||||
|  |     return icon; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void icon_free(Icon* icon) { | ||||||
|  |     assert(icon); | ||||||
|  |     free(icon); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const uint8_t* icon_get_data(Icon* icon) { | ||||||
|  |     assert(icon); | ||||||
|  |     if(icon->tick) { | ||||||
|  |         uint32_t now = osKernelGetTickCount(); | ||||||
|  |         if(now < icon->tick) { | ||||||
|  |             icon->tick = now; | ||||||
|  |             icon_next_frame(icon); | ||||||
|  |         } else if(now - icon->tick > osKernelGetTickFreq() / icon->data->frame_rate) { | ||||||
|  |             icon->tick = now; | ||||||
|  |             icon_next_frame(icon); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return icon->data->frames[icon->frame]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void icon_next_frame(Icon* icon) { | ||||||
|  |     assert(icon); | ||||||
|  |     icon->frame = (icon->frame + 1) % icon->data->frame_count; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint8_t icon_get_width(Icon* icon) { | ||||||
|  |     assert(icon); | ||||||
|  |     return icon->data->width; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | uint8_t icon_get_height(Icon* icon) { | ||||||
|  |     assert(icon); | ||||||
|  |     return icon->data->height; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool icon_is_animated(Icon* icon) { | ||||||
|  |     assert(icon); | ||||||
|  |     return icon->data->frame_count > 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void icon_start_animation(Icon* icon) { | ||||||
|  |     assert(icon); | ||||||
|  |     icon->tick = osKernelGetTickCount(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void icon_stop_animation(Icon* icon) { | ||||||
|  |     assert(icon); | ||||||
|  |     icon->tick = 0; | ||||||
|  |     icon->frame = 0; | ||||||
|  | } | ||||||
							
								
								
									
										21
									
								
								applications/gui/icon.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								applications/gui/icon.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <stdbool.h> | ||||||
|  | 
 | ||||||
|  | typedef struct IconData IconData; | ||||||
|  | typedef struct Icon Icon; | ||||||
|  | 
 | ||||||
|  | Icon* icon_alloc(const IconData* data); | ||||||
|  | 
 | ||||||
|  | void icon_free(Icon* icon); | ||||||
|  | 
 | ||||||
|  | uint8_t icon_get_width(Icon* icon); | ||||||
|  | 
 | ||||||
|  | uint8_t icon_get_height(Icon* icon); | ||||||
|  | 
 | ||||||
|  | bool icon_is_animated(Icon* icon); | ||||||
|  | 
 | ||||||
|  | void icon_start_animation(Icon* icon); | ||||||
|  | 
 | ||||||
|  | void icon_stop_animation(Icon* icon); | ||||||
							
								
								
									
										21
									
								
								applications/gui/icon_i.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								applications/gui/icon_i.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <stdint.h> | ||||||
|  | 
 | ||||||
|  | struct IconData { | ||||||
|  |     const uint8_t width; | ||||||
|  |     const uint8_t height; | ||||||
|  |     const uint8_t frame_count; | ||||||
|  |     const uint8_t frame_rate; | ||||||
|  |     const uint8_t** frames; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct Icon { | ||||||
|  |     const IconData* data; | ||||||
|  |     uint8_t frame; | ||||||
|  |     uint32_t tick; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const uint8_t* icon_get_data(Icon* icon); | ||||||
|  | 
 | ||||||
|  | void icon_next_frame(Icon* icon); | ||||||
| @ -32,9 +32,11 @@ void widget_free(Widget* widget) { | |||||||
| 
 | 
 | ||||||
| void widget_enabled_set(Widget* widget, bool enabled) { | void widget_enabled_set(Widget* widget, bool enabled) { | ||||||
|     assert(widget); |     assert(widget); | ||||||
|  |     if(widget->is_enabled != enabled) { | ||||||
|         widget->is_enabled = enabled; |         widget->is_enabled = enabled; | ||||||
|         widget_update(widget); |         widget_update(widget); | ||||||
|     } |     } | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| bool widget_is_enabled(Widget* widget) { | bool widget_is_enabled(Widget* widget) { | ||||||
|     assert(widget); |     assert(widget); | ||||||
|  | |||||||
| @ -262,7 +262,7 @@ void irda(void* p) { | |||||||
|         printf("gui is not available\n"); |         printf("gui is not available\n"); | ||||||
|         furiac_exit(NULL); |         furiac_exit(NULL); | ||||||
|     } |     } | ||||||
|     gui->add_widget(gui, widget, WidgetLayerFullscreen); |     gui->add_widget(gui, widget, GuiLayerFullscreen); | ||||||
| 
 | 
 | ||||||
|     AppEvent event; |     AppEvent event; | ||||||
|     while(1) { |     while(1) { | ||||||
|  | |||||||
							
								
								
									
										69
									
								
								applications/irukagotchi/irukagotchi.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								applications/irukagotchi/irukagotchi.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,69 @@ | |||||||
|  | #include "irukagotchi.h" | ||||||
|  | 
 | ||||||
|  | #include <assert.h> | ||||||
|  | #include <flipper_v2.h> | ||||||
|  | 
 | ||||||
|  | #include <gui/gui.h> | ||||||
|  | #include <gui/widget.h> | ||||||
|  | #include <gui/canvas.h> | ||||||
|  | #include <menu/menu.h> | ||||||
|  | 
 | ||||||
|  | #include <assets_icons.h> | ||||||
|  | 
 | ||||||
|  | struct Irukagotchi { | ||||||
|  |     Icon* icon; | ||||||
|  |     Widget* widget; | ||||||
|  |     ValueMutex* menu_vm; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void irukagotchi_draw_callback(CanvasApi* canvas, void* context) { | ||||||
|  |     Irukagotchi* irukagotchi = context; | ||||||
|  | 
 | ||||||
|  |     canvas->clear(canvas); | ||||||
|  |     canvas->set_color(canvas, ColorBlack); | ||||||
|  |     canvas->set_font(canvas, FontPrimary); | ||||||
|  |     canvas->draw_icon(canvas, 10, 20, irukagotchi->icon); | ||||||
|  |     canvas->draw_str(canvas, 30, 32, "Irukagotchi"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void irukagotchi_input_callback(InputEvent* event, void* context) { | ||||||
|  |     Irukagotchi* irukagotchi = context; | ||||||
|  | 
 | ||||||
|  |     if(!event->state || event->input != InputOk) return; | ||||||
|  | 
 | ||||||
|  |     with_value_mutex( | ||||||
|  |         irukagotchi->menu_vm, (Menu * menu) { menu_ok(menu); }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | Irukagotchi* irukagotchi_alloc() { | ||||||
|  |     Irukagotchi* irukagotchi = furi_alloc(sizeof(Irukagotchi)); | ||||||
|  | 
 | ||||||
|  |     irukagotchi->icon = assets_icons_get(A_Tamagotchi_14); | ||||||
|  |     icon_start_animation(irukagotchi->icon); | ||||||
|  | 
 | ||||||
|  |     irukagotchi->widget = widget_alloc(); | ||||||
|  |     widget_draw_callback_set(irukagotchi->widget, irukagotchi_draw_callback, irukagotchi); | ||||||
|  |     widget_input_callback_set(irukagotchi->widget, irukagotchi_input_callback, irukagotchi); | ||||||
|  | 
 | ||||||
|  |     irukagotchi->menu_vm = furi_open("menu"); | ||||||
|  |     assert(irukagotchi->menu_vm); | ||||||
|  | 
 | ||||||
|  |     return irukagotchi; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void irukagotchi_task() { | ||||||
|  |     Irukagotchi* irukagotchi = irukagotchi_alloc(); | ||||||
|  | 
 | ||||||
|  |     FuriRecordSubscriber* gui_record = furi_open_deprecated("gui", false, false, NULL, NULL, NULL); | ||||||
|  |     assert(gui_record); | ||||||
|  |     GuiApi* gui = furi_take(gui_record); | ||||||
|  |     assert(gui); | ||||||
|  |     gui->add_widget(gui, irukagotchi->widget, GuiLayerNone); | ||||||
|  |     furi_commit(gui_record); | ||||||
|  | 
 | ||||||
|  |     furiac_ready(); | ||||||
|  | 
 | ||||||
|  |     while(1) { | ||||||
|  |         osDelay(osWaitForever); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										3
									
								
								applications/irukagotchi/irukagotchi.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								applications/irukagotchi/irukagotchi.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | typedef struct Irukagotchi Irukagotchi; | ||||||
| @ -69,7 +69,7 @@ void lf_rfid_workaround(void* p) { | |||||||
|         printf("gui is not available\n"); |         printf("gui is not available\n"); | ||||||
|         furiac_exit(NULL); |         furiac_exit(NULL); | ||||||
|     } |     } | ||||||
|     gui->add_widget(gui, widget, WidgetLayerFullscreen); |     gui->add_widget(gui, widget, GuiLayerFullscreen); | ||||||
| 
 | 
 | ||||||
|     AppEvent event; |     AppEvent event; | ||||||
|     while(1) { |     while(1) { | ||||||
|  | |||||||
| @ -5,6 +5,7 @@ | |||||||
| 
 | 
 | ||||||
| #include <flipper_v2.h> | #include <flipper_v2.h> | ||||||
| #include <gui/gui.h> | #include <gui/gui.h> | ||||||
|  | #include <gui/elements.h> | ||||||
| 
 | 
 | ||||||
| #include "menu_event.h" | #include "menu_event.h" | ||||||
| #include "menu_item.h" | #include "menu_item.h" | ||||||
| @ -19,7 +20,6 @@ struct Menu { | |||||||
|     MenuItem* root; |     MenuItem* root; | ||||||
|     MenuItem* settings; |     MenuItem* settings; | ||||||
|     MenuItem* current; |     MenuItem* current; | ||||||
|     uint32_t position; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void menu_widget_callback(CanvasApi* canvas, void* context); | void menu_widget_callback(CanvasApi* canvas, void* context); | ||||||
| @ -42,8 +42,9 @@ ValueMutex* menu_init() { | |||||||
|     // Open GUI and register fullscreen widget
 |     // Open GUI and register fullscreen widget
 | ||||||
|     GuiApi* gui = furi_open("gui"); |     GuiApi* gui = furi_open("gui"); | ||||||
|     assert(gui); |     assert(gui); | ||||||
|     gui->add_widget(gui, menu->widget, WidgetLayerFullscreen); |     gui->add_widget(gui, menu->widget, GuiLayerFullscreen); | ||||||
| 
 | 
 | ||||||
|  |     widget_enabled_set(menu->widget, false); | ||||||
|     widget_draw_callback_set(menu->widget, menu_widget_callback, menu_mutex); |     widget_draw_callback_set(menu->widget, menu_widget_callback, menu_mutex); | ||||||
|     widget_input_callback_set(menu->widget, menu_event_input_callback, menu->event); |     widget_input_callback_set(menu->widget, menu_event_input_callback, menu->event); | ||||||
| 
 | 
 | ||||||
| @ -68,6 +69,12 @@ void menu_settings_item_add(Menu* menu, MenuItem* item) { | |||||||
|     menu_item_subitem_add(menu->settings, item); |     menu_item_subitem_add(menu->settings, item); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void menu_draw_primary(Menu* menu, CanvasApi* canvas) { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void menu_draw_secondary(Menu* menu, CanvasApi* canvas) { | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void menu_widget_callback(CanvasApi* canvas, void* context) { | void menu_widget_callback(CanvasApi* canvas, void* context) { | ||||||
|     assert(canvas); |     assert(canvas); | ||||||
|     assert(context); |     assert(context); | ||||||
| @ -75,27 +82,41 @@ void menu_widget_callback(CanvasApi* canvas, void* context) { | |||||||
|     Menu* menu = acquire_mutex((ValueMutex*)context, 100); // wait 10 ms to get mutex
 |     Menu* menu = acquire_mutex((ValueMutex*)context, 100); // wait 10 ms to get mutex
 | ||||||
|     if(menu == NULL) return; // redraw fail
 |     if(menu == NULL) return; // redraw fail
 | ||||||
| 
 | 
 | ||||||
|     if(!menu->current) { |     assert(menu->current); | ||||||
|         canvas->clear(canvas); |  | ||||||
|         canvas->set_color(canvas, ColorBlack); |  | ||||||
|         canvas->set_font(canvas, FontPrimary); |  | ||||||
|         canvas->draw_str(canvas, 2, 32, "Idle Screen"); |  | ||||||
|     } else { |  | ||||||
|         MenuItemArray_t* items = menu_item_get_subitems(menu->current); |  | ||||||
|         canvas->clear(canvas); |  | ||||||
|         canvas->set_color(canvas, ColorBlack); |  | ||||||
|         canvas->set_font(canvas, FontSecondary); |  | ||||||
| 
 | 
 | ||||||
|         if(MenuItemArray_size(*items)) { |     canvas->clear(canvas); | ||||||
|             for(size_t i = 0; i < 5; i++) { |     canvas->set_color(canvas, ColorBlack); | ||||||
|                 size_t shift_position = i + menu->position + MenuItemArray_size(*items) - 2; | 
 | ||||||
|                 shift_position = shift_position % (MenuItemArray_size(*items)); |     size_t position = menu_item_get_position(menu->current); | ||||||
|                 MenuItem* item = *MenuItemArray_get(*items, shift_position); |     MenuItemArray_t* items = menu_item_get_subitems(menu->current); | ||||||
|                 canvas->draw_str(canvas, 2, 12 * (i + 1), menu_item_get_label(item)); |     size_t items_count = MenuItemArray_size(*items); | ||||||
|             } |     if(items_count) { | ||||||
|  |         MenuItem* item; | ||||||
|  |         size_t shift_position; | ||||||
|  |         // First line
 | ||||||
|  |         canvas->set_font(canvas, FontSecondary); | ||||||
|  |         shift_position = (0 + position + items_count - 1) % (MenuItemArray_size(*items)); | ||||||
|  |         item = *MenuItemArray_get(*items, shift_position); | ||||||
|  |         canvas->draw_icon(canvas, 4, 3, menu_item_get_icon(item)); | ||||||
|  |         canvas->draw_str(canvas, 22, 14, menu_item_get_label(item)); | ||||||
|  |         // Second line main
 | ||||||
|  |         canvas->set_font(canvas, FontPrimary); | ||||||
|  |         shift_position = (1 + position + items_count - 1) % (MenuItemArray_size(*items)); | ||||||
|  |         item = *MenuItemArray_get(*items, shift_position); | ||||||
|  |         canvas->draw_icon(canvas, 4, 24, menu_item_get_icon(item)); | ||||||
|  |         canvas->draw_str(canvas, 22, 35, menu_item_get_label(item)); | ||||||
|  |         // Third line
 | ||||||
|  |         canvas->set_font(canvas, FontSecondary); | ||||||
|  |         shift_position = (2 + position + items_count - 1) % (MenuItemArray_size(*items)); | ||||||
|  |         item = *MenuItemArray_get(*items, shift_position); | ||||||
|  |         canvas->draw_icon(canvas, 4, 46, menu_item_get_icon(item)); | ||||||
|  |         canvas->draw_str(canvas, 22, 57, menu_item_get_label(item)); | ||||||
|  |         // Frame and scrollbar
 | ||||||
|  |         elements_frame(canvas, 0, 20, 128 - 5, 22); | ||||||
|  |         elements_scrollbar(canvas, position, items_count); | ||||||
|     } else { |     } else { | ||||||
|         canvas->draw_str(canvas, 2, 32, "Empty"); |         canvas->draw_str(canvas, 2, 32, "Empty"); | ||||||
|         } |         elements_scrollbar(canvas, 0, 0); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     release_mutex((ValueMutex*)context, menu); |     release_mutex((ValueMutex*)context, menu); | ||||||
| @ -111,18 +132,21 @@ void menu_update(Menu* menu) { | |||||||
| void menu_up(Menu* menu) { | void menu_up(Menu* menu) { | ||||||
|     assert(menu); |     assert(menu); | ||||||
| 
 | 
 | ||||||
|  |     size_t position = menu_item_get_position(menu->current); | ||||||
|     MenuItemArray_t* items = menu_item_get_subitems(menu->current); |     MenuItemArray_t* items = menu_item_get_subitems(menu->current); | ||||||
|     if(menu->position == 0) menu->position = MenuItemArray_size(*items); |     if(position == 0) position = MenuItemArray_size(*items); | ||||||
|     menu->position--; |     position--; | ||||||
|  |     menu_item_set_position(menu->current, position); | ||||||
|     menu_update(menu); |     menu_update(menu); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void menu_down(Menu* menu) { | void menu_down(Menu* menu) { | ||||||
|     assert(menu); |     assert(menu); | ||||||
| 
 |     size_t position = menu_item_get_position(menu->current); | ||||||
|     MenuItemArray_t* items = menu_item_get_subitems(menu->current); |     MenuItemArray_t* items = menu_item_get_subitems(menu->current); | ||||||
|     menu->position++; |     position++; | ||||||
|     menu->position = menu->position % MenuItemArray_size(*items); |     position = position % MenuItemArray_size(*items); | ||||||
|  |     menu_item_set_position(menu->current, position); | ||||||
|     menu_update(menu); |     menu_update(menu); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -130,18 +154,25 @@ void menu_ok(Menu* menu) { | |||||||
|     assert(menu); |     assert(menu); | ||||||
| 
 | 
 | ||||||
|     if(!menu->current) { |     if(!menu->current) { | ||||||
|  |         widget_enabled_set(menu->widget, true); | ||||||
|         menu->current = menu->root; |         menu->current = menu->root; | ||||||
|  |         menu_item_set_position(menu->current, 0); | ||||||
|         menu_update(menu); |         menu_update(menu); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     MenuItemArray_t* items = menu_item_get_subitems(menu->current); |     MenuItemArray_t* items = menu_item_get_subitems(menu->current); | ||||||
|     MenuItem* item = *MenuItemArray_get(*items, menu->position); |     if(!items || MenuItemArray_size(*items) == 0) { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     size_t position = menu_item_get_position(menu->current); | ||||||
|  |     MenuItem* item = *MenuItemArray_get(*items, position); | ||||||
|     MenuItemType type = menu_item_get_type(item); |     MenuItemType type = menu_item_get_type(item); | ||||||
| 
 | 
 | ||||||
|     if(type == MenuItemTypeMenu) { |     if(type == MenuItemTypeMenu) { | ||||||
|         menu->current = item; |         menu->current = item; | ||||||
|         menu->position = 0; |         menu_item_set_position(menu->current, 0); | ||||||
|         menu_update(menu); |         menu_update(menu); | ||||||
|     } else if(type == MenuItemTypeFunction) { |     } else if(type == MenuItemTypeFunction) { | ||||||
|         menu_item_function_call(item); |         menu_item_function_call(item); | ||||||
| @ -153,7 +184,6 @@ void menu_back(Menu* menu) { | |||||||
|     MenuItem* parent = menu_item_get_parent(menu->current); |     MenuItem* parent = menu_item_get_parent(menu->current); | ||||||
|     if(parent) { |     if(parent) { | ||||||
|         menu->current = parent; |         menu->current = parent; | ||||||
|         menu->position = 0; |  | ||||||
|         menu_update(menu); |         menu_update(menu); | ||||||
|     } else { |     } else { | ||||||
|         menu_exit(menu); |         menu_exit(menu); | ||||||
| @ -162,7 +192,7 @@ void menu_back(Menu* menu) { | |||||||
| 
 | 
 | ||||||
| void menu_exit(Menu* menu) { | void menu_exit(Menu* menu) { | ||||||
|     assert(menu); |     assert(menu); | ||||||
|     menu->position = 0; |     widget_enabled_set(menu->widget, false); | ||||||
|     menu->current = NULL; |     menu->current = NULL; | ||||||
|     menu_update(menu); |     menu_update(menu); | ||||||
| } | } | ||||||
|  | |||||||
| @ -6,10 +6,15 @@ | |||||||
| 
 | 
 | ||||||
| struct MenuItem { | struct MenuItem { | ||||||
|     MenuItemType type; |     MenuItemType type; | ||||||
|  | 
 | ||||||
|     const char* label; |     const char* label; | ||||||
|     void* icon; |     Icon* icon; | ||||||
|  | 
 | ||||||
|  |     size_t position; | ||||||
|     MenuItem* parent; |     MenuItem* parent; | ||||||
|     void* data; |     void* data; | ||||||
|  | 
 | ||||||
|  |     // callback related
 | ||||||
|     MenuItemCallback callback; |     MenuItemCallback callback; | ||||||
|     void* callback_context; |     void* callback_context; | ||||||
| }; | }; | ||||||
| @ -19,7 +24,7 @@ MenuItem* menu_item_alloc() { | |||||||
|     return menu_item; |     return menu_item; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| MenuItem* menu_item_alloc_menu(const char* label, void* icon) { | MenuItem* menu_item_alloc_menu(const char* label, Icon* icon) { | ||||||
|     MenuItem* menu_item = menu_item_alloc(); |     MenuItem* menu_item = menu_item_alloc(); | ||||||
| 
 | 
 | ||||||
|     menu_item->type = MenuItemTypeMenu; |     menu_item->type = MenuItemTypeMenu; | ||||||
| @ -34,7 +39,7 @@ MenuItem* menu_item_alloc_menu(const char* label, void* icon) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| MenuItem* | MenuItem* | ||||||
| menu_item_alloc_function(const char* label, void* icon, MenuItemCallback callback, void* context) { | menu_item_alloc_function(const char* label, Icon* icon, MenuItemCallback callback, void* context) { | ||||||
|     MenuItem* menu_item = menu_item_alloc(); |     MenuItem* menu_item = menu_item_alloc(); | ||||||
| 
 | 
 | ||||||
|     menu_item->type = MenuItemTypeFunction; |     menu_item->type = MenuItemTypeFunction; | ||||||
| @ -73,6 +78,16 @@ uint8_t menu_item_get_type(MenuItem* menu_item) { | |||||||
|     return menu_item->type; |     return menu_item->type; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void menu_item_set_position(MenuItem* menu_item, size_t position) { | ||||||
|  |     assert(menu_item); | ||||||
|  |     menu_item->position = position; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | size_t menu_item_get_position(MenuItem* menu_item) { | ||||||
|  |     assert(menu_item); | ||||||
|  |     return menu_item->position; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void menu_item_set_label(MenuItem* menu_item, const char* label) { | void menu_item_set_label(MenuItem* menu_item, const char* label) { | ||||||
|     assert(menu_item); |     assert(menu_item); | ||||||
|     menu_item->label = label; |     menu_item->label = label; | ||||||
| @ -83,12 +98,12 @@ const char* menu_item_get_label(MenuItem* menu_item) { | |||||||
|     return menu_item->label; |     return menu_item->label; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void menu_item_set_icon(MenuItem* menu_item, void* icon) { | void menu_item_set_icon(MenuItem* menu_item, Icon* icon) { | ||||||
|     assert(menu_item); |     assert(menu_item); | ||||||
|     menu_item->icon = icon; |     menu_item->icon = icon; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void* menu_item_get_icon(MenuItem* menu_item) { | Icon* menu_item_get_icon(MenuItem* menu_item) { | ||||||
|     assert(menu_item); |     assert(menu_item); | ||||||
|     return menu_item->icon; |     return menu_item->icon; | ||||||
| } | } | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ | |||||||
| 
 | 
 | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
| #include <m-array.h> | #include <m-array.h> | ||||||
|  | #include <gui/icon.h> | ||||||
| 
 | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
|     MenuItemTypeMenu = 0x00, |     MenuItemTypeMenu = 0x00, | ||||||
| @ -13,10 +14,10 @@ typedef void (*MenuItemCallback)(void* context); | |||||||
| 
 | 
 | ||||||
| ARRAY_DEF(MenuItemArray, MenuItem*, M_PTR_OPLIST); | ARRAY_DEF(MenuItemArray, MenuItem*, M_PTR_OPLIST); | ||||||
| 
 | 
 | ||||||
| MenuItem* menu_item_alloc_menu(const char* label, void* icon); | MenuItem* menu_item_alloc_menu(const char* label, Icon* icon); | ||||||
| 
 | 
 | ||||||
| MenuItem* | MenuItem* | ||||||
| menu_item_alloc_function(const char* label, void* icon, MenuItemCallback callback, void* context); | menu_item_alloc_function(const char* label, Icon* icon, MenuItemCallback callback, void* context); | ||||||
| 
 | 
 | ||||||
| void menu_item_release(MenuItem* menu_item); | void menu_item_release(MenuItem* menu_item); | ||||||
| 
 | 
 | ||||||
| @ -26,11 +27,14 @@ void menu_item_subitem_add(MenuItem* menu_item, MenuItem* sub_item); | |||||||
| 
 | 
 | ||||||
| MenuItemType menu_item_get_type(MenuItem* menu_item); | MenuItemType menu_item_get_type(MenuItem* menu_item); | ||||||
| 
 | 
 | ||||||
|  | void menu_item_set_position(MenuItem* menu_item, size_t position); | ||||||
|  | size_t menu_item_get_position(MenuItem* menu_item); | ||||||
|  | 
 | ||||||
| void menu_item_set_label(MenuItem* menu_item, const char* label); | void menu_item_set_label(MenuItem* menu_item, const char* label); | ||||||
| const char* menu_item_get_label(MenuItem* menu_item); | const char* menu_item_get_label(MenuItem* menu_item); | ||||||
| 
 | 
 | ||||||
| void menu_item_set_icon(MenuItem* menu_item, void* icon); | void menu_item_set_icon(MenuItem* menu_item, Icon* icon); | ||||||
| void* menu_item_get_icon(MenuItem* menu_item); | Icon* menu_item_get_icon(MenuItem* menu_item); | ||||||
| 
 | 
 | ||||||
| MenuItemArray_t* menu_item_get_subitems(MenuItem* menu_item); | MenuItemArray_t* menu_item_get_subitems(MenuItem* menu_item); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ | |||||||
| #include <gui/gui.h> | #include <gui/gui.h> | ||||||
| #include <gui/widget.h> | #include <gui/widget.h> | ||||||
| #include <gui/canvas.h> | #include <gui/canvas.h> | ||||||
|  | #include <assets_icons.h> | ||||||
| 
 | 
 | ||||||
| #include <menu/menu.h> | #include <menu/menu.h> | ||||||
| #include <menu/menu_item.h> | #include <menu/menu_item.h> | ||||||
| @ -28,10 +29,10 @@ typedef struct { | |||||||
| 
 | 
 | ||||||
| struct Nfc { | struct Nfc { | ||||||
|     Dispatcher* dispatcher; |     Dispatcher* dispatcher; | ||||||
|  |     Icon* icon; | ||||||
|     Widget* widget; |     Widget* widget; | ||||||
|  |     ValueMutex* menu_vm; | ||||||
|     MenuItem* menu; |     MenuItem* menu; | ||||||
|     FuriRecordSubscriber* gui_record; |  | ||||||
|     FuriRecordSubscriber* menu_record; |  | ||||||
|     rfalNfcDiscoverParam* disParams; |     rfalNfcDiscoverParam* disParams; | ||||||
| 
 | 
 | ||||||
|     osThreadAttr_t worker_attr; |     osThreadAttr_t worker_attr; | ||||||
| @ -222,15 +223,18 @@ void nfc_bridge_callback(void* context) { | |||||||
| 
 | 
 | ||||||
| Nfc* nfc_alloc() { | Nfc* nfc_alloc() { | ||||||
|     Nfc* nfc = furi_alloc(sizeof(Nfc)); |     Nfc* nfc = furi_alloc(sizeof(Nfc)); | ||||||
|     assert(nfc); |  | ||||||
| 
 | 
 | ||||||
|     nfc->dispatcher = dispatcher_alloc(32, sizeof(NfcMessage)); |     nfc->dispatcher = dispatcher_alloc(32, sizeof(NfcMessage)); | ||||||
| 
 | 
 | ||||||
|  |     nfc->icon = assets_icons_get(A_NFC_14); | ||||||
|     nfc->widget = widget_alloc(); |     nfc->widget = widget_alloc(); | ||||||
|     widget_draw_callback_set(nfc->widget, nfc_draw_callback, nfc); |     widget_draw_callback_set(nfc->widget, nfc_draw_callback, nfc); | ||||||
|     widget_input_callback_set(nfc->widget, nfc_input_callback, nfc); |     widget_input_callback_set(nfc->widget, nfc_input_callback, nfc); | ||||||
| 
 | 
 | ||||||
|     nfc->menu = menu_item_alloc_menu("NFC", NULL); |     nfc->menu_vm = furi_open("menu"); | ||||||
|  |     assert(nfc->menu_vm); | ||||||
|  | 
 | ||||||
|  |     nfc->menu = menu_item_alloc_menu("NFC", nfc->icon); | ||||||
|     menu_item_subitem_add( |     menu_item_subitem_add( | ||||||
|         nfc->menu, menu_item_alloc_function("Test", NULL, nfc_test_callback, nfc)); |         nfc->menu, menu_item_alloc_function("Test", NULL, nfc_test_callback, nfc)); | ||||||
|     menu_item_subitem_add( |     menu_item_subitem_add( | ||||||
| @ -240,12 +244,6 @@ Nfc* nfc_alloc() { | |||||||
|     menu_item_subitem_add( |     menu_item_subitem_add( | ||||||
|         nfc->menu, menu_item_alloc_function("Brdige", NULL, nfc_bridge_callback, nfc)); |         nfc->menu, menu_item_alloc_function("Brdige", NULL, nfc_bridge_callback, nfc)); | ||||||
| 
 | 
 | ||||||
|     nfc->gui_record = furi_open_deprecated("gui", false, false, NULL, NULL, NULL); |  | ||||||
|     assert(nfc->gui_record); |  | ||||||
| 
 |  | ||||||
|     nfc->menu_record = furi_open_deprecated("menu", false, false, NULL, NULL, NULL); |  | ||||||
|     assert(nfc->menu_record); |  | ||||||
| 
 |  | ||||||
|     nfc->worker_attr.name = "nfc_worker"; |     nfc->worker_attr.name = "nfc_worker"; | ||||||
|     // nfc->worker_attr.attr_bits = osThreadJoinable;
 |     // nfc->worker_attr.attr_bits = osThreadJoinable;
 | ||||||
|     nfc->worker_attr.stack_size = 4096; |     nfc->worker_attr.stack_size = 4096; | ||||||
| @ -255,29 +253,27 @@ Nfc* nfc_alloc() { | |||||||
| void nfc_task(void* p) { | void nfc_task(void* p) { | ||||||
|     Nfc* nfc = nfc_alloc(); |     Nfc* nfc = nfc_alloc(); | ||||||
| 
 | 
 | ||||||
|     GuiApi* gui = furi_take(nfc->gui_record); |     FuriRecordSubscriber* gui_record = furi_open_deprecated("gui", false, false, NULL, NULL, NULL); | ||||||
|  |     assert(gui_record); | ||||||
|  |     GuiApi* gui = furi_take(gui_record); | ||||||
|     assert(gui); |     assert(gui); | ||||||
|     widget_enabled_set(nfc->widget, false); |     widget_enabled_set(nfc->widget, false); | ||||||
|     gui->add_widget(gui, nfc->widget, WidgetLayerFullscreen); |     gui->add_widget(gui, nfc->widget, GuiLayerFullscreen); | ||||||
|     furi_commit(nfc->gui_record); |     furi_commit(gui_record); | ||||||
| 
 | 
 | ||||||
|     ValueMutex* menu_mutex = furi_open("menu"); |     with_value_mutex( | ||||||
|     assert(menu_mutex); |         nfc->menu_vm, (Menu * menu) { menu_item_add(menu, nfc->menu); }); | ||||||
| 
 |  | ||||||
|     Menu* menu = acquire_mutex_block(menu_mutex); |  | ||||||
|     menu_item_add(menu, nfc->menu); |  | ||||||
|     release_mutex(menu_mutex, menu); |  | ||||||
| 
 | 
 | ||||||
|     if(!furi_create("nfc", nfc)) { |     if(!furi_create("nfc", nfc)) { | ||||||
|         printf("[nfc_task] cannot create nfc record\n"); |         printf("[nfc_task] cannot create nfc record\n"); | ||||||
|         furiac_exit(NULL); |         furiac_exit(NULL); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     furiac_ready(); |  | ||||||
| 
 |  | ||||||
|     nfc->ret = rfalNfcInitialize(); |     nfc->ret = rfalNfcInitialize(); | ||||||
|     rfalLowPowerModeStart(); |     rfalLowPowerModeStart(); | ||||||
| 
 | 
 | ||||||
|  |     furiac_ready(); | ||||||
|  | 
 | ||||||
|     NfcMessage message; |     NfcMessage message; | ||||||
|     while(1) { |     while(1) { | ||||||
|         dispatcher_recieve(nfc->dispatcher, (Message*)&message); |         dispatcher_recieve(nfc->dispatcher, (Message*)&message); | ||||||
|  | |||||||
							
								
								
									
										1
									
								
								assets/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								assets/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | /headers | ||||||
							
								
								
									
										17
									
								
								assets/ReadMe.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								assets/ReadMe.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | |||||||
|  | # Asset naming rules | ||||||
|  | 
 | ||||||
|  | ## Images and Animations | ||||||
|  | 
 | ||||||
|  | `NAME_VARIANT_SIZE` | ||||||
|  | 
 | ||||||
|  | - `NAME`    - mandatory - Asset name in CamelCase. [A-Za-z0-9], special symbols not allowed | ||||||
|  | - `VARIANT` - optional  - icon variant: can relate to state or rendering conditions. Examples: active, inactive, inverted. | ||||||
|  | - `SIZE`    - mandatory - size in px. Example squere 10, 20, 24, etc. Example rectangular: 10x8, 19x5, etc. | ||||||
|  | 
 | ||||||
|  | Image names will be automatically prefixed with `I_`, animation names with `A_`. | ||||||
|  | Icons and Animations will be gathered into `icon.h` and `icon.c`. | ||||||
|  | 
 | ||||||
|  | # Important notes | ||||||
|  | 
 | ||||||
|  | Don't include assets that you are not using, compiller is not going to strip unusued assets. | ||||||
|  | 
 | ||||||
							
								
								
									
										10
									
								
								assets/assets.mk
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								assets/assets.mk
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | |||||||
|  | ASSETS_DIR			:= $(PROJECT_ROOT)/assets | ||||||
|  | ASSETS_COMPILLER	:= $(ASSETS_DIR)/assets.py | ||||||
|  | ASSETS_OUTPUT_DIR	:= $(ASSETS_DIR)/output | ||||||
|  | ASSETS_SOURCE_DIR	:= $(ASSETS_DIR)/icons | ||||||
|  | 
 | ||||||
|  | ASSETS_SOURCES		+= $(shell find $(ASSETS_SOURCE_DIR) -type f -iname '*.png' -or -iname 'frame_rate') | ||||||
|  | ASSETS				+= $(ASSETS_OUTPUT_DIR)/assets_icons.c | ||||||
|  | 
 | ||||||
|  | CFLAGS				+= -I$(ASSETS_OUTPUT_DIR) | ||||||
|  | C_SOURCES			+= $(ASSETS_OUTPUT_DIR)/assets_icons.c | ||||||
							
								
								
									
										184
									
								
								assets/assets.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										184
									
								
								assets/assets.py
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,184 @@ | |||||||
|  | #!/usr/bin/env python3 | ||||||
|  | 
 | ||||||
|  | import logging | ||||||
|  | import argparse | ||||||
|  | import subprocess | ||||||
|  | import io | ||||||
|  | import os | ||||||
|  | import sys | ||||||
|  | 
 | ||||||
|  | ICONS_SUPPORTED_FORMATS = ["png"] | ||||||
|  | 
 | ||||||
|  | ICONS_TEMPLATE_H_HEADER = """#pragma once | ||||||
|  | 
 | ||||||
|  | #include <gui/icon.h> | ||||||
|  | 
 | ||||||
|  | typedef enum { | ||||||
|  | """ | ||||||
|  | ICONS_TEMPLATE_H_ICON_NAME = "\t{name},\n" | ||||||
|  | ICONS_TEMPLATE_H_FOOTER = """} IconName; | ||||||
|  | 
 | ||||||
|  | Icon * assets_icons_get(IconName name); | ||||||
|  | """ | ||||||
|  | 
 | ||||||
|  | ICONS_TEMPLATE_C_HEADER = """#include \"assets_icons.h\" | ||||||
|  | #include <gui/icon_i.h> | ||||||
|  | 
 | ||||||
|  | """ | ||||||
|  | ICONS_TEMPLATE_C_FRAME = "const uint8_t {name}[] = {data};\n" | ||||||
|  | ICONS_TEMPLATE_C_DATA = "const uint8_t *{name}[] = {data};\n" | ||||||
|  | ICONS_TEMPLATE_C_ICONS_ARRAY_START = "const IconData icons[] = {\n" | ||||||
|  | ICONS_TEMPLATE_C_ICONS_ITEM = "\t{{ .width={width}, .height={height}, .frame_count={frame_count}, .frame_rate={frame_rate}, .frames=_{name} }},\n" | ||||||
|  | ICONS_TEMPLATE_C_ICONS_ARRAY_END = "};" | ||||||
|  | ICONS_TEMPLATE_C_FOOTER = """ | ||||||
|  | 
 | ||||||
|  | Icon * assets_icons_get(IconName name) { | ||||||
|  |     return icon_alloc(&icons[name]); | ||||||
|  | } | ||||||
|  | """ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Assets: | ||||||
|  |     def __init__(self): | ||||||
|  |         # command args | ||||||
|  |         self.parser = argparse.ArgumentParser() | ||||||
|  |         self.parser.add_argument("-d", "--debug", action="store_true", help="Debug") | ||||||
|  |         self.subparsers = self.parser.add_subparsers(help="sub-command help") | ||||||
|  |         self.parser_icons = self.subparsers.add_parser( | ||||||
|  |             "icons", help="Process icons and build icon registry" | ||||||
|  |         ) | ||||||
|  |         self.parser_icons.add_argument( | ||||||
|  |             "-s", "--source-directory", help="Source directory" | ||||||
|  |         ) | ||||||
|  |         self.parser_icons.add_argument( | ||||||
|  |             "-o", "--output-directory", help="Output directory" | ||||||
|  |         ) | ||||||
|  |         self.parser_icons.set_defaults(func=self.icons) | ||||||
|  |         # logging | ||||||
|  |         self.logger = logging.getLogger() | ||||||
|  | 
 | ||||||
|  |     def __call__(self): | ||||||
|  |         self.args = self.parser.parse_args() | ||||||
|  |         if "func" not in self.args: | ||||||
|  |             self.parser.error("Choose something to do") | ||||||
|  |         # configure log output | ||||||
|  |         self.log_level = logging.DEBUG if self.args.debug else logging.INFO | ||||||
|  |         self.logger.setLevel(self.log_level) | ||||||
|  |         self.handler = logging.StreamHandler(sys.stdout) | ||||||
|  |         self.handler.setLevel(self.log_level) | ||||||
|  |         self.formatter = logging.Formatter("%(asctime)s [%(levelname)s] %(message)s") | ||||||
|  |         self.handler.setFormatter(self.formatter) | ||||||
|  |         self.logger.addHandler(self.handler) | ||||||
|  |         # execute requested function | ||||||
|  |         self.args.func() | ||||||
|  | 
 | ||||||
|  |     def icons(self): | ||||||
|  |         self.logger.debug(f"Converting icons") | ||||||
|  |         icons_c = open(os.path.join(self.args.output_directory, "assets_icons.c"), "w") | ||||||
|  |         icons_c.write(ICONS_TEMPLATE_C_HEADER) | ||||||
|  |         icons = [] | ||||||
|  |         # Traverse icons tree, append image data to source file | ||||||
|  |         for dirpath, dirnames, filenames in os.walk(self.args.source_directory): | ||||||
|  |             self.logger.debug(f"Processing directory {dirpath}") | ||||||
|  |             if not filenames: | ||||||
|  |                 continue | ||||||
|  |             if "frame_rate" in filenames: | ||||||
|  |                 self.logger.debug(f"Folder contatins animation") | ||||||
|  |                 icon_name = "A_" + os.path.split(dirpath)[1].replace("-", "_") | ||||||
|  |                 width = height = None | ||||||
|  |                 frame_count = 0 | ||||||
|  |                 frame_rate = 0 | ||||||
|  |                 frame_names = [] | ||||||
|  |                 for filename in sorted(filenames): | ||||||
|  |                     fullfilename = os.path.join(dirpath, filename) | ||||||
|  |                     if filename == "frame_rate": | ||||||
|  |                         frame_rate = int(open(fullfilename, "r").read().strip()) | ||||||
|  |                         continue | ||||||
|  |                     elif not self.iconIsSupported(filename): | ||||||
|  |                         continue | ||||||
|  |                     self.logger.debug(f"Processing animation frame {filename}") | ||||||
|  |                     temp_width, temp_height, data = self.icon2header(fullfilename) | ||||||
|  |                     if width is None: | ||||||
|  |                         width = temp_width | ||||||
|  |                     if height is None: | ||||||
|  |                         height = temp_height | ||||||
|  |                     assert width == temp_width | ||||||
|  |                     assert height == temp_height | ||||||
|  |                     frame_name = f"_{icon_name}_{frame_count}" | ||||||
|  |                     frame_names.append(frame_name) | ||||||
|  |                     icons_c.write( | ||||||
|  |                         ICONS_TEMPLATE_C_FRAME.format(name=frame_name, data=data) | ||||||
|  |                     ) | ||||||
|  |                     frame_count += 1 | ||||||
|  |                 assert frame_rate > 0 | ||||||
|  |                 assert frame_count > 0 | ||||||
|  |                 icons_c.write( | ||||||
|  |                     ICONS_TEMPLATE_C_DATA.format( | ||||||
|  |                         name=f"_{icon_name}", data=f'{{{",".join(frame_names)}}}' | ||||||
|  |                     ) | ||||||
|  |                 ) | ||||||
|  |                 icons_c.write("\n") | ||||||
|  |                 icons.append((icon_name, width, height, frame_rate, frame_count)) | ||||||
|  |             else: | ||||||
|  |                 # process icons | ||||||
|  |                 for filename in filenames: | ||||||
|  |                     if not self.iconIsSupported(filename): | ||||||
|  |                         continue | ||||||
|  |                     self.logger.debug(f"Processing icon {filename}") | ||||||
|  |                     icon_name = "I_" + "_".join(filename.split(".")[:-1]).replace( | ||||||
|  |                         "-", "_" | ||||||
|  |                     ) | ||||||
|  |                     fullfilename = os.path.join(dirpath, filename) | ||||||
|  |                     width, height, data = self.icon2header(fullfilename) | ||||||
|  |                     frame_name = f"_{icon_name}_0" | ||||||
|  |                     icons_c.write( | ||||||
|  |                         ICONS_TEMPLATE_C_FRAME.format(name=frame_name, data=data) | ||||||
|  |                     ) | ||||||
|  |                     icons_c.write( | ||||||
|  |                         ICONS_TEMPLATE_C_DATA.format( | ||||||
|  |                             name=f"_{icon_name}", data=f"{{{frame_name}}}" | ||||||
|  |                         ) | ||||||
|  |                     ) | ||||||
|  |                     icons_c.write("\n") | ||||||
|  |                     icons.append((icon_name, width, height, 0, 1)) | ||||||
|  |         # Create array of images: | ||||||
|  |         self.logger.debug(f"Finalizing source file") | ||||||
|  |         icons_c.write(ICONS_TEMPLATE_C_ICONS_ARRAY_START) | ||||||
|  |         for name, width, height, frame_rate, frame_count in icons: | ||||||
|  |             icons_c.write( | ||||||
|  |                 ICONS_TEMPLATE_C_ICONS_ITEM.format( | ||||||
|  |                     name=name, | ||||||
|  |                     width=width, | ||||||
|  |                     height=height, | ||||||
|  |                     frame_rate=frame_rate, | ||||||
|  |                     frame_count=frame_count, | ||||||
|  |                 ) | ||||||
|  |             ) | ||||||
|  |         icons_c.write(ICONS_TEMPLATE_C_ICONS_ARRAY_END) | ||||||
|  |         icons_c.write(ICONS_TEMPLATE_C_FOOTER) | ||||||
|  |         icons_c.write("\n") | ||||||
|  |         # Create Header | ||||||
|  |         self.logger.debug(f"Creating header") | ||||||
|  |         icons_h = open(os.path.join(self.args.output_directory, "assets_icons.h"), "w") | ||||||
|  |         icons_h.write(ICONS_TEMPLATE_H_HEADER) | ||||||
|  |         for name, width, height, frame_rate, frame_count in icons: | ||||||
|  |             icons_h.write(ICONS_TEMPLATE_H_ICON_NAME.format(name=name)) | ||||||
|  |         icons_h.write(ICONS_TEMPLATE_H_FOOTER) | ||||||
|  |         self.logger.debug(f"Done") | ||||||
|  | 
 | ||||||
|  |     def icon2header(self, file): | ||||||
|  |         output = subprocess.check_output(["convert", file, "xbm:-"]) | ||||||
|  |         assert output | ||||||
|  |         f = io.StringIO(output.decode().strip()) | ||||||
|  |         width = int(f.readline().strip().split(" ")[2]) | ||||||
|  |         height = int(f.readline().strip().split(" ")[2]) | ||||||
|  |         data = f.read().strip().replace("\n", "").replace(" ", "").split("=")[1][:-1] | ||||||
|  |         return width, height, data | ||||||
|  | 
 | ||||||
|  |     def iconIsSupported(self, filename): | ||||||
|  |         extension = filename.lower().split(".")[-1] | ||||||
|  |         return extension in ICONS_SUPPORTED_FORMATS | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | if __name__ == "__main__": | ||||||
|  |     Assets()() | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/125khz_14/frame_01.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/125khz_14/frame_01.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:e3b8745f1c3cf2b3b5023d40cb2fde21afdb44f4eff3e456e2bd4eafbccb17f1 | ||||||
|  | size 257 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/125khz_14/frame_02.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/125khz_14/frame_02.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:6d24e445214cfc96ed699ad7f6fc5966e6fef08a7fe36add479e7b02e1458b4c | ||||||
|  | size 257 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/125khz_14/frame_03.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/125khz_14/frame_03.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:27f19713ab1d7b6113fb2f8a0402c93a763652e6b2c28693a858f26cce1acb6d | ||||||
|  | size 249 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/125khz_14/frame_04.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/125khz_14/frame_04.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:37271fbd71ebe1561fb4a292504d8692367c588688c534c3b9ce7122439bdca0 | ||||||
|  | size 255 | ||||||
							
								
								
									
										1
									
								
								assets/icons/MainMenu/125khz_14/frame_rate
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								assets/icons/MainMenu/125khz_14/frame_rate
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | 3 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/Bluetooth_14/frame_01.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/Bluetooth_14/frame_01.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:470df999ccb281350e21e86f5f21235f23ceed5fd2391d435af3b073403962ad | ||||||
|  | size 252 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/Bluetooth_14/frame_02.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/Bluetooth_14/frame_02.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:22b29a0bc9a2aa4c5258edd18def520813eefe6a028036b0f95629217565e814 | ||||||
|  | size 251 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/Bluetooth_14/frame_03.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/Bluetooth_14/frame_03.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:67fd7032e3b6bad02a2d8e58b1f9c3d10a77e3c8ed48b5819047ae35e98b405e | ||||||
|  | size 251 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/Bluetooth_14/frame_04.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/Bluetooth_14/frame_04.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:969215f7462ad2d4fdf053bf67ee3a912d46debe87815e10554b58399f2c4d20 | ||||||
|  | size 248 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/Bluetooth_14/frame_05.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/Bluetooth_14/frame_05.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:c1154e6634b065ab40849236a3172284ce1e7dd4fd7212a1ca4bdc5b48a26ffa | ||||||
|  | size 249 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/Bluetooth_14/frame_06.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/Bluetooth_14/frame_06.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:811a93e5b8770c2578be16c5cedce9663aa8608f7061c29cba949daf94a93b48 | ||||||
|  | size 251 | ||||||
							
								
								
									
										1
									
								
								assets/icons/MainMenu/Bluetooth_14/frame_rate
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								assets/icons/MainMenu/Bluetooth_14/frame_rate
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | 3 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/FileManager_14/frame_01.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/FileManager_14/frame_01.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:dbe853e0056d3b93e7beba725a660a6a8186562c2be20745aea3b2f30bcbbf91 | ||||||
|  | size 254 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/FileManager_14/frame_02.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/FileManager_14/frame_02.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:f7076f51c03ad1e5f2f9ab00679b1142a37224caa3a44b3ea272fec94a806cf5 | ||||||
|  | size 255 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/FileManager_14/frame_03.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/FileManager_14/frame_03.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:db95faeadfd4aeb9d7b56cb10f67a945d56f6d3c7199d066903d436ef2f0ceaa | ||||||
|  | size 249 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/FileManager_14/frame_04.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/FileManager_14/frame_04.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:267da4a3a640c4a75aa2d06ffd057c9ec10308137e0f73378a638ce96c3e9f19 | ||||||
|  | size 249 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/FileManager_14/frame_05.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/FileManager_14/frame_05.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:c88f44fcffc7ade9cfb1bcfc9dbd687776211a3d57e8278e75fbf19376d462fa | ||||||
|  | size 249 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/FileManager_14/frame_06.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/FileManager_14/frame_06.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:160e99941884fd6ac6ce19830a3b39cdc7197881689b8cbc0b3761be561c1cf7 | ||||||
|  | size 237 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/FileManager_14/frame_07.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/FileManager_14/frame_07.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:c88f44fcffc7ade9cfb1bcfc9dbd687776211a3d57e8278e75fbf19376d462fa | ||||||
|  | size 249 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/FileManager_14/frame_08.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/FileManager_14/frame_08.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:267da4a3a640c4a75aa2d06ffd057c9ec10308137e0f73378a638ce96c3e9f19 | ||||||
|  | size 249 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/FileManager_14/frame_09.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/FileManager_14/frame_09.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:db95faeadfd4aeb9d7b56cb10f67a945d56f6d3c7199d066903d436ef2f0ceaa | ||||||
|  | size 249 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/FileManager_14/frame_10.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/FileManager_14/frame_10.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:f7076f51c03ad1e5f2f9ab00679b1142a37224caa3a44b3ea272fec94a806cf5 | ||||||
|  | size 255 | ||||||
							
								
								
									
										1
									
								
								assets/icons/MainMenu/FileManager_14/frame_rate
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								assets/icons/MainMenu/FileManager_14/frame_rate
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | 3 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/GPIO_14/frame_01.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/GPIO_14/frame_01.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:9ab102ccd1b92236bed296eb3cdb4dc088fca6fa7e32e72d752b49e4012ffcff | ||||||
|  | size 242 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/GPIO_14/frame_02.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/GPIO_14/frame_02.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:588fabc1c63bd8815aaf61c8b8b6a7e88ef12a210f8ce04ecec6a75c4eaa48dd | ||||||
|  | size 237 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/GPIO_14/frame_03.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/GPIO_14/frame_03.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:66d2f7c971c180f7ea27c90aaf1ffeb8f62584c8fbd7c390fcda3165ecd9cdb2 | ||||||
|  | size 236 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/GPIO_14/frame_04.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/GPIO_14/frame_04.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:d4a40f59194adb698cac9472a14ac34a7e0b56e6251f157d11982bdff0f88745 | ||||||
|  | size 235 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/GPIO_14/frame_05.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/GPIO_14/frame_05.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:4ad47da62b20627fd428ec857cbadb14803d41702b639c72e820aa8759fbf424 | ||||||
|  | size 231 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/GPIO_14/frame_06.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/GPIO_14/frame_06.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:ededf42eb58de6082fc9f97abc73b053417f2421c547cd2f3aa9814d0eb985ab | ||||||
|  | size 235 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/GPIO_14/frame_07.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/GPIO_14/frame_07.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:44ef494e78d60728791a632dedad8a374fcd863e4a1d409c565bd7f11e142e52 | ||||||
|  | size 235 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/GPIO_14/frame_08.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/GPIO_14/frame_08.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:05e946f15d71eae155c5a6438cea4f5ad56ef310577fb894ebe5c3b41f9e2e24 | ||||||
|  | size 237 | ||||||
							
								
								
									
										1
									
								
								assets/icons/MainMenu/GPIO_14/frame_rate
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								assets/icons/MainMenu/GPIO_14/frame_rate
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | 3 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/Infrared_14/frame_01.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/Infrared_14/frame_01.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:b101d691964aa96546bb70bb08f638b48c6000230ded6597ac533b0bd36a8c86 | ||||||
|  | size 250 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/Infrared_14/frame_02.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/Infrared_14/frame_02.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:5322b1c4366b8931d132292c71318f02e6756536dd38165a1f65dea5c9dfb7b2 | ||||||
|  | size 247 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/Infrared_14/frame_03.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/Infrared_14/frame_03.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:da8a0d2055a7a835be42bde6f71ba2d17710ad308201946fb07d97207c32e3c4 | ||||||
|  | size 243 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/Infrared_14/frame_04.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/Infrared_14/frame_04.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:04bb17687f4b0572b4ffd7c7220cb0070456b95df9849fb55e620d02fd7fee94 | ||||||
|  | size 235 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/Infrared_14/frame_05.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/Infrared_14/frame_05.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:1eafe712679be62faa958b2a648a514a461c08ae846ae942888cf7f22d6c3deb | ||||||
|  | size 235 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/Infrared_14/frame_06.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/Infrared_14/frame_06.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:e58c3bbcfec585b2f920b06b7464dba32686571156c59a46265d599222c7331a | ||||||
|  | size 243 | ||||||
							
								
								
									
										1
									
								
								assets/icons/MainMenu/Infrared_14/frame_rate
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								assets/icons/MainMenu/Infrared_14/frame_rate
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | 3 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/NFC_14/frame_01.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/NFC_14/frame_01.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:3430783069a7fa3763bc1cbe6d251540128237249ab8268c666ee180715b6d36 | ||||||
|  | size 256 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/NFC_14/frame_02.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/NFC_14/frame_02.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:95ed4aa304cb3e7de4aa536fb67df8cd5b6413cb67f77924729d31015f298262 | ||||||
|  | size 250 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/NFC_14/frame_03.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/NFC_14/frame_03.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:2cb767e8560b1b7f25226aa1a0fc2c46625bbf94df77fcdbdb4b14834616e762 | ||||||
|  | size 244 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/NFC_14/frame_04.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/NFC_14/frame_04.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:00cac0303198a2baa9243b0466e755d98a408587d73c1899532a86aeb75a80c5 | ||||||
|  | size 247 | ||||||
							
								
								
									
										1
									
								
								assets/icons/MainMenu/NFC_14/frame_rate
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								assets/icons/MainMenu/NFC_14/frame_rate
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | 3 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/Sub1ghz_14/frame_01.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/Sub1ghz_14/frame_01.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:227acbe3f7482e1efefc11b0cf8734f01062540db99accb969a521907d58c693 | ||||||
|  | size 249 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/Sub1ghz_14/frame_02.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/Sub1ghz_14/frame_02.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:ebe14fca1ff8d5093a05d4d452c9ee55eb7bf48d8b8fc71f98a74476e703d030 | ||||||
|  | size 248 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/Sub1ghz_14/frame_03.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/Sub1ghz_14/frame_03.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:7b1b5373cf67c493b77dfcc5821754c8ec0c41eee633f81059e9507ce8102a27 | ||||||
|  | size 242 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/Sub1ghz_14/frame_04.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/Sub1ghz_14/frame_04.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:b12e03c09e699a5446bac1ad67bdf34e299b65e49995664e30bc8e14500dd26f | ||||||
|  | size 228 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/Sub1ghz_14/frame_05.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/Sub1ghz_14/frame_05.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:9592833f1c810b9939e5a213f448c090f86dbf75bf7721ca85a6c166ebc79a6c | ||||||
|  | size 231 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/Sub1ghz_14/frame_06.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/Sub1ghz_14/frame_06.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:950f24058fd92684f1665e280f740ce662e078d03c0e59a546d21d4569f691a8 | ||||||
|  | size 242 | ||||||
							
								
								
									
										1
									
								
								assets/icons/MainMenu/Sub1ghz_14/frame_rate
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								assets/icons/MainMenu/Sub1ghz_14/frame_rate
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | 3 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/Tamagotchi_14/frame_01.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/Tamagotchi_14/frame_01.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:68bda2a589f180b9e5231d74eab098cdaedc08ad44d74b37f3a69e6570799c42 | ||||||
|  | size 258 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/Tamagotchi_14/frame_02.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/Tamagotchi_14/frame_02.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:dfd4f583da99e73e11abb5acbb1235cf49acf6d61e337ad6c702cba1d8ff5ed6 | ||||||
|  | size 258 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/Tamagotchi_14/frame_03.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/Tamagotchi_14/frame_03.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:77ba2d0d27048bdc0d1b8faaef530e019c5ca2a7966c6d2e84bc4206c220a3a4 | ||||||
|  | size 258 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/Tamagotchi_14/frame_04.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/Tamagotchi_14/frame_04.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:bcb7b3c96a531cea583ec917a26037bce04e1704c0e96c096d88bd164891d3b8 | ||||||
|  | size 258 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/Tamagotchi_14/frame_05.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/Tamagotchi_14/frame_05.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:2ee856a02fb0c0b7e9f59825ce80d008bbdfde10d733db25ae2accac3cae7fb4 | ||||||
|  | size 258 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/Tamagotchi_14/frame_06.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/Tamagotchi_14/frame_06.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:159ed78bae7c6ba8b91dbd5fc72475478852c667bdece15f68f318bfdfd7a0fc | ||||||
|  | size 258 | ||||||
							
								
								
									
										1
									
								
								assets/icons/MainMenu/Tamagotchi_14/frame_rate
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								assets/icons/MainMenu/Tamagotchi_14/frame_rate
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | 3 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/U2F_14/frame_01.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/U2F_14/frame_01.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:11043601935b50e020ea672ed8aa8dddbec56a6925abd2cb6cfedf965c54e73b | ||||||
|  | size 256 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/U2F_14/frame_02.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/U2F_14/frame_02.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:abd8be6bfec3facb698a2c248f6ef75f0411d4ee75a0fc653959c5d07b4dab5e | ||||||
|  | size 255 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/U2F_14/frame_03.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/U2F_14/frame_03.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:75000555e5119e163d9b3afd28861e78347acfb1bf2f704e731a26d994edd1ff | ||||||
|  | size 254 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/U2F_14/frame_04.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/U2F_14/frame_04.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:abd8be6bfec3facb698a2c248f6ef75f0411d4ee75a0fc653959c5d07b4dab5e | ||||||
|  | size 255 | ||||||
							
								
								
									
										1
									
								
								assets/icons/MainMenu/U2F_14/frame_rate
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								assets/icons/MainMenu/U2F_14/frame_rate
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | |||||||
|  | 3 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/iButton_14/frame_01.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/iButton_14/frame_01.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:22cbd3b5f4c41d2ede7b89d1d4212f3da0b7da815d2bc219f95106d06424f3f2 | ||||||
|  | size 256 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/iButton_14/frame_02.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/iButton_14/frame_02.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:6f75d8bb8a4c2c67855053ca7eedf2ce724937b246a3b5a5cf95b8df6122116c | ||||||
|  | size 260 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/iButton_14/frame_03.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/iButton_14/frame_03.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:527ebea445642be096f4bd5209af3b7b74c53e688cea5d29de6d40dad31d08ca | ||||||
|  | size 256 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/iButton_14/frame_04.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/iButton_14/frame_04.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:ee6e95dbe9aae5a16504d42d94b24f8c3ef44108ddb726c43faec09d3cbedb7e | ||||||
|  | size 260 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/iButton_14/frame_05.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/iButton_14/frame_05.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:2b12ea1162db6e239562eff4cc434f4aaf86fe00b5c371805d801780a1e54258 | ||||||
|  | size 252 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/iButton_14/frame_06.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/iButton_14/frame_06.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:93c876d79ec21c394233392f6356d24078904a81f46e354ae591757287f074e7 | ||||||
|  | size 255 | ||||||
							
								
								
									
										3
									
								
								assets/icons/MainMenu/iButton_14/frame_07.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								assets/icons/MainMenu/iButton_14/frame_07.png
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,3 @@ | |||||||
|  | version https://git-lfs.github.com/spec/v1 | ||||||
|  | oid sha256:901b67368cd1df6f767200c021e180427830168496fe5dcc48b05bf51fcc0f38 | ||||||
|  | size 262 | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 あく
						あく