mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
Refactor the highlight handling and background drawing
This commit is contained in:
+50
-45
@@ -455,6 +455,54 @@ enum class BackgroundFillMode {
|
||||
FitToScreen = 2,
|
||||
};
|
||||
|
||||
void DrawBackgroundTexture(UIContext &dc, Draw::Texture *texture, Lin::Vec3 focus, float alpha) {
|
||||
dc.GetDrawContext()->BindTexture(0, texture);
|
||||
uint32_t color = whiteAlpha(std::clamp(alpha, 0.0f, 1.0f)) & 0xFFc0c0c0;
|
||||
|
||||
// TODO: Make this configurable?
|
||||
const BackgroundFillMode mode = BackgroundFillMode::AdaptiveCropToScreen;
|
||||
|
||||
const Bounds screenBounds = dc.GetBounds();
|
||||
float imageW = screenBounds.w;
|
||||
float imageH = screenBounds.h;
|
||||
float imageAspect = (float)texture->Width() / (float)texture->Height();
|
||||
|
||||
float squash = imageAspect / screenBounds.AspectRatio();
|
||||
|
||||
// Allow a lot of leeway for the image aspect - let it stretch a bit, and only then start cropping.
|
||||
const float aspectLeeway = 0.5f;
|
||||
if (mode == BackgroundFillMode::AdaptiveCropToScreen && squash >= 0.6f && squash < 1.7f) {
|
||||
imageAspect = screenBounds.AspectRatio();
|
||||
}
|
||||
|
||||
// Fit the image into the screen bounds according to the fill mode.
|
||||
if (imageAspect > screenBounds.AspectRatio()) {
|
||||
// Image is wider than screen.
|
||||
if (mode == BackgroundFillMode::AdaptiveCropToScreen) {
|
||||
// Crop width.
|
||||
imageW = screenBounds.h * imageAspect;
|
||||
} else if (mode == BackgroundFillMode::FitToScreen) {
|
||||
// Fit height.
|
||||
imageH = screenBounds.w / imageAspect;
|
||||
}
|
||||
} else {
|
||||
// Image is taller than screen.
|
||||
if (mode == BackgroundFillMode::AdaptiveCropToScreen) {
|
||||
// Crop height.
|
||||
imageH = screenBounds.w / imageAspect;
|
||||
} else if (mode == BackgroundFillMode::FitToScreen) {
|
||||
// Fit width.
|
||||
imageW = screenBounds.h / imageAspect;
|
||||
}
|
||||
}
|
||||
|
||||
Bounds finalImageBounds = Bounds::FromCenterWH(screenBounds.centerX(), screenBounds.centerY(), imageW, imageH);
|
||||
|
||||
dc.Draw()->DrawTexRect(finalImageBounds, 0, 0, 1, 1, color);
|
||||
dc.Flush();
|
||||
dc.RebindTexture();
|
||||
}
|
||||
|
||||
void DrawGameBackground(UIContext &dc, const Path &gamePath, Lin::Vec3 focus, float alpha) {
|
||||
using namespace Draw;
|
||||
using namespace UI;
|
||||
@@ -467,51 +515,8 @@ void DrawGameBackground(UIContext &dc, const Path &gamePath, Lin::Vec3 focus, fl
|
||||
|
||||
GameInfoTex *pic = (ginfo && ginfo->Ready(GameInfoFlags::PIC1)) ? ginfo->GetPIC1() : nullptr;
|
||||
if (pic && pic->texture) {
|
||||
dc.GetDrawContext()->BindTexture(0, pic->texture);
|
||||
uint32_t color = whiteAlpha(std::clamp(ease((time_now_d() - pic->timeLoaded) * 3.0f) * alpha, 0.0f, 1.0f)) & 0xFFc0c0c0;
|
||||
|
||||
// TODO: Make this configurable?
|
||||
const BackgroundFillMode mode = BackgroundFillMode::AdaptiveCropToScreen;
|
||||
|
||||
const Bounds screenBounds = dc.GetBounds();
|
||||
float imageW = screenBounds.w;
|
||||
float imageH = screenBounds.h;
|
||||
float imageAspect = (float)pic->texture->Width() / (float)pic->texture->Height();
|
||||
|
||||
float squash = imageAspect / screenBounds.AspectRatio();
|
||||
|
||||
// Allow a lot of leeway for the image aspect - let it stretch a bit, and only then start cropping.
|
||||
const float aspectLeeway = 0.5f;
|
||||
if (mode == BackgroundFillMode::AdaptiveCropToScreen && squash >= 0.6f && squash < 1.7f) {
|
||||
imageAspect = screenBounds.AspectRatio();
|
||||
}
|
||||
|
||||
// Fit the image into the screen bounds according to the fill mode.
|
||||
if (imageAspect > screenBounds.AspectRatio()) {
|
||||
// Image is wider than screen.
|
||||
if (mode == BackgroundFillMode::AdaptiveCropToScreen) {
|
||||
// Crop width.
|
||||
imageW = screenBounds.h * imageAspect;
|
||||
} else if (mode == BackgroundFillMode::FitToScreen) {
|
||||
// Fit height.
|
||||
imageH = screenBounds.w / imageAspect;
|
||||
}
|
||||
} else {
|
||||
// Image is taller than screen.
|
||||
if (mode == BackgroundFillMode::AdaptiveCropToScreen) {
|
||||
// Crop height.
|
||||
imageH = screenBounds.w / imageAspect;
|
||||
} else if (mode == BackgroundFillMode::FitToScreen) {
|
||||
// Fit width.
|
||||
imageW = screenBounds.h / imageAspect;
|
||||
}
|
||||
}
|
||||
|
||||
Bounds finalImageBounds = Bounds::FromCenterWH(screenBounds.centerX(), screenBounds.centerY(), imageW, imageH);
|
||||
|
||||
dc.Draw()->DrawTexRect(finalImageBounds, 0, 0, 1, 1, color);
|
||||
dc.Flush();
|
||||
dc.RebindTexture();
|
||||
float alphaMul = ease((time_now_d() - pic->timeLoaded) * 3.0f);
|
||||
DrawBackgroundTexture(dc, pic->texture, focus, alpha * alphaMul);
|
||||
} else {
|
||||
::DrawBackground(dc, 1.0f, focus);
|
||||
dc.RebindTexture();
|
||||
|
||||
+43
-29
@@ -1619,27 +1619,28 @@ void MainScreen::OnLoadFile(UI::EventParams &e) {
|
||||
}
|
||||
|
||||
void MainScreen::DrawBackground(UIContext &dc) {
|
||||
if (highlightedGamePath_.empty() && prevHighlightedGamePath_.empty()) {
|
||||
return;
|
||||
}
|
||||
constexpr float fadeTime = 0.5f; //
|
||||
|
||||
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;
|
||||
double now = time_now_d();
|
||||
|
||||
for (auto iter = highlightedBackgrounds_.begin(); iter != highlightedBackgrounds_.end(); ) {
|
||||
float timeSinceStart = float(now - iter->startTime);
|
||||
float alpha = std::clamp(timeSinceStart / fadeTime, 0.0f, 1.0f);
|
||||
if (iter->endTime > 0.0) {
|
||||
float fadeOutAlpha = std::max(0.0f, float(now - iter->endTime) / fadeTime);
|
||||
if (fadeOutAlpha > 1.0f) {
|
||||
iter = highlightedBackgrounds_.erase(iter);
|
||||
continue;
|
||||
}
|
||||
alpha *= 1.0f - fadeOutAlpha;
|
||||
}
|
||||
DrawBackgroundFor(dc, iter->gamePath, alpha);
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
bool MainScreen::DrawBackgroundFor(UIContext &dc, const Path &gamePath, float progress) {
|
||||
::DrawGameBackground(dc, gamePath, Lin::Vec3(0.f, 0.f, 0.f), progress);
|
||||
return true;
|
||||
void MainScreen::DrawBackgroundFor(UIContext &dc, const Path &gamePath, float alpha) {
|
||||
::DrawGameBackground(dc, gamePath, Lin::Vec3(0.f, 0.f, 0.f), alpha);
|
||||
}
|
||||
|
||||
void MainScreen::OnGameSelected(UI::EventParams &e) {
|
||||
@@ -1658,26 +1659,40 @@ void MainScreen::OnGameSelected(UI::EventParams &e) {
|
||||
screenManager()->push(new GameScreen(path, false));
|
||||
}
|
||||
|
||||
void MainScreen::InstantHighlight(const Path &path) {
|
||||
// Clear the previous highlight immediately, so we don't have multiple at once.
|
||||
highlightedBackgrounds_.clear();
|
||||
highlightedBackgrounds_.push_back({path, 0.0f, -1.0});
|
||||
}
|
||||
|
||||
void MainScreen::OnGameHighlight(UI::EventParams &e) {
|
||||
using namespace UI;
|
||||
|
||||
Path path(e.s);
|
||||
|
||||
// Don't change when re-highlighting what's already highlighted.
|
||||
if (path != highlightedGamePath_ || e.a == FF_LOSTFOCUS) {
|
||||
if (!highlightedGamePath_.empty()) {
|
||||
if (prevHighlightedGamePath_.empty() || prevHighlightProgress_ >= 0.75f) {
|
||||
prevHighlightedGamePath_ = highlightedGamePath_;
|
||||
prevHighlightProgress_ = 1.0 - highlightProgress_;
|
||||
}
|
||||
highlightedGamePath_.clear();
|
||||
}
|
||||
if (e.a == FF_GOTFOCUS) {
|
||||
highlightedGamePath_ = path;
|
||||
highlightProgress_ = 0.0f;
|
||||
if (path == highlightedGamePath_) {
|
||||
// Already highlighted, nothing to do.
|
||||
return;
|
||||
}
|
||||
|
||||
// Trigger fadeouts on any active highlights.
|
||||
for (auto &iter : highlightedBackgrounds_) {
|
||||
if (iter.endTime < 0.0) {
|
||||
iter.endTime = time_now_d();
|
||||
}
|
||||
}
|
||||
|
||||
highlightedGamePath_ = path;
|
||||
|
||||
_dbg_assert_(!path.empty());
|
||||
|
||||
if (path.empty()) {
|
||||
// Nothing highlighed? Exit.
|
||||
return;
|
||||
}
|
||||
|
||||
// Add a new entry to the highlight list.
|
||||
highlightedBackgrounds_.push_back({path, time_now_d(), -1.0});
|
||||
if ((!highlightedGamePath_.empty() || e.a == FF_LOSTFOCUS) && !lockBackgroundAudio_) {
|
||||
g_BackgroundAudio.SetGame(highlightedGamePath_);
|
||||
}
|
||||
@@ -1733,8 +1748,7 @@ void MainScreen::dialogFinished(const Screen *dialog, DialogResult result) {
|
||||
} else if (tag == "Game") {
|
||||
if (!restoreFocusGamePath_.empty() && UI::IsFocusMovementEnabled()) {
|
||||
// Prevent the background from fading, since we just were displaying it.
|
||||
highlightedGamePath_ = restoreFocusGamePath_;
|
||||
highlightProgress_ = 1.0f;
|
||||
InstantHighlight(restoreFocusGamePath_);
|
||||
|
||||
// Refocus the game button itself.
|
||||
int tab = tabHolder_->GetCurrentTab();
|
||||
|
||||
+11
-4
@@ -122,6 +122,12 @@ private:
|
||||
|
||||
class RemoteISOBrowseScreen;
|
||||
|
||||
struct HighlightedBackground {
|
||||
Path gamePath;
|
||||
double startTime;
|
||||
double endTime;
|
||||
};
|
||||
|
||||
class MainScreen : public UIBaseScreen {
|
||||
public:
|
||||
MainScreen();
|
||||
@@ -149,7 +155,7 @@ protected:
|
||||
void sendMessage(UIMessage message, const char *value) override;
|
||||
void dialogFinished(const Screen *dialog, DialogResult result) override;
|
||||
|
||||
bool DrawBackgroundFor(UIContext &dc, const Path &gamePath, float progress);
|
||||
void DrawBackgroundFor(UIContext &dc, const Path &gamePath, float alpha);
|
||||
|
||||
void OnGameSelected(UI::EventParams &e);
|
||||
void OnGameSelectedInstant(UI::EventParams &e);
|
||||
@@ -168,10 +174,9 @@ protected:
|
||||
Path restoreFocusGamePath_;
|
||||
std::vector<GameBrowser *> gameBrowsers_;
|
||||
|
||||
std::vector<HighlightedBackground> highlightedBackgrounds_;
|
||||
Path highlightedGamePath_;
|
||||
Path prevHighlightedGamePath_;
|
||||
float highlightProgress_ = 0.0f;
|
||||
float prevHighlightProgress_ = 0.0f;
|
||||
|
||||
bool backFromStore_ = false;
|
||||
bool lockBackgroundAudio_ = false;
|
||||
bool lastVertical_ = false;
|
||||
@@ -181,6 +186,8 @@ protected:
|
||||
std::string searchFilter_;
|
||||
|
||||
friend class RemoteISOBrowseScreen;
|
||||
private:
|
||||
void InstantHighlight(const Path &path);
|
||||
};
|
||||
|
||||
class UmdReplaceScreen : public UIBaseDialogScreen {
|
||||
|
||||
Reference in New Issue
Block a user