mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 05:19:56 +00:00
Refactor the on-screen display to be more customizable
This commit is contained in:
parent
1475fcb065
commit
48d577014a
@ -21,22 +21,6 @@ void OnScreenDisplay::Update() {
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto iter = sideEntries_.begin(); iter != sideEntries_.end(); ) {
|
||||
if (now >= iter->endTime) {
|
||||
iter = sideEntries_.erase(iter);
|
||||
} else {
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto iter = bars_.begin(); iter != bars_.end(); ) {
|
||||
if (now >= iter->endTime) {
|
||||
iter = bars_.erase(iter);
|
||||
} else {
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<OnScreenDisplay::Entry> OnScreenDisplay::Entries() {
|
||||
@ -44,16 +28,6 @@ std::vector<OnScreenDisplay::Entry> OnScreenDisplay::Entries() {
|
||||
return entries_; // makes a copy.
|
||||
}
|
||||
|
||||
std::vector<OnScreenDisplay::Entry> OnScreenDisplay::SideEntries() {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
return sideEntries_; // makes a copy.
|
||||
}
|
||||
|
||||
std::vector<OnScreenDisplay::ProgressBar> OnScreenDisplay::ProgressBars() {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
return bars_; // makes a copy.
|
||||
}
|
||||
|
||||
void OnScreenDisplay::NudgeSidebar() {
|
||||
sideBarShowTime_ = time_now_d();
|
||||
}
|
||||
@ -89,7 +63,7 @@ void OnScreenDisplay::Show(OSDType type, const std::string &text, const std::str
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
if (id) {
|
||||
for (auto iter = entries_.begin(); iter != entries_.end(); ++iter) {
|
||||
if (iter->id && !strcmp(iter->id, id)) {
|
||||
if (iter->id == id) {
|
||||
Entry msg = *iter;
|
||||
msg.endTime = now + duration_s;
|
||||
msg.text = text;
|
||||
@ -111,7 +85,9 @@ void OnScreenDisplay::Show(OSDType type, const std::string &text, const std::str
|
||||
msg.startTime = now;
|
||||
msg.endTime = now + duration_s;
|
||||
msg.type = type;
|
||||
msg.id = id;
|
||||
if (id) {
|
||||
msg.id = id;
|
||||
}
|
||||
entries_.insert(entries_.begin(), msg);
|
||||
}
|
||||
|
||||
@ -132,7 +108,7 @@ void OnScreenDisplay::ShowAchievementProgress(int achievementID, bool show) {
|
||||
double now = time_now_d();
|
||||
|
||||
// There can only be one of these at a time.
|
||||
for (auto &entry : sideEntries_) {
|
||||
for (auto &entry : entries_) {
|
||||
if (entry.type == OSDType::ACHIEVEMENT_PROGRESS) {
|
||||
if (!show) {
|
||||
// Hide and eventually delete it.
|
||||
@ -158,13 +134,13 @@ void OnScreenDisplay::ShowAchievementProgress(int achievementID, bool show) {
|
||||
entry.type = OSDType::ACHIEVEMENT_PROGRESS;
|
||||
entry.startTime = now;
|
||||
entry.endTime = now + forever_s;
|
||||
sideEntries_.insert(sideEntries_.begin(), entry);
|
||||
entries_.insert(entries_.begin(), entry);
|
||||
}
|
||||
|
||||
void OnScreenDisplay::ShowChallengeIndicator(int achievementID, bool show) {
|
||||
double now = time_now_d();
|
||||
|
||||
for (auto &entry : sideEntries_) {
|
||||
for (auto &entry : entries_) {
|
||||
if (entry.numericID == achievementID && entry.type == OSDType::ACHIEVEMENT_CHALLENGE_INDICATOR && !show) {
|
||||
// Hide and eventually delete it.
|
||||
entry.endTime = now + (double)FadeoutTime();
|
||||
@ -184,13 +160,13 @@ void OnScreenDisplay::ShowChallengeIndicator(int achievementID, bool show) {
|
||||
entry.type = OSDType::ACHIEVEMENT_CHALLENGE_INDICATOR;
|
||||
entry.startTime = now;
|
||||
entry.endTime = now + forever_s;
|
||||
sideEntries_.insert(sideEntries_.begin(), entry);
|
||||
entries_.insert(entries_.begin(), entry);
|
||||
}
|
||||
|
||||
void OnScreenDisplay::ShowLeaderboardTracker(int leaderboardTrackerID, const char *trackerText, bool show) { // show=true is used both for create and update.
|
||||
double now = time_now_d();
|
||||
|
||||
for (auto &entry : sideEntries_) {
|
||||
for (auto &entry : entries_) {
|
||||
if (entry.numericID == leaderboardTrackerID && entry.type == OSDType::LEADERBOARD_TRACKER) {
|
||||
if (show) {
|
||||
// Just an update.
|
||||
@ -218,7 +194,7 @@ void OnScreenDisplay::ShowLeaderboardTracker(int leaderboardTrackerID, const cha
|
||||
if (trackerText) {
|
||||
entry.text = trackerText;
|
||||
}
|
||||
sideEntries_.insert(sideEntries_.begin(), entry);
|
||||
entries_.insert(entries_.begin(), entry);
|
||||
}
|
||||
|
||||
void OnScreenDisplay::ShowOnOff(const std::string &message, bool on, float duration_s) {
|
||||
@ -235,32 +211,33 @@ void OnScreenDisplay::SetProgressBar(std::string id, std::string &&message, floa
|
||||
bool found = false;
|
||||
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
for (auto &bar : bars_) {
|
||||
if (bar.id == id) {
|
||||
for (auto &bar : entries_) {
|
||||
if (bar.type == OSDType::PROGRESS_BAR && bar.id == id) {
|
||||
bar.minValue = minValue;
|
||||
bar.maxValue = maxValue;
|
||||
bar.progress = progress;
|
||||
bar.message = message;
|
||||
bar.text = message;
|
||||
bar.endTime = now + 60.0; // Nudge the progress bar to keep it shown.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ProgressBar bar;
|
||||
Entry bar;
|
||||
bar.id = id;
|
||||
bar.message = std::move(message);
|
||||
bar.type = OSDType::PROGRESS_BAR;
|
||||
bar.text = std::move(message);
|
||||
bar.minValue = minValue;
|
||||
bar.maxValue = maxValue;
|
||||
bar.progress = progress;
|
||||
bar.startTime = now + delay;
|
||||
bar.endTime = now + 60.0; // Show the progress bar for 60 seconds, then fade it out.
|
||||
bars_.push_back(bar);
|
||||
entries_.push_back(bar);
|
||||
}
|
||||
|
||||
void OnScreenDisplay::RemoveProgressBar(std::string id, bool success, float delay_s) {
|
||||
std::lock_guard<std::mutex> guard(mutex_);
|
||||
for (auto iter = bars_.begin(); iter != bars_.end(); iter++) {
|
||||
if (iter->id == id) {
|
||||
for (auto iter = entries_.begin(); iter != entries_.end(); iter++) {
|
||||
if (iter->type == OSDType::PROGRESS_BAR && iter->id == id) {
|
||||
if (success) {
|
||||
// Quickly shoot up to max, if we weren't there.
|
||||
if (iter->maxValue != 0.0f) {
|
||||
@ -293,16 +270,4 @@ void OnScreenDisplay::ClearAchievementStuff() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (auto &iter : sideEntries_) {
|
||||
switch (iter.type) {
|
||||
case OSDType::ACHIEVEMENT_CHALLENGE_INDICATOR:
|
||||
case OSDType::ACHIEVEMENT_UNLOCKED:
|
||||
case OSDType::ACHIEVEMENT_PROGRESS:
|
||||
case OSDType::LEADERBOARD_TRACKER:
|
||||
iter.endTime = now;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,22 @@ enum class OSDType {
|
||||
ACHIEVEMENT_CHALLENGE_INDICATOR, // Achievement icon ONLY, no auto-hide
|
||||
|
||||
LEADERBOARD_TRACKER,
|
||||
|
||||
PROGRESS_BAR,
|
||||
|
||||
VALUE_COUNT,
|
||||
};
|
||||
|
||||
enum class ScreenEdgePosition {
|
||||
BOTTOM_LEFT = 0,
|
||||
BOTTOM_CENTER = 1,
|
||||
BOTTOM_RIGHT = 2,
|
||||
TOP_LEFT = 3,
|
||||
TOP_CENTER = 4,
|
||||
TOP_RIGHT = 5,
|
||||
CENTER_LEFT = 6,
|
||||
CENTER_RIGHT = 7,
|
||||
VALUE_COUNT,
|
||||
};
|
||||
|
||||
// Data holder for on-screen messages.
|
||||
@ -67,31 +83,23 @@ public:
|
||||
std::string text2;
|
||||
std::string iconName;
|
||||
int numericID;
|
||||
const char *id;
|
||||
std::string id;
|
||||
double startTime;
|
||||
double endTime;
|
||||
};
|
||||
|
||||
struct ProgressBar {
|
||||
std::string id;
|
||||
std::string message;
|
||||
// Progress-bar-only data:
|
||||
float minValue;
|
||||
float maxValue;
|
||||
float progress;
|
||||
double startTime;
|
||||
double endTime;
|
||||
};
|
||||
|
||||
std::vector<Entry> Entries();
|
||||
std::vector<Entry> SideEntries();
|
||||
std::vector<ProgressBar> ProgressBars();
|
||||
|
||||
static float FadeinTime() { return 0.1f; }
|
||||
static float FadeoutTime() { return 0.25f; }
|
||||
|
||||
private:
|
||||
std::vector<Entry> entries_;
|
||||
std::vector<Entry> sideEntries_;
|
||||
std::vector<ProgressBar> bars_;
|
||||
std::mutex mutex_;
|
||||
|
||||
double sideBarShowTime_ = 0.0;
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "Common/Thread/ThreadUtil.h"
|
||||
#include "Common/GPU/Vulkan/VulkanLoader.h"
|
||||
#include "Common/VR/PPSSPPVR.h"
|
||||
#include "Common/System/OSD.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/ConfigSettings.h"
|
||||
#include "Core/ConfigValues.h"
|
||||
|
@ -29,17 +29,6 @@
|
||||
|
||||
extern const char *PPSSPP_GIT_VERSION;
|
||||
|
||||
enum class ScreenEdgePosition {
|
||||
BOTTOM_LEFT = 0,
|
||||
BOTTOM_CENTER = 1,
|
||||
BOTOM_RIGHT = 2,
|
||||
TOP_LEFT = 3,
|
||||
TOP_CENTER = 4,
|
||||
TOP_RIGHT = 5,
|
||||
CENTER_LEFT = 6,
|
||||
CENTER_RIGHT = 7,
|
||||
};
|
||||
|
||||
namespace http {
|
||||
class Request;
|
||||
class RequestManager;
|
||||
|
@ -459,6 +459,11 @@ const char *GetCompilerABI() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void SystemInfoScreen::update() {
|
||||
TabbedUIDialogScreenWithGameBackground::update();
|
||||
g_OSD.NudgeSidebar();
|
||||
}
|
||||
|
||||
void SystemInfoScreen::CreateTabs() {
|
||||
using namespace Draw;
|
||||
using namespace UI;
|
||||
|
@ -113,6 +113,8 @@ public:
|
||||
|
||||
void CreateTabs() override;
|
||||
|
||||
void update() override;
|
||||
|
||||
protected:
|
||||
bool ShowSearchControls() const override { return false; }
|
||||
};
|
||||
|
@ -897,7 +897,7 @@ static UI::AnchorLayoutParams *AnchorInCorner(const Bounds &bounds, int corner,
|
||||
switch ((ScreenEdgePosition)g_Config.iChatButtonPosition) {
|
||||
case ScreenEdgePosition::BOTTOM_LEFT: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, xOffset, NONE, NONE, yOffset, true);
|
||||
case ScreenEdgePosition::BOTTOM_CENTER: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, bounds.centerX(), NONE, NONE, yOffset, true);
|
||||
case ScreenEdgePosition::BOTOM_RIGHT: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, NONE, NONE, xOffset, yOffset, true);
|
||||
case ScreenEdgePosition::BOTTOM_RIGHT: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, NONE, NONE, xOffset, yOffset, true);
|
||||
case ScreenEdgePosition::TOP_LEFT: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, xOffset, yOffset, NONE, NONE, true);
|
||||
case ScreenEdgePosition::TOP_CENTER: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, bounds.centerX(), yOffset, NONE, NONE, true);
|
||||
case ScreenEdgePosition::TOP_RIGHT: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, NONE, yOffset, xOffset, NONE, true);
|
||||
|
@ -156,12 +156,12 @@ static void RenderOSDEntry(UIContext &dc, const OnScreenDisplay::Entry &entry, B
|
||||
}
|
||||
}
|
||||
|
||||
static void MeasureOSDProgressBar(const UIContext &dc, const OnScreenDisplay::ProgressBar &bar, float *width, float *height) {
|
||||
static void MeasureOSDProgressBar(const UIContext &dc, const OnScreenDisplay::Entry &bar, float *width, float *height) {
|
||||
*height = 36;
|
||||
*width = 450.0f;
|
||||
}
|
||||
|
||||
static void RenderOSDProgressBar(UIContext &dc, const OnScreenDisplay::ProgressBar &entry, Bounds bounds, int align, float alpha) {
|
||||
static void RenderOSDProgressBar(UIContext &dc, const OnScreenDisplay::Entry &entry, Bounds bounds, int align, float alpha) {
|
||||
uint32_t foreGround = whiteAlpha(alpha);
|
||||
|
||||
dc.DrawRectDropShadow(bounds, 12.0f, 0.7f * alpha);
|
||||
@ -197,7 +197,7 @@ static void RenderOSDProgressBar(UIContext &dc, const OnScreenDisplay::ProgressB
|
||||
dc.SetFontStyle(dc.theme->uiFont);
|
||||
dc.SetFontScale(1.0f, 1.0f);
|
||||
|
||||
dc.DrawTextShadowRect(entry.message.c_str(), bounds, colorAlpha(0xFFFFFFFF, alpha), (align & FLAG_DYNAMIC_ASCII) | ALIGN_CENTER);
|
||||
dc.DrawTextShadowRect(entry.text.c_str(), bounds, colorAlpha(0xFFFFFFFF, alpha), (align & FLAG_DYNAMIC_ASCII) | ALIGN_CENTER);
|
||||
}
|
||||
|
||||
static void MeasureLeaderboardTracker(UIContext &dc, const std::string &text, float *width, float *height) {
|
||||
@ -226,143 +226,209 @@ void OnScreenMessagesView::Draw(UIContext &dc) {
|
||||
|
||||
double now = time_now_d();
|
||||
|
||||
float y = 10.0f;
|
||||
const float padding = 5.0f;
|
||||
|
||||
const float fadeinCoef = 1.0f / OnScreenDisplay::FadeinTime();
|
||||
const float fadeoutCoef = 1.0f / OnScreenDisplay::FadeoutTime();
|
||||
|
||||
float sidebarAlpha = g_OSD.SidebarAlpha();
|
||||
|
||||
if (sidebarAlpha > 0.0f) {
|
||||
// Draw side entries. Top entries should apply on top of them if there's a collision, so drawing
|
||||
// these first makes sense.
|
||||
const std::vector<OnScreenDisplay::Entry> sideEntries = g_OSD.SideEntries();
|
||||
for (auto &entry : sideEntries) {
|
||||
float tw, th;
|
||||
struct LayoutEdge {
|
||||
float height;
|
||||
float maxWidth;
|
||||
float alpha;
|
||||
};
|
||||
|
||||
const rc_client_achievement_t *achievement = nullptr;
|
||||
AchievementRenderStyle style;
|
||||
struct MeasuredEntry {
|
||||
float w;
|
||||
float h;
|
||||
float h1;
|
||||
float alpha;
|
||||
int align;
|
||||
int align2;
|
||||
AchievementRenderStyle style;
|
||||
};
|
||||
|
||||
switch (entry.type) {
|
||||
case OSDType::ACHIEVEMENT_PROGRESS:
|
||||
{
|
||||
achievement = rc_client_get_achievement_info(Achievements::GetClient(), entry.numericID);
|
||||
if (!achievement)
|
||||
continue;
|
||||
style = AchievementRenderStyle::PROGRESS_INDICATOR;
|
||||
MeasureAchievement(dc, achievement, style, &tw, &th);
|
||||
break;
|
||||
}
|
||||
case OSDType::ACHIEVEMENT_CHALLENGE_INDICATOR:
|
||||
{
|
||||
achievement = rc_client_get_achievement_info(Achievements::GetClient(), entry.numericID);
|
||||
if (!achievement)
|
||||
continue;
|
||||
style = AchievementRenderStyle::CHALLENGE_INDICATOR;
|
||||
MeasureAchievement(dc, achievement, style, &tw, &th);
|
||||
break;
|
||||
}
|
||||
case OSDType::LEADERBOARD_TRACKER:
|
||||
{
|
||||
MeasureLeaderboardTracker(dc, entry.text, &tw, &th);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
Bounds b(10.0f, y, tw, th);
|
||||
// We don't multiply in sidebarAlpha here because it shouldn't drive the below animation.
|
||||
float alpha = Clamp((float)(entry.endTime - now) * fadeoutCoef, 0.0f, 1.0f);
|
||||
// OK, render the thing.
|
||||
|
||||
switch (entry.type) {
|
||||
case OSDType::ACHIEVEMENT_PROGRESS:
|
||||
case OSDType::ACHIEVEMENT_CHALLENGE_INDICATOR:
|
||||
{
|
||||
RenderAchievement(dc, achievement, style, b, alpha * sidebarAlpha, entry.startTime, now, false);
|
||||
break;
|
||||
}
|
||||
case OSDType::LEADERBOARD_TRACKER:
|
||||
RenderLeaderboardTracker(dc, b, entry.text, alpha * sidebarAlpha);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
y += (b.h + 4.0f) * alpha; // including alpha here gets us smooth animations.
|
||||
}
|
||||
}
|
||||
|
||||
y = 10.0f;
|
||||
|
||||
// Draw the progress bars.
|
||||
const std::vector<OnScreenDisplay::ProgressBar> bars = g_OSD.ProgressBars();
|
||||
for (auto &bar : bars) {
|
||||
float tw, th;
|
||||
MeasureOSDProgressBar(dc, bar, &tw, &th);
|
||||
Bounds b(0.0f, y, tw, th);
|
||||
b.x = (bounds_.w - b.w) * 0.5f;
|
||||
|
||||
float enterAlpha = saturatef((float)(now - bar.startTime) * 4.0f);
|
||||
float leaveAlpha = saturatef((float)(bar.endTime - now) * 4.0f);
|
||||
float alpha = std::min(enterAlpha, leaveAlpha);
|
||||
RenderOSDProgressBar(dc, bar, b, 0, alpha);
|
||||
y += (b.h + 4.0f) * alpha; // including alpha here gets us smooth animations.
|
||||
}
|
||||
|
||||
// Draw the rest of the top-center messages.
|
||||
// Grab all the entries. Makes a copy so we can release the lock ASAP.
|
||||
const std::vector<OnScreenDisplay::Entry> entries = g_OSD.Entries();
|
||||
for (const auto &entry : entries) {
|
||||
dc.SetFontScale(1.0f, 1.0f);
|
||||
// Messages that are wider than the screen are left-aligned instead of centered.
|
||||
|
||||
int align = 0;
|
||||
std::vector<MeasuredEntry> measuredEntries;
|
||||
measuredEntries.resize(entries.size());
|
||||
|
||||
// Indexed by the enum ScreenEdgePosition.
|
||||
LayoutEdge edges[(size_t)ScreenEdgePosition::VALUE_COUNT]{};
|
||||
for (size_t i = 0; i < (size_t)ScreenEdgePosition::VALUE_COUNT; i++) {
|
||||
edges[i].alpha = sidebarAlpha;
|
||||
}
|
||||
edges[(size_t)ScreenEdgePosition::TOP_CENTER].alpha = 1.0f;
|
||||
|
||||
ScreenEdgePosition typeEdges[(size_t)OSDType::VALUE_COUNT]{};
|
||||
// Default to top.
|
||||
for (int i = 0; i < (size_t)OSDType::VALUE_COUNT; i++) {
|
||||
typeEdges[i] = ScreenEdgePosition::TOP_CENTER;
|
||||
}
|
||||
|
||||
// TODO: Add ability to override these with g_Config settings.
|
||||
typeEdges[(size_t)OSDType::ACHIEVEMENT_CHALLENGE_INDICATOR] = ScreenEdgePosition::TOP_LEFT;
|
||||
typeEdges[(size_t)OSDType::ACHIEVEMENT_PROGRESS] = ScreenEdgePosition::TOP_LEFT;
|
||||
typeEdges[(size_t)OSDType::LEADERBOARD_TRACKER] = ScreenEdgePosition::TOP_LEFT;
|
||||
|
||||
dc.SetFontScale(1.0f, 1.0f);
|
||||
|
||||
// First pass: Measure all the sides.
|
||||
for (size_t i = 0; i < entries.size(); i++) {
|
||||
const auto &entry = entries[i];
|
||||
auto &measuredEntry = measuredEntries[i];
|
||||
|
||||
ScreenEdgePosition pos = typeEdges[(size_t)entry.type];
|
||||
|
||||
measuredEntry.align = 0;
|
||||
measuredEntry.align2 = 0;
|
||||
// If we have newlines, we may be looking at ASCII debug output. But let's verify.
|
||||
if (entry.text.find('\n') != 0) {
|
||||
if (entry.text.find('\n') != std::string::npos) {
|
||||
if (!UTF8StringHasNonASCII(entry.text.c_str()))
|
||||
align |= FLAG_DYNAMIC_ASCII;
|
||||
measuredEntry.align |= FLAG_DYNAMIC_ASCII;
|
||||
}
|
||||
if (entry.text2.find('\n') != std::string::npos) {
|
||||
if (!UTF8StringHasNonASCII(entry.text2.c_str()))
|
||||
measuredEntry.align2 |= FLAG_DYNAMIC_ASCII;
|
||||
}
|
||||
|
||||
float tw, th = 0.0f, h1 = 0.0f;
|
||||
|
||||
switch (entry.type) {
|
||||
case OSDType::ACHIEVEMENT_PROGRESS:
|
||||
{
|
||||
const rc_client_achievement_t *achievement = rc_client_get_achievement_info(Achievements::GetClient(), entry.numericID);
|
||||
if (!achievement)
|
||||
continue;
|
||||
measuredEntry.style = AchievementRenderStyle::PROGRESS_INDICATOR;
|
||||
MeasureAchievement(dc, achievement, measuredEntry.style, &measuredEntry.w, &measuredEntry.h);
|
||||
break;
|
||||
}
|
||||
case OSDType::ACHIEVEMENT_CHALLENGE_INDICATOR:
|
||||
{
|
||||
const rc_client_achievement_t *achievement = rc_client_get_achievement_info(Achievements::GetClient(), entry.numericID);
|
||||
if (!achievement)
|
||||
continue;
|
||||
measuredEntry.style = AchievementRenderStyle::CHALLENGE_INDICATOR;
|
||||
MeasureAchievement(dc, achievement, measuredEntry.style, &measuredEntry.w, &measuredEntry.h);
|
||||
break;
|
||||
}
|
||||
case OSDType::LEADERBOARD_TRACKER:
|
||||
{
|
||||
MeasureLeaderboardTracker(dc, entry.text, &measuredEntry.w, &measuredEntry.h);
|
||||
break;
|
||||
}
|
||||
case OSDType::ACHIEVEMENT_UNLOCKED:
|
||||
{
|
||||
const rc_client_achievement_t *achievement = rc_client_get_achievement_info(Achievements::GetClient(), entry.numericID);
|
||||
if (achievement) {
|
||||
MeasureAchievement(dc, achievement, AchievementRenderStyle::UNLOCKED, &tw, &th);
|
||||
h1 = th;
|
||||
}
|
||||
tw = 550.0f;
|
||||
if (!achievement)
|
||||
continue;
|
||||
measuredEntry.style = AchievementRenderStyle::UNLOCKED;
|
||||
MeasureAchievement(dc, achievement, AchievementRenderStyle::UNLOCKED, &measuredEntry.w, &measuredEntry.h);
|
||||
measuredEntry.h1 = measuredEntry.h;
|
||||
measuredEntry.w = 550.0f;
|
||||
break;
|
||||
}
|
||||
case OSDType::PROGRESS_BAR:
|
||||
MeasureOSDProgressBar(dc, entry, &measuredEntry.w, &measuredEntry.h);
|
||||
break;
|
||||
default:
|
||||
MeasureOSDEntry(dc, entry, align, &tw, &th, &h1);
|
||||
MeasureOSDEntry(dc, entry, measuredEntry.align, &measuredEntry.w, &measuredEntry.h, &measuredEntry.h1);
|
||||
break;
|
||||
}
|
||||
|
||||
Bounds b(0.0f, y, tw, th);
|
||||
float enterAlpha = saturatef((float)(now - entry.startTime) * fadeoutCoef);
|
||||
float leaveAlpha = saturatef((float)(entry.endTime - now) * fadeoutCoef);
|
||||
float alpha = std::min(enterAlpha, leaveAlpha);
|
||||
measuredEntry.alpha = alpha;
|
||||
|
||||
if (tw > bounds_.w) {
|
||||
// Left-aligned
|
||||
b.x = 2;
|
||||
} else {
|
||||
// Centered
|
||||
b.x = (bounds_.w - b.w) * 0.5f;
|
||||
edges[(size_t)pos].height += (measuredEntry.h + 4.0f) * alpha;
|
||||
edges[(size_t)pos].maxWidth = std::max(edges[(size_t)pos].maxWidth, measuredEntry.w);
|
||||
}
|
||||
|
||||
// Now, perform layout for all 8 edges.
|
||||
for (size_t i = 0; i < (size_t)ScreenEdgePosition::VALUE_COUNT; i++) {
|
||||
if (edges[i].height == 0.0f) {
|
||||
// Nothing on this side, ignore it entirely.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Scale down if height doesn't fit.
|
||||
float scale = 1.0f;
|
||||
if (th > bounds_.h - y) {
|
||||
// Scale down!
|
||||
scale = std::max(0.15f, (bounds_.h - y) / th);
|
||||
dc.SetFontScale(scale, scale);
|
||||
b.w *= scale;
|
||||
b.h *= scale;
|
||||
// First, compute the start position.
|
||||
float y = padding;
|
||||
int horizAdj = 0;
|
||||
int vertAdj = 0;
|
||||
switch ((ScreenEdgePosition)i) {
|
||||
case ScreenEdgePosition::TOP_LEFT: horizAdj = -1; vertAdj = -1; break;
|
||||
case ScreenEdgePosition::CENTER_LEFT: horizAdj = -1; break;
|
||||
case ScreenEdgePosition::BOTTOM_LEFT: horizAdj = -1; vertAdj = 1; break;
|
||||
case ScreenEdgePosition::TOP_RIGHT: horizAdj = 1; vertAdj = -1; break;
|
||||
case ScreenEdgePosition::CENTER_RIGHT: horizAdj = 1; break;
|
||||
case ScreenEdgePosition::BOTTOM_RIGHT: horizAdj = 1; vertAdj = 1; break;
|
||||
case ScreenEdgePosition::TOP_CENTER: vertAdj = -1; break;
|
||||
case ScreenEdgePosition::BOTTOM_CENTER: vertAdj = 1; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
float alpha = Clamp((float)(entry.endTime - now) * 4.0f, 0.0f, 1.0f);
|
||||
RenderOSDEntry(dc, entry, b, h1, align, alpha);
|
||||
y += (b.h * scale + 4.0f) * alpha; // including alpha here gets us smooth animations.
|
||||
if (vertAdj == 0) {
|
||||
// Center vertically
|
||||
y = (bounds_.h - edges[i].height) * 0.5f;
|
||||
} else if (vertAdj == 1) {
|
||||
y = (bounds_.h - edges[i].height);
|
||||
}
|
||||
|
||||
// Then, loop through the entries and those belonging here, get rendered here.
|
||||
for (size_t j = 0; j < (size_t)entries.size(); j++) {
|
||||
auto &entry = entries[j];
|
||||
if (typeEdges[(size_t)entry.type] != (ScreenEdgePosition)i) { // yes, i
|
||||
continue;
|
||||
}
|
||||
auto &measuredEntry = measuredEntries[j];
|
||||
float alpha = measuredEntry.alpha * edges[i].alpha;
|
||||
|
||||
Bounds b(padding, y, measuredEntry.w, measuredEntry.h);
|
||||
|
||||
if (horizAdj == 0) {
|
||||
// Centered
|
||||
b.x = (bounds_.w - b.w) * 0.5f;
|
||||
} else if (horizAdj == 1) {
|
||||
// Right-aligned
|
||||
b.x = bounds_.w - (b.w + padding);
|
||||
}
|
||||
|
||||
switch (entry.type) {
|
||||
case OSDType::ACHIEVEMENT_PROGRESS:
|
||||
case OSDType::ACHIEVEMENT_CHALLENGE_INDICATOR:
|
||||
{
|
||||
const rc_client_achievement_t *achievement = rc_client_get_achievement_info(Achievements::GetClient(), entry.numericID);
|
||||
RenderAchievement(dc, achievement, measuredEntry.style, b, alpha, entry.startTime, now, false);
|
||||
break;
|
||||
}
|
||||
case OSDType::LEADERBOARD_TRACKER:
|
||||
RenderLeaderboardTracker(dc, b, entry.text, alpha);
|
||||
break;
|
||||
case OSDType::PROGRESS_BAR:
|
||||
RenderOSDProgressBar(dc, entry, b, 0, alpha);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
// Scale down if height doesn't fit.
|
||||
float scale = 1.0f;
|
||||
if (measuredEntry.h > bounds_.h - y) {
|
||||
// Scale down!
|
||||
scale = std::max(0.15f, (bounds_.h - y) / measuredEntry.h);
|
||||
dc.SetFontScale(scale, scale);
|
||||
b.w *= scale;
|
||||
b.h *= scale;
|
||||
}
|
||||
|
||||
float alpha = Clamp((float)(entry.endTime - now) * 4.0f, 0.0f, 1.0f);
|
||||
RenderOSDEntry(dc, entry, b, measuredEntry.h1, measuredEntry.align, alpha);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
y += (measuredEntry.h + 4.0f) * measuredEntry.alpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -275,7 +275,7 @@ void RetroAchievementsSettingsScreen::CreateAccountTab(UI::ViewGroup *viewGroup)
|
||||
using namespace UI;
|
||||
|
||||
if (!g_Config.bAchievementsEnable) {
|
||||
viewGroup->Add(new TextView(ac->T("Achievements are disabled")));
|
||||
viewGroup->Add(new NoticeView(NoticeLevel::INFO, ac->T("Achievements are disabled"), "", new LinearLayoutParams(Margins(5))));
|
||||
} else if (Achievements::IsLoggedIn()) {
|
||||
const rc_client_user_t *info = rc_client_get_user_info(Achievements::GetClient());
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user