mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-09-24 21:36:26 +02:00
Merge pull request #6388 from unknownbrackets/ui-tweaks
Show game background during controller/keyboard game selection
This commit is contained in:
@@ -24,7 +24,7 @@ enum PBPSubFile {
|
||||
PBP_PARAM_SFO,
|
||||
PBP_ICON0_PNG,
|
||||
PBP_ICON1_PMF,
|
||||
PBP_UNKNOWN_PNG, // PIC0?
|
||||
PBP_PIC0_PNG,
|
||||
PBP_PIC1_PNG,
|
||||
PBP_SND0_AT3,
|
||||
PBP_EXECUTABLE_PSP,
|
||||
|
||||
@@ -240,7 +240,7 @@ void GenerateDepalShader100(char *buffer, GEBufferFormat pixelFormat) {
|
||||
case GE_FORMAT_565:
|
||||
if ((mask & (mask + 1)) == 0 && shift < 16) {
|
||||
const u8 shifts[16] = {0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4};
|
||||
const u32 multipliers[16] = {31, 31, 31, 31, 31, 63, 63, 63, 63, 63, 63, 31, 31, 31, 31, 31};
|
||||
const int multipliers[16] = {31, 31, 31, 31, 31, 63, 63, 63, 63, 63, 63, 31, 31, 31, 31, 31};
|
||||
const char *rgba = "rrrrrggggggbbbbb";
|
||||
const u8 rgba_shift = shifts[shift];
|
||||
if (rgba_shift == 0 && mask == multipliers[shift]) {
|
||||
|
||||
+73
-57
@@ -293,12 +293,26 @@ public:
|
||||
}
|
||||
delete [] contents;
|
||||
}
|
||||
info_->iconDataLoaded = true;
|
||||
}
|
||||
|
||||
if (info_->wantBG) {
|
||||
if (info_->wantFlags & GAMEINFO_WANTBG) {
|
||||
if (pbp.GetSubFileSize(PBP_PIC0_PNG) > 0) {
|
||||
lock_guard lock(info_->lock);
|
||||
pbp.GetSubFileAsString(PBP_PIC0_PNG, &info_->pic0TextureData);
|
||||
info_->pic0DataLoaded = true;
|
||||
}
|
||||
if (pbp.GetSubFileSize(PBP_PIC1_PNG) > 0) {
|
||||
lock_guard lock(info_->lock);
|
||||
pbp.GetSubFileAsString(PBP_PIC1_PNG, &info_->pic1TextureData);
|
||||
info_->pic1DataLoaded = true;
|
||||
}
|
||||
}
|
||||
if (info_->wantFlags & GAMEINFO_WANTSND) {
|
||||
if (pbp.GetSubFileSize(PBP_SND0_AT3) > 0) {
|
||||
lock_guard lock(info_->lock);
|
||||
pbp.GetSubFileAsString(PBP_SND0_AT3, &info_->sndFileData);
|
||||
info_->sndDataLoaded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -319,6 +333,7 @@ handleELF:
|
||||
if (contents) {
|
||||
lock_guard lock(info_->lock);
|
||||
info_->iconTextureData = std::string((const char *)contents, sz);
|
||||
info_->iconDataLoaded = true;
|
||||
}
|
||||
delete [] contents;
|
||||
}
|
||||
@@ -339,10 +354,17 @@ handleELF:
|
||||
}
|
||||
|
||||
ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->iconTextureData, &info_->lock);
|
||||
if (info_->wantBG) {
|
||||
info_->iconDataLoaded = true;
|
||||
if (info_->wantFlags & GAMEINFO_WANTBG) {
|
||||
ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info_->pic0TextureData, &info_->lock);
|
||||
info_->pic0DataLoaded = true;
|
||||
ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1TextureData, &info_->lock);
|
||||
info_->pic1DataLoaded = true;
|
||||
}
|
||||
if (info_->wantFlags & GAMEINFO_WANTSND) {
|
||||
ReadFileToString(&umd, "/PSP_GAME/SND0.AT3", &info_->sndFileData, &info_->lock);
|
||||
info_->pic1DataLoaded = true;
|
||||
}
|
||||
ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1TextureData, &info_->lock);
|
||||
break;
|
||||
}
|
||||
case FILETYPE_PSP_ISO:
|
||||
@@ -365,10 +387,16 @@ handleELF:
|
||||
info_->paramSFO.ReadSFO((const u8 *)paramSFOcontents.data(), paramSFOcontents.size());
|
||||
info_->ParseParamSFO();
|
||||
|
||||
if (info_->wantBG) {
|
||||
if (info_->wantFlags & GAMEINFO_WANTBG) {
|
||||
ReadFileToString(&umd, "/PSP_GAME/PIC0.PNG", &info_->pic0TextureData, &info_->lock);
|
||||
info_->pic0DataLoaded = true;
|
||||
ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1TextureData, &info_->lock);
|
||||
info_->pic1DataLoaded = true;
|
||||
}
|
||||
if (info_->wantFlags & GAMEINFO_WANTSND) {
|
||||
ReadFileToString(&umd, "/PSP_GAME/SND0.AT3", &info_->sndFileData, &info_->lock);
|
||||
info_->pic1DataLoaded = true;
|
||||
}
|
||||
ReadFileToString(&umd, "/PSP_GAME/PIC1.PNG", &info_->pic1TextureData, &info_->lock);
|
||||
}
|
||||
|
||||
// Fall back to unknown icon if ISO is broken/is a homebrew ISO, override is allowed though
|
||||
@@ -382,12 +410,12 @@ handleELF:
|
||||
}
|
||||
delete [] contents;
|
||||
}
|
||||
info_->iconDataLoaded = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case FILETYPE_ARCHIVE_ZIP:
|
||||
info_->paramSFOLoaded = true;
|
||||
info_->wantBG = false;
|
||||
{
|
||||
// Read standard icon
|
||||
size_t sz;
|
||||
@@ -395,6 +423,7 @@ handleELF:
|
||||
if (contents) {
|
||||
lock_guard lock(info_->lock);
|
||||
info_->iconTextureData = std::string((const char *)contents, sz);
|
||||
info_->iconDataLoaded = true;
|
||||
}
|
||||
delete [] contents;
|
||||
}
|
||||
@@ -402,7 +431,6 @@ handleELF:
|
||||
|
||||
case FILETYPE_ARCHIVE_RAR:
|
||||
info_->paramSFOLoaded = true;
|
||||
info_->wantBG = false;
|
||||
{
|
||||
// Read standard icon
|
||||
size_t sz;
|
||||
@@ -410,6 +438,7 @@ handleELF:
|
||||
if (contents) {
|
||||
lock_guard lock(info_->lock);
|
||||
info_->iconTextureData = std::string((const char *)contents, sz);
|
||||
info_->iconDataLoaded = true;
|
||||
}
|
||||
delete [] contents;
|
||||
}
|
||||
@@ -418,12 +447,10 @@ handleELF:
|
||||
case FILETYPE_NORMAL_DIRECTORY:
|
||||
default:
|
||||
info_->paramSFOLoaded = true;
|
||||
info_->wantBG = false;
|
||||
break;
|
||||
}
|
||||
// probably only want these when we ask for the background image...
|
||||
// should maybe flip the flag to "onlyIcon"
|
||||
if (info_->wantBG) {
|
||||
|
||||
if (info_->wantFlags & GAMEINFO_WANTSIZE) {
|
||||
info_->gameSize = info_->GetGameSizeInBytes();
|
||||
info_->saveDataSize = info_->GetSaveDataSizeInBytes();
|
||||
info_->installDataSize = info_->GetInstallDataSizeInBytes();
|
||||
@@ -455,8 +482,7 @@ void GameInfoCache::Shutdown() {
|
||||
StopProcessingWorkQueue(gameInfoWQ_);
|
||||
}
|
||||
|
||||
void GameInfoCache::Save()
|
||||
{
|
||||
void GameInfoCache::Save() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@@ -515,61 +541,31 @@ void GameInfoCache::FlushBGs() {
|
||||
delete iter->second->pic1Texture;
|
||||
iter->second->pic1Texture = 0;
|
||||
}
|
||||
iter->second->wantBG = false;
|
||||
iter->second->wantFlags &= ~GAMEINFO_WANTBG;
|
||||
}
|
||||
}
|
||||
|
||||
// This may run off-main-thread and we thus can't use the global
|
||||
// pspFileSystem (well, we could with synchronization but there might not
|
||||
// even be a game running).
|
||||
GameInfo *GameInfoCache::GetInfo(const std::string &gamePath, bool wantBG) {
|
||||
GameInfo *GameInfoCache::GetInfo(const std::string &gamePath, int wantFlags) {
|
||||
GameInfo *info = 0;
|
||||
|
||||
auto iter = info_.find(gamePath);
|
||||
if (iter != info_.end()) {
|
||||
GameInfo *info = iter->second;
|
||||
if (!info->wantBG && wantBG) {
|
||||
info = iter->second;
|
||||
if ((info->wantFlags & wantFlags) != wantFlags) {
|
||||
// Need to start over. We'll just add a new work item.
|
||||
delete info; // Hm, how dangerous is this? There might be a race condition here.
|
||||
goto again;
|
||||
}
|
||||
{
|
||||
lock_guard lock(info->lock);
|
||||
if (info->iconTextureData.size()) {
|
||||
// We'd have to split up Texture->LoadPNG though, creating some intermediate Image class maybe.
|
||||
info->iconTexture = new Texture();
|
||||
if (info->iconTexture->LoadPNG((const u8 *)info->iconTextureData.data(), info->iconTextureData.size(), false)) {
|
||||
info->timeIconWasLoaded = time_now_d();
|
||||
} else {
|
||||
delete info->iconTexture;
|
||||
info->iconTexture = 0;
|
||||
}
|
||||
info->iconTextureData.clear();
|
||||
}
|
||||
if (info->iconDataLoaded) {
|
||||
SetupTexture(info, info->iconTextureData, info->iconTexture, info->timeIconWasLoaded);
|
||||
}
|
||||
{
|
||||
lock_guard lock(info->lock);
|
||||
if (info->pic0TextureData.size()) {
|
||||
info->pic0Texture = new Texture();
|
||||
if (info->pic0Texture->LoadPNG((const u8 *)info->pic0TextureData.data(), info->pic0TextureData.size(), false)) {
|
||||
info->timePic0WasLoaded = time_now_d();
|
||||
} else {
|
||||
delete info->pic0Texture;
|
||||
info->pic0Texture = 0;
|
||||
}
|
||||
info->pic0TextureData.clear();
|
||||
}
|
||||
if (info->pic0DataLoaded) {
|
||||
SetupTexture(info, info->pic0TextureData, info->pic0Texture, info->timePic0WasLoaded);
|
||||
}
|
||||
{
|
||||
lock_guard lock(info->lock);
|
||||
if (info->pic1TextureData.size()) {
|
||||
info->pic1Texture = new Texture();
|
||||
if (info->pic1Texture->LoadPNG((const u8 *)info->pic1TextureData.data(), info->pic1TextureData.size(), false)) {
|
||||
info->timePic1WasLoaded = time_now_d();
|
||||
} else {
|
||||
delete info->pic1Texture;
|
||||
info->pic1Texture = 0;
|
||||
}
|
||||
info->pic1TextureData.clear();
|
||||
}
|
||||
if (info->pic1DataLoaded) {
|
||||
SetupTexture(info, info->pic1TextureData, info->pic1Texture, info->timePic1WasLoaded);
|
||||
}
|
||||
iter->second->lastAccessedTime = time_now_d();
|
||||
return iter->second;
|
||||
@@ -577,8 +573,13 @@ GameInfo *GameInfoCache::GetInfo(const std::string &gamePath, bool wantBG) {
|
||||
|
||||
again:
|
||||
|
||||
GameInfo *info = new GameInfo();
|
||||
info->wantBG = wantBG;
|
||||
if (!info) {
|
||||
info = new GameInfo();
|
||||
}
|
||||
{
|
||||
lock_guard lock(info->lock);
|
||||
info->wantFlags |= wantFlags;
|
||||
}
|
||||
|
||||
GameInfoWorkItem *item = new GameInfoWorkItem(gamePath, info);
|
||||
gameInfoWQ_->Add(item);
|
||||
@@ -586,3 +587,18 @@ again:
|
||||
info_[gamePath] = info;
|
||||
return info;
|
||||
}
|
||||
|
||||
void GameInfoCache::SetupTexture(GameInfo *info, std::string &textureData, Texture *&tex, double &loadTime) {
|
||||
if (textureData.size()) {
|
||||
if (!tex) {
|
||||
tex = new Texture();
|
||||
if (tex->LoadPNG((const u8 *)textureData.data(), textureData.size(), false)) {
|
||||
loadTime = time_now_d();
|
||||
} else {
|
||||
delete tex;
|
||||
tex = 0;
|
||||
}
|
||||
}
|
||||
textureData.clear();
|
||||
}
|
||||
}
|
||||
|
||||
+59
-3
@@ -42,11 +42,58 @@ enum GameRegion {
|
||||
GAMEREGION_MAX,
|
||||
};
|
||||
|
||||
enum GameInfoWantFlags {
|
||||
GAMEINFO_WANTBG = 0x01,
|
||||
GAMEINFO_WANTSIZE = 0x02,
|
||||
GAMEINFO_WANTSND = 0x04,
|
||||
};
|
||||
|
||||
// TODO: Need to fix c++11 still on Symbian and use std::atomic<bool> instead.
|
||||
class CompletionFlag {
|
||||
public:
|
||||
CompletionFlag() : pending(1) {
|
||||
}
|
||||
|
||||
void SetDone() {
|
||||
#if defined(_WIN32)
|
||||
_WriteBarrier();
|
||||
pending = 0;
|
||||
#else
|
||||
__sync_lock_release(&pending);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool IsDone() {
|
||||
const bool done = pending == 0;
|
||||
#if defined(_WIN32)
|
||||
_ReadBarrier();
|
||||
#else
|
||||
__sync_synchronize();
|
||||
#endif
|
||||
return done;
|
||||
}
|
||||
|
||||
CompletionFlag &operator =(const bool &v) {
|
||||
pending = v ? 0 : 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator bool() {
|
||||
return IsDone();
|
||||
}
|
||||
|
||||
private:
|
||||
volatile u32 pending;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CompletionFlag);
|
||||
};
|
||||
|
||||
class GameInfo {
|
||||
public:
|
||||
GameInfo()
|
||||
: disc_total(0), disc_number(0), region(-1), fileType(FILETYPE_UNKNOWN), paramSFOLoaded(false),
|
||||
iconTexture(NULL), pic0Texture(NULL), pic1Texture(NULL), wantBG(false),
|
||||
iconTexture(NULL), pic0Texture(NULL), pic1Texture(NULL), wantFlags(0),
|
||||
timeIconWasLoaded(0.0), timePic0WasLoaded(0.0), timePic1WasLoaded(0.0),
|
||||
gameSize(0), saveDataSize(0), installDataSize(0) {}
|
||||
|
||||
bool DeleteGame(); // Better be sure what you're doing when calling this.
|
||||
@@ -87,7 +134,9 @@ public:
|
||||
std::string pic1TextureData;
|
||||
Texture *pic1Texture;
|
||||
|
||||
bool wantBG;
|
||||
std::string sndFileData;
|
||||
|
||||
int wantFlags;
|
||||
|
||||
double lastAccessedTime;
|
||||
|
||||
@@ -97,6 +146,11 @@ public:
|
||||
double timePic0WasLoaded;
|
||||
double timePic1WasLoaded;
|
||||
|
||||
CompletionFlag iconDataLoaded;
|
||||
CompletionFlag pic0DataLoaded;
|
||||
CompletionFlag pic1DataLoaded;
|
||||
CompletionFlag sndDataLoaded;
|
||||
|
||||
u64 gameSize;
|
||||
u64 saveDataSize;
|
||||
u64 installDataSize;
|
||||
@@ -116,7 +170,7 @@ public:
|
||||
// but filled in later asynchronously in the background. So keep calling this,
|
||||
// redrawing the UI often. Only set wantBG if you really want it because
|
||||
// it's big. bgTextures may be discarded over time as well.
|
||||
GameInfo *GetInfo(const std::string &gamePath, bool wantBG);
|
||||
GameInfo *GetInfo(const std::string &gamePath, int wantFlags);
|
||||
void Decimate(); // Deletes old info.
|
||||
void FlushBGs(); // Gets rid of all BG textures.
|
||||
|
||||
@@ -125,6 +179,8 @@ public:
|
||||
void Load();
|
||||
|
||||
private:
|
||||
void SetupTexture(GameInfo *info, std::string &textureData, Texture *&tex, double &loadTime);
|
||||
|
||||
// Maps ISO path to info.
|
||||
std::map<std::string, GameInfo *> info_;
|
||||
|
||||
|
||||
+18
-9
@@ -15,6 +15,7 @@
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include <algorithm>
|
||||
#include "base/colorutil.h"
|
||||
#include "base/timeutil.h"
|
||||
#include "gfx_es2/draw_buffer.h"
|
||||
@@ -34,7 +35,7 @@
|
||||
#include "Core/Config.h"
|
||||
|
||||
void GameScreen::CreateViews() {
|
||||
GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, true);
|
||||
GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE);
|
||||
|
||||
I18NCategory *d = GetI18NCategory("Dialog");
|
||||
I18NCategory *ga = GetI18NCategory("Game");
|
||||
@@ -91,13 +92,21 @@ void GameScreen::update(InputState &input) {
|
||||
UIScreen::update(input);
|
||||
|
||||
I18NCategory *ga = GetI18NCategory("Game");
|
||||
GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, true);
|
||||
GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE);
|
||||
|
||||
if (tvTitle_)
|
||||
tvTitle_->SetText(info->title + " (" + info->id + ")");
|
||||
if (info->iconTexture && texvGameIcon_) {
|
||||
texvGameIcon_->SetTexture(info->iconTexture);
|
||||
uint32_t color = whiteAlpha(ease((time_now_d() - info->timeIconWasLoaded) * 3));
|
||||
// Fade the icon with the background.
|
||||
double loadTime = info->timeIconWasLoaded;
|
||||
if (info->pic1Texture) {
|
||||
loadTime = std::max(loadTime, info->timePic1WasLoaded);
|
||||
}
|
||||
if (info->pic0Texture) {
|
||||
loadTime = std::max(loadTime, info->timePic0WasLoaded);
|
||||
}
|
||||
uint32_t color = whiteAlpha(ease((time_now_d() - loadTime) * 3));
|
||||
texvGameIcon_->SetColor(color);
|
||||
}
|
||||
|
||||
@@ -144,7 +153,7 @@ UI::EventReturn GameScreen::OnPlay(UI::EventParams &e) {
|
||||
}
|
||||
|
||||
UI::EventReturn GameScreen::OnGameSettings(UI::EventParams &e) {
|
||||
GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, true);
|
||||
GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE);
|
||||
if (info && info->paramSFOLoaded) {
|
||||
std::string discID = info->paramSFO.GetValueString("DISC_ID");
|
||||
screenManager()->push(new GameSettingsScreen(gamePath_, discID));
|
||||
@@ -155,7 +164,7 @@ UI::EventReturn GameScreen::OnGameSettings(UI::EventParams &e) {
|
||||
UI::EventReturn GameScreen::OnDeleteSaveData(UI::EventParams &e) {
|
||||
I18NCategory *d = GetI18NCategory("Dialog");
|
||||
I18NCategory *ga = GetI18NCategory("Game");
|
||||
GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, true);
|
||||
GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE);
|
||||
if (info) {
|
||||
screenManager()->push(
|
||||
new PromptScreen(d->T("DeleteConfirmAll", "Do you really want to delete all\nyour save data for this game?"), ga->T("ConfirmDelete"), d->T("Cancel"),
|
||||
@@ -167,7 +176,7 @@ UI::EventReturn GameScreen::OnDeleteSaveData(UI::EventParams &e) {
|
||||
}
|
||||
|
||||
void GameScreen::CallbackDeleteSaveData(bool yes) {
|
||||
GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, false);
|
||||
GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, 0);
|
||||
if (yes) {
|
||||
info->DeleteAllSaveData();
|
||||
info->saveDataSize = 0;
|
||||
@@ -178,7 +187,7 @@ void GameScreen::CallbackDeleteSaveData(bool yes) {
|
||||
UI::EventReturn GameScreen::OnDeleteGame(UI::EventParams &e) {
|
||||
I18NCategory *d = GetI18NCategory("Dialog");
|
||||
I18NCategory *ga = GetI18NCategory("Game");
|
||||
GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, true);
|
||||
GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE);
|
||||
if (info) {
|
||||
screenManager()->push(
|
||||
new PromptScreen(d->T("DeleteConfirmGame", "Do you really want to delete this game\nfrom your device? You can't undo this."), ga->T("ConfirmDelete"), d->T("Cancel"),
|
||||
@@ -189,7 +198,7 @@ UI::EventReturn GameScreen::OnDeleteGame(UI::EventParams &e) {
|
||||
}
|
||||
|
||||
void GameScreen::CallbackDeleteGame(bool yes) {
|
||||
GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, false);
|
||||
GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, 0);
|
||||
if (yes) {
|
||||
info->DeleteGame();
|
||||
g_gameInfoCache.Clear();
|
||||
@@ -198,7 +207,7 @@ void GameScreen::CallbackDeleteGame(bool yes) {
|
||||
}
|
||||
|
||||
UI::EventReturn GameScreen::OnCreateShortcut(UI::EventParams &e) {
|
||||
GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, false);
|
||||
GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, 0);
|
||||
if (info) {
|
||||
host->CreateDesktopShortcut(gamePath_, info->title);
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ extern bool iosCanUseJit;
|
||||
#endif
|
||||
|
||||
void GameSettingsScreen::CreateViews() {
|
||||
GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, true);
|
||||
GameInfo *info = g_gameInfoCache.GetInfo(gamePath_, GAMEINFO_WANTBG | GAMEINFO_WANTSIZE);
|
||||
|
||||
cap60FPS_ = g_Config.iForceMaxEmulatedFPS == 60;
|
||||
|
||||
|
||||
+101
-2
@@ -138,7 +138,13 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void FocusChanged(int focusFlags) {
|
||||
UI::Clickable::FocusChanged(focusFlags);
|
||||
TriggerOnHighlight(focusFlags);
|
||||
}
|
||||
|
||||
UI::Event OnHoldClick;
|
||||
UI::Event OnHighlight;
|
||||
|
||||
private:
|
||||
void TriggerOnHoldClick() {
|
||||
@@ -149,6 +155,13 @@ private:
|
||||
down_ = false;
|
||||
OnHoldClick.Trigger(e);
|
||||
}
|
||||
void TriggerOnHighlight(int focusFlags) {
|
||||
UI::EventParams e;
|
||||
e.v = this;
|
||||
e.s = gamePath_;
|
||||
e.a = focusFlags;
|
||||
OnHighlight.Trigger(e);
|
||||
}
|
||||
|
||||
bool gridStyle_;
|
||||
std::string gamePath_;
|
||||
@@ -160,7 +173,7 @@ private:
|
||||
};
|
||||
|
||||
void GameButton::Draw(UIContext &dc) {
|
||||
GameInfo *ginfo = g_gameInfoCache.GetInfo(gamePath_, false);
|
||||
GameInfo *ginfo = g_gameInfoCache.GetInfo(gamePath_, 0);
|
||||
Texture *texture = 0;
|
||||
u32 color = 0, shadowColor = 0;
|
||||
|
||||
@@ -376,6 +389,7 @@ public:
|
||||
|
||||
UI::Event OnChoice;
|
||||
UI::Event OnHoldChoice;
|
||||
UI::Event OnHighlight;
|
||||
|
||||
UI::Choice *HomebrewStoreButton() { return homebrewStoreButton_; }
|
||||
private:
|
||||
@@ -386,6 +400,7 @@ private:
|
||||
|
||||
UI::EventReturn GameButtonClick(UI::EventParams &e);
|
||||
UI::EventReturn GameButtonHoldClick(UI::EventParams &e);
|
||||
UI::EventReturn GameButtonHighlight(UI::EventParams &e);
|
||||
UI::EventReturn NavigateClick(UI::EventParams &e);
|
||||
UI::EventReturn LayoutChange(UI::EventParams &e);
|
||||
UI::EventReturn LastClick(UI::EventParams &e);
|
||||
@@ -568,6 +583,7 @@ void GameBrowser::Refresh() {
|
||||
GameButton *b = gameList_->Add(gameButtons[i]);
|
||||
b->OnClick.Handle(this, &GameBrowser::GameButtonClick);
|
||||
b->OnHoldClick.Handle(this, &GameBrowser::GameButtonHoldClick);
|
||||
b->OnHighlight.Handle(this, &GameBrowser::GameButtonHighlight);
|
||||
}
|
||||
|
||||
// Show a button to toggle pinning at the very end.
|
||||
@@ -667,6 +683,12 @@ UI::EventReturn GameBrowser::GameButtonHoldClick(UI::EventParams &e) {
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
UI::EventReturn GameBrowser::GameButtonHighlight(UI::EventParams &e) {
|
||||
// Insta-update - here we know we are already on the right thread.
|
||||
OnHighlight.Trigger(e);
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
UI::EventReturn GameBrowser::NavigateClick(UI::EventParams &e) {
|
||||
DirButton *button = static_cast<DirButton *>(e.v);
|
||||
std::string text = button->GetPath();
|
||||
@@ -680,7 +702,7 @@ UI::EventReturn GameBrowser::NavigateClick(UI::EventParams &e) {
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
MainScreen::MainScreen() : backFromStore_(false) {
|
||||
MainScreen::MainScreen() : highlightProgress_(0.0f), prevHighlightProgress_(0.0f), backFromStore_(false) {
|
||||
System_SendMessage("event", "mainscreen");
|
||||
}
|
||||
|
||||
@@ -736,6 +758,9 @@ void MainScreen::CreateViews() {
|
||||
tabRecentGames->OnHoldChoice.Handle(this, &MainScreen::OnGameSelected);
|
||||
tabAllGames->OnHoldChoice.Handle(this, &MainScreen::OnGameSelected);
|
||||
tabHomebrew->OnHoldChoice.Handle(this, &MainScreen::OnGameSelected);
|
||||
tabRecentGames->OnHighlight.Handle(this, &MainScreen::OnGameHighlight);
|
||||
tabAllGames->OnHighlight.Handle(this, &MainScreen::OnGameHighlight);
|
||||
tabHomebrew->OnHighlight.Handle(this, &MainScreen::OnGameHighlight);
|
||||
|
||||
if (g_Config.recentIsos.size() > 0) {
|
||||
leftColumn->SetCurrentTab(0);
|
||||
@@ -884,6 +909,59 @@ UI::EventReturn MainScreen::OnLoadFile(UI::EventParams &e) {
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
extern void DrawBackground(UIContext &dc, float alpha);
|
||||
|
||||
void MainScreen::DrawBackground(UIContext &dc) {
|
||||
UIScreenWithBackground::DrawBackground(dc);
|
||||
if (highlightedGamePath_.empty() && prevHighlightedGamePath_.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (DrawBackgroundFor(dc, prevHighlightedGamePath_, 1.0f - prevHighlightProgress_)) {
|
||||
if (prevHighlightProgress_ < 1.0f) {
|
||||
prevHighlightProgress_ += 1.0f / 20.0f;
|
||||
}
|
||||
}
|
||||
if (!highlightedGamePath_.empty()) {
|
||||
if (DrawBackgroundFor(dc, highlightedGamePath_, highlightProgress_)) {
|
||||
if (highlightProgress_ < 1.0f) {
|
||||
highlightProgress_ += 1.0f / 20.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MainScreen::DrawBackgroundFor(UIContext &dc, const std::string &gamePath, float progress) {
|
||||
dc.Flush();
|
||||
|
||||
GameInfo *ginfo = 0;
|
||||
if (!gamePath.empty()) {
|
||||
ginfo = g_gameInfoCache.GetInfo(gamePath, GAMEINFO_WANTBG);
|
||||
// Loading texture data may bind a texture.
|
||||
dc.RebindTexture();
|
||||
|
||||
// Let's not bother if there's no picture.
|
||||
if (!ginfo || (!ginfo->pic1Texture && !ginfo->pic0Texture)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ginfo->pic1Texture) {
|
||||
ginfo->pic1Texture->Bind(0);
|
||||
} else if (ginfo->pic0Texture) {
|
||||
ginfo->pic0Texture->Bind(0);
|
||||
}
|
||||
|
||||
uint32_t color = whiteAlpha(ease(progress)) & 0xFFc0c0c0;
|
||||
dc.Draw()->DrawTexRect(dc.GetBounds(), 0,0,1,1, color);
|
||||
dc.Flush();
|
||||
dc.RebindTexture();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
UI::EventReturn MainScreen::OnGameSelected(UI::EventParams &e) {
|
||||
#ifdef _WIN32
|
||||
std::string path = ReplaceAll(e.s, "\\", "/");
|
||||
@@ -894,6 +972,27 @@ UI::EventReturn MainScreen::OnGameSelected(UI::EventParams &e) {
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
UI::EventReturn MainScreen::OnGameHighlight(UI::EventParams &e) {
|
||||
#ifdef _WIN32
|
||||
std::string path = ReplaceAll(e.s, "\\", "/");
|
||||
#else
|
||||
std::string path = e.s;
|
||||
#endif
|
||||
|
||||
if (!highlightedGamePath_.empty() || (e.a == FF_LOSTFOCUS && highlightedGamePath_ == path)) {
|
||||
if (prevHighlightedGamePath_.empty() || prevHighlightProgress_ >= 0.75f) {
|
||||
prevHighlightedGamePath_ = highlightedGamePath_;
|
||||
prevHighlightProgress_ = 1.0 - highlightProgress_;
|
||||
}
|
||||
highlightedGamePath_.clear();
|
||||
}
|
||||
if (e.a == FF_GOTFOCUS) {
|
||||
highlightedGamePath_ = path;
|
||||
highlightProgress_ = 0.0f;
|
||||
}
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
UI::EventReturn MainScreen::OnGameSelectedInstant(UI::EventParams &e) {
|
||||
#ifdef _WIN32
|
||||
std::string path = ReplaceAll(e.s, "\\", "/");
|
||||
|
||||
@@ -37,13 +37,17 @@ public:
|
||||
|
||||
protected:
|
||||
virtual void CreateViews();
|
||||
virtual void DrawBackground(UIContext &dc);
|
||||
virtual void update(InputState &input);
|
||||
virtual void sendMessage(const char *message, const char *value);
|
||||
virtual void dialogFinished(const Screen *dialog, DialogResult result);
|
||||
|
||||
private:
|
||||
bool DrawBackgroundFor(UIContext &dc, const std::string &gamePath, float progress);
|
||||
|
||||
UI::EventReturn OnGameSelected(UI::EventParams &e);
|
||||
UI::EventReturn OnGameSelectedInstant(UI::EventParams &e);
|
||||
UI::EventReturn OnGameHighlight(UI::EventParams &e);
|
||||
// Event handlers
|
||||
UI::EventReturn OnLoadFile(UI::EventParams &e);
|
||||
UI::EventReturn OnGameSettings(UI::EventParams &e);
|
||||
@@ -60,6 +64,10 @@ private:
|
||||
UI::LinearLayout *upgradeBar_;
|
||||
UI::TabHolder *tabHolder_;
|
||||
|
||||
std::string highlightedGamePath_;
|
||||
std::string prevHighlightedGamePath_;
|
||||
float highlightProgress_;
|
||||
float prevHighlightProgress_;
|
||||
bool backFromStore_;
|
||||
};
|
||||
|
||||
|
||||
+5
-2
@@ -105,20 +105,23 @@ void DrawBackground(UIContext &dc, float alpha = 1.0f) {
|
||||
}
|
||||
|
||||
void DrawGameBackground(UIContext &dc, const std::string &gamePath) {
|
||||
GameInfo *ginfo = g_gameInfoCache.GetInfo(gamePath, true);
|
||||
GameInfo *ginfo = g_gameInfoCache.GetInfo(gamePath, GAMEINFO_WANTBG);
|
||||
dc.Flush();
|
||||
|
||||
if (ginfo) {
|
||||
bool hasPic = false;
|
||||
double loadTime;
|
||||
if (ginfo->pic1Texture) {
|
||||
ginfo->pic1Texture->Bind(0);
|
||||
loadTime = ginfo->timePic1WasLoaded;
|
||||
hasPic = true;
|
||||
} else if (ginfo->pic0Texture) {
|
||||
ginfo->pic0Texture->Bind(0);
|
||||
loadTime = ginfo->timePic0WasLoaded;
|
||||
hasPic = true;
|
||||
}
|
||||
if (hasPic) {
|
||||
uint32_t color = whiteAlpha(ease((time_now_d() - ginfo->timePic1WasLoaded) * 3)) & 0xFFc0c0c0;
|
||||
uint32_t color = whiteAlpha(ease((time_now_d() - loadTime) * 3)) & 0xFFc0c0c0;
|
||||
dc.Draw()->DrawTexRect(dc.GetBounds(), 0,0,1,1, color);
|
||||
dc.Flush();
|
||||
dc.RebindTexture();
|
||||
|
||||
Reference in New Issue
Block a user