/** * menu_animation_ticker_str: * @s : buffer to write new message line to. * @len : length of buffer @input. * @idx : Index. Will be used for ticker logic. * @str : Input string. * @selected : Is the item currently selected in the menu? * * Take the contents of @str and apply a ticker effect to it, * and write the results in @s. **/ void menu_animation_ticker_str(char *s, size_t len, uint64_t idx, const char *str, bool selected) { menu_animation_t *anim = menu_animation_get_ptr(); size_t str_len = strlen(str); size_t offset = 0; if ((size_t)str_len <= len) { strlcpy(s, str, len + 1); return; } if (!selected) { strlcpy(s, str, len + 1 - 3); strlcat(s, "...", len + 1); return; } menu_animation_ticker_generic(idx, len, &offset, &str_len); strlcpy(s, str - offset, str_len + 1); anim->is_active = true; }
bool menu_animation_ticker(const menu_animation_ctx_ticker_t *ticker) { size_t str_len = utf8len(ticker->str); size_t offset = 0; if ((size_t)str_len <= ticker->len) { utf8cpy(ticker->s, PATH_MAX_LENGTH, ticker->str, ticker->len); return true; } if (!ticker->selected) { utf8cpy(ticker->s, PATH_MAX_LENGTH, ticker->str, ticker->len - 3); strlcat(ticker->s, "...", PATH_MAX_LENGTH); return true; } if (str_len > ticker->len) menu_animation_ticker_generic( ticker->idx, ticker->len, &offset, &str_len); utf8cpy( ticker->s, PATH_MAX_LENGTH, utf8skip(ticker->str, offset), str_len); animation_is_active = true; return true; }
bool menu_animation_ctl(enum menu_animation_ctl_state state, void *data) { static menu_animation_t anim; static retro_time_t cur_time = 0; static retro_time_t old_time = 0; static float delta_time = 0.0f; static bool animation_is_active = false; switch (state) { case MENU_ANIMATION_CTL_DEINIT: { size_t i; for (i = 0; i < anim.size; i++) { if (anim.list[i].subject) anim.list[i].subject = NULL; } free(anim.list); memset(&anim, 0, sizeof(menu_animation_t)); } cur_time = 0; old_time = 0; delta_time = 0.0f; break; case MENU_ANIMATION_CTL_IS_ACTIVE: return animation_is_active; case MENU_ANIMATION_CTL_CLEAR_ACTIVE: animation_is_active = false; break; case MENU_ANIMATION_CTL_SET_ACTIVE: animation_is_active = true; break; case MENU_ANIMATION_CTL_DELTA_TIME: { float *ptr = (float*)data; if (!ptr) return false; *ptr = delta_time; } break; case MENU_ANIMATION_CTL_UPDATE_TIME: { static retro_time_t last_clock_update = 0; settings_t *settings = config_get_ptr(); cur_time = cpu_features_get_time_usec(); delta_time = cur_time - old_time; if (delta_time >= IDEAL_DELTA_TIME* 4) delta_time = IDEAL_DELTA_TIME * 4; if (delta_time <= IDEAL_DELTA_TIME / 4) delta_time = IDEAL_DELTA_TIME / 4; old_time = cur_time; if (((cur_time - last_clock_update) > 1000000) && settings->menu.timedate_enable) { animation_is_active = true; last_clock_update = cur_time; } } break; case MENU_ANIMATION_CTL_UPDATE: { unsigned i; unsigned active_tweens = 0; float *dt = (float*)data; if (!dt) return false; for(i = 0; i < anim.size; i++) menu_animation_iterate(&anim, i, *dt, &active_tweens); if (!active_tweens) { anim.size = 0; anim.first_dead = 0; return false; } animation_is_active = true; } break; case MENU_ANIMATION_CTL_KILL_BY_TAG: { unsigned i; menu_animation_ctx_tag_t *tag = (menu_animation_ctx_tag_t*)data; if (!tag || tag->id == -1) return false; for (i = 0; i < anim.size; ++i) { if (anim.list[i].tag != tag->id) continue; anim.list[i].alive = false; anim.list[i].subject = NULL; if (i < anim.first_dead) anim.first_dead = i; } } break; case MENU_ANIMATION_CTL_KILL_BY_SUBJECT: { unsigned i, j, killed = 0; menu_animation_ctx_subject_t *subject = (menu_animation_ctx_subject_t*)data; float **sub = (float**)subject->data; for (i = 0; i < anim.size; ++i) { if (!anim.list[i].alive) continue; for (j = 0; j < subject->count; ++j) { if (anim.list[i].subject != sub[j]) continue; anim.list[i].alive = false; anim.list[i].subject = NULL; if (i < anim.first_dead) anim.first_dead = i; killed++; break; } } } break; case MENU_ANIMATION_CTL_TICKER: { menu_animation_ctx_ticker_t *ticker = (menu_animation_ctx_ticker_t*) data; size_t str_len = utf8len(ticker->str); size_t offset = 0; if ((size_t)str_len <= ticker->len) { utf8cpy(ticker->s, PATH_MAX_LENGTH, ticker->str, ticker->len); return true; } if (!ticker->selected) { utf8cpy(ticker->s, PATH_MAX_LENGTH, ticker->str, ticker->len - 3); strlcat(ticker->s, "...", PATH_MAX_LENGTH); return true; } menu_animation_ticker_generic( ticker->idx, ticker->len, &offset, &str_len); utf8cpy( ticker->s, PATH_MAX_LENGTH, utf8skip(ticker->str, offset), str_len); animation_is_active = true; } break; case MENU_ANIMATION_CTL_IDEAL_DELTA_TIME_GET: { menu_animation_ctx_delta_t *delta = (menu_animation_ctx_delta_t*)data; if (!delta) return false; delta->ideal = delta->current / IDEAL_DELTA_TIME; } break; case MENU_ANIMATION_CTL_PUSH: return menu_animation_push(&anim, data); case MENU_ANIMATION_CTL_NONE: default: break; } return true; }