UI: Add BG animation for recent games.

Just a subdued slideshow in the background.
This commit is contained in:
Unknown W. Brackets 2021-04-04 10:48:42 -07:00
parent 233b0a87c1
commit e2a8c83b9f
4 changed files with 122 additions and 17 deletions

View file

@ -38,11 +38,6 @@ enum ChatPositions {
CENTER_RIGHT = 7,
};
enum class BackgroundAnimation {
OFF = 0,
FLOATING_SYMBOLS = 1,
};
namespace http {
class Download;
class Downloader;

View file

@ -116,3 +116,9 @@ enum class UnthrottleMode {
SKIP_DRAW = 1,
SKIP_FLIP = 2,
};
enum class BackgroundAnimation {
OFF = 0,
FLOATING_SYMBOLS = 1,
RECENT_GAMES = 2,
};

View file

@ -875,7 +875,7 @@ void GameSettingsScreen::CreateViews() {
if (backgroundChoice_ != nullptr) {
backgroundChoice_->OnClick.Handle(this, &GameSettingsScreen::OnChangeBackground);
}
static const char *backgroundAnimations[] = { "No animation", "Floating Symbols" };
static const char *backgroundAnimations[] = { "No animation", "Floating symbols", "Recent games" };
systemSettings->Add(new PopupMultiChoice(&g_Config.iBackgroundAnimation, sy->T("UI background animation"), backgroundAnimations, 0, ARRAY_SIZE(backgroundAnimations), sy->GetName(), screenManager()));
systemSettings->Add(new ItemHeader(sy->T("Help the PPSSPP team")));

View file

@ -85,17 +85,11 @@ public:
void Draw(UIContext &dc, double t, float alpha) override {
float xres = dc.GetBounds().w;
float yres = dc.GetBounds().h;
if (xbase[0] == 0.0f || last_xres != xres || last_yres != yres) {
GMRng rng;
for (int i = 0; i < 100; i++) {
xbase[i] = rng.F() * xres;
ybase[i] = rng.F() * yres;
}
last_xres = xres;
last_yres = yres;
if (last_xres != xres || last_yres != yres) {
Regenerate(xres, yres);
}
for (int i = 0; i < 100; i++) {
for (int i = 0; i < COUNT; i++) {
float x = xbase[i] + dc.GetBounds().x;
float y = ybase[i] + dc.GetBounds().y + 40 * cosf(i * 7.2f + t * 1.3f);
float angle = (float)sin(i + t);
@ -103,11 +97,118 @@ public:
ui_draw2d.DrawImageRotated(symbols[n], x, y, 1.0f, angle, colorAlpha(colors[n], alpha * 0.1f));
}
}
private:
float xbase[100] = { 0 };
float ybase[100] = { 0 };
static constexpr int COUNT = 100;
float xbase[COUNT]{};
float ybase[COUNT]{};
float last_xres = 0;
float last_yres = 0;
void Regenerate(int xres, int yres) {
GMRng rng;
for (int i = 0; i < COUNT; i++) {
xbase[i] = rng.F() * xres;
ybase[i] = rng.F() * yres;
}
last_xres = xres;
last_yres = yres;
}
};
class RecentGamesAnimation : public FloatingSymbolsAnimation {
public:
~RecentGamesAnimation() override {}
void Draw(UIContext &dc, double t, float alpha) override {
if (lastIndex_ == nextIndex_) {
CheckNext(dc, t);
} else if (t > nextT_) {
lastIndex_ = nextIndex_;
}
if (!g_Config.recentIsos.empty()) {
std::shared_ptr<GameInfo> lastInfo = GetInfo(dc, lastIndex_);
std::shared_ptr<GameInfo> nextInfo = GetInfo(dc, nextIndex_);
dc.Flush();
float lastAmount = Clamp((float)(nextT_ - t) * 1.0f / TRANSITION, 0.0f, 1.0f);
DrawTex(dc, lastInfo, lastAmount * alpha * 0.2f);
float nextAmount = lastAmount <= 0.0f ? 1.0f : 1.0f - lastAmount;
DrawTex(dc, nextInfo, nextAmount * alpha * 0.2f);
dc.RebindTexture();
}
FloatingSymbolsAnimation::Draw(dc, t, alpha * 0.5f);
}
private:
void CheckNext(UIContext &dc, double t) {
if (g_Config.recentIsos.empty()) {
return;
}
for (int index = lastIndex_ + 1; index != lastIndex_; ++index) {
if (index < 0 || index >= (int)g_Config.recentIsos.size()) {
if (lastIndex_ == -1)
break;
index = 0;
}
std::shared_ptr<GameInfo> ginfo = GetInfo(dc, index);
if (ginfo && ginfo->pending) {
// Wait for it to load. It might be the next one.
break;
}
if (ginfo && (ginfo->pic1.texture || ginfo->pic0.texture)) {
nextIndex_ = index;
nextT_ = t + INTERVAL;
break;
}
// Otherwise, keep going. This skips games with no BG.
}
}
std::shared_ptr<GameInfo> GetInfo(UIContext &dc, int index) {
if (index < 0) {
return nullptr;
}
return g_gameInfoCache->GetInfo(dc.GetDrawContext(), g_Config.recentIsos[index], GAMEINFO_WANTBG);
}
Draw::Texture *GetTex(std::shared_ptr<GameInfo> &ginfo) {
if (ginfo && ginfo->pic1.texture) {
return ginfo->pic1.texture->GetTexture();
}
if (ginfo && ginfo->pic0.texture) {
return ginfo->pic0.texture->GetTexture();
}
return nullptr;
}
void DrawTex(UIContext &dc, std::shared_ptr<GameInfo> &ginfo, float amount) {
if (!ginfo || amount <= 0.0f)
return;
Draw::Texture *tex = GetTex(ginfo);
if (!tex)
return;
dc.GetDrawContext()->BindTexture(0, tex);
uint32_t color = whiteAlpha(amount) & 0xFFc0c0c0;
dc.Draw()->DrawTexRect(dc.GetBounds(), 0, 0, 1, 1, color);
dc.Flush();
}
static constexpr double INTERVAL = 8.0;
static constexpr float TRANSITION = 3.0f;
int lastIndex_ = -1;
int nextIndex_ = -1;
double nextT_ = -INTERVAL;
};
// TODO: Add more styles. Remember to add to the enum in Config.cpp and the selector in GameSettings too.
@ -137,6 +238,9 @@ void DrawBackground(UIContext &dc, float alpha) {
case BackgroundAnimation::FLOATING_SYMBOLS:
g_Animation.reset(new FloatingSymbolsAnimation());
break;
case BackgroundAnimation::RECENT_GAMES:
g_Animation.reset(new RecentGamesAnimation());
break;
default:
g_Animation.reset(nullptr);
}