[FL-1995] New dolphin animations (part 1) (#835)
* Desktop Animation (part 1): Ugly naked ohmygod architecture
* fix butthurt, fix locked scene
* Change SD icons, fixes
* Fix level update animation
* Fixes, correct butthurt
* Clean up code
* furi_assert(0) -> furi_crash("msg")
* Gui: rename none layer to desktop, update docs.
Co-authored-by: あく <alleteam@gmail.com>
			
			
This commit is contained in:
		| @@ -1,28 +1,365 @@ | ||||
| #include "desktop_animation.h" | ||||
| #include "desktop/helpers/desktop_animation.h" | ||||
| #include "assets_icons.h" | ||||
| #include "desktop_animation_i.h" | ||||
| #include "cmsis_os2.h" | ||||
| #include "furi/common_defines.h" | ||||
| #include "furi/record.h" | ||||
| #include "storage/filesystem-api-defines.h" | ||||
| #include <power/power_service/power.h> | ||||
| #include <m-list.h> | ||||
| #include <storage/storage.h> | ||||
| #include <desktop/desktop.h> | ||||
| #include <dolphin/dolphin.h> | ||||
|  | ||||
| #define TAG "DesktopAnimation" | ||||
| LIST_DEF(AnimationList, const PairedAnimation*, M_PTR_OPLIST) | ||||
| #define M_OPL_AnimationList_t() LIST_OPLIST(AnimationList) | ||||
|  | ||||
| static const Icon* idle_scenes[] = {&A_Wink_128x64, &A_WatchingTV_128x64}; | ||||
| #define PUSH_BACK_ANIMATIONS(listname, animations, butthurt)                          \ | ||||
|     for(int i = 0; i < COUNT_OF(animations); ++i) {                                   \ | ||||
|         if(!(animations)[i].basic->butthurt_level_mask ||                             \ | ||||
|            ((animations)[i].basic->butthurt_level_mask & BUTTHURT_LEVEL(butthurt))) { \ | ||||
|             AnimationList_push_back(animation_list, &(animations)[i]);                \ | ||||
|         }                                                                             \ | ||||
|     } | ||||
|  | ||||
| const Icon* desktop_get_icon() { | ||||
|     uint8_t new = 0; | ||||
| #define IS_BLOCKING_ANIMATION(x) \ | ||||
|     (((x) != DesktopAnimationStateBasic) && ((x) != DesktopAnimationStateActive)) | ||||
| #define IS_ONESHOT_ANIMATION(x) ((x) == DesktopAnimationStateLevelUpIsPending) | ||||
|  | ||||
| #if 0 | ||||
|     // checking dolphin state here to choose appropriate animation | ||||
| static void desktop_animation_timer_callback(void* context); | ||||
|  | ||||
| struct DesktopAnimation { | ||||
|     bool sd_shown_error_db; | ||||
|     bool sd_shown_error_card_bad; | ||||
|     osTimerId_t timer; | ||||
|     const PairedAnimation* current; | ||||
|     const Icon* current_blocking_icon; | ||||
|     const Icon** current_one_shot_icons; | ||||
|     uint8_t one_shot_animation_counter; | ||||
|     uint8_t one_shot_animation_size; | ||||
|     DesktopAnimationState state; | ||||
|     TickType_t basic_started_at; | ||||
|     TickType_t active_finished_at; | ||||
|     AnimationChangedCallback animation_changed_callback; | ||||
|     void* animation_changed_callback_context; | ||||
| }; | ||||
|  | ||||
| DesktopAnimation* desktop_animation_alloc(void) { | ||||
|     DesktopAnimation* animation = furi_alloc(sizeof(DesktopAnimation)); | ||||
|  | ||||
|     animation->timer = osTimerNew( | ||||
|         desktop_animation_timer_callback, osTimerPeriodic /* osTimerOnce */, animation, NULL); | ||||
|     animation->active_finished_at = (TickType_t)(-30); | ||||
|     animation->basic_started_at = 0; | ||||
|     animation->animation_changed_callback = NULL; | ||||
|     animation->animation_changed_callback_context = NULL; | ||||
|     desktop_start_new_idle_animation(animation); | ||||
|  | ||||
|     return animation; | ||||
| } | ||||
|  | ||||
| void desktop_animation_free(DesktopAnimation* animation) { | ||||
|     furi_assert(animation); | ||||
|  | ||||
|     osTimerDelete(animation->timer); | ||||
|     free(animation); | ||||
| } | ||||
|  | ||||
| void desktop_animation_set_animation_changed_callback( | ||||
|     DesktopAnimation* animation, | ||||
|     AnimationChangedCallback callback, | ||||
|     void* context) { | ||||
|     furi_assert(animation); | ||||
|  | ||||
|     animation->animation_changed_callback = callback; | ||||
|     animation->animation_changed_callback_context = context; | ||||
| } | ||||
|  | ||||
| void desktop_start_new_idle_animation(DesktopAnimation* animation) { | ||||
|     Dolphin* dolphin = furi_record_open("dolphin"); | ||||
|     DolphinStats stats = dolphin_stats(dolphin); | ||||
|     furi_record_close("dolphin"); | ||||
|  | ||||
|     furi_assert((stats.level >= 1) && (stats.level <= 3)); | ||||
|     uint8_t level = stats.level; | ||||
|  | ||||
|     AnimationList_t animation_list; | ||||
|     AnimationList_init(animation_list); | ||||
|  | ||||
|     PUSH_BACK_ANIMATIONS(animation_list, mad_animation, stats.butthurt); | ||||
|     PUSH_BACK_ANIMATIONS(animation_list, calm_animation, stats.butthurt); | ||||
|     switch(level) { | ||||
|     case 1: | ||||
|         PUSH_BACK_ANIMATIONS(animation_list, level_1_animation, stats.butthurt); | ||||
|         break; | ||||
|     case 2: | ||||
|         PUSH_BACK_ANIMATIONS(animation_list, level_2_animation, stats.butthurt); | ||||
|         break; | ||||
|     case 3: | ||||
|         PUSH_BACK_ANIMATIONS(animation_list, level_3_animation, stats.butthurt); | ||||
|         break; | ||||
|     default: | ||||
|         furi_crash("Dolphin level is out of bounds"); | ||||
|     } | ||||
|  | ||||
|     Power* power = furi_record_open("power"); | ||||
|     PowerInfo info; | ||||
|     power_get_info(power, &info); | ||||
|  | ||||
|     if(!power_is_battery_well(&info)) { | ||||
|         PUSH_BACK_ANIMATIONS(animation_list, check_battery_animation, stats.butthurt); | ||||
|     } | ||||
|  | ||||
|     Storage* storage = furi_record_open("storage"); | ||||
|     FS_Error sd_status = storage_sd_status(storage); | ||||
|     animation->current = NULL; | ||||
|  | ||||
|     if(sd_status == FSE_NOT_READY) { | ||||
|         PUSH_BACK_ANIMATIONS(animation_list, no_sd_animation, stats.butthurt); | ||||
|         animation->sd_shown_error_card_bad = false; | ||||
|         animation->sd_shown_error_db = false; | ||||
|     } | ||||
|  | ||||
|     uint32_t whole_weight = 0; | ||||
|     for | ||||
|         M_EACH(item, animation_list, AnimationList_t) { | ||||
|             whole_weight += (*item)->basic->weight; | ||||
|         } | ||||
|  | ||||
|     uint32_t lucky_number = random() % whole_weight; | ||||
|     uint32_t weight = 0; | ||||
|  | ||||
|     const PairedAnimation* selected = NULL; | ||||
|     for | ||||
|         M_EACH(item, animation_list, AnimationList_t) { | ||||
|             if(lucky_number < weight) { | ||||
|                 break; | ||||
|             } | ||||
|             weight += (*item)->basic->weight; | ||||
|             selected = *item; | ||||
|         } | ||||
|     animation->basic_started_at = osKernelGetTickCount(); | ||||
|     animation->current = selected; | ||||
|     osTimerStart(animation->timer, animation->current->basic->duration * 1000); | ||||
|     animation->state = DesktopAnimationStateBasic; | ||||
|     furi_assert(selected); | ||||
|     AnimationList_clear(animation_list); | ||||
| } | ||||
|  | ||||
| static void desktop_animation_timer_callback(void* context) { | ||||
|     furi_assert(context); | ||||
|     DesktopAnimation* animation = context; | ||||
|     TickType_t now_ms = osKernelGetTickCount(); | ||||
|     AnimationList_t animation_list; | ||||
|     AnimationList_init(animation_list); | ||||
|     bool new_basic_animation = false; | ||||
|  | ||||
|     if(animation->state == DesktopAnimationStateActive) { | ||||
|         animation->state = DesktopAnimationStateBasic; | ||||
|         TickType_t basic_lasts_ms = now_ms - animation->basic_started_at; | ||||
|         animation->active_finished_at = now_ms; | ||||
|         TickType_t basic_duration_ms = animation->current->basic->duration * 1000; | ||||
|         if(basic_lasts_ms > basic_duration_ms) { | ||||
|             // if active animation finished, and basic duration came to an end | ||||
|             // select new idle animation | ||||
|             new_basic_animation = true; | ||||
|         } else { | ||||
|             // if active animation finished, but basic duration is not finished | ||||
|             // play current animation for the rest of time | ||||
|             furi_assert(basic_duration_ms != basic_lasts_ms); | ||||
|             osTimerStart(animation->timer, basic_duration_ms - basic_lasts_ms); | ||||
|         } | ||||
|     } else if(animation->state == DesktopAnimationStateBasic) { | ||||
|         // if basic animation finished | ||||
|         // select new idle animation | ||||
|         new_basic_animation = true; | ||||
|     } | ||||
|  | ||||
|     if(new_basic_animation) { | ||||
|         animation->basic_started_at = now_ms; | ||||
|         desktop_start_new_idle_animation(animation); | ||||
|     } | ||||
|  | ||||
|     // for oneshot generate events every time | ||||
|     if(animation->animation_changed_callback) { | ||||
|         animation->animation_changed_callback(animation->animation_changed_callback_context); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void desktop_animation_activate(DesktopAnimation* animation) { | ||||
|     furi_assert(animation); | ||||
|  | ||||
|     if(animation->state != DesktopAnimationStateBasic) { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     if(animation->state == DesktopAnimationStateActive) { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     if(!animation->current->active) { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     TickType_t now = osKernelGetTickCount(); | ||||
|     TickType_t time_since_last_active = now - animation->active_finished_at; | ||||
|  | ||||
|     if(time_since_last_active > (animation->current->basic->active_cooldown * 1000)) { | ||||
|         animation->state = DesktopAnimationStateActive; | ||||
|         furi_assert(animation->current->active->duration > 0); | ||||
|         osTimerStart(animation->timer, animation->current->active->duration * 1000); | ||||
|         if(animation->animation_changed_callback) { | ||||
|             animation->animation_changed_callback(animation->animation_changed_callback_context); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static const Icon* desktop_animation_get_current_idle_animation(DesktopAnimation* animation) { | ||||
|     const Icon* active_icon = animation->current->active->icon; | ||||
|     const Icon* basic_icon = animation->current->basic->icon; | ||||
|     return (animation->state == DesktopAnimationStateActive && active_icon) ? active_icon : | ||||
|                                                                               basic_icon; | ||||
| } | ||||
|  | ||||
| // Every time somebody starts 'desktop_animation_get_animation()' | ||||
| // 1) check if there is a new level | ||||
| // 2) check if there is SD card corruption | ||||
| // 3) check if the SD card is empty | ||||
| // 4) if all false - get idle animation | ||||
|  | ||||
| const Icon* desktop_animation_get_animation(DesktopAnimation* animation) { | ||||
|     Dolphin* dolphin = furi_record_open("dolphin"); | ||||
|     Storage* storage = furi_record_open("storage"); | ||||
|     const Icon* icon = NULL; | ||||
|     furi_assert(animation); | ||||
|     FS_Error sd_status = storage_sd_status(storage); | ||||
|  | ||||
|     if(IS_BLOCKING_ANIMATION(animation->state)) { | ||||
|         // don't give new animation till blocked animation | ||||
|         // is reseted | ||||
|         icon = animation->current_blocking_icon; | ||||
|     } | ||||
|  | ||||
|     if(!icon) { | ||||
|         if(sd_status == FSE_INTERNAL) { | ||||
|             osTimerStop(animation->timer); | ||||
|             icon = &A_CardBad_128x51; | ||||
|             animation->current_blocking_icon = icon; | ||||
|             animation->state = DesktopAnimationStateSDCorrupted; | ||||
|             animation->sd_shown_error_card_bad = true; | ||||
|             animation->sd_shown_error_db = false; | ||||
|         } else if(sd_status == FSE_NOT_READY) { | ||||
|             animation->sd_shown_error_card_bad = false; | ||||
|             animation->sd_shown_error_db = false; | ||||
|         } else if(sd_status == FSE_OK) { | ||||
|             bool db_exists = storage_common_stat(storage, "/ext/manifest.txt", NULL) == FSE_OK; | ||||
|             if(db_exists && !animation->sd_shown_error_db) { | ||||
|                 osTimerStop(animation->timer); | ||||
|                 icon = &A_CardNoDB_128x51; | ||||
|                 animation->current_blocking_icon = icon; | ||||
|                 animation->state = DesktopAnimationStateSDEmpty; | ||||
|                 animation->sd_shown_error_db = true; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     DolphinStats stats = dolphin_stats(dolphin); | ||||
|     if(!icon && stats.level_up_is_pending) { | ||||
|         osTimerStop(animation->timer); | ||||
|         icon = &A_LevelUpPending_128x51; | ||||
|         animation->current_blocking_icon = icon; | ||||
|         animation->state = DesktopAnimationStateLevelUpIsPending; | ||||
|     } | ||||
|  | ||||
|     if(!icon) { | ||||
|         icon = desktop_animation_get_current_idle_animation(animation); | ||||
|     } | ||||
|  | ||||
|     furi_record_close("storage"); | ||||
|     furi_record_close("dolphin"); | ||||
|  | ||||
|     return icon; | ||||
| } | ||||
|  | ||||
| DesktopAnimationState desktop_animation_handle_right(DesktopAnimation* animation) { | ||||
|     furi_assert(animation); | ||||
|  | ||||
|     bool reset_animation = false; | ||||
|     bool update_animation = false; | ||||
|  | ||||
|     switch(animation->state) { | ||||
|     case DesktopAnimationStateActive: | ||||
|     case DesktopAnimationStateBasic: | ||||
|         /* nothing */ | ||||
|         break; | ||||
|     case DesktopAnimationStateLevelUpIsPending: | ||||
|         /* do nothing, main scene should change itself */ | ||||
|         break; | ||||
|     case DesktopAnimationStateSDCorrupted: | ||||
|         reset_animation = true; | ||||
|         break; | ||||
|     case DesktopAnimationStateSDEmpty: | ||||
|         animation->state = DesktopAnimationStateSDEmptyURL; | ||||
|         animation->current_blocking_icon = &A_CardNoDBUrl_128x51; | ||||
|         update_animation = true; | ||||
|         break; | ||||
|     case DesktopAnimationStateSDEmptyURL: | ||||
|         reset_animation = true; | ||||
|         break; | ||||
|     default: | ||||
|         furi_crash("Unhandled desktop animation state"); | ||||
|     } | ||||
|  | ||||
|     if(reset_animation) { | ||||
|         desktop_start_new_idle_animation(animation); | ||||
|         update_animation = true; | ||||
|     } | ||||
|  | ||||
|     if(update_animation) { | ||||
|         if(animation->animation_changed_callback) { | ||||
|             animation->animation_changed_callback(animation->animation_changed_callback_context); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return animation->state; | ||||
| } | ||||
|  | ||||
| #define LEVELUP_FRAME_RATE (0.2) | ||||
|  | ||||
| void desktop_animation_start_oneshot_levelup(DesktopAnimation* animation) { | ||||
|     animation->one_shot_animation_counter = 0; | ||||
|     animation->state = DesktopAnimationStateLevelUpIsPending; | ||||
|  | ||||
|     Dolphin* dolphin = furi_record_open("dolphin"); | ||||
|     DolphinStats stats = dolphin_stats(dolphin); | ||||
|     float timediff = fabs(difftime(stats.timestamp, dolphin_state_timestamp())); | ||||
|     furi_record_close("dolphin"); | ||||
|     furi_assert(stats.level_up_is_pending); | ||||
|     if(stats.level == 1) { | ||||
|         animation->current_one_shot_icons = animation_level2up; | ||||
|         animation->one_shot_animation_size = COUNT_OF(animation_level2up); | ||||
|     } else if(stats.level == 2) { | ||||
|         animation->current_one_shot_icons = animation_level3up; | ||||
|         animation->one_shot_animation_size = COUNT_OF(animation_level3up); | ||||
|     } else { | ||||
|         furi_crash("Dolphin level is out of bounds"); | ||||
|     } | ||||
|     osTimerStart(animation->timer, LEVELUP_FRAME_RATE * 1000); | ||||
| } | ||||
|  | ||||
|     FURI_LOG_I(TAG, "background change"); | ||||
|     FURI_LOG_I(TAG, "icounter: %d", stats.icounter); | ||||
|     FURI_LOG_I(TAG, "butthurt: %d", stats.butthurt); | ||||
|     FURI_LOG_I(TAG, "time since deeed: %.0f", timediff); | ||||
| #endif | ||||
| const Icon* desktop_animation_get_oneshot_frame(DesktopAnimation* animation) { | ||||
|     furi_assert(IS_ONESHOT_ANIMATION(animation->state)); | ||||
|     furi_assert(animation->one_shot_animation_size > 0); | ||||
|     const Icon* icon = NULL; | ||||
|  | ||||
|     if((random() % 100) > 50) { // temp rnd selection | ||||
|         new = random() % COUNT_OF(idle_scenes); | ||||
|     if(animation->one_shot_animation_counter < animation->one_shot_animation_size) { | ||||
|         icon = animation->current_one_shot_icons[animation->one_shot_animation_counter]; | ||||
|         ++animation->one_shot_animation_counter; | ||||
|     } else { | ||||
|         animation->state = DesktopAnimationStateBasic; | ||||
|         animation->one_shot_animation_size = 0; | ||||
|         osTimerStop(animation->timer); | ||||
|         icon = NULL; | ||||
|     } | ||||
|  | ||||
|     return idle_scenes[new]; | ||||
|     return icon; | ||||
| } | ||||
|   | ||||
| @@ -1,10 +1,55 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <furi.h> | ||||
| #include <math.h> | ||||
| #include <assets_icons.h> | ||||
| #include "dolphin/dolphin.h" | ||||
| #include "dolphin/helpers/dolphin_state.h" | ||||
| #include "time.h" | ||||
| #include <stdint.h> | ||||
| #include <gui/icon.h> | ||||
|  | ||||
| const Icon* desktop_get_icon(); | ||||
| typedef struct DesktopAnimation DesktopAnimation; | ||||
|  | ||||
| typedef struct ActiveAnimation ActiveAnimation; | ||||
| typedef struct BasicAnimation BasicAnimation; | ||||
|  | ||||
| typedef enum { | ||||
|     DesktopAnimationStateBasic, | ||||
|     DesktopAnimationStateActive, | ||||
|     DesktopAnimationStateLevelUpIsPending, | ||||
|     DesktopAnimationStateSDEmpty, | ||||
|     DesktopAnimationStateSDEmptyURL, | ||||
|     DesktopAnimationStateSDCorrupted, | ||||
| } DesktopAnimationState; | ||||
|  | ||||
| struct BasicAnimation { | ||||
|     const Icon* icon; | ||||
|     uint16_t duration; // sec | ||||
|     uint16_t active_cooldown; | ||||
|     uint8_t weight; | ||||
|     uint16_t butthurt_level_mask; | ||||
| }; | ||||
|  | ||||
| struct ActiveAnimation { | ||||
|     const Icon* icon; | ||||
|     uint16_t duration; // sec | ||||
| }; | ||||
|  | ||||
| typedef struct { | ||||
|     const BasicAnimation* basic; | ||||
|     const ActiveAnimation* active; | ||||
| } PairedAnimation; | ||||
|  | ||||
| typedef void (*AnimationChangedCallback)(void*); | ||||
|  | ||||
| DesktopAnimation* desktop_animation_alloc(void); | ||||
| void desktop_animation_free(DesktopAnimation*); | ||||
| void desktop_animation_activate(DesktopAnimation* instance); | ||||
| void desktop_animation_set_animation_changed_callback( | ||||
|     DesktopAnimation* instance, | ||||
|     AnimationChangedCallback callback, | ||||
|     void* context); | ||||
|  | ||||
| DesktopAnimationState desktop_animation_handle_right(DesktopAnimation* animation); | ||||
|  | ||||
| void desktop_animation_start_oneshot_levelup(DesktopAnimation* animation); | ||||
|  | ||||
| const Icon* desktop_animation_get_animation(DesktopAnimation* animation); | ||||
| const Icon* desktop_animation_get_oneshot_frame(DesktopAnimation* animation); | ||||
|  | ||||
| void desktop_start_new_idle_animation(DesktopAnimation* animation); | ||||
|   | ||||
							
								
								
									
										330
									
								
								applications/desktop/helpers/desktop_animation_i.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										330
									
								
								applications/desktop/helpers/desktop_animation_i.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,330 @@ | ||||
| #include <assets_icons.h> | ||||
| #include <stddef.h> | ||||
| #include <stdint.h> | ||||
| #include <gui/icon.h> | ||||
| #include "desktop_animation.h" | ||||
|  | ||||
| // Calm/Mad Basic Idle Animations | ||||
|  | ||||
| #define COMMON_BASIC_DURATION (60 * 60) | ||||
| #define COMMON_ACTIVE_CYCLES 7 | ||||
| #define COMMON_ACTIVE_COOLDOWN 30 | ||||
| #define COMMON_WEIGHT 3 | ||||
|  | ||||
| #define BUTTHURT_LEVEL(x) (1UL << (x)) | ||||
| #define BUTTHURT_LEVEL_0 0 | ||||
|  | ||||
| // frames * cycles / frame_rate | ||||
| #define COMMON_ACTIVE_DURATION(x) ((x)*COMMON_ACTIVE_CYCLES / 2) | ||||
|  | ||||
| static const BasicAnimation animation_TV = { | ||||
|     .icon = &A_TV_128x51, | ||||
|     .duration = COMMON_BASIC_DURATION, | ||||
|     .weight = COMMON_WEIGHT, | ||||
|     .active_cooldown = COMMON_ACTIVE_COOLDOWN, | ||||
|     .butthurt_level_mask = BUTTHURT_LEVEL(0) | BUTTHURT_LEVEL(1) | BUTTHURT_LEVEL(2) | | ||||
|                            BUTTHURT_LEVEL(3) | BUTTHURT_LEVEL(4) | BUTTHURT_LEVEL(5) | | ||||
|                            BUTTHURT_LEVEL(6) | BUTTHURT_LEVEL(7)}; | ||||
|  | ||||
| static const ActiveAnimation animation_TV_active = { | ||||
|     .icon = &A_TVActive_128x51, | ||||
|     .duration = COMMON_ACTIVE_DURATION(2), | ||||
| }; | ||||
|  | ||||
| static const BasicAnimation animation_sleep = { | ||||
|     .icon = &A_Sleep_128x51, | ||||
|     .duration = COMMON_BASIC_DURATION, | ||||
|     .weight = COMMON_WEIGHT, | ||||
|     .active_cooldown = COMMON_ACTIVE_COOLDOWN, | ||||
|     .butthurt_level_mask = BUTTHURT_LEVEL(0) | BUTTHURT_LEVEL(1) | BUTTHURT_LEVEL(2) | | ||||
|                            BUTTHURT_LEVEL(3) | BUTTHURT_LEVEL(4) | BUTTHURT_LEVEL(5) | | ||||
|                            BUTTHURT_LEVEL(6) | BUTTHURT_LEVEL(7) | BUTTHURT_LEVEL(8) | | ||||
|                            BUTTHURT_LEVEL(9) | BUTTHURT_LEVEL(10)}; | ||||
|  | ||||
| static const ActiveAnimation animation_sleep_active = { | ||||
|     .icon = &A_SleepActive_128x51, | ||||
|     .duration = COMMON_ACTIVE_DURATION(2), | ||||
| }; | ||||
|  | ||||
| static const BasicAnimation animation_leaving = { | ||||
|     .icon = &A_Leaving_128x51, | ||||
|     .duration = COMMON_BASIC_DURATION, | ||||
|     .weight = COMMON_WEIGHT, | ||||
|     .active_cooldown = COMMON_ACTIVE_COOLDOWN, | ||||
|     .butthurt_level_mask = BUTTHURT_LEVEL(13) | BUTTHURT_LEVEL(14), | ||||
| }; | ||||
|  | ||||
| static const ActiveAnimation animation_leaving_active = { | ||||
|     .icon = &A_LeavingActive_128x51, | ||||
|     .duration = COMMON_ACTIVE_DURATION(2), | ||||
| }; | ||||
|  | ||||
| static const BasicAnimation animation_laptop = { | ||||
|     .icon = &A_Laptop_128x51, | ||||
|     .duration = COMMON_BASIC_DURATION, | ||||
|     .weight = COMMON_WEIGHT, | ||||
|     .active_cooldown = COMMON_ACTIVE_COOLDOWN, | ||||
|     .butthurt_level_mask = BUTTHURT_LEVEL(0) | BUTTHURT_LEVEL(1) | BUTTHURT_LEVEL(2) | | ||||
|                            BUTTHURT_LEVEL(3) | BUTTHURT_LEVEL(4) | BUTTHURT_LEVEL(5)}; | ||||
|  | ||||
| static const ActiveAnimation animation_laptop_active = { | ||||
|     .icon = &A_LaptopActive_128x51, | ||||
|     .duration = COMMON_ACTIVE_DURATION(2), | ||||
| }; | ||||
|  | ||||
| static const BasicAnimation animation_knife = { | ||||
|     .icon = &A_Knife_128x51, | ||||
|     .duration = COMMON_BASIC_DURATION, | ||||
|     .weight = COMMON_WEIGHT, | ||||
|     .active_cooldown = COMMON_ACTIVE_COOLDOWN, | ||||
|     .butthurt_level_mask = BUTTHURT_LEVEL(5) | BUTTHURT_LEVEL(6) | BUTTHURT_LEVEL(7) | | ||||
|                            BUTTHURT_LEVEL(8) | BUTTHURT_LEVEL(9) | BUTTHURT_LEVEL(10) | | ||||
|                            BUTTHURT_LEVEL(11) | BUTTHURT_LEVEL(12) | BUTTHURT_LEVEL(13)}; | ||||
|  | ||||
| static const ActiveAnimation animation_knife_active = { | ||||
|     .icon = &A_KnifeActive_128x51, | ||||
|     .duration = COMMON_ACTIVE_DURATION(2), | ||||
| }; | ||||
|  | ||||
| static const BasicAnimation animation_cry = { | ||||
|     .icon = &A_Cry_128x51, | ||||
|     .duration = COMMON_BASIC_DURATION, | ||||
|     .weight = COMMON_WEIGHT, | ||||
|     .active_cooldown = COMMON_ACTIVE_COOLDOWN, | ||||
|     .butthurt_level_mask = BUTTHURT_LEVEL(3) | BUTTHURT_LEVEL(4) | BUTTHURT_LEVEL(5) | | ||||
|                            BUTTHURT_LEVEL(6) | BUTTHURT_LEVEL(7) | BUTTHURT_LEVEL(8) | | ||||
|                            BUTTHURT_LEVEL(9) | BUTTHURT_LEVEL(10) | BUTTHURT_LEVEL(11) | | ||||
|                            BUTTHURT_LEVEL(12) | BUTTHURT_LEVEL(13)}; | ||||
|  | ||||
| static const ActiveAnimation animation_cry_active = { | ||||
|     .icon = &A_CryActive_128x51, | ||||
|     .duration = COMMON_ACTIVE_DURATION(3), | ||||
| }; | ||||
|  | ||||
| static const BasicAnimation animation_box = { | ||||
|     .icon = &A_Box_128x51, | ||||
|     .duration = COMMON_BASIC_DURATION, | ||||
|     .weight = COMMON_WEIGHT, | ||||
|     .active_cooldown = COMMON_ACTIVE_COOLDOWN, | ||||
|     .butthurt_level_mask = BUTTHURT_LEVEL(7) | BUTTHURT_LEVEL(8) | BUTTHURT_LEVEL(9) | | ||||
|                            BUTTHURT_LEVEL(10) | BUTTHURT_LEVEL(11) | BUTTHURT_LEVEL(12) | | ||||
|                            BUTTHURT_LEVEL(13)}; | ||||
|  | ||||
| static const ActiveAnimation animation_box_active = { | ||||
|     .icon = &A_BoxActive_128x51, | ||||
|     .duration = COMMON_ACTIVE_DURATION(2), | ||||
| }; | ||||
|  | ||||
| static const BasicAnimation animation_waves = { | ||||
|     .icon = &A_Waves_128x51, | ||||
|     .duration = COMMON_BASIC_DURATION, | ||||
|     .weight = COMMON_WEIGHT, | ||||
|     .active_cooldown = COMMON_ACTIVE_COOLDOWN, | ||||
|     .butthurt_level_mask = BUTTHURT_LEVEL(0) | BUTTHURT_LEVEL(1) | BUTTHURT_LEVEL(2)}; | ||||
|  | ||||
| static const ActiveAnimation animation_waves_active = { | ||||
|     .icon = &A_WavesActive_128x51, | ||||
|     .duration = COMMON_ACTIVE_DURATION(2), | ||||
| }; | ||||
|  | ||||
| // Level Idle Animations | ||||
|  | ||||
| static const BasicAnimation animation_level1furippa = { | ||||
|     .icon = &A_Level1Furippa_128x51, | ||||
|     .duration = COMMON_BASIC_DURATION, | ||||
|     .weight = COMMON_WEIGHT, | ||||
|     .active_cooldown = COMMON_ACTIVE_COOLDOWN, | ||||
|     .butthurt_level_mask = BUTTHURT_LEVEL(0) | BUTTHURT_LEVEL(1) | BUTTHURT_LEVEL(2) | | ||||
|                            BUTTHURT_LEVEL(3) | BUTTHURT_LEVEL(4) | BUTTHURT_LEVEL(5) | | ||||
|                            BUTTHURT_LEVEL(6) | BUTTHURT_LEVEL(7)}; | ||||
|  | ||||
| static const ActiveAnimation animation_level1furippa_active = { | ||||
|     .icon = &A_Level1FurippaActive_128x51, | ||||
|     .duration = COMMON_ACTIVE_DURATION(6), | ||||
| }; | ||||
|  | ||||
| static const BasicAnimation animation_level1read = { | ||||
|     .icon = &A_Level1Read_128x51, | ||||
|     .duration = COMMON_BASIC_DURATION, | ||||
|     .weight = COMMON_WEIGHT, | ||||
|     .active_cooldown = COMMON_ACTIVE_COOLDOWN, | ||||
|     .butthurt_level_mask = BUTTHURT_LEVEL(0) | BUTTHURT_LEVEL(1) | BUTTHURT_LEVEL(2)}; | ||||
|  | ||||
| static const ActiveAnimation animation_level1read_active = { | ||||
|     .icon = &A_Level1ReadActive_128x51, | ||||
|     .duration = COMMON_ACTIVE_DURATION(2), | ||||
| }; | ||||
|  | ||||
| static const BasicAnimation animation_level1toys = { | ||||
|     .icon = &A_Level1Toys_128x51, | ||||
|     .duration = COMMON_BASIC_DURATION, | ||||
|     .weight = COMMON_WEIGHT, | ||||
|     .active_cooldown = COMMON_ACTIVE_COOLDOWN, | ||||
|     .butthurt_level_mask = BUTTHURT_LEVEL(0) | BUTTHURT_LEVEL(1) | BUTTHURT_LEVEL(2) | | ||||
|                            BUTTHURT_LEVEL(3) | BUTTHURT_LEVEL(4) | BUTTHURT_LEVEL(5) | | ||||
|                            BUTTHURT_LEVEL(6) | BUTTHURT_LEVEL(7) | BUTTHURT_LEVEL(8)}; | ||||
|  | ||||
| static const ActiveAnimation animation_level1toys_active = { | ||||
|     .icon = &A_Level1ToysActive_128x51, | ||||
|     .duration = COMMON_ACTIVE_DURATION(2), | ||||
| }; | ||||
|  | ||||
| static const BasicAnimation animation_level2furippa = { | ||||
|     .icon = &A_Level2Furippa_128x51, | ||||
|     .duration = COMMON_BASIC_DURATION, | ||||
|     .weight = COMMON_WEIGHT, | ||||
|     .active_cooldown = COMMON_ACTIVE_COOLDOWN, | ||||
|     .butthurt_level_mask = BUTTHURT_LEVEL(0) | BUTTHURT_LEVEL(1) | BUTTHURT_LEVEL(2) | | ||||
|                            BUTTHURT_LEVEL(3) | BUTTHURT_LEVEL(4) | BUTTHURT_LEVEL(5) | | ||||
|                            BUTTHURT_LEVEL(6) | BUTTHURT_LEVEL(7)}; | ||||
|  | ||||
| static const ActiveAnimation animation_level2furippa_active = { | ||||
|     .icon = &A_Level2FurippaActive_128x51, | ||||
|     .duration = COMMON_ACTIVE_DURATION(6), | ||||
| }; | ||||
|  | ||||
| static const BasicAnimation animation_level2soldering = { | ||||
|     .icon = &A_Level2Soldering_128x51, | ||||
|     .duration = COMMON_BASIC_DURATION, | ||||
|     .weight = COMMON_WEIGHT, | ||||
|     .active_cooldown = COMMON_ACTIVE_COOLDOWN, | ||||
|     .butthurt_level_mask = BUTTHURT_LEVEL(0) | BUTTHURT_LEVEL(1) | BUTTHURT_LEVEL(2) | | ||||
|                            BUTTHURT_LEVEL(3) | BUTTHURT_LEVEL(4) | BUTTHURT_LEVEL(5) | | ||||
|                            BUTTHURT_LEVEL(6) | BUTTHURT_LEVEL(7) | BUTTHURT_LEVEL(8) | | ||||
|                            BUTTHURT_LEVEL(9)}; | ||||
|  | ||||
| static const ActiveAnimation animation_level2soldering_active = { | ||||
|     .icon = &A_Level2SolderingActive_128x51, | ||||
|     .duration = COMMON_ACTIVE_DURATION(2), | ||||
| }; | ||||
|  | ||||
| static const BasicAnimation animation_level2hack = { | ||||
|     .icon = &A_Level2Hack_128x51, | ||||
|     .duration = COMMON_BASIC_DURATION, | ||||
|     .weight = COMMON_WEIGHT, | ||||
|     .active_cooldown = COMMON_ACTIVE_COOLDOWN, | ||||
|     .butthurt_level_mask = BUTTHURT_LEVEL(0) | BUTTHURT_LEVEL(1) | BUTTHURT_LEVEL(2) | | ||||
|                            BUTTHURT_LEVEL(3) | BUTTHURT_LEVEL(4) | BUTTHURT_LEVEL(5) | | ||||
|                            BUTTHURT_LEVEL(6) | BUTTHURT_LEVEL(7) | BUTTHURT_LEVEL(8)}; | ||||
|  | ||||
| static const ActiveAnimation animation_level2hack_active = { | ||||
|     .icon = &A_Level2HackActive_128x51, | ||||
|     .duration = COMMON_ACTIVE_DURATION(2), | ||||
| }; | ||||
|  | ||||
| static const BasicAnimation animation_level3furippa = { | ||||
|     .icon = &A_Level3Furippa_128x51, | ||||
|     .duration = COMMON_BASIC_DURATION, | ||||
|     .weight = COMMON_WEIGHT, | ||||
|     .active_cooldown = COMMON_ACTIVE_COOLDOWN, | ||||
|     .butthurt_level_mask = BUTTHURT_LEVEL(0) | BUTTHURT_LEVEL(1) | BUTTHURT_LEVEL(2) | | ||||
|                            BUTTHURT_LEVEL(3) | BUTTHURT_LEVEL(4) | BUTTHURT_LEVEL(5) | | ||||
|                            BUTTHURT_LEVEL(6) | BUTTHURT_LEVEL(7)}; | ||||
|  | ||||
| static const ActiveAnimation animation_level3furippa_active = { | ||||
|     .icon = &A_Level3FurippaActive_128x51, | ||||
|     .duration = COMMON_ACTIVE_DURATION(6), | ||||
| }; | ||||
|  | ||||
| static const BasicAnimation animation_level3hijack = { | ||||
|     .icon = &A_Level3Hijack_128x51, | ||||
|     .duration = COMMON_BASIC_DURATION, | ||||
|     .weight = COMMON_WEIGHT, | ||||
|     .active_cooldown = COMMON_ACTIVE_COOLDOWN, | ||||
|     .butthurt_level_mask = BUTTHURT_LEVEL(0) | BUTTHURT_LEVEL(1) | BUTTHURT_LEVEL(2) | | ||||
|                            BUTTHURT_LEVEL(3) | BUTTHURT_LEVEL(4) | BUTTHURT_LEVEL(5) | | ||||
|                            BUTTHURT_LEVEL(6) | BUTTHURT_LEVEL(7) | BUTTHURT_LEVEL(8) | | ||||
|                            BUTTHURT_LEVEL(9)}; | ||||
|  | ||||
| static const ActiveAnimation animation_level3hijack_active = { | ||||
|     .icon = &A_Level3HijackActive_128x51, | ||||
|     .duration = COMMON_ACTIVE_DURATION(2), | ||||
| }; | ||||
|  | ||||
| static const BasicAnimation animation_level3lab = { | ||||
|     .icon = &A_Level3Lab_128x51, | ||||
|     .duration = COMMON_BASIC_DURATION, | ||||
|     .weight = COMMON_WEIGHT, | ||||
|     .active_cooldown = COMMON_ACTIVE_COOLDOWN, | ||||
|     .butthurt_level_mask = BUTTHURT_LEVEL(0) | BUTTHURT_LEVEL(1) | BUTTHURT_LEVEL(2) | | ||||
|                            BUTTHURT_LEVEL(3) | BUTTHURT_LEVEL(4) | BUTTHURT_LEVEL(5) | | ||||
|                            BUTTHURT_LEVEL(6) | BUTTHURT_LEVEL(7) | BUTTHURT_LEVEL(8)}; | ||||
|  | ||||
| static const ActiveAnimation animation_level3lab_active = { | ||||
|     .icon = &A_Level3LabActive_128x51, | ||||
|     .duration = COMMON_ACTIVE_DURATION(2), | ||||
| }; | ||||
|  | ||||
| // System Idle Animations | ||||
|  | ||||
| static const BasicAnimation animation_bad_battery = { | ||||
|     .icon = &A_BadBattery_128x51, | ||||
|     .duration = COMMON_BASIC_DURATION, | ||||
|     .weight = 7, | ||||
| }; | ||||
|  | ||||
| static const BasicAnimation animation_no_sd_card = { | ||||
|     .icon = &A_NoSdCard_128x51, | ||||
|     .duration = COMMON_BASIC_DURATION, | ||||
|     .weight = 7, | ||||
| }; | ||||
|  | ||||
| const Icon* animation_level2up[] = { | ||||
|     &I_LevelUp2_01, | ||||
|     &I_LevelUp2_02, | ||||
|     &I_LevelUp2_03, | ||||
|     &I_LevelUp2_04, | ||||
|     &I_LevelUp2_05, | ||||
|     &I_LevelUp2_06, | ||||
|     &I_LevelUp2_07}; | ||||
|  | ||||
| const Icon* animation_level3up[] = { | ||||
|     &I_LevelUp3_01, | ||||
|     &I_LevelUp3_02, | ||||
|     &I_LevelUp3_03, | ||||
|     &I_LevelUp3_04, | ||||
|     &I_LevelUp3_05, | ||||
|     &I_LevelUp3_06, | ||||
|     &I_LevelUp3_07}; | ||||
|  | ||||
| // Blocking Idle Animations & One shot Animations represented as naked Icon | ||||
|  | ||||
| static const PairedAnimation calm_animation[] = { | ||||
|     {.basic = &animation_TV, .active = &animation_TV_active}, | ||||
|     {.basic = &animation_waves, .active = &animation_waves_active}, | ||||
|     {.basic = &animation_sleep, .active = &animation_sleep_active}, | ||||
|     {.basic = &animation_laptop, .active = &animation_laptop_active}, | ||||
| }; | ||||
|  | ||||
| static const PairedAnimation mad_animation[] = { | ||||
|     {.basic = &animation_cry, .active = &animation_cry_active}, | ||||
|     {.basic = &animation_knife, .active = &animation_knife_active}, | ||||
|     {.basic = &animation_box, .active = &animation_box_active}, | ||||
|     {.basic = &animation_leaving, .active = &animation_leaving_active}, | ||||
| }; | ||||
|  | ||||
| static const PairedAnimation level_1_animation[] = { | ||||
|     {.basic = &animation_level1furippa, .active = &animation_level1furippa_active}, | ||||
|     {.basic = &animation_level1read, .active = &animation_level1read_active}, | ||||
|     {.basic = &animation_level1toys, .active = &animation_level1toys_active}, | ||||
| }; | ||||
|  | ||||
| static const PairedAnimation level_2_animation[] = { | ||||
|     {.basic = &animation_level2furippa, .active = &animation_level2furippa_active}, | ||||
|     {.basic = &animation_level2soldering, .active = &animation_level2soldering_active}, | ||||
|     {.basic = &animation_level2hack, .active = &animation_level2hack_active}, | ||||
| }; | ||||
|  | ||||
| static const PairedAnimation level_3_animation[] = { | ||||
|     {.basic = &animation_level3furippa, .active = &animation_level3furippa_active}, | ||||
|     {.basic = &animation_level3hijack, .active = &animation_level3hijack_active}, | ||||
|     {.basic = &animation_level3lab, .active = &animation_level3lab_active}, | ||||
| }; | ||||
|  | ||||
| static const PairedAnimation no_sd_animation[] = { | ||||
|     {.basic = &animation_no_sd_card, .active = NULL}, | ||||
| }; | ||||
|  | ||||
| static const PairedAnimation check_battery_animation[] = { | ||||
|     {.basic = &animation_bad_battery, .active = NULL}, | ||||
| }; | ||||
		Reference in New Issue
	
	Block a user